autotel-cloudflare 2.1.0
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.
- package/LICENSE +21 -0
- package/README.md +432 -0
- package/dist/actors.d.ts +248 -0
- package/dist/actors.js +1030 -0
- package/dist/actors.js.map +1 -0
- package/dist/agents.d.ts +219 -0
- package/dist/agents.js +276 -0
- package/dist/agents.js.map +1 -0
- package/dist/bindings.d.ts +40 -0
- package/dist/bindings.js +4 -0
- package/dist/bindings.js.map +1 -0
- package/dist/chunk-JDPN3HND.js +520 -0
- package/dist/chunk-JDPN3HND.js.map +1 -0
- package/dist/chunk-QXFYTHQF.js +298 -0
- package/dist/chunk-QXFYTHQF.js.map +1 -0
- package/dist/chunk-SKKRPS5K.js +50 -0
- package/dist/chunk-SKKRPS5K.js.map +1 -0
- package/dist/events.d.ts +1 -0
- package/dist/events.js +3 -0
- package/dist/events.js.map +1 -0
- package/dist/handlers.d.ts +121 -0
- package/dist/handlers.js +4 -0
- package/dist/handlers.js.map +1 -0
- package/dist/index.d.ts +144 -0
- package/dist/index.js +576 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +1 -0
- package/dist/logger.js +3 -0
- package/dist/logger.js.map +1 -0
- package/dist/sampling.d.ts +4 -0
- package/dist/sampling.js +3 -0
- package/dist/sampling.js.map +1 -0
- package/dist/testing.d.ts +1 -0
- package/dist/testing.js +3 -0
- package/dist/testing.js.map +1 -0
- package/package.json +107 -0
- package/src/actors/alarms.ts +225 -0
- package/src/actors/index.ts +36 -0
- package/src/actors/instrument-actor.test.ts +179 -0
- package/src/actors/instrument-actor.ts +574 -0
- package/src/actors/sockets.ts +217 -0
- package/src/actors/storage.ts +263 -0
- package/src/actors/traced-handler.ts +300 -0
- package/src/actors/types.ts +98 -0
- package/src/actors.ts +50 -0
- package/src/agents/index.ts +42 -0
- package/src/agents/otel-observability.test.ts +329 -0
- package/src/agents/otel-observability.ts +465 -0
- package/src/agents/types.ts +167 -0
- package/src/agents.ts +76 -0
- package/src/bindings/bindings.ts +621 -0
- package/src/bindings/common.ts +75 -0
- package/src/bindings/index.ts +12 -0
- package/src/bindings.ts +6 -0
- package/src/events.ts +6 -0
- package/src/global/cache.test.ts +292 -0
- package/src/global/cache.ts +164 -0
- package/src/global/fetch.test.ts +344 -0
- package/src/global/fetch.ts +134 -0
- package/src/global/index.ts +7 -0
- package/src/handlers/durable-objects.test.ts +524 -0
- package/src/handlers/durable-objects.ts +250 -0
- package/src/handlers/index.ts +6 -0
- package/src/handlers/workflows.ts +318 -0
- package/src/handlers.ts +6 -0
- package/src/index.ts +57 -0
- package/src/logger.ts +6 -0
- package/src/sampling.ts +6 -0
- package/src/testing.ts +6 -0
- package/src/wrappers/index.ts +8 -0
- package/src/wrappers/instrument.integration.test.ts +468 -0
- package/src/wrappers/instrument.ts +643 -0
- package/src/wrappers/wrap-do.ts +34 -0
- package/src/wrappers/wrap-module.ts +37 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Actor sockets instrumentation
|
|
3
|
+
*
|
|
4
|
+
* Traces operations on actor.sockets
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { trace, SpanStatusCode, SpanKind } from '@opentelemetry/api';
|
|
8
|
+
import type { WorkerTracer } from 'autotel-edge';
|
|
9
|
+
import { wrap } from '../bindings/common';
|
|
10
|
+
import type { ActorLike } from './types';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get the tracer instance
|
|
14
|
+
*/
|
|
15
|
+
function getTracer(): WorkerTracer {
|
|
16
|
+
return trace.getTracer('autotel-cloudflare-actors') as WorkerTracer;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Instrument Actor sockets for tracing
|
|
21
|
+
*
|
|
22
|
+
* Captures:
|
|
23
|
+
* - acceptWebSocket: Accept an incoming WebSocket connection
|
|
24
|
+
* - broadcast: Send message to all connected sockets
|
|
25
|
+
* - send: Send message to a specific socket
|
|
26
|
+
*/
|
|
27
|
+
export function instrumentActorSockets(
|
|
28
|
+
sockets: unknown,
|
|
29
|
+
actorInstance: ActorLike,
|
|
30
|
+
actorClass: object,
|
|
31
|
+
): unknown {
|
|
32
|
+
if (!sockets || typeof sockets !== 'object') {
|
|
33
|
+
return sockets;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const actorClassName = (actorClass as { name?: string }).name || 'Actor';
|
|
37
|
+
const actorName = actorInstance.name || actorClassName;
|
|
38
|
+
|
|
39
|
+
const socketsHandler: ProxyHandler<object> = {
|
|
40
|
+
get(target, prop) {
|
|
41
|
+
const value = Reflect.get(target, prop);
|
|
42
|
+
|
|
43
|
+
// Instrument acceptWebSocket method
|
|
44
|
+
if (prop === 'acceptWebSocket' && typeof value === 'function') {
|
|
45
|
+
return function instrumentedAcceptWebSocket(
|
|
46
|
+
this: unknown,
|
|
47
|
+
request: Request,
|
|
48
|
+
): unknown {
|
|
49
|
+
const tracer = getTracer();
|
|
50
|
+
const spanName = `Actor ${actorName}: sockets.acceptWebSocket`;
|
|
51
|
+
|
|
52
|
+
return tracer.startActiveSpan(
|
|
53
|
+
spanName,
|
|
54
|
+
{
|
|
55
|
+
kind: SpanKind.SERVER,
|
|
56
|
+
attributes: {
|
|
57
|
+
'actor.name': actorName,
|
|
58
|
+
'actor.class': actorClassName,
|
|
59
|
+
'websocket.operation': 'accept',
|
|
60
|
+
'url.full': request.url,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
(span) => {
|
|
64
|
+
try {
|
|
65
|
+
const result = value.call(target, request);
|
|
66
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
67
|
+
return result;
|
|
68
|
+
} catch (error) {
|
|
69
|
+
span.recordException(error as Error);
|
|
70
|
+
span.setStatus({
|
|
71
|
+
code: SpanStatusCode.ERROR,
|
|
72
|
+
message: error instanceof Error ? error.message : String(error),
|
|
73
|
+
});
|
|
74
|
+
throw error;
|
|
75
|
+
} finally {
|
|
76
|
+
span.end();
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Instrument broadcast method
|
|
84
|
+
if (prop === 'broadcast' && typeof value === 'function') {
|
|
85
|
+
return function instrumentedBroadcast(this: unknown, message: unknown): void {
|
|
86
|
+
const tracer = getTracer();
|
|
87
|
+
const spanName = `Actor ${actorName}: sockets.broadcast`;
|
|
88
|
+
|
|
89
|
+
tracer.startActiveSpan(
|
|
90
|
+
spanName,
|
|
91
|
+
{
|
|
92
|
+
kind: SpanKind.PRODUCER,
|
|
93
|
+
attributes: {
|
|
94
|
+
'actor.name': actorName,
|
|
95
|
+
'actor.class': actorClassName,
|
|
96
|
+
'websocket.operation': 'broadcast',
|
|
97
|
+
'websocket.message.type': typeof message,
|
|
98
|
+
'websocket.message.size':
|
|
99
|
+
typeof message === 'string'
|
|
100
|
+
? message.length
|
|
101
|
+
: message instanceof ArrayBuffer
|
|
102
|
+
? message.byteLength
|
|
103
|
+
: 0,
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
(span) => {
|
|
107
|
+
try {
|
|
108
|
+
value.call(target, message);
|
|
109
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
110
|
+
} catch (error) {
|
|
111
|
+
span.recordException(error as Error);
|
|
112
|
+
span.setStatus({
|
|
113
|
+
code: SpanStatusCode.ERROR,
|
|
114
|
+
message: error instanceof Error ? error.message : String(error),
|
|
115
|
+
});
|
|
116
|
+
throw error;
|
|
117
|
+
} finally {
|
|
118
|
+
span.end();
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
);
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Instrument send method
|
|
126
|
+
if (prop === 'send' && typeof value === 'function') {
|
|
127
|
+
return function instrumentedSend(this: unknown, ws: WebSocket, message: unknown): void {
|
|
128
|
+
const tracer = getTracer();
|
|
129
|
+
const spanName = `Actor ${actorName}: sockets.send`;
|
|
130
|
+
|
|
131
|
+
tracer.startActiveSpan(
|
|
132
|
+
spanName,
|
|
133
|
+
{
|
|
134
|
+
kind: SpanKind.PRODUCER,
|
|
135
|
+
attributes: {
|
|
136
|
+
'actor.name': actorName,
|
|
137
|
+
'actor.class': actorClassName,
|
|
138
|
+
'websocket.operation': 'send',
|
|
139
|
+
'websocket.message.type': typeof message,
|
|
140
|
+
'websocket.message.size':
|
|
141
|
+
typeof message === 'string'
|
|
142
|
+
? message.length
|
|
143
|
+
: message instanceof ArrayBuffer
|
|
144
|
+
? message.byteLength
|
|
145
|
+
: 0,
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
(span) => {
|
|
149
|
+
try {
|
|
150
|
+
value.call(target, ws, message);
|
|
151
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
152
|
+
} catch (error) {
|
|
153
|
+
span.recordException(error as Error);
|
|
154
|
+
span.setStatus({
|
|
155
|
+
code: SpanStatusCode.ERROR,
|
|
156
|
+
message: error instanceof Error ? error.message : String(error),
|
|
157
|
+
});
|
|
158
|
+
throw error;
|
|
159
|
+
} finally {
|
|
160
|
+
span.end();
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
);
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Instrument getConnections method (if exists)
|
|
168
|
+
if (prop === 'getConnections' && typeof value === 'function') {
|
|
169
|
+
return function instrumentedGetConnections(this: unknown): unknown {
|
|
170
|
+
const tracer = getTracer();
|
|
171
|
+
const spanName = `Actor ${actorName}: sockets.getConnections`;
|
|
172
|
+
|
|
173
|
+
return tracer.startActiveSpan(
|
|
174
|
+
spanName,
|
|
175
|
+
{
|
|
176
|
+
kind: SpanKind.CLIENT,
|
|
177
|
+
attributes: {
|
|
178
|
+
'actor.name': actorName,
|
|
179
|
+
'actor.class': actorClassName,
|
|
180
|
+
'websocket.operation': 'getConnections',
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
(span) => {
|
|
184
|
+
try {
|
|
185
|
+
const result = value.call(target);
|
|
186
|
+
// Try to capture connection count if result is array-like
|
|
187
|
+
if (Array.isArray(result)) {
|
|
188
|
+
span.setAttribute('websocket.connections.count', result.length);
|
|
189
|
+
}
|
|
190
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
191
|
+
return result;
|
|
192
|
+
} catch (error) {
|
|
193
|
+
span.recordException(error as Error);
|
|
194
|
+
span.setStatus({
|
|
195
|
+
code: SpanStatusCode.ERROR,
|
|
196
|
+
message: error instanceof Error ? error.message : String(error),
|
|
197
|
+
});
|
|
198
|
+
throw error;
|
|
199
|
+
} finally {
|
|
200
|
+
span.end();
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
);
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// Bind other methods to the target
|
|
208
|
+
if (typeof value === 'function') {
|
|
209
|
+
return value.bind(target);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
return value;
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
return wrap(sockets, socketsHandler);
|
|
217
|
+
}
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Actor storage instrumentation
|
|
3
|
+
*
|
|
4
|
+
* Traces operations on actor.storage including SQL queries
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { trace, SpanStatusCode, SpanKind } from '@opentelemetry/api';
|
|
8
|
+
import type { WorkerTracer } from 'autotel-edge';
|
|
9
|
+
import { wrap } from '../bindings/common';
|
|
10
|
+
import type { ActorLike } from './types';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Get the tracer instance
|
|
14
|
+
*/
|
|
15
|
+
function getTracer(): WorkerTracer {
|
|
16
|
+
return trace.getTracer('autotel-cloudflare-actors') as WorkerTracer;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Instrument Actor storage for tracing
|
|
21
|
+
*
|
|
22
|
+
* Captures:
|
|
23
|
+
* - SQL query operations
|
|
24
|
+
* - Key-value operations (if available)
|
|
25
|
+
*/
|
|
26
|
+
export function instrumentActorStorage(
|
|
27
|
+
storage: unknown,
|
|
28
|
+
actorInstance: ActorLike,
|
|
29
|
+
actorClass: object,
|
|
30
|
+
): unknown {
|
|
31
|
+
if (!storage || typeof storage !== 'object') {
|
|
32
|
+
return storage;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const actorClassName = (actorClass as { name?: string }).name || 'Actor';
|
|
36
|
+
const actorName = actorInstance.name || actorClassName;
|
|
37
|
+
|
|
38
|
+
const storageHandler: ProxyHandler<object> = {
|
|
39
|
+
get(target, prop) {
|
|
40
|
+
const value = Reflect.get(target, prop);
|
|
41
|
+
|
|
42
|
+
// Instrument SQL query method if it exists
|
|
43
|
+
// The Actors Storage class has an exec method for SQL
|
|
44
|
+
if (prop === 'exec' && typeof value === 'function') {
|
|
45
|
+
return function instrumentedExec(
|
|
46
|
+
this: unknown,
|
|
47
|
+
query: string,
|
|
48
|
+
...params: unknown[]
|
|
49
|
+
): unknown {
|
|
50
|
+
const tracer = getTracer();
|
|
51
|
+
const spanName = `Actor ${actorName}: storage.exec`;
|
|
52
|
+
|
|
53
|
+
return tracer.startActiveSpan(
|
|
54
|
+
spanName,
|
|
55
|
+
{
|
|
56
|
+
kind: SpanKind.CLIENT,
|
|
57
|
+
attributes: {
|
|
58
|
+
'actor.name': actorName,
|
|
59
|
+
'actor.class': actorClassName,
|
|
60
|
+
'db.system': 'sqlite',
|
|
61
|
+
'db.operation': 'exec',
|
|
62
|
+
'db.statement': query,
|
|
63
|
+
'db.statement.params_count': params.length,
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
(span) => {
|
|
67
|
+
try {
|
|
68
|
+
const result = value.call(target, query, ...params);
|
|
69
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
70
|
+
return result;
|
|
71
|
+
} catch (error) {
|
|
72
|
+
span.recordException(error as Error);
|
|
73
|
+
span.setStatus({
|
|
74
|
+
code: SpanStatusCode.ERROR,
|
|
75
|
+
message: error instanceof Error ? error.message : String(error),
|
|
76
|
+
});
|
|
77
|
+
throw error;
|
|
78
|
+
} finally {
|
|
79
|
+
span.end();
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
);
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Instrument query method (alternative name for exec)
|
|
87
|
+
if (prop === 'query' && typeof value === 'function') {
|
|
88
|
+
return function instrumentedQuery(
|
|
89
|
+
this: unknown,
|
|
90
|
+
query: string,
|
|
91
|
+
...params: unknown[]
|
|
92
|
+
): unknown {
|
|
93
|
+
const tracer = getTracer();
|
|
94
|
+
const spanName = `Actor ${actorName}: storage.query`;
|
|
95
|
+
|
|
96
|
+
return tracer.startActiveSpan(
|
|
97
|
+
spanName,
|
|
98
|
+
{
|
|
99
|
+
kind: SpanKind.CLIENT,
|
|
100
|
+
attributes: {
|
|
101
|
+
'actor.name': actorName,
|
|
102
|
+
'actor.class': actorClassName,
|
|
103
|
+
'db.system': 'sqlite',
|
|
104
|
+
'db.operation': 'query',
|
|
105
|
+
'db.statement': query,
|
|
106
|
+
'db.statement.params_count': params.length,
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
(span) => {
|
|
110
|
+
try {
|
|
111
|
+
const result = value.call(target, query, ...params);
|
|
112
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
113
|
+
return result;
|
|
114
|
+
} catch (error) {
|
|
115
|
+
span.recordException(error as Error);
|
|
116
|
+
span.setStatus({
|
|
117
|
+
code: SpanStatusCode.ERROR,
|
|
118
|
+
message: error instanceof Error ? error.message : String(error),
|
|
119
|
+
});
|
|
120
|
+
throw error;
|
|
121
|
+
} finally {
|
|
122
|
+
span.end();
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
);
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Instrument get method
|
|
130
|
+
if (prop === 'get' && typeof value === 'function') {
|
|
131
|
+
return async function instrumentedGet(this: unknown, key: string): Promise<unknown> {
|
|
132
|
+
const tracer = getTracer();
|
|
133
|
+
const spanName = `Actor ${actorName}: storage.get`;
|
|
134
|
+
|
|
135
|
+
return tracer.startActiveSpan(
|
|
136
|
+
spanName,
|
|
137
|
+
{
|
|
138
|
+
kind: SpanKind.CLIENT,
|
|
139
|
+
attributes: {
|
|
140
|
+
'actor.name': actorName,
|
|
141
|
+
'actor.class': actorClassName,
|
|
142
|
+
'db.system': 'durable_object_storage',
|
|
143
|
+
'db.operation': 'get',
|
|
144
|
+
'db.key': key,
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
async (span) => {
|
|
148
|
+
try {
|
|
149
|
+
const result = await value.call(target, key);
|
|
150
|
+
span.setAttributes({
|
|
151
|
+
'db.result.found': result !== null && result !== undefined,
|
|
152
|
+
});
|
|
153
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
154
|
+
return result;
|
|
155
|
+
} catch (error) {
|
|
156
|
+
span.recordException(error as Error);
|
|
157
|
+
span.setStatus({
|
|
158
|
+
code: SpanStatusCode.ERROR,
|
|
159
|
+
message: error instanceof Error ? error.message : String(error),
|
|
160
|
+
});
|
|
161
|
+
throw error;
|
|
162
|
+
} finally {
|
|
163
|
+
span.end();
|
|
164
|
+
}
|
|
165
|
+
},
|
|
166
|
+
);
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Instrument put method
|
|
171
|
+
if (prop === 'put' && typeof value === 'function') {
|
|
172
|
+
return async function instrumentedPut(
|
|
173
|
+
this: unknown,
|
|
174
|
+
key: string,
|
|
175
|
+
val: unknown,
|
|
176
|
+
): Promise<void> {
|
|
177
|
+
const tracer = getTracer();
|
|
178
|
+
const spanName = `Actor ${actorName}: storage.put`;
|
|
179
|
+
|
|
180
|
+
return tracer.startActiveSpan(
|
|
181
|
+
spanName,
|
|
182
|
+
{
|
|
183
|
+
kind: SpanKind.CLIENT,
|
|
184
|
+
attributes: {
|
|
185
|
+
'actor.name': actorName,
|
|
186
|
+
'actor.class': actorClassName,
|
|
187
|
+
'db.system': 'durable_object_storage',
|
|
188
|
+
'db.operation': 'put',
|
|
189
|
+
'db.key': key,
|
|
190
|
+
'db.value_type': typeof val,
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
async (span) => {
|
|
194
|
+
try {
|
|
195
|
+
await value.call(target, key, val);
|
|
196
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
197
|
+
} catch (error) {
|
|
198
|
+
span.recordException(error as Error);
|
|
199
|
+
span.setStatus({
|
|
200
|
+
code: SpanStatusCode.ERROR,
|
|
201
|
+
message: error instanceof Error ? error.message : String(error),
|
|
202
|
+
});
|
|
203
|
+
throw error;
|
|
204
|
+
} finally {
|
|
205
|
+
span.end();
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
);
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Instrument delete method
|
|
213
|
+
if (prop === 'delete' && typeof value === 'function') {
|
|
214
|
+
return async function instrumentedDelete(this: unknown, key: string): Promise<boolean> {
|
|
215
|
+
const tracer = getTracer();
|
|
216
|
+
const spanName = `Actor ${actorName}: storage.delete`;
|
|
217
|
+
|
|
218
|
+
return tracer.startActiveSpan(
|
|
219
|
+
spanName,
|
|
220
|
+
{
|
|
221
|
+
kind: SpanKind.CLIENT,
|
|
222
|
+
attributes: {
|
|
223
|
+
'actor.name': actorName,
|
|
224
|
+
'actor.class': actorClassName,
|
|
225
|
+
'db.system': 'durable_object_storage',
|
|
226
|
+
'db.operation': 'delete',
|
|
227
|
+
'db.key': key,
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
async (span) => {
|
|
231
|
+
try {
|
|
232
|
+
const result = await value.call(target, key);
|
|
233
|
+
span.setAttributes({
|
|
234
|
+
'db.result.deleted': result,
|
|
235
|
+
});
|
|
236
|
+
span.setStatus({ code: SpanStatusCode.OK });
|
|
237
|
+
return result;
|
|
238
|
+
} catch (error) {
|
|
239
|
+
span.recordException(error as Error);
|
|
240
|
+
span.setStatus({
|
|
241
|
+
code: SpanStatusCode.ERROR,
|
|
242
|
+
message: error instanceof Error ? error.message : String(error),
|
|
243
|
+
});
|
|
244
|
+
throw error;
|
|
245
|
+
} finally {
|
|
246
|
+
span.end();
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
);
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Bind other methods to the target
|
|
254
|
+
if (typeof value === 'function') {
|
|
255
|
+
return value.bind(target);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return value;
|
|
259
|
+
},
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
return wrap(storage, storageHandler);
|
|
263
|
+
}
|