rspec-otel 0.0.1 → 0.0.2
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/README.md +8 -3
- data/lib/rspec_otel/matchers/emit_span.rb +126 -0
- data/lib/rspec_otel/matchers.rb +3 -3
- data/lib/rspec_otel/rspec.rb +0 -1
- data/lib/rspec_otel/version.rb +1 -1
- metadata +4 -4
- data/lib/rspec_otel/matchers/have_emitted_span.rb +0 -96
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2157d604dda12e0b5a3a31d5f43659ef015578f772cb0bd93ac61fafdc8946ee
|
4
|
+
data.tar.gz: 5b41c471c61f4fdb603585c52855c350f4e67de3776d7eb5718252b5bc0e875f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf5b6711af8c60e5cd9d2e46c580b6fe59aa87438154b585c77cc55ad4cf12933f1bf7bb9db4f686cadc124e397805fb8a028fb7f7744c86d44d297f5ec46e2d
|
7
|
+
data.tar.gz: 4ee5c3e4deed68810dca54d594d7cc6002b9ef4d15133aeb37e5f77deebbd2a0b952308dfd50df60d1ec62c4a68b52ffca8c7e5e97c3de74b885d53f72007cca
|
data/README.md
CHANGED
@@ -28,7 +28,7 @@ end
|
|
28
28
|
|
29
29
|
### Matching the presence of a span
|
30
30
|
|
31
|
-
You can match the emission of a span with the `
|
31
|
+
You can match the emission of a span with the `emit_span` matcher:
|
32
32
|
|
33
33
|
```ruby
|
34
34
|
require 'spec_helper'
|
@@ -37,7 +37,7 @@ 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
|
40
|
+
end.to emit_span('GET /user').with_attributes({'user.id' => '1'})
|
41
41
|
end
|
42
42
|
end
|
43
43
|
```
|
@@ -45,6 +45,11 @@ end
|
|
45
45
|
Several conditions can be added to the matcher:
|
46
46
|
|
47
47
|
* `with_attributes` - Will match only the spans with the specified attributes.
|
48
|
-
* `
|
48
|
+
* `without_attributes` - Will only match the spans that do not have the specified attributes
|
49
|
+
* `with_event` - Will match only the spans with the specified event.
|
50
|
+
* `without_event` - Will only match the spans that do not have the specified event
|
49
51
|
* `with_status` - Will match only the spans that have the proper status.
|
50
52
|
* `with_exception` - Will match only the spans that have the specified exception event.
|
53
|
+
* `without_exception` - Will match only the spans that do not have the specified exception event.
|
54
|
+
|
55
|
+
The `*_event` condition can be called multiple times with different events.
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RspecOtel
|
4
|
+
module Matchers
|
5
|
+
class EmitSpan
|
6
|
+
attr_reader :name
|
7
|
+
|
8
|
+
def initialize(name = nil)
|
9
|
+
@name = name
|
10
|
+
@filters = [
|
11
|
+
->(span) { span.name == name }
|
12
|
+
]
|
13
|
+
end
|
14
|
+
|
15
|
+
def matches?(block)
|
16
|
+
before_spans = []
|
17
|
+
if block.respond_to?(:call)
|
18
|
+
before_spans = RspecOtel.exporter.finished_spans
|
19
|
+
block.call
|
20
|
+
end
|
21
|
+
|
22
|
+
(RspecOtel.exporter.finished_spans - before_spans).each do |span|
|
23
|
+
return true if @filters.all? { |f| f.call(span) }
|
24
|
+
end
|
25
|
+
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
29
|
+
def with_attributes(attributes)
|
30
|
+
@filters << lambda do |span|
|
31
|
+
attributes_match?(span.attributes, attributes)
|
32
|
+
end
|
33
|
+
|
34
|
+
self
|
35
|
+
end
|
36
|
+
|
37
|
+
def without_attributes(attributes)
|
38
|
+
@filters << lambda do |span|
|
39
|
+
!attributes_match?(span.attributes, attributes)
|
40
|
+
end
|
41
|
+
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
def with_event(name, attributes = {})
|
46
|
+
@filters << lambda do |span|
|
47
|
+
event_match?(span.events, OpenTelemetry::SDK::Trace::Event.new(name, attributes))
|
48
|
+
end
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
def without_event(name, attributes = {})
|
53
|
+
@filters << lambda do |span|
|
54
|
+
!event_match?(span.events, OpenTelemetry::SDK::Trace::Event.new(name, attributes))
|
55
|
+
end
|
56
|
+
self
|
57
|
+
end
|
58
|
+
|
59
|
+
def with_status(code, description)
|
60
|
+
@filters << lambda do |span|
|
61
|
+
status_match?(span.status, code, description)
|
62
|
+
end
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
def with_exception(exception = nil)
|
67
|
+
with_event('exception', exception_attributes(exception))
|
68
|
+
end
|
69
|
+
|
70
|
+
def without_exception(exception = nil)
|
71
|
+
without_event('exception', exception_attributes(exception))
|
72
|
+
end
|
73
|
+
|
74
|
+
def failure_message
|
75
|
+
"expected span #{name} to have been emitted, but it couldn't be found"
|
76
|
+
end
|
77
|
+
|
78
|
+
def failure_message_when_negated
|
79
|
+
"expected span #{name} to not have been emitted"
|
80
|
+
end
|
81
|
+
|
82
|
+
def supports_block_expectations?
|
83
|
+
true
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def exception_attributes(exception)
|
89
|
+
attributes = {}
|
90
|
+
unless exception.nil?
|
91
|
+
attributes['exception.type'] = exception.class.to_s
|
92
|
+
attributes['exception.message'] = exception.message
|
93
|
+
end
|
94
|
+
|
95
|
+
attributes
|
96
|
+
end
|
97
|
+
|
98
|
+
def attributes_match?(span_attributes, attributes)
|
99
|
+
attributes.each do |ak, av|
|
100
|
+
sa = span_attributes.select do |k, v|
|
101
|
+
ak == k && av == v
|
102
|
+
end
|
103
|
+
|
104
|
+
return false if sa.empty?
|
105
|
+
end
|
106
|
+
|
107
|
+
true
|
108
|
+
end
|
109
|
+
|
110
|
+
def status_match?(span_status, code, description)
|
111
|
+
code == span_status.code && description == span_status.description
|
112
|
+
end
|
113
|
+
|
114
|
+
def event_match?(span_events, event)
|
115
|
+
return true if span_events.nil?
|
116
|
+
|
117
|
+
se = span_events.select do |s|
|
118
|
+
s.name == event.name &&
|
119
|
+
attributes_match?(s.attributes, event.attributes || {})
|
120
|
+
end
|
121
|
+
|
122
|
+
!se.empty?
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
data/lib/rspec_otel/matchers.rb
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
module RspecOtel
|
4
4
|
module Matchers
|
5
|
-
def
|
6
|
-
|
5
|
+
def emit_span(name)
|
6
|
+
EmitSpan.new(name)
|
7
7
|
end
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
require 'rspec_otel/matchers/
|
11
|
+
require 'rspec_otel/matchers/emit_span'
|
data/lib/rspec_otel/rspec.rb
CHANGED
data/lib/rspec_otel/version.rb
CHANGED
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.2
|
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-02-
|
11
|
+
date: 2024-02-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: opentelemetry-api
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name: rspec
|
42
|
+
name: rspec-core
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
@@ -63,7 +63,7 @@ files:
|
|
63
63
|
- README.md
|
64
64
|
- lib/rspec_otel.rb
|
65
65
|
- lib/rspec_otel/matchers.rb
|
66
|
-
- lib/rspec_otel/matchers/
|
66
|
+
- lib/rspec_otel/matchers/emit_span.rb
|
67
67
|
- lib/rspec_otel/rspec.rb
|
68
68
|
- lib/rspec_otel/version.rb
|
69
69
|
homepage: https://github.com/dmathieu/rspec-otel
|
@@ -1,96 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module RspecOtel
|
4
|
-
module Matchers
|
5
|
-
class HaveEmittedSpan
|
6
|
-
attr_reader :name
|
7
|
-
|
8
|
-
def initialize(name)
|
9
|
-
@name = name
|
10
|
-
@attributes = {}
|
11
|
-
end
|
12
|
-
|
13
|
-
def matches?(block)
|
14
|
-
block.call if block.respond_to?(:call)
|
15
|
-
|
16
|
-
RspecOtel.exporter.finished_spans.each do |span|
|
17
|
-
return true if span.name == name &&
|
18
|
-
attributes_match?(span.attributes, @attributes) &&
|
19
|
-
status_match?(span.status, @status) &&
|
20
|
-
events_match?(span.events, @events)
|
21
|
-
end
|
22
|
-
|
23
|
-
false
|
24
|
-
end
|
25
|
-
|
26
|
-
def with_attributes(attributes)
|
27
|
-
@attributes = attributes
|
28
|
-
self
|
29
|
-
end
|
30
|
-
|
31
|
-
def with_event(name, attributes = {})
|
32
|
-
@events ||= []
|
33
|
-
@events << OpenTelemetry::SDK::Trace::Event.new(name, attributes)
|
34
|
-
self
|
35
|
-
end
|
36
|
-
|
37
|
-
def with_status(code, description)
|
38
|
-
@status = { code:, description: }
|
39
|
-
self
|
40
|
-
end
|
41
|
-
|
42
|
-
def with_exception(exception)
|
43
|
-
with_event('exception', {
|
44
|
-
'exception.type' => exception.class.to_s,
|
45
|
-
'exception.message' => exception.message
|
46
|
-
})
|
47
|
-
end
|
48
|
-
|
49
|
-
def failure_message
|
50
|
-
"expected span #{name} to have been emitted, but it couldn't be found"
|
51
|
-
end
|
52
|
-
|
53
|
-
def failure_message_when_negated
|
54
|
-
"expected span #{name} to not have been emitted"
|
55
|
-
end
|
56
|
-
|
57
|
-
def supports_block_expectations?
|
58
|
-
true
|
59
|
-
end
|
60
|
-
|
61
|
-
private
|
62
|
-
|
63
|
-
def attributes_match?(span_attributes, attributes)
|
64
|
-
attributes.each do |ak, av|
|
65
|
-
sa = span_attributes.select do |k, v|
|
66
|
-
ak == k && av == v
|
67
|
-
end
|
68
|
-
|
69
|
-
return false if sa.empty?
|
70
|
-
end
|
71
|
-
|
72
|
-
true
|
73
|
-
end
|
74
|
-
|
75
|
-
def status_match?(span_status, status)
|
76
|
-
status.nil? ||
|
77
|
-
(status[:code] == span_status.code && status[:description] == span_status.description)
|
78
|
-
end
|
79
|
-
|
80
|
-
def events_match?(span_events, events)
|
81
|
-
return true if span_events.nil?
|
82
|
-
|
83
|
-
events.each do |e|
|
84
|
-
se = span_events.select do |s|
|
85
|
-
s.name == e.name &&
|
86
|
-
attributes_match?(s.attributes, e.attributes)
|
87
|
-
end
|
88
|
-
|
89
|
-
return false if se.empty?
|
90
|
-
end
|
91
|
-
|
92
|
-
true
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|