mnemosyne-ruby 1.15.0 → 1.16.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/.github/workflows/test.yml +8 -0
- data/Appraisals +8 -0
- data/CHANGELOG.md +12 -1
- data/Gemfile +1 -0
- data/gemfiles/sidekiq_70.gemfile +27 -0
- data/lib/mnemosyne/probes/redis/command.rb +4 -136
- data/lib/mnemosyne/probes/redis-client/command.rb +29 -0
- data/lib/mnemosyne/support/redis.rb +128 -0
- data/lib/mnemosyne/version.rb +1 -1
- data/lib/mnemosyne.rb +5 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 43c02b1229d902d187dee8281c88820a95d13a30ee594af7ca131645ffd85485
|
4
|
+
data.tar.gz: c6ebd7b760e56adacacbb89390d5abc463ded7a72e37d346de0d51fb615a6582
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 14220075cac092132c13d0c6d82bdfbc374c0c7a50db0d3e0d07e950fae0eda073b6958c30657f3bb089cbfcc0137d18fd56ae2f505e1f16d61917b929d25a6e
|
7
|
+
data.tar.gz: a568b0e9ea1b96549ed78082c9ccef3946a5a8dbd8b7b9dc231a609a52d59c928069d7f7a5cf4c99f509589830279ff16b1e05a055114674d5dac8d2ccf85274
|
data/.github/workflows/test.yml
CHANGED
@@ -28,9 +28,11 @@ jobs:
|
|
28
28
|
- rails-7.0
|
29
29
|
- redis-4.0
|
30
30
|
- redis-5.0
|
31
|
+
- redis-client
|
31
32
|
- restify
|
32
33
|
- sidekiq-5
|
33
34
|
- sidekiq-6
|
35
|
+
- sidekiq-7
|
34
36
|
include:
|
35
37
|
- suite: core
|
36
38
|
spec: --tag ~probe
|
@@ -65,6 +67,9 @@ jobs:
|
|
65
67
|
- suite: redis-5.0
|
66
68
|
spec: --tag probe:redis
|
67
69
|
gemfile: gemfiles/redis_50.gemfile
|
70
|
+
- suite: redis-client
|
71
|
+
spec: --tag probe:redis_client
|
72
|
+
gemfile: gemfiles/core.gemfile
|
68
73
|
- suite: restify
|
69
74
|
spec: --tag probe:restify
|
70
75
|
gemfile: gemfiles/core.gemfile
|
@@ -74,6 +79,9 @@ jobs:
|
|
74
79
|
- suite: sidekiq-6
|
75
80
|
spec: --tag probe:sidekiq
|
76
81
|
gemfile: gemfiles/sidekiq_60.gemfile
|
82
|
+
- suite: sidekiq-7
|
83
|
+
spec: --tag probe:sidekiq
|
84
|
+
gemfile: gemfiles/sidekiq_70.gemfile
|
77
85
|
exclude:
|
78
86
|
- suite: rails-5.2
|
79
87
|
ruby: '3.2'
|
data/Appraisals
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,16 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [1.16.0] - 2023-08-24
|
10
|
+
|
11
|
+
### Added
|
12
|
+
|
13
|
+
- Separate new tracing for `redis-client` gem
|
14
|
+
|
15
|
+
### Fixed
|
16
|
+
|
17
|
+
- `NoMethodError` when `RedisClient` is used directly
|
18
|
+
|
9
19
|
## [1.15.0] - 2023-08-23
|
10
20
|
|
11
21
|
### Added
|
@@ -192,7 +202,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
192
202
|
|
193
203
|
- Add platform identifier
|
194
204
|
|
195
|
-
[Unreleased]: https://github.com/mnemosyne-mon/mnemosyne-ruby/compare/v1.
|
205
|
+
[Unreleased]: https://github.com/mnemosyne-mon/mnemosyne-ruby/compare/v1.16.0...HEAD
|
206
|
+
[1.16.0]: https://github.com/mnemosyne-mon/mnemosyne-ruby/compare/v1.15.0...v1.16.0
|
196
207
|
[1.15.0]: https://github.com/mnemosyne-mon/mnemosyne-ruby/compare/v1.14.0...v1.15.0
|
197
208
|
[1.14.0]: https://github.com/mnemosyne-mon/mnemosyne-ruby/compare/v1.14.0...v1.13.0
|
198
209
|
[1.13.0]: https://github.com/mnemosyne-mon/mnemosyne-ruby/compare/v1.13.0...v1.12.1
|
data/Gemfile
CHANGED
@@ -0,0 +1,27 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "rake", "~> 13.0"
|
6
|
+
|
7
|
+
group :test do
|
8
|
+
gem "rspec", "~> 3.6"
|
9
|
+
gem "timecop", "~> 0.9.1"
|
10
|
+
gem "faraday"
|
11
|
+
gem "msgr"
|
12
|
+
gem "rails"
|
13
|
+
gem "redis"
|
14
|
+
gem "restify"
|
15
|
+
gem "sidekiq", "~> 7.0"
|
16
|
+
gem "sqlite3"
|
17
|
+
gem "webmock"
|
18
|
+
end
|
19
|
+
|
20
|
+
group :development do
|
21
|
+
gem "appraisal"
|
22
|
+
gem "rake-release", "~> 1.3.0"
|
23
|
+
gem "pry", require: false
|
24
|
+
gem "pry-byebug", require: false
|
25
|
+
end
|
26
|
+
|
27
|
+
gemspec path: "../"
|
@@ -6,147 +6,15 @@ module Mnemosyne
|
|
6
6
|
module Command
|
7
7
|
class Probe < ::Mnemosyne::Probe
|
8
8
|
def setup
|
9
|
-
|
10
|
-
|
11
|
-
else
|
12
|
-
::Redis::Client.prepend ClientPatch
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
module Instrumentation
|
17
|
-
def call(command, redis_config)
|
18
|
-
Instrumentation.instrument([command], client.server_url) { super }
|
19
|
-
end
|
20
|
-
|
21
|
-
def call_pipelined(commands, redis_config)
|
22
|
-
Instrumentation.instrument(commands, client.server_url) { super }
|
23
|
-
end
|
24
|
-
|
25
|
-
class << self
|
26
|
-
def instrument(commands, server_url)
|
27
|
-
trace = ::Mnemosyne::Instrumenter.current_trace
|
28
|
-
return yield unless trace
|
29
|
-
|
30
|
-
span = ::Mnemosyne::Span.new 'db.query.redis',
|
31
|
-
meta: extract_span_meta(commands, server_url)
|
32
|
-
|
33
|
-
span.start!
|
34
|
-
|
35
|
-
begin
|
36
|
-
yield.tap do |retval|
|
37
|
-
span.meta[:error] = retval.message if retval.is_a?(::Redis::CommandError)
|
38
|
-
|
39
|
-
trace << span.finish!
|
40
|
-
end
|
41
|
-
rescue StandardError => e
|
42
|
-
span.meta[:error] = e.message
|
43
|
-
trace << span.finish!
|
44
|
-
raise
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
private
|
9
|
+
# Redis v5+ used redis-client, which has it's own probe
|
10
|
+
return if Gem::Version.new(::Redis::VERSION) >= Gem::Version.new('5')
|
49
11
|
|
50
|
-
|
51
|
-
{
|
52
|
-
server: server_url,
|
53
|
-
|
54
|
-
# Each command is an array, consisting of the command name and any
|
55
|
-
# arguments. We are only interested in the command name.
|
56
|
-
commands: extract_command_names(commands),
|
57
|
-
|
58
|
-
# If there are multiple commands, that must mean they were pipelined
|
59
|
-
# (i.e. run in parallel).
|
60
|
-
pipelined: commands.length > 1
|
61
|
-
}
|
62
|
-
end
|
63
|
-
|
64
|
-
def extract_command_names(commands)
|
65
|
-
commands.map do |c|
|
66
|
-
# Depending on how the methods on the Redis gem are called,
|
67
|
-
# there may be an additional level of nesting.
|
68
|
-
c = c[0] if c[0].is_a?(Array)
|
69
|
-
|
70
|
-
# For some commands, we also extract *some* of the arguments.
|
71
|
-
name, args = parse_name_and_args(c)
|
72
|
-
|
73
|
-
"#{name} #{args}".strip
|
74
|
-
end.join("\n")
|
75
|
-
end
|
76
|
-
|
77
|
-
##
|
78
|
-
# A map of known commands to the arguments (identified by position)
|
79
|
-
# that should be included verbatim in the metadata. Arguments not
|
80
|
-
# listed here will be replaced by a "?" character.
|
81
|
-
#
|
82
|
-
# The value can be a list of safe argument indices, or "*" (all).
|
83
|
-
#
|
84
|
-
KNOWN_ARGUMENTS = {
|
85
|
-
'BLPOP' => '*',
|
86
|
-
'BRPOP' => '*',
|
87
|
-
'EVALSHA' => [0, 1],
|
88
|
-
'EXISTS' => '*',
|
89
|
-
'EXPIRE' => '*',
|
90
|
-
'GET' => '*',
|
91
|
-
'HGET' => '*',
|
92
|
-
'HGETALL' => '*',
|
93
|
-
'HMGET' => '*',
|
94
|
-
'HMSET' => [0, 1],
|
95
|
-
'HSCAN' => '*',
|
96
|
-
'INCRBY' => '*',
|
97
|
-
'LLEN' => '*',
|
98
|
-
'LPUSH' => [0],
|
99
|
-
'LRANGE' => '*',
|
100
|
-
'LREM' => [0, 1],
|
101
|
-
'MGET' => '*',
|
102
|
-
'MSET' => [0],
|
103
|
-
'RPUSH' => [0],
|
104
|
-
'RPOP' => '*',
|
105
|
-
'SADD' => [0],
|
106
|
-
'SCARD' => '*',
|
107
|
-
'SCAN' => '*',
|
108
|
-
'SCRIPT LOAD' => [],
|
109
|
-
'SET' => [0],
|
110
|
-
'SREM' => [0],
|
111
|
-
'SSCAN' => '*',
|
112
|
-
'UNLINK' => '*',
|
113
|
-
'ZADD' => [0],
|
114
|
-
'ZCARD' => '*',
|
115
|
-
'ZINCRBY' => [0, 1],
|
116
|
-
'ZRANGE' => '*',
|
117
|
-
'ZRANGEBYSCORE' => '*',
|
118
|
-
'ZREM' => [0],
|
119
|
-
'ZREMRANGEBYSCORE' => '*',
|
120
|
-
'ZREVRANGE' => '*',
|
121
|
-
'ZSCAN' => '*'
|
122
|
-
}.freeze
|
123
|
-
|
124
|
-
def parse_name_and_args(command)
|
125
|
-
command = command.dup
|
126
|
-
|
127
|
-
# Symbols and lower-case names are allowed
|
128
|
-
name = command.delete_at(0).to_s.upcase
|
129
|
-
|
130
|
-
allowed = KNOWN_ARGUMENTS[name] || []
|
131
|
-
args = case allowed
|
132
|
-
when '*' # All arguments considered safe
|
133
|
-
command
|
134
|
-
when Array # A list of allowed argument indices
|
135
|
-
command.each_with_index.map do |arg, index|
|
136
|
-
allowed.include?(index) ? arg : '?'
|
137
|
-
end
|
138
|
-
else # Unknown command - assume nothing is safe
|
139
|
-
Array.new(command.length, '?')
|
140
|
-
end.join(' ')
|
141
|
-
|
142
|
-
[name, args]
|
143
|
-
end
|
144
|
-
end
|
12
|
+
::Redis::Client.prepend ClientPatch
|
145
13
|
end
|
146
14
|
|
147
15
|
module ClientPatch
|
148
16
|
def process(commands)
|
149
|
-
|
17
|
+
::Mnemosyne::Support::Redis.instrument(commands, id) { super }
|
150
18
|
end
|
151
19
|
end
|
152
20
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mnemosyne
|
4
|
+
module Probes
|
5
|
+
module RedisClient
|
6
|
+
module Command
|
7
|
+
class Probe < ::Mnemosyne::Probe
|
8
|
+
def setup
|
9
|
+
::RedisClient.register Instrumentation
|
10
|
+
end
|
11
|
+
|
12
|
+
module Instrumentation
|
13
|
+
def call(command, redis_config)
|
14
|
+
::Mnemosyne::Support::Redis.instrument([command], redis_config.server_url) { super }
|
15
|
+
end
|
16
|
+
|
17
|
+
def call_pipelined(commands, redis_config)
|
18
|
+
::Mnemosyne::Support::Redis.instrument(commands, redis_config.server_url) { super }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
register 'RedisClient',
|
26
|
+
'redis_client',
|
27
|
+
RedisClient::Command::Probe.new
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mnemosyne
|
4
|
+
module Support
|
5
|
+
module Redis
|
6
|
+
##
|
7
|
+
# A map of known commands to the arguments (identified by position)
|
8
|
+
# that should be included verbatim in the metadata. Arguments not
|
9
|
+
# listed here will be replaced by a "?" character.
|
10
|
+
#
|
11
|
+
# The value can be a list of safe argument indices, or "*" (all).
|
12
|
+
#
|
13
|
+
KNOWN_ARGUMENTS = {
|
14
|
+
'BLPOP' => '*',
|
15
|
+
'BRPOP' => '*',
|
16
|
+
'EVALSHA' => [0, 1],
|
17
|
+
'EXISTS' => '*',
|
18
|
+
'EXPIRE' => '*',
|
19
|
+
'GET' => '*',
|
20
|
+
'HGET' => '*',
|
21
|
+
'HGETALL' => '*',
|
22
|
+
'HMGET' => '*',
|
23
|
+
'HMSET' => [0, 1],
|
24
|
+
'HSCAN' => '*',
|
25
|
+
'INCRBY' => '*',
|
26
|
+
'LLEN' => '*',
|
27
|
+
'LPUSH' => [0],
|
28
|
+
'LRANGE' => '*',
|
29
|
+
'LREM' => [0, 1],
|
30
|
+
'MGET' => '*',
|
31
|
+
'MSET' => [0],
|
32
|
+
'RPUSH' => [0],
|
33
|
+
'RPOP' => '*',
|
34
|
+
'SADD' => [0],
|
35
|
+
'SCARD' => '*',
|
36
|
+
'SCAN' => '*',
|
37
|
+
'SCRIPT LOAD' => [],
|
38
|
+
'SET' => [0],
|
39
|
+
'SREM' => [0],
|
40
|
+
'SSCAN' => '*',
|
41
|
+
'UNLINK' => '*',
|
42
|
+
'ZADD' => [0],
|
43
|
+
'ZCARD' => '*',
|
44
|
+
'ZINCRBY' => [0, 1],
|
45
|
+
'ZRANGE' => '*',
|
46
|
+
'ZRANGEBYSCORE' => '*',
|
47
|
+
'ZREM' => [0],
|
48
|
+
'ZREMRANGEBYSCORE' => '*',
|
49
|
+
'ZREVRANGE' => '*',
|
50
|
+
'ZSCAN' => '*'
|
51
|
+
}.freeze
|
52
|
+
|
53
|
+
class << self
|
54
|
+
def instrument(commands, server_url)
|
55
|
+
trace = ::Mnemosyne::Instrumenter.current_trace
|
56
|
+
return yield unless trace
|
57
|
+
|
58
|
+
span = ::Mnemosyne::Span.new 'db.query.redis',
|
59
|
+
meta: extract_span_meta(commands, server_url)
|
60
|
+
|
61
|
+
span.start!
|
62
|
+
|
63
|
+
begin
|
64
|
+
yield.tap do |retval|
|
65
|
+
if defined?(::Redis::CommandError) && retval.is_a?(::Redis::CommandError)
|
66
|
+
span.meta[:error] = retval.message
|
67
|
+
end
|
68
|
+
|
69
|
+
trace << span.finish!
|
70
|
+
end
|
71
|
+
rescue StandardError => e
|
72
|
+
span.meta[:error] = e.message
|
73
|
+
trace << span.finish!
|
74
|
+
raise
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def extract_span_meta(commands, server_url)
|
79
|
+
{
|
80
|
+
server: server_url,
|
81
|
+
|
82
|
+
# Each command is an array, consisting of the command name and any
|
83
|
+
# arguments. We are only interested in the command name.
|
84
|
+
commands: extract_command_names(commands),
|
85
|
+
|
86
|
+
# If there are multiple commands, that must mean they were pipelined
|
87
|
+
# (i.e. run in parallel).
|
88
|
+
pipelined: commands.length > 1
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
def parse_name_and_args(command)
|
93
|
+
command = command.dup
|
94
|
+
|
95
|
+
# Symbols and lower-case names are allowed
|
96
|
+
name = command.delete_at(0).to_s.upcase
|
97
|
+
|
98
|
+
allowed = KNOWN_ARGUMENTS[name] || []
|
99
|
+
args = case allowed
|
100
|
+
when '*' # All arguments considered safe
|
101
|
+
command
|
102
|
+
when Array # A list of allowed argument indices
|
103
|
+
command.each_with_index.map do |arg, index|
|
104
|
+
allowed.include?(index) ? arg : '?'
|
105
|
+
end
|
106
|
+
else # Unknown command - assume nothing is safe
|
107
|
+
Array.new(command.length, '?')
|
108
|
+
end.join(' ')
|
109
|
+
|
110
|
+
[name, args]
|
111
|
+
end
|
112
|
+
|
113
|
+
def extract_command_names(commands)
|
114
|
+
commands.map do |c|
|
115
|
+
# Depending on how the methods on the Redis gem are called,
|
116
|
+
# there may be an additional level of nesting.
|
117
|
+
c = c[0] if c[0].is_a?(Array)
|
118
|
+
|
119
|
+
# For some commands, we also extract *some* of the arguments.
|
120
|
+
name, args = parse_name_and_args(c)
|
121
|
+
|
122
|
+
"#{name} #{args}".strip
|
123
|
+
end.join("\n")
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/mnemosyne/version.rb
CHANGED
data/lib/mnemosyne.rb
CHANGED
@@ -43,6 +43,7 @@ module Mnemosyne
|
|
43
43
|
require 'mnemosyne/probes/msgr/client'
|
44
44
|
require 'mnemosyne/probes/msgr/consumer'
|
45
45
|
require 'mnemosyne/probes/redis/command'
|
46
|
+
require 'mnemosyne/probes/redis-client/command'
|
46
47
|
require 'mnemosyne/probes/responder/respond'
|
47
48
|
require 'mnemosyne/probes/restify/base'
|
48
49
|
require 'mnemosyne/probes/sidekiq/client'
|
@@ -54,5 +55,9 @@ module Mnemosyne
|
|
54
55
|
require 'mnemosyne/middleware/rack'
|
55
56
|
end
|
56
57
|
|
58
|
+
module Support
|
59
|
+
require 'mnemosyne/support/redis'
|
60
|
+
end
|
61
|
+
|
57
62
|
require 'mnemosyne/railtie' if defined?(Rails)
|
58
63
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mnemosyne-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan Graichen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-08-
|
11
|
+
date: 2023-08-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -70,6 +70,7 @@ files:
|
|
70
70
|
- gemfiles/redis_50.gemfile
|
71
71
|
- gemfiles/sidekiq_50.gemfile
|
72
72
|
- gemfiles/sidekiq_60.gemfile
|
73
|
+
- gemfiles/sidekiq_70.gemfile
|
73
74
|
- lib/mnemosyne-ruby.rb
|
74
75
|
- lib/mnemosyne.rb
|
75
76
|
- lib/mnemosyne/client.rb
|
@@ -100,6 +101,7 @@ files:
|
|
100
101
|
- lib/mnemosyne/probes/mnemosyne/tracer.rb
|
101
102
|
- lib/mnemosyne/probes/msgr/client.rb
|
102
103
|
- lib/mnemosyne/probes/msgr/consumer.rb
|
104
|
+
- lib/mnemosyne/probes/redis-client/command.rb
|
103
105
|
- lib/mnemosyne/probes/redis/command.rb
|
104
106
|
- lib/mnemosyne/probes/responder/respond.rb
|
105
107
|
- lib/mnemosyne/probes/restify/base.rb
|
@@ -109,6 +111,7 @@ files:
|
|
109
111
|
- lib/mnemosyne/railtie.rb
|
110
112
|
- lib/mnemosyne/registry.rb
|
111
113
|
- lib/mnemosyne/span.rb
|
114
|
+
- lib/mnemosyne/support/redis.rb
|
112
115
|
- lib/mnemosyne/trace.rb
|
113
116
|
- lib/mnemosyne/version.rb
|
114
117
|
- mnemosyne-ruby.gemspec
|