|
31 | 31 | end |
32 | 32 |
|
33 | 33 | it 'executes the block without instrumentation' do |
34 | | - result = idempotency.send(:with_apm_instrumentation, 'test.operation', action: 'test') do |
| 34 | + result = idempotency.send(:with_apm_instrumentation, 'test.operation', 'test') do |
35 | 35 | test_block.call |
36 | 36 | end |
37 | 37 |
|
|
42 | 42 | context 'when AppSignal is enabled' do |
43 | 43 | before do |
44 | 44 | stub_const('Appsignal', double('Appsignal')) |
| 45 | + allow(Appsignal).to receive(:instrument).and_yield |
45 | 46 |
|
46 | 47 | Idempotency.configure do |config| |
47 | 48 | config.redis_pool = redis_pool |
|
51 | 52 | end |
52 | 53 | end |
53 | 54 |
|
54 | | - it 'wraps execution in AppSignal transaction' do |
55 | | - expect(Appsignal).to receive(:monitor_transaction).with( |
56 | | - 'test.operation', |
57 | | - { action: 'test' } |
| 55 | + it 'wraps execution in AppSignal instrumentation' do |
| 56 | + expect(Appsignal).to receive(:instrument).with( |
| 57 | + 'test.operation', 'test' |
58 | 58 | ).and_yield |
59 | 59 |
|
60 | | - result = idempotency.send(:with_apm_instrumentation, 'test.operation', action: 'test') do |
| 60 | + result = idempotency.send(:with_apm_instrumentation, 'test.operation', 'test') do |
61 | 61 | test_block.call |
62 | 62 | end |
63 | 63 |
|
|
67 | 67 | it 'reports errors to AppSignal and re-raises' do |
68 | 68 | test_error = StandardError.new('test error') |
69 | 69 |
|
70 | | - expect(Appsignal).to receive(:monitor_transaction).with( |
71 | | - 'test.operation', |
72 | | - { action: 'test' } |
| 70 | + expect(Appsignal).to receive(:instrument).with( |
| 71 | + 'test.operation', 'test' |
73 | 72 | ).and_yield |
74 | 73 |
|
75 | 74 | expect(Appsignal).to receive(:set_error).with(test_error) |
76 | 75 |
|
77 | 76 | expect do |
78 | | - idempotency.send(:with_apm_instrumentation, 'test.operation', action: 'test') do |
| 77 | + idempotency.send(:with_apm_instrumentation, 'test.operation', 'test') do |
79 | 78 | raise test_error |
80 | 79 | end |
81 | 80 | end.to raise_error(StandardError, 'test error') |
|
84 | 83 | it 'handles exceptions during error reporting gracefully' do |
85 | 84 | test_error = StandardError.new('test error') |
86 | 85 |
|
87 | | - expect(Appsignal).to receive(:monitor_transaction).with( |
88 | | - 'test.operation', |
89 | | - { action: 'test' } |
| 86 | + expect(Appsignal).to receive(:instrument).with( |
| 87 | + 'test.operation', 'test' |
90 | 88 | ).and_yield |
91 | 89 |
|
92 | 90 | expect(Appsignal).to receive(:set_error).with(test_error).and_raise('AppSignal error') |
93 | 91 |
|
94 | 92 | expect do |
95 | | - idempotency.send(:with_apm_instrumentation, 'test.operation', action: 'test') do |
| 93 | + idempotency.send(:with_apm_instrumentation, 'test.operation', 'test') do |
96 | 94 | raise test_error |
97 | 95 | end |
98 | 96 | end.to raise_error('AppSignal error') |
99 | 97 | end |
100 | 98 | end |
101 | 99 |
|
102 | 100 | context 'when Sentry is enabled' do |
103 | | - let(:mock_transaction) { double('Sentry::Transaction', finish: true) } |
104 | | - let(:mock_scope) { double('Sentry::Scope') } |
| 101 | + let(:mock_span) { double('Sentry::Span') } |
105 | 102 |
|
106 | 103 | before do |
107 | 104 | stub_const('Sentry', double('Sentry')) |
108 | | - allow(Sentry).to receive(:start_transaction).and_return(mock_transaction) |
109 | | - allow(Sentry).to receive(:get_current_scope).and_return(mock_scope) |
110 | | - allow(mock_scope).to receive(:set_span) |
| 105 | + allow(Sentry).to receive(:with_child_span).and_yield(mock_span) |
111 | 106 |
|
112 | 107 | Idempotency.configure do |config| |
113 | 108 | config.redis_pool = redis_pool |
|
117 | 112 | end |
118 | 113 | end |
119 | 114 |
|
120 | | - it 'wraps execution in Sentry transaction' do |
121 | | - expect(Sentry).to receive(:start_transaction).with( |
122 | | - name: 'test.operation', |
123 | | - op: 'idempotency', |
124 | | - action: 'test' |
125 | | - ).and_return(mock_transaction) |
| 115 | + it 'wraps execution in Sentry child span' do |
| 116 | + expect(Sentry).to receive(:with_child_span).with( |
| 117 | + op: 'test.operation', |
| 118 | + description: 'test' |
| 119 | + ).and_yield(mock_span) |
126 | 120 |
|
127 | | - expect(Sentry).to receive(:get_current_scope).and_return(mock_scope) |
128 | | - expect(mock_scope).to receive(:set_span).with(mock_transaction) |
129 | | - expect(mock_transaction).to receive(:finish) |
130 | | - |
131 | | - result = idempotency.send(:with_apm_instrumentation, 'test.operation', action: 'test') do |
| 121 | + result = idempotency.send(:with_apm_instrumentation, 'test.operation', 'test') do |
132 | 122 | test_block.call |
133 | 123 | end |
134 | 124 |
|
|
138 | 128 | it 'captures exceptions with Sentry and re-raises' do |
139 | 129 | test_error = StandardError.new('test error') |
140 | 130 |
|
141 | | - expect(Sentry).to receive(:start_transaction).with( |
142 | | - name: 'test.operation', |
143 | | - op: 'idempotency', |
144 | | - action: 'test' |
145 | | - ).and_return(mock_transaction) |
| 131 | + expect(Sentry).to receive(:with_child_span).with( |
| 132 | + op: 'test.operation', |
| 133 | + description: 'test' |
| 134 | + ).and_yield(mock_span) |
146 | 135 |
|
147 | | - expect(Sentry).to receive(:get_current_scope).and_return(mock_scope) |
148 | | - expect(mock_scope).to receive(:set_span).with(mock_transaction) |
149 | 136 | expect(Sentry).to receive(:capture_exception).with(test_error) |
150 | | - expect(mock_transaction).to receive(:finish) |
151 | 137 |
|
152 | 138 | expect do |
153 | | - idempotency.send(:with_apm_instrumentation, 'test.operation', action: 'test') do |
154 | | - raise test_error |
155 | | - end |
156 | | - end.to raise_error(StandardError, 'test error') |
157 | | - end |
158 | | - |
159 | | - it 'ensures transaction is finished even when error occurs' do |
160 | | - test_error = StandardError.new('test error') |
161 | | - |
162 | | - expect(Sentry).to receive(:start_transaction).and_return(mock_transaction) |
163 | | - expect(Sentry).to receive(:get_current_scope).and_return(mock_scope) |
164 | | - expect(mock_scope).to receive(:set_span).with(mock_transaction) |
165 | | - expect(Sentry).to receive(:capture_exception).with(test_error) |
166 | | - expect(mock_transaction).to receive(:finish) |
167 | | - |
168 | | - expect do |
169 | | - idempotency.send(:with_apm_instrumentation, 'test.operation', action: 'test') do |
| 139 | + idempotency.send(:with_apm_instrumentation, 'test.operation', 'test') do |
170 | 140 | raise test_error |
171 | 141 | end |
172 | 142 | end.to raise_error(StandardError, 'test error') |
|
186 | 156 | end |
187 | 157 |
|
188 | 158 | it 'falls back to executing without instrumentation' do |
189 | | - result = idempotency.send(:with_apm_instrumentation, 'test.operation', action: 'test') do |
| 159 | + result = idempotency.send(:with_apm_instrumentation, 'test.operation', 'test') do |
190 | 160 | test_block.call |
191 | 161 | end |
192 | 162 |
|
|
207 | 177 | end |
208 | 178 |
|
209 | 179 | it 'falls back to executing without instrumentation' do |
210 | | - result = idempotency.send(:with_apm_instrumentation, 'test.operation', action: 'test') do |
| 180 | + result = idempotency.send(:with_apm_instrumentation, 'test.operation', 'test') do |
211 | 181 | test_block.call |
212 | 182 | end |
213 | 183 |
|
|
216 | 186 | end |
217 | 187 |
|
218 | 188 | context 'when both AppSignal and Sentry are enabled' do |
219 | | - let(:mock_transaction) { double('Sentry::Transaction', finish: true) } |
220 | | - let(:mock_scope) { double('Sentry::Scope') } |
| 189 | + let(:mock_span) { double('Sentry::Span') } |
221 | 190 |
|
222 | 191 | before do |
223 | 192 | stub_const('Appsignal', double('Appsignal')) |
224 | 193 | stub_const('Sentry', double('Sentry')) |
225 | | - allow(Sentry).to receive(:start_transaction).and_return(mock_transaction) |
226 | | - allow(Sentry).to receive(:get_current_scope).and_return(mock_scope) |
227 | | - allow(mock_scope).to receive(:set_span) |
| 194 | + allow(Appsignal).to receive(:instrument).and_yield |
| 195 | + allow(Sentry).to receive(:with_child_span).and_yield(mock_span) |
228 | 196 |
|
229 | 197 | Idempotency.configure do |config| |
230 | 198 | config.redis_pool = redis_pool |
|
236 | 204 |
|
237 | 205 | it 'instruments in both AppSignal and Sentry (nested)' do |
238 | 206 | # Expect Sentry to be set up (inner layer) |
239 | | - expect(Sentry).to receive(:start_transaction).with( |
240 | | - name: 'test.operation', |
241 | | - op: 'idempotency', |
242 | | - action: 'test' |
243 | | - ).and_return(mock_transaction) |
244 | | - |
245 | | - expect(Sentry).to receive(:get_current_scope).and_return(mock_scope) |
246 | | - expect(mock_scope).to receive(:set_span).with(mock_transaction) |
247 | | - expect(mock_transaction).to receive(:finish) |
| 207 | + expect(Sentry).to receive(:with_child_span).with( |
| 208 | + op: 'test.operation', |
| 209 | + description: 'test' |
| 210 | + ).and_yield(mock_span) |
248 | 211 |
|
249 | 212 | # Expect AppSignal to wrap everything (outer layer) |
250 | | - expect(Appsignal).to receive(:monitor_transaction).with( |
| 213 | + expect(Appsignal).to receive(:instrument).with( |
251 | 214 | 'test.operation', |
252 | | - { action: 'test' } |
| 215 | + 'test' |
253 | 216 | ).and_yield |
254 | 217 |
|
255 | | - result = idempotency.send(:with_apm_instrumentation, 'test.operation', action: 'test') do |
| 218 | + result = idempotency.send(:with_apm_instrumentation, 'test.operation', 'test') do |
256 | 219 | test_block.call |
257 | 220 | end |
258 | 221 |
|
|
262 | 225 | it 'reports errors to both AppSignal and Sentry' do |
263 | 226 | test_error = StandardError.new('test error') |
264 | 227 |
|
265 | | - # Expect Sentry to capture the exception |
266 | | - expect(Sentry).to receive(:start_transaction).and_return(mock_transaction) |
267 | | - expect(Sentry).to receive(:get_current_scope).and_return(mock_scope) |
268 | | - expect(mock_scope).to receive(:set_span).with(mock_transaction) |
| 228 | + # Expect Sentry to capture the exception (inner layer) |
| 229 | + expect(Sentry).to receive(:with_child_span).with( |
| 230 | + op: 'test.operation', |
| 231 | + description: 'test' |
| 232 | + ).and_yield(mock_span) |
269 | 233 | expect(Sentry).to receive(:capture_exception).with(test_error) |
270 | | - expect(mock_transaction).to receive(:finish) |
271 | 234 |
|
272 | | - # Expect AppSignal to also capture the exception |
273 | | - expect(Appsignal).to receive(:monitor_transaction).and_yield |
| 235 | + # Expect AppSignal to also capture the exception (outer layer) |
| 236 | + expect(Appsignal).to receive(:instrument).with( |
| 237 | + 'test.operation', |
| 238 | + 'test' |
| 239 | + ).and_yield |
274 | 240 | expect(Appsignal).to receive(:set_error).with(test_error) |
275 | 241 |
|
276 | 242 | expect do |
277 | | - idempotency.send(:with_apm_instrumentation, 'test.operation', action: 'test') do |
| 243 | + idempotency.send(:with_apm_instrumentation, 'test.operation', 'test') do |
278 | 244 | raise test_error |
279 | 245 | end |
280 | 246 | end.to raise_error(StandardError, 'test error') |
|
0 commit comments