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
|