rspec-otel 0.0.3 → 0.0.5

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 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