gitlab-fluent-plugin-redis-slowlog 0.0.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8fc7a7afc37728bd3e9ae94eeaa408103bf28f00a87c6e931a4568f675bab927
4
- data.tar.gz: 3e7fc4b3bc8dbb082f84f211f4de09ceb9b415b2d9d7c0c59b67316498586730
3
+ metadata.gz: 3c1ce26c15184cd4542891a3175434b81ed44b295a6ffd2a8c96222d4fd16da8
4
+ data.tar.gz: 632613b3d6b036a6f94c66bea02dc08d5dff119202b1614f5df4ff1efd3c1c58
5
5
  SHA512:
6
- metadata.gz: 4e315c9db4c5d3b70c196fcb9dd912304ea8619766f8d9bbc8c00eeb1d4389f96fd37f1279f061e1c3d977944a972209763cadf417bb1dc18c98b12aceeeb9c9
7
- data.tar.gz: 59f9771844039b0a250c9f6bcbf342ea42163d2710d79b9121f222c39736d3cb8f40e2978cf40a2e86496b507ef1da549fdfbeadea47098c9c6dc86efffb8739
6
+ metadata.gz: aea063934370511db16b64743463868b909d4685c141e0d56365f2edb604688125851d815b5c241f0a721be42e17785aea0f6ce862e726b050e1812d70a0bd2a
7
+ data.tar.gz: 99ff9bf22f51fc3b5d6bffc55db8c3979b67bc41a4ef0ba69bb4ab136332a6de938694f39a9f4fc4409a2f41dcfdcb84a14bc8aec6fc353544a14dd9578713c2
data/.gitignore CHANGED
@@ -1 +1,2 @@
1
1
  *.gem
2
+ Gemfile.lock
@@ -1,19 +1,40 @@
1
- test:
2
- image: ruby:2.6
1
+ workflow:
2
+ rules:
3
+ # For merge requests, create a pipeline.
4
+ - if: '$CI_MERGE_REQUEST_IID'
5
+ # For `master` branch, create a pipeline (this includes on schedules, pushes, merges, etc.).
6
+ - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
7
+ # For tags, create a pipeline.
8
+ - if: '$CI_COMMIT_TAG'
9
+
10
+ .test_template: &test_definition
3
11
  stage: test
4
12
  script:
5
13
  - gem install bundler
6
14
  - bundle install
7
15
  - bundle exec rake
8
16
 
17
+ test2.6:
18
+ image: ruby:2.6
19
+ <<: *test_definition
20
+ test2.5:
21
+ image: ruby:2.5
22
+ <<: *test_definition
23
+ test2.4:
24
+ image: ruby:2.4
25
+ <<: *test_definition
26
+
9
27
  deploy:
28
+ image: ruby:2.6
10
29
  stage: deploy
11
30
  script:
31
+ - gem install bundler
12
32
  - tools/deploy-rubygem.sh
13
33
  only:
14
34
  - tags
15
35
 
16
36
  release:
37
+ image: ruby:2.6
17
38
  stage: deploy
18
39
  script:
19
40
  - tools/update-changelog.rb "${CI_COMMIT_TAG}"
@@ -3,14 +3,14 @@ inherit_gem:
3
3
  - rubocop-default.yml
4
4
 
5
5
  AllCops:
6
- TargetRubyVersion: 2.6
6
+ TargetRubyVersion: 2.4
7
7
 
8
8
  # Let's just pick something from the beginning
9
9
  Style/StringLiterals:
10
10
  Enabled: true
11
11
  EnforcedStyle: double_quotes
12
12
 
13
- # This isn't Rails, so diable these
13
+ # This isn't Rails, so disable these
14
14
  Rails/RakeEnvironment:
15
15
  Enabled: false
16
16
  CodeReuse/ActiveRecord:
data/README.md CHANGED
@@ -118,16 +118,15 @@ rake verify # Run RuboCop
118
118
  rake verify:auto_correct # Auto-correct RuboCop offenses
119
119
  ```
120
120
 
121
-
122
121
  ### Releasing a new version
123
122
 
124
123
  Releasing a new version can be done by pushing a new tag, or creating
125
124
  it from the
126
125
  [interface](https://gitlab.com/gitlab-org/fluent-plugin-redis-slowlog/-/tags).
127
126
 
128
- A new changelog will automatically be added to the release on Gitlab.
127
+ A new changelog will automatically be added to the release on GitLab.
129
128
 
130
129
  The new version will automatically be published to
131
- [rubygems](https://rubygems.org/gems/gitlab-labkit) when the pipeline
132
- for the tag completes. It might take a few minutes before the update
133
- is available.
130
+ [rubygems](https://rubygems.org/gems/gitlab-fluent-plugin-redis-slowlog)
131
+ when the pipeline for the tag completes. It might take a few minutes
132
+ before the update is available.
@@ -3,12 +3,12 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  Gem::Specification.new do |spec|
5
5
  spec.name = "gitlab-fluent-plugin-redis-slowlog"
6
- spec.version = "0.0.0" # `git describe --tags`.chomp.gsub(/^v/, "")
6
+ spec.version = `git describe --tags`.chomp.gsub(/^v/, "")
7
7
  spec.metadata = { "source_code_uri" => "https://gitlab.com/gitlab-org/fluent-plugin-redis-slowlog" }
8
8
  spec.authors = ["Bob Van Landuyt"]
9
9
  spec.email = ["bob@gitlab.com"]
10
10
 
11
- spec.required_ruby_version = ">= 2.6"
11
+ spec.required_ruby_version = ">= 2.4"
12
12
 
13
13
  spec.summary = "Emit redis slowlog entries into fluentd"
14
14
  spec.homepage = "http://gitlab.com/gitlab-org/gitlab-fluent-plugin-redis-slowlog"
@@ -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,50 @@ module Fluent
55
51
  private
56
52
 
57
53
  attr_reader :redis, :interval
58
- attr_accessor :watcher, :watching, :current_log_id
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
- self.current_log_id = output(current_log_id)
63
+ current_log_id = output(current_log_id)
65
64
  end
66
65
  end
67
66
 
68
- def output(last_id = 0)
69
- slowlogs = redis.slowlog("get", logsize)
67
+ def output(last_id)
68
+ slowlogs = get_slowlogs(logsize)
70
69
  return last_id if slowlogs.empty?
71
70
 
72
- emit_slowlog(slowlogs)
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.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.first <= current_log_id
85
+ next if log.id <= last_id
83
86
 
84
- log_hash = { "id" => log[0],
85
- "timestamp" => Time.at(log[1]),
86
- "exec_time" => log[2],
87
- "command" => log[3] }
88
- router.emit(tag, Time.now.to_i, log_hash)
87
+ log_hash = { "id" => log.id,
88
+ "time" => Time.at(log.timestamp.to_i).utc.iso8601(3),
89
+ "exec_time" => log.exec_time_us,
90
+ "command" => log.command }
91
+ router.emit(tag, Fluent::EventTime.new(log.timestamp.to_i), log_hash)
89
92
  end
90
93
  end
94
+
95
+ def get_slowlogs(size)
96
+ redis.slowlog("get", size).map { |slowlog_entry| Entry.new(*slowlog_entry.first(4)) }
97
+ end
91
98
  end
92
99
  end
93
100
  end
@@ -6,21 +6,24 @@ describe Fluent::Plugin::RedisSlowlogInput do
6
6
  end
7
7
 
8
8
  let(:plugin) { driver.instance }
9
- let(:slowlog) { [] }
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 { driver.run }.to raise_error(Redis::CannotConnectError)
26
+ expect { run }.to raise_error(Redis::CannotConnectError)
24
27
  end
25
28
  end
26
29
 
@@ -35,11 +38,12 @@ describe Fluent::Plugin::RedisSlowlogInput do
35
38
  end
36
39
 
37
40
  it "delegates all of them to redis-rb" do
38
- redis_params = [:url, :path, :host, :port, :password]
41
+ # In ruby 2.5+ this could be config.slice(*[])
42
+ redis_params = config.select { |name, _| [:url, :path, :host, :port, :password].include?(name) }
39
43
 
40
- expect(Redis).to receive(:new).with(config.slice(*redis_params)).and_return(fake_redis)
44
+ expect(Redis).to receive(:new).with(redis_params).and_return(fake_redis)
41
45
 
42
- driver.run
46
+ run
43
47
  end
44
48
  end
45
49
 
@@ -62,10 +66,11 @@ describe Fluent::Plugin::RedisSlowlogInput do
62
66
  end
63
67
 
64
68
  it "does not raise errors" do
65
- expect { driver.run }.not_to raise_error
69
+ expect { run }.not_to raise_error
66
70
  end
67
71
 
68
- it "polls the slowlog at with the configured interval and size" do
72
+ it "polls the slowlog with the configured interval and size" do
73
+ expect(fake_redis).to receive(:slowlog).with("get", 1).ordered
69
74
  expect(plugin).to receive(:sleep).with(0).ordered
70
75
  expect(fake_redis).to receive(:slowlog).with("get", 10).ordered
71
76
  expect(plugin).to receive(:sleep).with(0).ordered
@@ -74,45 +79,77 @@ describe Fluent::Plugin::RedisSlowlogInput do
74
79
  # Limit to 2 cycles
75
80
  allow(plugin).to receive(:watching).thrice.and_return(true, true, false)
76
81
 
77
- driver.run
82
+ run
78
83
  end
79
84
 
80
- context "when the slowlog returns entries" do
81
- let(:slowlog) do
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
82
88
  [
83
89
  [25640, 1590522258, 1, %w[ping]],
84
90
  [25639, 1590522249, 1, %w[ping]],
85
91
  [25638, 1590522208, 5, %w[SCAN 0]]
86
92
  ]
87
93
  end
94
+ let(:slowlog) { logged_slowlog + startup_slowlog }
88
95
 
89
96
  let(:expected_entries) do
90
- slowlog.map(&method(:log_entry)).sort_by { |event| event["id"] }
97
+ logged_slowlog.map(&method(:log_entry)).sort_by { |event| event["id"] }
91
98
  end
92
99
 
93
100
  let(:emitted_entries) { driver.events.map(&:last) }
94
101
 
95
102
  it "emits an event for each slowlog in reverse order" do
96
- driver.run(expect_emits: 3)
103
+ expect(fake_redis).to receive(:slowlog).and_return(startup_slowlog, slowlog)
104
+
105
+ run(expect_emits: 3)
97
106
 
98
107
  expect(driver.events.size).to eq(3)
99
108
  expect(emitted_entries).to eq(expected_entries)
100
109
  end
101
110
 
102
111
  it "does not log the same event twice" do
103
- expect(fake_redis).to receive(:slowlog).and_return(slowlog.last(1), slowlog)
112
+ expect(fake_redis).to receive(:slowlog).and_return(startup_slowlog, slowlog.last(2), slowlog)
104
113
 
105
- driver.run(expect_emits: 3)
114
+ run(expect_emits: 3)
106
115
 
107
116
  expect(driver.events.size).to eq(3)
108
117
  expect(emitted_entries).to eq(expected_entries)
109
118
  end
119
+
120
+ it "emits results that can be streamed to fluent using MessagePack" do
121
+ expect(fake_redis).to receive(:slowlog).and_return(startup_slowlog, slowlog)
122
+
123
+ run(expect_emits: 3)
124
+
125
+ expect { driver.events.map(&:to_msgpack) }.not_to raise_error
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
110
147
  end
111
148
  end
112
149
 
113
150
  def log_entry(slowlog_entry)
114
151
  { "id" => slowlog_entry.first,
115
- "timestamp" => Time.at(slowlog_entry[1]),
152
+ "time" => Time.at(slowlog_entry[1].to_i).utc.iso8601(3),
116
153
  "exec_time" => slowlog_entry[2],
117
154
  "command" => slowlog_entry.last }
118
155
  end
@@ -27,5 +27,5 @@ set -x
27
27
  rm -rf pkg/
28
28
  mkdir -p pkg/
29
29
  bundle install
30
- bundle exec rake verify build
30
+ bundle exec rake build
31
31
  gem push pkg/*.gem
@@ -26,8 +26,8 @@ def gitlab_client(path, method, body = nil)
26
26
  raise "Unknown method: #{method}"
27
27
  end
28
28
 
29
- request["content-type"] = "application/json"
30
- request["PRIVATE-TOKEN"] = ENV["GITLAB_TOKEN"]
29
+ request["Content-Type"] = "application/json"
30
+ request["Private-Token"] = ENV["GITLAB_TOKEN"]
31
31
  request.body = JSON.dump(body) if body
32
32
 
33
33
  response = http.request(request)
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.0
4
+ version: 0.1.1
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-05-28 00:00:00.000000000 Z
11
+ date: 2020-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -145,7 +145,6 @@ files:
145
145
  - ".gitlab-ci.yml"
146
146
  - ".rubocop.yml"
147
147
  - Gemfile
148
- - Gemfile.lock
149
148
  - LICENSE
150
149
  - README.md
151
150
  - Rakefile
@@ -168,7 +167,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
168
167
  requirements:
169
168
  - - ">="
170
169
  - !ruby/object:Gem::Version
171
- version: '2.6'
170
+ version: '2.4'
172
171
  required_rubygems_version: !ruby/object:Gem::Requirement
173
172
  requirements:
174
173
  - - ">="
@@ -1,103 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- gitlab-fluent-plugin-redis-slowlog (0.0.0)
5
- fluentd (>= 0.14.10, < 2)
6
- redis (>= 4.1.3, < 5)
7
-
8
- GEM
9
- remote: https://rubygems.org/
10
- specs:
11
- ast (2.4.0)
12
- coderay (1.1.2)
13
- concurrent-ruby (1.1.6)
14
- cool.io (1.6.0)
15
- diff-lcs (1.3)
16
- fluentd (1.10.4)
17
- cool.io (>= 1.4.5, < 2.0.0)
18
- http_parser.rb (>= 0.5.1, < 0.7.0)
19
- msgpack (>= 1.3.1, < 2.0.0)
20
- serverengine (>= 2.0.4, < 3.0.0)
21
- sigdump (~> 0.2.2)
22
- strptime (>= 0.2.2, < 1.0.0)
23
- tzinfo (>= 1.0, < 3.0)
24
- tzinfo-data (~> 1.0)
25
- yajl-ruby (~> 1.0)
26
- gitlab-styles (3.2.0)
27
- rubocop (~> 0.74.0)
28
- rubocop-gitlab-security (~> 0.1.0)
29
- rubocop-performance (~> 1.4.1)
30
- rubocop-rails (~> 2.0)
31
- rubocop-rspec (~> 1.36)
32
- http_parser.rb (0.6.0)
33
- jaro_winkler (1.5.4)
34
- method_source (0.9.2)
35
- msgpack (1.3.3)
36
- parallel (1.19.1)
37
- parser (2.7.1.2)
38
- ast (~> 2.4.0)
39
- power_assert (1.1.3)
40
- pry (0.12.2)
41
- coderay (~> 1.1.0)
42
- method_source (~> 0.9.0)
43
- rack (2.2.2)
44
- rainbow (3.0.0)
45
- rake (12.3.3)
46
- redis (4.1.4)
47
- rspec (3.9.0)
48
- rspec-core (~> 3.9.0)
49
- rspec-expectations (~> 3.9.0)
50
- rspec-mocks (~> 3.9.0)
51
- rspec-core (3.9.2)
52
- rspec-support (~> 3.9.3)
53
- rspec-expectations (3.9.2)
54
- diff-lcs (>= 1.2.0, < 2.0)
55
- rspec-support (~> 3.9.0)
56
- rspec-mocks (3.9.1)
57
- diff-lcs (>= 1.2.0, < 2.0)
58
- rspec-support (~> 3.9.0)
59
- rspec-support (3.9.3)
60
- rubocop (0.74.0)
61
- jaro_winkler (~> 1.5.1)
62
- parallel (~> 1.10)
63
- parser (>= 2.6)
64
- rainbow (>= 2.2.2, < 4.0)
65
- ruby-progressbar (~> 1.7)
66
- unicode-display_width (>= 1.4.0, < 1.7)
67
- rubocop-gitlab-security (0.1.1)
68
- rubocop (>= 0.51)
69
- rubocop-performance (1.4.1)
70
- rubocop (>= 0.71.0)
71
- rubocop-rails (2.4.0)
72
- rack (>= 1.1)
73
- rubocop (>= 0.72.0)
74
- rubocop-rspec (1.37.0)
75
- rubocop (>= 0.68.1)
76
- ruby-progressbar (1.10.1)
77
- serverengine (2.2.1)
78
- sigdump (~> 0.2.2)
79
- sigdump (0.2.4)
80
- strptime (0.2.4)
81
- test-unit (3.2.9)
82
- power_assert
83
- tzinfo (2.0.2)
84
- concurrent-ruby (~> 1.0)
85
- tzinfo-data (1.2020.1)
86
- tzinfo (>= 1.0.0)
87
- unicode-display_width (1.6.1)
88
- yajl-ruby (1.4.1)
89
-
90
- PLATFORMS
91
- ruby
92
-
93
- DEPENDENCIES
94
- bundler (~> 2.1.4)
95
- gitlab-fluent-plugin-redis-slowlog!
96
- gitlab-styles (~> 3.2.0)
97
- pry (~> 0.12.2)
98
- rake (~> 12.0)
99
- rspec (~> 3.9.0)
100
- test-unit (~> 3.2.9)
101
-
102
- BUNDLED WITH
103
- 2.1.4