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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ea44639a383fcb72b5c235528dc72363e0f3b431198e97c7d0c740bd5032bcd1
4
- data.tar.gz: ed21a83d381fc8441ac7e09aa6e06d48582bbb256eaf0f5830c02363d4308f7d
3
+ metadata.gz: c2db5ebf1aa940bae5b290f6d6683e1f1bea754fc83e8eaf9997bb3971235244
4
+ data.tar.gz: 5c7b7ca60e93ca6ccf82479cfe3374c5420ab5be80484787c4cdc74ed67548cb
5
5
  SHA512:
6
- metadata.gz: b59d5eb23c4e42a7fb8489ca49a68aed7adf095da7277ea7e372648f678e39851dc5d4bc31e4ecaf8d3fef9d55ff5129168898bbde7430a0fde4feb851a746ee
7
- data.tar.gz: 5270c5b5dd720e89e5243cfddeb26ac3aac76d44ff4ef42b75b79fe13667825b1633db676323c573a5d7154a3470e311aaae39f7c4ca1e640b0e323833c450aa
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').with_attributes({'user.id' => '1'})
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
- The `*_event` condition can be called multiple times with different events.
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
- ->(span) { span.name == name }
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
- event_match?(span.events, OpenTelemetry::SDK::Trace::Event.new(name, attributes))
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
- !event_match?(span.events, OpenTelemetry::SDK::Trace::Event.new(name, attributes))
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 #{name} to have been emitted, but it couldn't be found"
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 #{name} to not have been emitted"
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
@@ -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.run
16
- RspecOtel.exporter.reset
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RspecOtel
4
- VERSION = '0.0.3'
4
+ VERSION = '0.0.5'
5
5
  end
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.3
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-06-20 00:00:00.000000000 Z
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