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 +4 -4
- data/.gitignore +1 -0
- data/.gitlab-ci.yml +23 -2
- data/.rubocop.yml +2 -2
- data/README.md +4 -5
- data/gitlab-fluent-plugin-redis-slowlog.gemspec +2 -2
- data/lib/fluent/plugin/in_redis_slowlog.rb +26 -19
- data/spec/fluent/plugin/redis_slowlog_input_spec.rb +53 -16
- data/tools/deploy-rubygem.sh +1 -1
- data/tools/update-changelog.rb +2 -2
- metadata +3 -4
- data/Gemfile.lock +0 -103
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3c1ce26c15184cd4542891a3175434b81ed44b295a6ffd2a8c96222d4fd16da8
|
4
|
+
data.tar.gz: 632613b3d6b036a6f94c66bea02dc08d5dff119202b1614f5df4ff1efd3c1c58
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aea063934370511db16b64743463868b909d4685c141e0d56365f2edb604688125851d815b5c241f0a721be42e17785aea0f6ce862e726b050e1812d70a0bd2a
|
7
|
+
data.tar.gz: 99ff9bf22f51fc3b5d6bffc55db8c3979b67bc41a4ef0ba69bb4ab136332a6de938694f39a9f4fc4409a2f41dcfdcb84a14bc8aec6fc353544a14dd9578713c2
|
data/.gitignore
CHANGED
data/.gitlab-ci.yml
CHANGED
@@ -1,19 +1,40 @@
|
|
1
|
-
|
2
|
-
|
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}"
|
data/.rubocop.yml
CHANGED
@@ -3,14 +3,14 @@ inherit_gem:
|
|
3
3
|
- rubocop-default.yml
|
4
4
|
|
5
5
|
AllCops:
|
6
|
-
TargetRubyVersion: 2.
|
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
|
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
|
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-
|
132
|
-
for the tag completes. It might take a few minutes
|
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 =
|
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.
|
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
|
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
|
-
"exec_time" => log
|
87
|
-
"command" => log
|
88
|
-
router.emit(tag,
|
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(:
|
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
|
|
@@ -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
|
-
|
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(
|
44
|
+
expect(Redis).to receive(:new).with(redis_params).and_return(fake_redis)
|
41
45
|
|
42
|
-
|
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 {
|
69
|
+
expect { run }.not_to raise_error
|
66
70
|
end
|
67
71
|
|
68
|
-
it "polls the slowlog
|
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
|
-
|
82
|
+
run
|
78
83
|
end
|
79
84
|
|
80
|
-
context "when the slowlog returns entries" do
|
81
|
-
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
|
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
|
-
|
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
|
-
|
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(
|
112
|
+
expect(fake_redis).to receive(:slowlog).and_return(startup_slowlog, slowlog.last(2), slowlog)
|
104
113
|
|
105
|
-
|
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
|
-
"
|
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
|
data/tools/deploy-rubygem.sh
CHANGED
data/tools/update-changelog.rb
CHANGED
@@ -26,8 +26,8 @@ def gitlab_client(path, method, body = nil)
|
|
26
26
|
raise "Unknown method: #{method}"
|
27
27
|
end
|
28
28
|
|
29
|
-
request["
|
30
|
-
request["
|
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.
|
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-
|
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.
|
170
|
+
version: '2.4'
|
172
171
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
173
172
|
requirements:
|
174
173
|
- - ">="
|
data/Gemfile.lock
DELETED
@@ -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
|