rspec-otel 0.0.6 → 0.0.8

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: f5e1d1bb621033e9a0fb1d1195d745a2d4300f00723b83ca8cb380f170a660d5
4
- data.tar.gz: 0d4812bb0b05657bcae39dae45e89f2db35cbb13c25bb47c8ff180e562e6c050
3
+ metadata.gz: 494c22ee6a688468f77094d8b4f27242edd872ec3a24232337375b8dd611d38e
4
+ data.tar.gz: ecc743b5a1752adfa8d624d17ab3f6ce87a291ce4393d480fb33f7ef92068e77
5
5
  SHA512:
6
- metadata.gz: 948d9807ebe6e5a96c6555c6e707f170928feae596cfc304550342ce894b94aa51db2c755c0aa77814ff8a3e7bd518d5004a328ec9e9f4f67c278d806a5fd265
7
- data.tar.gz: 7780de8e139754b3255514c49ebbf742f09c73011737245d509cc9f04284a90f28d6edf9dac148d357e09e0839d22242ffae05c4df3ad5d2cc3c8f19a9d7613c
6
+ metadata.gz: 496f2ac07d3b62cc36c4027266d0dbd6188e75fb075140b52791d3697845585223cdaebaf7e79e60b733a175b1b2352ffbbac88c00c0920c7567c319f2526253
7
+ data.tar.gz: d26ee3edc01891c632cb97cd92b02507849ee4c33c20faae47057a7f523f01e010c38ccabf4940dbdc601ac9f8734ffe56fae5f0c7c6aea4aced9ce7103feb2f
@@ -9,18 +9,23 @@ module RspecOtel
9
9
  @name = name
10
10
  @filters = []
11
11
  @before_spans = []
12
+ @closest_span = nil
12
13
 
13
14
  @filters << name_filter
14
15
  end
15
16
 
16
- def matches?(block)
17
+ def matches?(block) # rubocop:disable Metrics/MethodLength
17
18
  if block.respond_to?(:call)
18
19
  @before_spans = RspecOtel.exporter.finished_spans
19
20
  block.call
20
21
  end
21
22
 
23
+ closest_count = 0
22
24
  (RspecOtel.exporter.finished_spans - @before_spans).each do |span|
23
- return true if @filters.all? { |f| f.call(span) }
25
+ count = @filters.count { |f| f.call(span) }
26
+ @closest_span = span if count > closest_count
27
+ closest_count = count
28
+ return true if count == @filters.count
24
29
  end
25
30
 
26
31
  false
@@ -111,15 +116,12 @@ module RspecOtel
111
116
 
112
117
  def failure_message
113
118
  closest = closest_span
114
- expect_content = "expected span #{failure_match_description} #{printable_name} to have been emitted"
119
+ prefix = "expected span #{failure_match_description} #{printable_name} to have been emitted"
115
120
 
116
121
  case closest
117
- when nil
118
- "#{expect_content}, but there were no spans emitted at all"
119
- when OpenTelemetry::SDK::Trace::SpanData
120
- "#{expect_content}, but it couldn't be found. Found a close matching span named `#{closest.name}`"
121
- else
122
- raise "I don't know what to do with a #{closest.class} span"
122
+ when nil then "#{prefix}, but there were no spans emitted at all"
123
+ when OpenTelemetry::SDK::Trace::SpanData then closest_not_found_message(prefix, closest)
124
+ else raise "I don't know what to do with a #{closest.class} span"
123
125
  end
124
126
  end
125
127
 
@@ -134,12 +136,9 @@ module RspecOtel
134
136
  private
135
137
 
136
138
  def closest_span
137
- all_spans = (RspecOtel.exporter.finished_spans - @before_spans)
138
- span = all_spans.filter_map do |s|
139
- span if name_filter.call(s)
140
- end.first
141
- span = all_spans.first if span.nil?
142
- span
139
+ return @closest_span unless @closest_span.nil?
140
+
141
+ (RspecOtel.exporter.finished_spans - @before_spans).first
143
142
  end
144
143
 
145
144
  def failure_match_description
@@ -173,9 +172,13 @@ module RspecOtel
173
172
 
174
173
  def exception_attributes(exception)
175
174
  attributes = {}
176
- unless exception.nil?
175
+ return attributes if exception.nil?
176
+
177
+ if exception.is_a?(Exception)
177
178
  attributes['exception.type'] = exception.class.to_s
178
179
  attributes['exception.message'] = exception.message
180
+ else
181
+ attributes['exception.type'] = exception.to_s
179
182
  end
180
183
 
181
184
  attributes
@@ -213,6 +216,11 @@ module RspecOtel
213
216
 
214
217
  !link.empty?
215
218
  end
219
+
220
+ def closest_not_found_message(prefix, span)
221
+ "#{prefix}, but it couldn't be found. " \
222
+ "Found a close matching span named `#{span.name}`#{SpanDetails.new(span)}"
223
+ end
216
224
  end
217
225
  end
218
226
  end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RspecOtel
4
+ module Matchers
5
+ class SpanDetails
6
+ def initialize(span)
7
+ @span = span
8
+ end
9
+
10
+ def to_s
11
+ lines = [attributes_details, events_details, links_details, status_details].compact
12
+ return '' if lines.empty?
13
+
14
+ "\n#{lines.join("\n")}"
15
+ end
16
+
17
+ private
18
+
19
+ def attributes_details
20
+ return unless @span.attributes&.any?
21
+
22
+ " attributes: #{@span.attributes.inspect}"
23
+ end
24
+
25
+ def events_details
26
+ return unless @span.events&.any?
27
+
28
+ format_collection('events', @span.events) { |e| format_item(e.name, e.attributes) }
29
+ end
30
+
31
+ def links_details
32
+ return unless @span.links&.any?
33
+
34
+ format_collection('links', @span.links) { |l| format_item('link', l.attributes) }
35
+ end
36
+
37
+ def status_details
38
+ return if @span.status.nil? || @span.status.code == OpenTelemetry::Trace::Status::UNSET
39
+
40
+ label = status_label(@span.status.code)
41
+ desc = @span.status.description
42
+ status_str = desc.to_s.empty? ? label : "#{label} (#{desc})"
43
+ " status: #{status_str}"
44
+ end
45
+
46
+ def format_collection(header, collection, &)
47
+ item_lines = collection.map(&)
48
+ " #{header}:\n#{item_lines.join("\n")}"
49
+ end
50
+
51
+ def format_item(label, attributes)
52
+ attributes&.any? ? " - #{label} #{attributes.inspect}" : " - #{label}"
53
+ end
54
+
55
+ def status_label(code)
56
+ case code
57
+ when OpenTelemetry::Trace::Status::OK then 'ok'
58
+ when OpenTelemetry::Trace::Status::ERROR then 'error'
59
+ else 'unknown'
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -9,3 +9,4 @@ module RspecOtel
9
9
  end
10
10
 
11
11
  require 'rspec_otel/matchers/emit_span'
12
+ require 'rspec_otel/matchers/span_details'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module RspecOtel
4
- VERSION = '0.0.6'
4
+ VERSION = '0.0.8'
5
5
  end
metadata CHANGED
@@ -1,14 +1,28 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-otel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Damien MATHIEU
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-03-21 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: logger
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '0'
12
26
  - !ruby/object:Gem::Dependency
13
27
  name: opentelemetry-api
14
28
  requirement: !ruby/object:Gem::Requirement
@@ -77,6 +91,7 @@ files:
77
91
  - lib/rspec_otel.rb
78
92
  - lib/rspec_otel/matchers.rb
79
93
  - lib/rspec_otel/matchers/emit_span.rb
94
+ - lib/rspec_otel/matchers/span_details.rb
80
95
  - lib/rspec_otel/rspec.rb
81
96
  - lib/rspec_otel/version.rb
82
97
  homepage: https://github.com/dmathieu/rspec-otel
@@ -98,7 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
113
  - !ruby/object:Gem::Version
99
114
  version: '0'
100
115
  requirements: []
101
- rubygems_version: 3.6.2
116
+ rubygems_version: 4.0.6
102
117
  specification_version: 4
103
118
  summary: RSpec matchers for the OpenTelemetry framework
104
119
  test_files: []