rspec-otel 0.0.3 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +35 -2
- data/lib/rspec_otel/matchers/emit_span.rb +83 -10
- data/lib/rspec_otel/rspec.rb +7 -10
- data/lib/rspec_otel/version.rb +1 -1
- data/lib/rspec_otel.rb +18 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2db5ebf1aa940bae5b290f6d6683e1f1bea754fc83e8eaf9997bb3971235244
|
4
|
+
data.tar.gz: 5c7b7ca60e93ca6ccf82479cfe3374c5420ab5be80484787c4cdc74ed67548cb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f99a6e31d6acc0fc5dc26453690a7b66a6ed8352cc4790b26fccdad93dfa1692adaaa9f3f4fd5798c8d1e9084a8c509ebf1800936a3b4a1354ca3ddc6e9b701e
|
7
|
+
data.tar.gz: 12a5346b1eb3b3247d9d5d62e46aa1c4e3c13f891a0abdd72a2f2931e054f86bcc6d9634959faf65329689933af438075de259682b7357995bb596dfd8b5a008
|
data/README.md
CHANGED
@@ -37,22 +37,55 @@ RSpec.describe 'User API' do
|
|
37
37
|
it 'emits a span' do
|
38
38
|
expect do
|
39
39
|
get :user, id: 1
|
40
|
-
end.to emit_span('GET /user')
|
40
|
+
end.to emit_span('GET /user')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
```
|
44
|
+
|
45
|
+
`emit_span` will also match a regular expression:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
require 'spec_helper'
|
49
|
+
|
50
|
+
RSpec.describe 'User API' do
|
51
|
+
it 'emits a span' do
|
52
|
+
expect do
|
53
|
+
get :user, id: 1
|
54
|
+
end.to emit_span(/^GET /)
|
41
55
|
end
|
42
56
|
end
|
43
57
|
```
|
44
58
|
|
45
59
|
Several conditions can be added to the matcher:
|
46
60
|
|
61
|
+
* `as_root` - Will match spans that are the root of a trace.
|
62
|
+
* `as_child` - Will match spans that are not the root of a trace
|
47
63
|
* `with_attributes` - Will match only the spans with the specified attributes.
|
48
64
|
* `without_attributes` - Will only match the spans that do not have the specified attributes
|
49
65
|
* `with_event` - Will match only the spans with the specified event.
|
50
66
|
* `without_event` - Will only match the spans that do not have the specified event
|
67
|
+
* `with_link` - Will match only the spans with the specified link.
|
68
|
+
* `without_link` - Will only match the spans that do not have the specified link
|
51
69
|
* `with_status` - Will match only the spans that have the proper status.
|
52
70
|
* `with_exception` - Will match only the spans that have the specified exception event.
|
53
71
|
* `without_exception` - Will match only the spans that do not have the specified exception event.
|
54
72
|
|
55
|
-
|
73
|
+
_The `*_event` condition can be called multiple times with different events._
|
74
|
+
|
75
|
+
|
76
|
+
### Disabling
|
77
|
+
|
78
|
+
We wrap every example in a new OpenTelemetry SDK configuration by default, if you wish to disable this you can tag your example with `:rspec_otel_disable_tracing`:
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
require 'spec_helper'
|
82
|
+
|
83
|
+
RSpec.describe 'User API', :rspec_otel_disable_tracing do
|
84
|
+
it 'tests my code' do
|
85
|
+
expect(true).to be true
|
86
|
+
end
|
87
|
+
end
|
88
|
+
```
|
56
89
|
|
57
90
|
## Compatibility
|
58
91
|
|
@@ -2,14 +2,14 @@
|
|
2
2
|
|
3
3
|
module RspecOtel
|
4
4
|
module Matchers
|
5
|
-
class EmitSpan
|
5
|
+
class EmitSpan # rubocop:disable Metrics/ClassLength
|
6
6
|
attr_reader :name
|
7
7
|
|
8
8
|
def initialize(name = nil)
|
9
9
|
@name = name
|
10
|
-
@filters = [
|
11
|
-
|
12
|
-
|
10
|
+
@filters = []
|
11
|
+
|
12
|
+
add_name_filter
|
13
13
|
end
|
14
14
|
|
15
15
|
def matches?(block)
|
@@ -26,6 +26,22 @@ module RspecOtel
|
|
26
26
|
false
|
27
27
|
end
|
28
28
|
|
29
|
+
def as_child
|
30
|
+
@filters << lambda do |span|
|
31
|
+
span.parent_span_id && span.parent_span_id != OpenTelemetry::Trace::INVALID_SPAN_ID
|
32
|
+
end
|
33
|
+
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def as_root
|
38
|
+
@filters << lambda do |span|
|
39
|
+
span.parent_span_id == OpenTelemetry::Trace::INVALID_SPAN_ID
|
40
|
+
end
|
41
|
+
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
29
45
|
def with_attributes(attributes)
|
30
46
|
@filters << lambda do |span|
|
31
47
|
attributes_match?(span.attributes, attributes)
|
@@ -42,17 +58,39 @@ module RspecOtel
|
|
42
58
|
self
|
43
59
|
end
|
44
60
|
|
61
|
+
def with_link(attributes = {})
|
62
|
+
@filters << lambda do |span|
|
63
|
+
span.links &&
|
64
|
+
link_match?(span.links, attributes)
|
65
|
+
end
|
66
|
+
|
67
|
+
self
|
68
|
+
end
|
69
|
+
|
70
|
+
def without_link(attributes = {})
|
71
|
+
@filters << lambda do |span|
|
72
|
+
span.links.nil? ||
|
73
|
+
!link_match?(span.links, attributes)
|
74
|
+
end
|
75
|
+
|
76
|
+
self
|
77
|
+
end
|
78
|
+
|
45
79
|
def with_event(name, attributes = {})
|
46
80
|
@filters << lambda do |span|
|
47
|
-
|
81
|
+
span.events &&
|
82
|
+
event_match?(span.events, OpenTelemetry::SDK::Trace::Event.new(name, attributes))
|
48
83
|
end
|
84
|
+
|
49
85
|
self
|
50
86
|
end
|
51
87
|
|
52
88
|
def without_event(name, attributes = {})
|
53
89
|
@filters << lambda do |span|
|
54
|
-
|
90
|
+
span.events.nil? ||
|
91
|
+
!event_match?(span.events, OpenTelemetry::SDK::Trace::Event.new(name, attributes))
|
55
92
|
end
|
93
|
+
|
56
94
|
self
|
57
95
|
end
|
58
96
|
|
@@ -72,11 +110,11 @@ module RspecOtel
|
|
72
110
|
end
|
73
111
|
|
74
112
|
def failure_message
|
75
|
-
"expected span #{
|
113
|
+
"expected span #{failure_match_description} #{printable_name} to have been emitted, but it couldn't be found"
|
76
114
|
end
|
77
115
|
|
78
116
|
def failure_message_when_negated
|
79
|
-
"expected span #{
|
117
|
+
"expected span #{failure_match_description} #{printable_name} to not have been emitted"
|
80
118
|
end
|
81
119
|
|
82
120
|
def supports_block_expectations?
|
@@ -85,6 +123,35 @@ module RspecOtel
|
|
85
123
|
|
86
124
|
private
|
87
125
|
|
126
|
+
def failure_match_description
|
127
|
+
case name
|
128
|
+
when String
|
129
|
+
'named'
|
130
|
+
when Regexp
|
131
|
+
'matching'
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def printable_name
|
136
|
+
case name
|
137
|
+
when String
|
138
|
+
"'#{name}'"
|
139
|
+
when Regexp
|
140
|
+
name.inspect
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def add_name_filter
|
145
|
+
@filters << lambda do |span|
|
146
|
+
case name
|
147
|
+
when String
|
148
|
+
span.name == name
|
149
|
+
when Regexp
|
150
|
+
span.name.match?(name)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
88
155
|
def exception_attributes(exception)
|
89
156
|
attributes = {}
|
90
157
|
unless exception.nil?
|
@@ -112,8 +179,6 @@ module RspecOtel
|
|
112
179
|
end
|
113
180
|
|
114
181
|
def event_match?(span_events, event)
|
115
|
-
return true if span_events.nil?
|
116
|
-
|
117
182
|
se = span_events.select do |s|
|
118
183
|
s.name == event.name &&
|
119
184
|
attributes_match?(s.attributes, event.attributes || {})
|
@@ -121,6 +186,14 @@ module RspecOtel
|
|
121
186
|
|
122
187
|
!se.empty?
|
123
188
|
end
|
189
|
+
|
190
|
+
def link_match?(links, attributes)
|
191
|
+
link = links.select do |l|
|
192
|
+
attributes_match?(l.attributes, attributes || {})
|
193
|
+
end
|
194
|
+
|
195
|
+
!link.empty?
|
196
|
+
end
|
124
197
|
end
|
125
198
|
end
|
126
199
|
end
|
data/lib/rspec_otel/rspec.rb
CHANGED
@@ -3,16 +3,13 @@
|
|
3
3
|
require 'rspec/core'
|
4
4
|
|
5
5
|
RSpec.configure do |config|
|
6
|
-
config.before(:suite) do
|
7
|
-
span_processor = OpenTelemetry::SDK::Trace::Export::SimpleSpanProcessor.new(RspecOtel.exporter)
|
8
|
-
|
9
|
-
OpenTelemetry::SDK.configure do |c|
|
10
|
-
c.add_span_processor span_processor
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
6
|
config.around(:each) do |example|
|
15
|
-
example.
|
16
|
-
|
7
|
+
if example.metadata[:rspec_otel_disable_tracing]
|
8
|
+
example.run
|
9
|
+
else
|
10
|
+
RspecOtel.record do
|
11
|
+
example.run
|
12
|
+
end
|
13
|
+
end
|
17
14
|
end
|
18
15
|
end
|
data/lib/rspec_otel/version.rb
CHANGED
data/lib/rspec_otel.rb
CHANGED
@@ -1,11 +1,29 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'opentelemetry/sdk'
|
4
|
+
require 'opentelemetry-test-helpers'
|
4
5
|
|
5
6
|
module RspecOtel
|
6
7
|
def self.exporter
|
7
8
|
@exporter ||= OpenTelemetry::SDK::Trace::Export::InMemorySpanExporter.new
|
8
9
|
end
|
10
|
+
|
11
|
+
def self.record
|
12
|
+
span_processor = OpenTelemetry::SDK::Trace::Export::SimpleSpanProcessor.new(exporter)
|
13
|
+
|
14
|
+
OpenTelemetry::SDK.configure do |c|
|
15
|
+
c.add_span_processor span_processor
|
16
|
+
end
|
17
|
+
|
18
|
+
yield
|
19
|
+
ensure
|
20
|
+
reset
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.reset
|
24
|
+
OpenTelemetry::TestHelpers.reset_opentelemetry
|
25
|
+
@exporter = nil
|
26
|
+
end
|
9
27
|
end
|
10
28
|
|
11
29
|
require 'rspec_otel/matchers'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-otel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Damien MATHIEU
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opentelemetry-api
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: opentelemetry-test-helpers
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rspec-core
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|