@geekmidas/telescope 9.0.2 → 10.0.0-alpha.1

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.
Files changed (122) hide show
  1. package/README.md +14 -4
  2. package/dist/{http-D5kn3_Mt.d.mts → http-BiNtg85L.d.mts} +3 -3
  3. package/dist/{http-D5kn3_Mt.d.mts.map → http-BiNtg85L.d.mts.map} +1 -1
  4. package/dist/instrumentation/http.d.mts +1 -1
  5. package/dist/instrumentation/index.cjs +2 -2
  6. package/dist/instrumentation/index.d.cts +2 -2
  7. package/dist/instrumentation/index.d.mts +3 -3
  8. package/dist/instrumentation/index.mjs +2 -2
  9. package/dist/instrumentation/middleware.cjs +1 -1
  10. package/dist/instrumentation/middleware.d.cts +1 -1
  11. package/dist/instrumentation/middleware.d.mts +1 -1
  12. package/dist/instrumentation/middleware.mjs +1 -1
  13. package/dist/instrumentation/otel.cjs +1 -1
  14. package/dist/instrumentation/otel.d.cts +1 -1
  15. package/dist/instrumentation/otel.d.mts +1 -1
  16. package/dist/instrumentation/otel.mjs +1 -1
  17. package/dist/logger/console.d.cts.map +1 -1
  18. package/dist/logger/pino.d.mts +2 -2
  19. package/dist/{middleware-DqPQpcup.cjs → middleware-Bcq6XXGG.cjs} +2 -2
  20. package/dist/middleware-Bcq6XXGG.cjs.map +1 -0
  21. package/dist/{middleware-4-GrQlOT.mjs → middleware-D1XEHvyy.mjs} +2 -2
  22. package/dist/middleware-D1XEHvyy.mjs.map +1 -0
  23. package/dist/{middleware-CA84nsNN.d.cts → middleware-PeyS-9Ny.d.cts} +2 -2
  24. package/dist/{middleware-CA84nsNN.d.cts.map → middleware-PeyS-9Ny.d.cts.map} +1 -1
  25. package/dist/{middleware-DAceVpfw.d.mts → middleware-oHvo_ZgU.d.mts} +2 -2
  26. package/dist/{middleware-DAceVpfw.d.mts.map → middleware-oHvo_ZgU.d.mts.map} +1 -1
  27. package/dist/{otel-40udNP5g.mjs → otel-B9bNoeZ2.mjs} +3 -3
  28. package/dist/otel-B9bNoeZ2.mjs.map +1 -0
  29. package/dist/{otel-SBVoVEHr.d.cts → otel-Bk89b1lX.d.cts} +3 -3
  30. package/dist/{otel-1bJPb2Z7.d.mts.map → otel-Bk89b1lX.d.cts.map} +1 -1
  31. package/dist/{otel-COrpz_GZ.cjs → otel-BzjOtVxZ.cjs} +3 -3
  32. package/dist/otel-BzjOtVxZ.cjs.map +1 -0
  33. package/dist/{otel-1bJPb2Z7.d.mts → otel-lPMsM26e.d.mts} +3 -3
  34. package/dist/{otel-SBVoVEHr.d.cts.map → otel-lPMsM26e.d.mts.map} +1 -1
  35. package/dist/storage/kysely.cjs +48 -38
  36. package/dist/storage/kysely.cjs.map +1 -1
  37. package/dist/storage/kysely.d.cts +29 -9
  38. package/dist/storage/kysely.d.cts.map +1 -1
  39. package/dist/storage/kysely.d.mts +29 -9
  40. package/dist/storage/kysely.d.mts.map +1 -1
  41. package/dist/storage/kysely.mjs +48 -38
  42. package/dist/storage/kysely.mjs.map +1 -1
  43. package/dist/tracing-PnECEbEu.d.mts.map +1 -1
  44. package/package.json +6 -3
  45. package/CHANGELOG.md +0 -72
  46. package/dist/middleware-4-GrQlOT.mjs.map +0 -1
  47. package/dist/middleware-DqPQpcup.cjs.map +0 -1
  48. package/dist/otel-40udNP5g.mjs.map +0 -1
  49. package/dist/otel-COrpz_GZ.cjs.map +0 -1
  50. package/src/Telescope.ts +0 -561
  51. package/src/__tests__/Telescope.spec.ts +0 -438
  52. package/src/__tests__/pino-transport.spec.ts +0 -115
  53. package/src/__tests__/redact.spec.ts +0 -336
  54. package/src/adapters/__tests__/lambda.spec.ts +0 -318
  55. package/src/adapters/__tests__/middy.spec.ts +0 -741
  56. package/src/adapters/index.ts +0 -22
  57. package/src/adapters/lambda.ts +0 -432
  58. package/src/adapters/middy.ts +0 -402
  59. package/src/adapters/types.ts +0 -181
  60. package/src/core.ts +0 -51
  61. package/src/index.ts +0 -34
  62. package/src/instrumentation/__tests__/core.spec.ts +0 -248
  63. package/src/instrumentation/__tests__/hono.spec.ts +0 -348
  64. package/src/instrumentation/__tests__/middleware.spec.ts +0 -528
  65. package/src/instrumentation/__tests__/otel.spec.ts +0 -291
  66. package/src/instrumentation/__tests__/tracing.spec.ts +0 -208
  67. package/src/instrumentation/core.ts +0 -228
  68. package/src/instrumentation/hono.ts +0 -270
  69. package/src/instrumentation/http.ts +0 -306
  70. package/src/instrumentation/index.ts +0 -90
  71. package/src/instrumentation/middleware.ts +0 -297
  72. package/src/instrumentation/otel.ts +0 -271
  73. package/src/instrumentation/setup.ts +0 -246
  74. package/src/instrumentation/tracing.ts +0 -145
  75. package/src/logger/__tests__/console.spec.ts +0 -366
  76. package/src/logger/__tests__/pino.spec.ts +0 -217
  77. package/src/logger/console.ts +0 -230
  78. package/src/logger/pino.ts +0 -201
  79. package/src/metrics/MetricsAggregator.ts +0 -555
  80. package/src/metrics/__tests__/MetricsAggregator.spec.ts +0 -298
  81. package/src/metrics/index.ts +0 -2
  82. package/src/metrics/storage/InMemoryMetricsStorage.ts +0 -380
  83. package/src/metrics/storage/MetricsStorage.ts +0 -74
  84. package/src/metrics/storage/index.ts +0 -3
  85. package/src/metrics/storage/types.ts +0 -243
  86. package/src/otlp/__tests__/receiver.spec.ts +0 -367
  87. package/src/otlp/__tests__/transformer.spec.ts +0 -455
  88. package/src/otlp/hono.ts +0 -120
  89. package/src/otlp/index.ts +0 -22
  90. package/src/otlp/receiver.ts +0 -162
  91. package/src/otlp/transformer.ts +0 -367
  92. package/src/otlp/types.ts +0 -364
  93. package/src/redact.ts +0 -116
  94. package/src/server/__tests__/hono.spec.ts +0 -814
  95. package/src/server/hono.ts +0 -442
  96. package/src/storage/__tests__/kysely.spec.ts +0 -715
  97. package/src/storage/__tests__/memory.spec.ts +0 -694
  98. package/src/storage/kysely.ts +0 -599
  99. package/src/storage/memory.ts +0 -204
  100. package/src/types.ts +0 -447
  101. package/src/ui-assets.ts +0 -40
  102. package/tsconfig.json +0 -9
  103. package/ui/CHANGELOG.md +0 -7
  104. package/ui/index.html +0 -12
  105. package/ui/node_modules/.bin/tsc +0 -21
  106. package/ui/node_modules/.bin/tsserver +0 -21
  107. package/ui/node_modules/.bin/vite +0 -21
  108. package/ui/package.json +0 -24
  109. package/ui/src/App.tsx +0 -595
  110. package/ui/src/api.ts +0 -88
  111. package/ui/src/components/ExceptionDetail.tsx +0 -100
  112. package/ui/src/components/FilterBar.tsx +0 -162
  113. package/ui/src/components/LogDetail.tsx +0 -91
  114. package/ui/src/components/RequestDetail.tsx +0 -143
  115. package/ui/src/main.tsx +0 -10
  116. package/ui/src/styles.css +0 -11
  117. package/ui/src/types.ts +0 -63
  118. package/ui/src/vite-env.d.ts +0 -1
  119. package/ui/src/vite-plugin-gkm-config.ts +0 -54
  120. package/ui/tsconfig.json +0 -20
  121. package/ui/tsconfig.tsbuildinfo +0 -1
  122. package/ui/vite.config.ts +0 -13
@@ -1,291 +0,0 @@
1
- import { trace } from '@opentelemetry/api';
2
- import {
3
- BasicTracerProvider,
4
- InMemorySpanExporter,
5
- SimpleSpanProcessor,
6
- } from '@opentelemetry/sdk-trace-base';
7
- import type { Context } from 'aws-lambda';
8
- import { afterEach, beforeEach, describe, expect, it } from 'vitest';
9
- import { OTelTelemetry } from '../otel';
10
-
11
- describe('OTelTelemetry', () => {
12
- let exporter: InMemorySpanExporter;
13
- let provider: BasicTracerProvider;
14
-
15
- const mockLambdaContext: Context = {
16
- awsRequestId: 'test-request-id',
17
- functionName: 'test-function',
18
- functionVersion: '1',
19
- invokedFunctionArn: 'arn:aws:lambda:us-east-1:123456789:function:test',
20
- memoryLimitInMB: '128',
21
- logGroupName: '/aws/lambda/test',
22
- logStreamName: '2024/01/01/[$LATEST]abc123',
23
- callbackWaitsForEmptyEventLoop: true,
24
- getRemainingTimeInMillis: () => 30000,
25
- done: () => {},
26
- fail: () => {},
27
- succeed: () => {},
28
- };
29
-
30
- beforeEach(() => {
31
- exporter = new InMemorySpanExporter();
32
- provider = new BasicTracerProvider();
33
- provider.addSpanProcessor(new SimpleSpanProcessor(exporter));
34
- provider.register();
35
- });
36
-
37
- afterEach(async () => {
38
- exporter.reset();
39
- await provider.shutdown();
40
- trace.disable();
41
- });
42
-
43
- describe('API Gateway v2 events', () => {
44
- it('should create span for API Gateway v2 request', () => {
45
- const telemetry = new OTelTelemetry();
46
-
47
- const event = {
48
- requestContext: {
49
- http: {
50
- method: 'GET',
51
- path: '/api/users',
52
- sourceIp: '192.168.1.1',
53
- userAgent: 'test-agent',
54
- },
55
- requestId: 'apigw-request-id',
56
- },
57
- rawPath: '/api/users',
58
- rawQueryString: 'page=1',
59
- headers: { host: 'api.example.com' },
60
- };
61
-
62
- const ctx = telemetry.onRequestStart({
63
- event,
64
- context: mockLambdaContext,
65
- });
66
-
67
- telemetry.onRequestEnd(ctx, { statusCode: 200 });
68
-
69
- const spans = exporter.getFinishedSpans();
70
- expect(spans).toHaveLength(1);
71
- expect(spans[0].name).toBe('GET /api/users');
72
- expect(spans[0].attributes['http.request.method']).toBe('GET');
73
- expect(spans[0].attributes['url.path']).toBe('/api/users');
74
- expect(spans[0].attributes['faas.invocation_id']).toBe('test-request-id');
75
- expect(spans[0].attributes['faas.name']).toBe('test-function');
76
- });
77
-
78
- it('should record error on request failure', () => {
79
- const telemetry = new OTelTelemetry();
80
-
81
- const event = {
82
- requestContext: {
83
- http: { method: 'POST', path: '/api/users', sourceIp: '10.0.0.1' },
84
- requestId: 'req-123',
85
- },
86
- rawPath: '/api/users',
87
- headers: {},
88
- };
89
-
90
- const ctx = telemetry.onRequestStart({
91
- event,
92
- context: mockLambdaContext,
93
- });
94
-
95
- telemetry.onRequestError(ctx, new Error('Database connection failed'));
96
-
97
- const spans = exporter.getFinishedSpans();
98
- expect(spans).toHaveLength(1);
99
- expect(spans[0].status.code).toBe(2); // SpanStatusCode.ERROR
100
- expect(spans[0].events).toHaveLength(1);
101
- expect(spans[0].events[0].name).toBe('exception');
102
- });
103
- });
104
-
105
- describe('API Gateway v1 events', () => {
106
- it('should create span for API Gateway v1 request', () => {
107
- const telemetry = new OTelTelemetry();
108
-
109
- const event = {
110
- httpMethod: 'POST',
111
- path: '/api/orders',
112
- resource: '/api/orders',
113
- requestContext: {
114
- requestId: 'v1-request-id',
115
- identity: { sourceIp: '10.0.0.1' },
116
- },
117
- headers: {
118
- Host: 'api.example.com',
119
- 'User-Agent': 'test-client',
120
- },
121
- };
122
-
123
- const ctx = telemetry.onRequestStart({
124
- event,
125
- context: mockLambdaContext,
126
- });
127
-
128
- telemetry.onRequestEnd(ctx, { statusCode: 201 });
129
-
130
- const spans = exporter.getFinishedSpans();
131
- expect(spans).toHaveLength(1);
132
- expect(spans[0].attributes['http.request.method']).toBe('POST');
133
- expect(spans[0].attributes['url.path']).toBe('/api/orders');
134
- expect(spans[0].attributes['http.route']).toBe('/api/orders');
135
- });
136
- });
137
-
138
- describe('options', () => {
139
- it('should record request body when recordBody is true', () => {
140
- const telemetry = new OTelTelemetry({ recordBody: true });
141
-
142
- const event = {
143
- requestContext: {
144
- http: { method: 'POST', path: '/api/users', sourceIp: '10.0.0.1' },
145
- requestId: 'req-123',
146
- },
147
- rawPath: '/api/users',
148
- headers: {},
149
- body: JSON.stringify({ name: 'John', email: 'john@example.com' }),
150
- };
151
-
152
- const ctx = telemetry.onRequestStart({
153
- event,
154
- context: mockLambdaContext,
155
- });
156
-
157
- telemetry.onRequestEnd(ctx, { statusCode: 200 });
158
-
159
- const spans = exporter.getFinishedSpans();
160
- expect(spans[0].attributes['http.request.body']).toContain('John');
161
- });
162
-
163
- it('should record response body when recordResponseBody is true', () => {
164
- const telemetry = new OTelTelemetry({ recordResponseBody: true });
165
-
166
- const event = {
167
- requestContext: {
168
- http: { method: 'GET', path: '/api/users', sourceIp: '10.0.0.1' },
169
- requestId: 'req-123',
170
- },
171
- rawPath: '/api/users',
172
- headers: {},
173
- };
174
-
175
- const ctx = telemetry.onRequestStart({
176
- event,
177
- context: mockLambdaContext,
178
- });
179
-
180
- telemetry.onRequestEnd(ctx, {
181
- statusCode: 200,
182
- body: JSON.stringify({ users: [{ id: '1', name: 'John' }] }),
183
- });
184
-
185
- const spans = exporter.getFinishedSpans();
186
- expect(spans[0].attributes['http.response.body']).toContain('John');
187
- });
188
-
189
- it('should extract user ID using custom function', () => {
190
- const telemetry = new OTelTelemetry({
191
- getUserId: (event) => event.requestContext?.authorizer?.userId,
192
- });
193
-
194
- const event = {
195
- requestContext: {
196
- http: { method: 'GET', path: '/api/profile', sourceIp: '10.0.0.1' },
197
- requestId: 'req-123',
198
- authorizer: { userId: 'user-456' },
199
- },
200
- rawPath: '/api/profile',
201
- headers: {},
202
- };
203
-
204
- const ctx = telemetry.onRequestStart({
205
- event,
206
- context: mockLambdaContext,
207
- });
208
-
209
- telemetry.onRequestEnd(ctx, { statusCode: 200 });
210
-
211
- const spans = exporter.getFinishedSpans();
212
- expect(spans[0].attributes['enduser.id']).toBe('user-456');
213
- });
214
-
215
- it('should extract endpoint name using custom function', () => {
216
- const telemetry = new OTelTelemetry({
217
- getEndpointName: (event) => event.endpointName,
218
- });
219
-
220
- const event = {
221
- requestContext: {
222
- http: { method: 'GET', path: '/api/users', sourceIp: '10.0.0.1' },
223
- requestId: 'req-123',
224
- },
225
- rawPath: '/api/users',
226
- headers: {},
227
- endpointName: 'ListUsers',
228
- };
229
-
230
- const ctx = telemetry.onRequestStart({
231
- event,
232
- context: mockLambdaContext,
233
- });
234
-
235
- telemetry.onRequestEnd(ctx, { statusCode: 200 });
236
-
237
- const spans = exporter.getFinishedSpans();
238
- expect(spans[0].attributes['endpoint.name']).toBe('ListUsers');
239
- });
240
- });
241
-
242
- describe('ALB events', () => {
243
- it('should create span for ALB request', () => {
244
- const telemetry = new OTelTelemetry();
245
-
246
- const event = {
247
- httpMethod: 'GET',
248
- path: '/health',
249
- headers: {
250
- host: 'alb.example.com',
251
- 'user-agent': 'ALB-HealthChecker',
252
- 'x-forwarded-for': '10.0.0.1, 10.0.0.2',
253
- },
254
- };
255
-
256
- const ctx = telemetry.onRequestStart({
257
- event,
258
- context: mockLambdaContext,
259
- });
260
-
261
- telemetry.onRequestEnd(ctx, { statusCode: 200 });
262
-
263
- const spans = exporter.getFinishedSpans();
264
- expect(spans).toHaveLength(1);
265
- expect(spans[0].attributes['http.request.method']).toBe('GET');
266
- expect(spans[0].attributes['url.path']).toBe('/health');
267
- });
268
- });
269
-
270
- describe('direct Lambda invocation', () => {
271
- it('should create span for direct invocation', () => {
272
- const telemetry = new OTelTelemetry();
273
-
274
- const event = {
275
- action: 'processJob',
276
- data: { jobId: '123' },
277
- };
278
-
279
- const ctx = telemetry.onRequestStart({
280
- event,
281
- context: mockLambdaContext,
282
- });
283
-
284
- telemetry.onRequestEnd(ctx, { statusCode: 200 });
285
-
286
- const spans = exporter.getFinishedSpans();
287
- expect(spans).toHaveLength(1);
288
- expect(spans[0].attributes['http.request.method']).toBe('INVOKE');
289
- });
290
- });
291
- });
@@ -1,208 +0,0 @@
1
- import { trace } from '@opentelemetry/api';
2
- import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
3
- import { afterAll, beforeAll, describe, expect, it } from 'vitest';
4
- import {
5
- addSpanEvent,
6
- createSpan,
7
- getActiveSpan,
8
- getSpanId,
9
- getTraceId,
10
- recordException,
11
- setSpanAttributes,
12
- withSpan,
13
- withSpanSync,
14
- } from '../tracing';
15
-
16
- describe('Tracing Utilities', () => {
17
- let provider: NodeTracerProvider;
18
-
19
- beforeAll(() => {
20
- // Register a real tracer provider for tests
21
- provider = new NodeTracerProvider();
22
- provider.register();
23
- });
24
-
25
- afterAll(async () => {
26
- await provider.shutdown();
27
- // Reset to default noop provider
28
- trace.disable();
29
- });
30
- describe('createSpan', () => {
31
- it('should create a new span', () => {
32
- const span = createSpan('test-span');
33
- expect(span).toBeDefined();
34
- expect(span.spanContext().spanId).toBeDefined();
35
- span.end();
36
- });
37
-
38
- it('should create span with attributes', () => {
39
- const span = createSpan('test-span-attrs', { 'test.attr': 'value' });
40
- expect(span).toBeDefined();
41
- span.end();
42
- });
43
- });
44
-
45
- describe('withSpan', () => {
46
- it('should execute function within span context', async () => {
47
- const result = await withSpan('async-operation', async (span) => {
48
- expect(span).toBeDefined();
49
- expect(span.spanContext().spanId).toBeDefined();
50
- return 'result';
51
- });
52
-
53
- expect(result).toBe('result');
54
- });
55
-
56
- it('should propagate errors', async () => {
57
- await expect(
58
- withSpan('error-span', async () => {
59
- throw new Error('Test error');
60
- }),
61
- ).rejects.toThrow('Test error');
62
- });
63
-
64
- it('should pass attributes to span', async () => {
65
- let spanReceived = false;
66
- await withSpan(
67
- 'attr-span',
68
- async (span) => {
69
- spanReceived = true;
70
- expect(span).toBeDefined();
71
- return 'done';
72
- },
73
- { 'custom.attr': 123 },
74
- );
75
- expect(spanReceived).toBe(true);
76
- });
77
- });
78
-
79
- describe('withSpanSync', () => {
80
- it('should execute synchronous function within span context', () => {
81
- const result = withSpanSync('sync-operation', (span) => {
82
- expect(span).toBeDefined();
83
- return 42;
84
- });
85
-
86
- expect(result).toBe(42);
87
- });
88
-
89
- it('should handle errors in sync functions', () => {
90
- expect(() =>
91
- withSpanSync('sync-error', () => {
92
- throw new Error('Sync error');
93
- }),
94
- ).toThrow('Sync error');
95
- });
96
- });
97
-
98
- describe('getActiveSpan', () => {
99
- it('should return active span within withSpan', async () => {
100
- await withSpan('active-span', async () => {
101
- const active = getActiveSpan();
102
- expect(active).toBeDefined();
103
- });
104
- });
105
- });
106
-
107
- describe('getTraceId and getSpanId', () => {
108
- it('should return trace and span IDs within span context', async () => {
109
- let traceId: string | undefined;
110
- let spanId: string | undefined;
111
-
112
- await withSpan('id-span', async (span) => {
113
- traceId = getTraceId();
114
- spanId = getSpanId();
115
- // Verify they match the span we're in
116
- expect(traceId).toBe(span.spanContext().traceId);
117
- expect(spanId).toBe(span.spanContext().spanId);
118
- });
119
-
120
- expect(traceId).toBeDefined();
121
- expect(traceId?.length).toBe(32); // 16 bytes hex
122
- expect(spanId).toBeDefined();
123
- expect(spanId?.length).toBe(16); // 8 bytes hex
124
- });
125
-
126
- it('should return undefined outside span context', () => {
127
- // Outside of any span context
128
- const traceId = getTraceId();
129
- const spanId = getSpanId();
130
- // These may be undefined if no span is active
131
- expect(traceId === undefined || typeof traceId === 'string').toBe(true);
132
- expect(spanId === undefined || typeof spanId === 'string').toBe(true);
133
- });
134
- });
135
-
136
- describe('setSpanAttributes', () => {
137
- it('should set attributes on active span', async () => {
138
- await withSpan('attrs-span', async (span) => {
139
- setSpanAttributes({ 'custom.key': 'custom-value', 'custom.num': 42 });
140
- // Span should still be valid
141
- expect(span.isRecording()).toBe(true);
142
- });
143
- });
144
-
145
- it('should not throw when no active span', () => {
146
- // Should not throw even when called outside span context
147
- expect(() => {
148
- setSpanAttributes({ key: 'value' });
149
- }).not.toThrow();
150
- });
151
- });
152
-
153
- describe('recordException', () => {
154
- it('should record exception on active span', async () => {
155
- await withSpan('exception-span', async () => {
156
- const error = new Error('Test exception');
157
- recordException(error);
158
- // Should not throw
159
- });
160
- });
161
-
162
- it('should not throw when no active span', () => {
163
- expect(() => {
164
- recordException(new Error('No span error'));
165
- }).not.toThrow();
166
- });
167
- });
168
-
169
- describe('addSpanEvent', () => {
170
- it('should add event to active span', async () => {
171
- await withSpan('event-span', async () => {
172
- addSpanEvent('test.event', { detail: 'some detail' });
173
- // Should not throw
174
- });
175
- });
176
-
177
- it('should add event without attributes', async () => {
178
- await withSpan('event-span-simple', async () => {
179
- addSpanEvent('simple.event');
180
- // Should not throw
181
- });
182
- });
183
-
184
- it('should not throw when no active span', () => {
185
- expect(() => {
186
- addSpanEvent('orphan.event', { data: 123 });
187
- }).not.toThrow();
188
- });
189
- });
190
-
191
- describe('error handling edge cases', () => {
192
- it('should handle non-Error exceptions in withSpan', async () => {
193
- await expect(
194
- withSpan('string-error-span', async () => {
195
- throw 'string error'; // Non-Error exception
196
- }),
197
- ).rejects.toBe('string error');
198
- });
199
-
200
- it('should handle non-Error exceptions in withSpanSync', () => {
201
- expect(() =>
202
- withSpanSync('sync-string-error', () => {
203
- throw 'sync string error';
204
- }),
205
- ).toThrow();
206
- });
207
- });
208
- });