gitlab-fluent-plugin-redis-slowlog 0.0.2 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/lib/fluent/plugin/in_redis_slowlog.rb +25 -19
 - data/spec/fluent/plugin/redis_slowlog_input_spec.rb +43 -14
 - metadata +2 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: d38f425f2f17bdb5aa44efb1c3901240bb1f41f340cef86c9cca6834716e975b
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: e6739b5077e8d9c6b6482c7de64c80fea53d960cceb22f100ea55237269320f3
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: ae4c9a0fafe66b7df1d9c49f639f882c5c834ad368dab29a9d0599a5af75ae4e73f4f113f4b4e3e6bc2f71b9aa9358403c48188865ffabd3797302e9add5ea53
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 3d748722aa7ae4690f9298c455ee91fbbd4106f1fc505fa98b28f5198722086286a8343b907d10fbea0dab6bd9ad55a368b9f8af3bb1794f7f11b244d1614ff8
         
     | 
| 
         @@ -6,6 +6,8 @@ module Fluent 
     | 
|
| 
       6 
6 
     | 
    
         
             
                class RedisSlowlogInput < Fluent::Plugin::Input
         
     | 
| 
       7 
7 
     | 
    
         
             
                  Fluent::Plugin.register_input("redis_slowlog", self)
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
      
 9 
     | 
    
         
            +
                  Entry = Struct.new(:id, :timestamp, :exec_time_us, :command)
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
       9 
11 
     | 
    
         
             
                  config_param :tag,      :string
         
     | 
| 
       10 
12 
     | 
    
         
             
                  config_param :url,      :string,  default: nil
         
     | 
| 
       11 
13 
     | 
    
         
             
                  config_param :path,     :string,  default: nil
         
     | 
| 
         @@ -15,12 +17,6 @@ module Fluent 
     | 
|
| 
       15 
17 
     | 
    
         
             
                  config_param :logsize,  :integer, default: 128
         
     | 
| 
       16 
18 
     | 
    
         
             
                  config_param :interval, :integer, default: 10
         
     | 
| 
       17 
19 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
                  def initialize
         
     | 
| 
       19 
     | 
    
         
            -
                    super
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
                    @current_log_id = 0
         
     | 
| 
       22 
     | 
    
         
            -
                  end
         
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
20 
     | 
    
         
             
                  def configure(conf)
         
     | 
| 
       25 
21 
     | 
    
         
             
                    super
         
     | 
| 
       26 
22 
     | 
    
         | 
| 
         @@ -55,39 +51,49 @@ module Fluent 
     | 
|
| 
       55 
51 
     | 
    
         
             
                  private
         
     | 
| 
       56 
52 
     | 
    
         | 
| 
       57 
53 
     | 
    
         
             
                  attr_reader :redis, :interval
         
     | 
| 
       58 
     | 
    
         
            -
                  attr_accessor :watcher, :watching 
     | 
| 
      
 54 
     | 
    
         
            +
                  attr_accessor :watcher, :watching
         
     | 
| 
       59 
55 
     | 
    
         | 
| 
       60 
56 
     | 
    
         
             
                  def watch
         
     | 
| 
      
 57 
     | 
    
         
            +
                    # Check the current id of the slowlog, and start logging from there
         
     | 
| 
      
 58 
     | 
    
         
            +
                    current_log_id = get_slowlogs(1).first&.id || -1
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
       61 
60 
     | 
    
         
             
                    while watching
         
     | 
| 
       62 
61 
     | 
    
         
             
                      sleep interval
         
     | 
| 
       63 
62 
     | 
    
         | 
| 
       64 
     | 
    
         
            -
                       
     | 
| 
      
 63 
     | 
    
         
            +
                      current_log_id = output(current_log_id)
         
     | 
| 
       65 
64 
     | 
    
         
             
                    end
         
     | 
| 
       66 
65 
     | 
    
         
             
                  end
         
     | 
| 
       67 
66 
     | 
    
         | 
| 
       68 
     | 
    
         
            -
                  def output(last_id 
     | 
| 
       69 
     | 
    
         
            -
                    slowlogs =  
     | 
| 
      
 67 
     | 
    
         
            +
                  def output(last_id)
         
     | 
| 
      
 68 
     | 
    
         
            +
                    slowlogs = get_slowlogs(logsize)
         
     | 
| 
       70 
69 
     | 
    
         
             
                    return last_id if slowlogs.empty?
         
     | 
| 
       71 
70 
     | 
    
         | 
| 
       72 
     | 
    
         
            -
                     
     | 
| 
      
 71 
     | 
    
         
            +
                    # If the latest entry is smaller than what we last saw, redis was restarted
         
     | 
| 
      
 72 
     | 
    
         
            +
                    # Restart logging from the beginning.
         
     | 
| 
      
 73 
     | 
    
         
            +
                    last_id = -1 if slowlogs.first.id < last_id
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                    emit_slowlog(slowlogs, last_id)
         
     | 
| 
       73 
76 
     | 
    
         | 
| 
       74 
77 
     | 
    
         
             
                    # Return the id of the last slowlog entry we've logged
         
     | 
| 
       75 
78 
     | 
    
         
             
                    # The first entry is the one that occurred last
         
     | 
| 
       76 
     | 
    
         
            -
                    slowlogs.first. 
     | 
| 
      
 79 
     | 
    
         
            +
                    slowlogs.first.id
         
     | 
| 
       77 
80 
     | 
    
         
             
                  end
         
     | 
| 
       78 
81 
     | 
    
         | 
| 
       79 
     | 
    
         
            -
                  def emit_slowlog(slowlogs)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  def emit_slowlog(slowlogs, last_id)
         
     | 
| 
       80 
83 
     | 
    
         
             
                    slowlogs.reverse_each do |log|
         
     | 
| 
       81 
84 
     | 
    
         
             
                      # Don't emit logs for entries we've already logged
         
     | 
| 
       82 
     | 
    
         
            -
                      next if log. 
     | 
| 
      
 85 
     | 
    
         
            +
                      next if log.id <= last_id
         
     | 
| 
       83 
86 
     | 
    
         | 
| 
       84 
     | 
    
         
            -
                      log_hash = { "id" => log 
     | 
| 
       85 
     | 
    
         
            -
                                   " 
     | 
| 
       86 
     | 
    
         
            -
                                   " 
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
       88 
     | 
    
         
            -
                      router.emit(tag, Time.now.to_i, log_hash)
         
     | 
| 
      
 87 
     | 
    
         
            +
                      log_hash = { "id" => log.id,
         
     | 
| 
      
 88 
     | 
    
         
            +
                                   "exec_time" => log.exec_time_us,
         
     | 
| 
      
 89 
     | 
    
         
            +
                                   "command" => log.command }
         
     | 
| 
      
 90 
     | 
    
         
            +
                      router.emit(tag, Fluent::EventTime.new(log.timestamp.to_i), log_hash)
         
     | 
| 
       89 
91 
     | 
    
         
             
                    end
         
     | 
| 
       90 
92 
     | 
    
         
             
                  end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                  def get_slowlogs(size)
         
     | 
| 
      
 95 
     | 
    
         
            +
                    redis.slowlog("get", size).map { |slowlog_entry| Entry.new(*slowlog_entry.first(4)) }
         
     | 
| 
      
 96 
     | 
    
         
            +
                  end
         
     | 
| 
       91 
97 
     | 
    
         
             
                end
         
     | 
| 
       92 
98 
     | 
    
         
             
              end
         
     | 
| 
       93 
99 
     | 
    
         
             
            end
         
     | 
| 
         @@ -6,21 +6,24 @@ describe Fluent::Plugin::RedisSlowlogInput do 
     | 
|
| 
       6 
6 
     | 
    
         
             
              end
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
              let(:plugin) { driver.instance }
         
     | 
| 
       9 
     | 
    
         
            -
              let(: 
     | 
| 
       10 
     | 
    
         
            -
              let(:fake_redis) { instance_double(Redis, ping: "PONG", quit: "OK", slowlog: slowlog) }
         
     | 
| 
      
 9 
     | 
    
         
            +
              let(:fake_redis) { instance_double(Redis, ping: "PONG", quit: "OK", slowlog: []) }
         
     | 
| 
       11 
10 
     | 
    
         | 
| 
       12 
11 
     | 
    
         
             
              subject(:driver) do
         
     | 
| 
       13 
12 
     | 
    
         
             
                config_string = config.map { |key, value| "#{key} #{value}" }.join("\n")
         
     | 
| 
       14 
13 
     | 
    
         
             
                Fluent::Test::Driver::Input.new(described_class).configure(config_string)
         
     | 
| 
       15 
14 
     | 
    
         
             
              end
         
     | 
| 
       16 
15 
     | 
    
         | 
| 
      
 16 
     | 
    
         
            +
              def run(**options)
         
     | 
| 
      
 17 
     | 
    
         
            +
                driver.run({ timeout: 1 }.merge(options))
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
       17 
20 
     | 
    
         
             
              before do
         
     | 
| 
       18 
21 
     | 
    
         
             
                Fluent::Test.setup
         
     | 
| 
       19 
22 
     | 
    
         
             
              end
         
     | 
| 
       20 
23 
     | 
    
         | 
| 
       21 
24 
     | 
    
         
             
              context "when redis can't be reached" do
         
     | 
| 
       22 
25 
     | 
    
         
             
                it "raises an error" do
         
     | 
| 
       23 
     | 
    
         
            -
                  expect {  
     | 
| 
      
 26 
     | 
    
         
            +
                  expect { run }.to raise_error(Redis::CannotConnectError)
         
     | 
| 
       24 
27 
     | 
    
         
             
                end
         
     | 
| 
       25 
28 
     | 
    
         
             
              end
         
     | 
| 
       26 
29 
     | 
    
         | 
| 
         @@ -40,7 +43,7 @@ describe Fluent::Plugin::RedisSlowlogInput do 
     | 
|
| 
       40 
43 
     | 
    
         | 
| 
       41 
44 
     | 
    
         
             
                  expect(Redis).to receive(:new).with(redis_params).and_return(fake_redis)
         
     | 
| 
       42 
45 
     | 
    
         | 
| 
       43 
     | 
    
         
            -
                   
     | 
| 
      
 46 
     | 
    
         
            +
                  run
         
     | 
| 
       44 
47 
     | 
    
         
             
                end
         
     | 
| 
       45 
48 
     | 
    
         
             
              end
         
     | 
| 
       46 
49 
     | 
    
         | 
| 
         @@ -63,10 +66,11 @@ describe Fluent::Plugin::RedisSlowlogInput do 
     | 
|
| 
       63 
66 
     | 
    
         
             
                end
         
     | 
| 
       64 
67 
     | 
    
         | 
| 
       65 
68 
     | 
    
         
             
                it "does not raise errors" do
         
     | 
| 
       66 
     | 
    
         
            -
                  expect {  
     | 
| 
      
 69 
     | 
    
         
            +
                  expect { run }.not_to raise_error
         
     | 
| 
       67 
70 
     | 
    
         
             
                end
         
     | 
| 
       68 
71 
     | 
    
         | 
| 
       69 
72 
     | 
    
         
             
                it "polls the slowlog with the configured interval and size" do
         
     | 
| 
      
 73 
     | 
    
         
            +
                  expect(fake_redis).to receive(:slowlog).with("get", 1).ordered
         
     | 
| 
       70 
74 
     | 
    
         
             
                  expect(plugin).to receive(:sleep).with(0).ordered
         
     | 
| 
       71 
75 
     | 
    
         
             
                  expect(fake_redis).to receive(:slowlog).with("get", 10).ordered
         
     | 
| 
       72 
76 
     | 
    
         
             
                  expect(plugin).to receive(:sleep).with(0).ordered
         
     | 
| 
         @@ -75,51 +79,76 @@ describe Fluent::Plugin::RedisSlowlogInput do 
     | 
|
| 
       75 
79 
     | 
    
         
             
                  # Limit to 2 cycles
         
     | 
| 
       76 
80 
     | 
    
         
             
                  allow(plugin).to receive(:watching).thrice.and_return(true, true, false)
         
     | 
| 
       77 
81 
     | 
    
         | 
| 
       78 
     | 
    
         
            -
                   
     | 
| 
      
 82 
     | 
    
         
            +
                  run
         
     | 
| 
       79 
83 
     | 
    
         
             
                end
         
     | 
| 
       80 
84 
     | 
    
         | 
| 
       81 
     | 
    
         
            -
                context "when the slowlog returns entries" do
         
     | 
| 
       82 
     | 
    
         
            -
                  let(: 
     | 
| 
      
 85 
     | 
    
         
            +
                context "when the slowlog returns entries", :aggregate_failures do
         
     | 
| 
      
 86 
     | 
    
         
            +
                  let(:startup_slowlog) { [[25637, 1590522108, 5, %w[SCAN 0]]] }
         
     | 
| 
      
 87 
     | 
    
         
            +
                  let(:logged_slowlog) do
         
     | 
| 
       83 
88 
     | 
    
         
             
                    [
         
     | 
| 
       84 
89 
     | 
    
         
             
                      [25640, 1590522258, 1, %w[ping]],
         
     | 
| 
       85 
90 
     | 
    
         
             
                      [25639, 1590522249, 1, %w[ping]],
         
     | 
| 
       86 
91 
     | 
    
         
             
                      [25638, 1590522208, 5, %w[SCAN 0]]
         
     | 
| 
       87 
92 
     | 
    
         
             
                    ]
         
     | 
| 
       88 
93 
     | 
    
         
             
                  end
         
     | 
| 
      
 94 
     | 
    
         
            +
                  let(:slowlog) { logged_slowlog + startup_slowlog }
         
     | 
| 
       89 
95 
     | 
    
         | 
| 
       90 
96 
     | 
    
         
             
                  let(:expected_entries) do
         
     | 
| 
       91 
     | 
    
         
            -
                     
     | 
| 
      
 97 
     | 
    
         
            +
                    logged_slowlog.map(&method(:log_entry)).sort_by { |event| event["id"] }
         
     | 
| 
       92 
98 
     | 
    
         
             
                  end
         
     | 
| 
       93 
99 
     | 
    
         | 
| 
       94 
100 
     | 
    
         
             
                  let(:emitted_entries) { driver.events.map(&:last) }
         
     | 
| 
       95 
101 
     | 
    
         | 
| 
       96 
102 
     | 
    
         
             
                  it "emits an event for each slowlog in reverse order" do
         
     | 
| 
       97 
     | 
    
         
            -
                     
     | 
| 
      
 103 
     | 
    
         
            +
                    expect(fake_redis).to receive(:slowlog).and_return(startup_slowlog, slowlog)
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                    run(expect_emits: 3)
         
     | 
| 
       98 
106 
     | 
    
         | 
| 
       99 
107 
     | 
    
         
             
                    expect(driver.events.size).to eq(3)
         
     | 
| 
       100 
108 
     | 
    
         
             
                    expect(emitted_entries).to eq(expected_entries)
         
     | 
| 
       101 
109 
     | 
    
         
             
                  end
         
     | 
| 
       102 
110 
     | 
    
         | 
| 
       103 
111 
     | 
    
         
             
                  it "does not log the same event twice" do
         
     | 
| 
       104 
     | 
    
         
            -
                    expect(fake_redis).to receive(:slowlog).and_return(slowlog.last( 
     | 
| 
      
 112 
     | 
    
         
            +
                    expect(fake_redis).to receive(:slowlog).and_return(startup_slowlog, slowlog.last(2), slowlog)
         
     | 
| 
       105 
113 
     | 
    
         | 
| 
       106 
     | 
    
         
            -
                     
     | 
| 
      
 114 
     | 
    
         
            +
                    run(expect_emits: 3)
         
     | 
| 
       107 
115 
     | 
    
         | 
| 
       108 
116 
     | 
    
         
             
                    expect(driver.events.size).to eq(3)
         
     | 
| 
       109 
117 
     | 
    
         
             
                    expect(emitted_entries).to eq(expected_entries)
         
     | 
| 
       110 
118 
     | 
    
         
             
                  end
         
     | 
| 
       111 
119 
     | 
    
         | 
| 
       112 
120 
     | 
    
         
             
                  it "emits results that can be streamed to fluent using MessagePack" do
         
     | 
| 
       113 
     | 
    
         
            -
                     
     | 
| 
      
 121 
     | 
    
         
            +
                    expect(fake_redis).to receive(:slowlog).and_return(startup_slowlog, slowlog)
         
     | 
| 
      
 122 
     | 
    
         
            +
             
     | 
| 
      
 123 
     | 
    
         
            +
                    run(expect_emits: 3)
         
     | 
| 
       114 
124 
     | 
    
         | 
| 
       115 
125 
     | 
    
         
             
                    expect { driver.events.map(&:to_msgpack) }.not_to raise_error
         
     | 
| 
       116 
126 
     | 
    
         
             
                  end
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
                  context "when redis restarts" do
         
     | 
| 
      
 129 
     | 
    
         
            +
                    let(:logged_slowlog) { [[25638, 1590522208, 5, %w[SCAN 0]]] }
         
     | 
| 
      
 130 
     | 
    
         
            +
                    let(:reset_slowlog) do
         
     | 
| 
      
 131 
     | 
    
         
            +
                      [
         
     | 
| 
      
 132 
     | 
    
         
            +
                        [2, 1590522258, 1, %w[ping]],
         
     | 
| 
      
 133 
     | 
    
         
            +
                        [1, 1590522249, 1, %w[ping]]
         
     | 
| 
      
 134 
     | 
    
         
            +
                      ]
         
     | 
| 
      
 135 
     | 
    
         
            +
                    end
         
     | 
| 
      
 136 
     | 
    
         
            +
             
     | 
| 
      
 137 
     | 
    
         
            +
                    it "emits all items" do
         
     | 
| 
      
 138 
     | 
    
         
            +
                      reset_entries = reset_slowlog.map(&method(:log_entry)).sort_by { |e| e["id"] }
         
     | 
| 
      
 139 
     | 
    
         
            +
                      expect(fake_redis).to receive(:slowlog).and_return(startup_slowlog, slowlog, [], reset_slowlog)
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
                      run(expect_emits: 3)
         
     | 
| 
      
 142 
     | 
    
         
            +
             
     | 
| 
      
 143 
     | 
    
         
            +
                      expect(emitted_entries.size).to eq(3)
         
     | 
| 
      
 144 
     | 
    
         
            +
                      expect(emitted_entries).to eq(expected_entries + reset_entries)
         
     | 
| 
      
 145 
     | 
    
         
            +
                    end
         
     | 
| 
      
 146 
     | 
    
         
            +
                  end
         
     | 
| 
       117 
147 
     | 
    
         
             
                end
         
     | 
| 
       118 
148 
     | 
    
         
             
              end
         
     | 
| 
       119 
149 
     | 
    
         | 
| 
       120 
150 
     | 
    
         
             
              def log_entry(slowlog_entry)
         
     | 
| 
       121 
151 
     | 
    
         
             
                { "id" => slowlog_entry.first,
         
     | 
| 
       122 
     | 
    
         
            -
                  "timestamp" => slowlog_entry[1].to_i,
         
     | 
| 
       123 
152 
     | 
    
         
             
                  "exec_time" => slowlog_entry[2],
         
     | 
| 
       124 
153 
     | 
    
         
             
                  "command" => slowlog_entry.last }
         
     | 
| 
       125 
154 
     | 
    
         
             
              end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: gitlab-fluent-plugin-redis-slowlog
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.0 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.1.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Bob Van Landuyt
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2020-06- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2020-06-22 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: bundler
         
     |