@moostjs/otel 0.6.48 → 0.6.50
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/dist/index.cjs +47 -34
- package/dist/index.d.ts +1 -2
- package/dist/index.mjs +47 -34
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -184,6 +184,29 @@ function readHandlerOtelMeta(controller, method) {
|
|
|
184
184
|
}
|
|
185
185
|
return meta;
|
|
186
186
|
}
|
|
187
|
+
/** Root spans already owned by a Moost event — never attached to (renamed, re-attributed) twice. */ const claimedSpans = /* @__PURE__ */ new WeakSet();
|
|
188
|
+
/**
|
|
189
|
+
* Whether the active span is the server span of the http instrumentation, not yet owned by a
|
|
190
|
+
* Moost event. Anything else active (a lifecycle span of a running event, a client span) is a
|
|
191
|
+
* parent, not the request's own span.
|
|
192
|
+
*/ function isInstrumentationServerSpan(span) {
|
|
193
|
+
return !!span && !claimedSpans.has(span) && span.kind === _opentelemetry_api.SpanKind.SERVER;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* The controller context of the current event, or `undefined` while no handler is resolved yet
|
|
197
|
+
* (an unmatched route reports `Handler:not_found` before any controller context exists).
|
|
198
|
+
*/ function readControllerContext() {
|
|
199
|
+
const cc = (0, moost.useControllerContext)();
|
|
200
|
+
try {
|
|
201
|
+
return {
|
|
202
|
+
controller: cc.getController(),
|
|
203
|
+
method: cc.getMethod(),
|
|
204
|
+
route: cc.getRoute()
|
|
205
|
+
};
|
|
206
|
+
} catch {
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
187
210
|
/** Context injector that wraps Moost lifecycle hooks with OpenTelemetry spans and records metrics. */ var SpanInjector = class extends moost.ContextInjector {
|
|
188
211
|
with(name, attributes, cb) {
|
|
189
212
|
const fn = typeof attributes === "function" ? attributes : cb;
|
|
@@ -206,45 +229,39 @@ function readHandlerOtelMeta(controller, method) {
|
|
|
206
229
|
const res = this.getResponse();
|
|
207
230
|
if (res) {
|
|
208
231
|
const originalWriteHead = res.writeHead;
|
|
209
|
-
|
|
210
|
-
res._statusCode =
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
return originalWriteHead.apply(res, [
|
|
214
|
-
arg0,
|
|
215
|
-
arg1,
|
|
216
|
-
arg2
|
|
217
|
-
]);
|
|
218
|
-
} });
|
|
232
|
+
res.writeHead = (...args) => {
|
|
233
|
+
res._statusCode = args[0];
|
|
234
|
+
return originalWriteHead.apply(res, args);
|
|
235
|
+
};
|
|
219
236
|
}
|
|
220
237
|
}
|
|
221
238
|
startEvent(eventType, cb) {
|
|
222
239
|
if (eventType === "init") return cb();
|
|
223
240
|
const { registerSpan } = useOtelContext();
|
|
224
|
-
|
|
225
|
-
if (
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
241
|
+
const isHttp = eventType === _moostjs_event_http.httpKind.name;
|
|
242
|
+
if (isHttp) this.patchRsponse();
|
|
243
|
+
const active = isHttp ? _opentelemetry_api.trace.getActiveSpan() : void 0;
|
|
244
|
+
const attached = isInstrumentationServerSpan(active) ? active : void 0;
|
|
245
|
+
const span = attached ?? tracer.startSpan(`${eventType} Event`, isHttp && !active ? { kind: _opentelemetry_api.SpanKind.SERVER } : void 0);
|
|
246
|
+
claimedSpans.add(span);
|
|
247
|
+
registerSpan(span);
|
|
248
|
+
return this.withSpan(span, cb, {
|
|
249
|
+
withMetrics: true,
|
|
250
|
+
endSpan: !attached
|
|
251
|
+
});
|
|
235
252
|
}
|
|
236
253
|
getEventType() {
|
|
237
254
|
const ctx = (0, moost.current)();
|
|
238
255
|
return ctx.has(moost.eventTypeKey) ? ctx.get(moost.eventTypeKey) : void 0;
|
|
239
256
|
}
|
|
240
257
|
getIgnoreSpan() {
|
|
241
|
-
const
|
|
242
|
-
return readHandlerOtelMeta(
|
|
258
|
+
const cc = readControllerContext();
|
|
259
|
+
return readHandlerOtelMeta(cc?.controller, cc?.method).ignoreSpan;
|
|
243
260
|
}
|
|
244
261
|
getControllerHandlerMeta() {
|
|
245
|
-
const
|
|
246
|
-
const methodName =
|
|
247
|
-
const meta = readHandlerOtelMeta(
|
|
262
|
+
const cc = readControllerContext();
|
|
263
|
+
const methodName = cc?.method;
|
|
264
|
+
const meta = readHandlerOtelMeta(cc?.controller, methodName);
|
|
248
265
|
return {
|
|
249
266
|
ignoreMeter: meta.ignoreMeter,
|
|
250
267
|
ignoreSpan: meta.ignoreSpan,
|
|
@@ -255,7 +272,7 @@ function readHandlerOtelMeta(controller, method) {
|
|
|
255
272
|
"moost.handler_label": meta.label,
|
|
256
273
|
"moost.handler_id": meta.id,
|
|
257
274
|
"moost.ignore": meta.ignoreSpan,
|
|
258
|
-
"moost.route":
|
|
275
|
+
"moost.route": cc?.route,
|
|
259
276
|
"moost.event_type": this.getEventType()
|
|
260
277
|
}
|
|
261
278
|
};
|
|
@@ -273,10 +290,7 @@ function readHandlerOtelMeta(controller, method) {
|
|
|
273
290
|
const chm = this.getControllerHandlerMeta();
|
|
274
291
|
const span = getSpan();
|
|
275
292
|
if (span) {
|
|
276
|
-
if (this.getEventType() === _moostjs_event_http.httpKind.
|
|
277
|
-
const req = this.getRequest();
|
|
278
|
-
span.updateName(`${req?.method || ""} ${req?.url}`);
|
|
279
|
-
}
|
|
293
|
+
if (this.getEventType() === _moostjs_event_http.httpKind.name) span.updateName(this.getRequest()?.method || "HTTP");
|
|
280
294
|
}
|
|
281
295
|
this.startEventMetrics(chm.attrs, route);
|
|
282
296
|
} else if (name === "Controller:registered") {
|
|
@@ -286,7 +300,7 @@ function readHandlerOtelMeta(controller, method) {
|
|
|
286
300
|
const span = getSpan();
|
|
287
301
|
if (span) {
|
|
288
302
|
span.setAttributes(chm.attrs);
|
|
289
|
-
if (chm.attrs["moost.event_type"] === _moostjs_event_http.httpKind.
|
|
303
|
+
if (chm.attrs["moost.event_type"] === _moostjs_event_http.httpKind.name) span.updateName(`${this.getRequest()?.method || ""} ${_route || "<unresolved>"}`);
|
|
290
304
|
else span.updateName(`${chm.attrs["moost.event_type"]} ${_route || "<unresolved>"}`);
|
|
291
305
|
}
|
|
292
306
|
}
|
|
@@ -321,8 +335,7 @@ function readHandlerOtelMeta(controller, method) {
|
|
|
321
335
|
"moost.event_type": a["moost.event_type"],
|
|
322
336
|
"moost.is_error": error ? 1 : 0
|
|
323
337
|
};
|
|
324
|
-
if (a["moost.event_type"] === _moostjs_event_http.httpKind.
|
|
325
|
-
if (!attrs.route) attrs.route = this.getRequest()?.url || "";
|
|
338
|
+
if (a["moost.event_type"] === _moostjs_event_http.httpKind.name) {
|
|
326
339
|
attrs["http.status_code"] = this.getResponse()?._statusCode || 0;
|
|
327
340
|
attrs["moost.is_error"] = attrs["moost.is_error"] || attrs["http.status_code"] > 399 ? 1 : 0;
|
|
328
341
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -135,7 +135,7 @@ declare class SpanInjector extends ContextInjector<TContextInjectorHook> {
|
|
|
135
135
|
'moost.handler_label': string | undefined;
|
|
136
136
|
'moost.handler_id': string | undefined;
|
|
137
137
|
'moost.ignore': boolean | undefined;
|
|
138
|
-
'moost.route': string;
|
|
138
|
+
'moost.route': string | undefined;
|
|
139
139
|
'moost.event_type': string | undefined;
|
|
140
140
|
};
|
|
141
141
|
};
|
|
@@ -149,7 +149,6 @@ declare class SpanInjector extends ContextInjector<TContextInjectorHook> {
|
|
|
149
149
|
getRequest(): http.IncomingMessage | undefined;
|
|
150
150
|
getResponse(): (ServerResponse<http.IncomingMessage> & {
|
|
151
151
|
_statusCode?: number;
|
|
152
|
-
_contentLength?: number;
|
|
153
152
|
}) | undefined;
|
|
154
153
|
}
|
|
155
154
|
|
package/dist/index.mjs
CHANGED
|
@@ -183,6 +183,29 @@ function readHandlerOtelMeta(controller, method) {
|
|
|
183
183
|
}
|
|
184
184
|
return meta;
|
|
185
185
|
}
|
|
186
|
+
/** Root spans already owned by a Moost event — never attached to (renamed, re-attributed) twice. */ const claimedSpans = /* @__PURE__ */ new WeakSet();
|
|
187
|
+
/**
|
|
188
|
+
* Whether the active span is the server span of the http instrumentation, not yet owned by a
|
|
189
|
+
* Moost event. Anything else active (a lifecycle span of a running event, a client span) is a
|
|
190
|
+
* parent, not the request's own span.
|
|
191
|
+
*/ function isInstrumentationServerSpan(span) {
|
|
192
|
+
return !!span && !claimedSpans.has(span) && span.kind === SpanKind.SERVER;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* The controller context of the current event, or `undefined` while no handler is resolved yet
|
|
196
|
+
* (an unmatched route reports `Handler:not_found` before any controller context exists).
|
|
197
|
+
*/ function readControllerContext() {
|
|
198
|
+
const cc = useControllerContext();
|
|
199
|
+
try {
|
|
200
|
+
return {
|
|
201
|
+
controller: cc.getController(),
|
|
202
|
+
method: cc.getMethod(),
|
|
203
|
+
route: cc.getRoute()
|
|
204
|
+
};
|
|
205
|
+
} catch {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
186
209
|
/** Context injector that wraps Moost lifecycle hooks with OpenTelemetry spans and records metrics. */ var SpanInjector = class extends ContextInjector {
|
|
187
210
|
with(name, attributes, cb) {
|
|
188
211
|
const fn = typeof attributes === "function" ? attributes : cb;
|
|
@@ -205,45 +228,39 @@ function readHandlerOtelMeta(controller, method) {
|
|
|
205
228
|
const res = this.getResponse();
|
|
206
229
|
if (res) {
|
|
207
230
|
const originalWriteHead = res.writeHead;
|
|
208
|
-
|
|
209
|
-
res._statusCode =
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
return originalWriteHead.apply(res, [
|
|
213
|
-
arg0,
|
|
214
|
-
arg1,
|
|
215
|
-
arg2
|
|
216
|
-
]);
|
|
217
|
-
} });
|
|
231
|
+
res.writeHead = (...args) => {
|
|
232
|
+
res._statusCode = args[0];
|
|
233
|
+
return originalWriteHead.apply(res, args);
|
|
234
|
+
};
|
|
218
235
|
}
|
|
219
236
|
}
|
|
220
237
|
startEvent(eventType, cb) {
|
|
221
238
|
if (eventType === "init") return cb();
|
|
222
239
|
const { registerSpan } = useOtelContext();
|
|
223
|
-
|
|
224
|
-
if (
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
240
|
+
const isHttp = eventType === httpKind.name;
|
|
241
|
+
if (isHttp) this.patchRsponse();
|
|
242
|
+
const active = isHttp ? trace.getActiveSpan() : void 0;
|
|
243
|
+
const attached = isInstrumentationServerSpan(active) ? active : void 0;
|
|
244
|
+
const span = attached ?? tracer.startSpan(`${eventType} Event`, isHttp && !active ? { kind: SpanKind.SERVER } : void 0);
|
|
245
|
+
claimedSpans.add(span);
|
|
246
|
+
registerSpan(span);
|
|
247
|
+
return this.withSpan(span, cb, {
|
|
248
|
+
withMetrics: true,
|
|
249
|
+
endSpan: !attached
|
|
250
|
+
});
|
|
234
251
|
}
|
|
235
252
|
getEventType() {
|
|
236
253
|
const ctx = current();
|
|
237
254
|
return ctx.has(eventTypeKey) ? ctx.get(eventTypeKey) : void 0;
|
|
238
255
|
}
|
|
239
256
|
getIgnoreSpan() {
|
|
240
|
-
const
|
|
241
|
-
return readHandlerOtelMeta(
|
|
257
|
+
const cc = readControllerContext();
|
|
258
|
+
return readHandlerOtelMeta(cc?.controller, cc?.method).ignoreSpan;
|
|
242
259
|
}
|
|
243
260
|
getControllerHandlerMeta() {
|
|
244
|
-
const
|
|
245
|
-
const methodName =
|
|
246
|
-
const meta = readHandlerOtelMeta(
|
|
261
|
+
const cc = readControllerContext();
|
|
262
|
+
const methodName = cc?.method;
|
|
263
|
+
const meta = readHandlerOtelMeta(cc?.controller, methodName);
|
|
247
264
|
return {
|
|
248
265
|
ignoreMeter: meta.ignoreMeter,
|
|
249
266
|
ignoreSpan: meta.ignoreSpan,
|
|
@@ -254,7 +271,7 @@ function readHandlerOtelMeta(controller, method) {
|
|
|
254
271
|
"moost.handler_label": meta.label,
|
|
255
272
|
"moost.handler_id": meta.id,
|
|
256
273
|
"moost.ignore": meta.ignoreSpan,
|
|
257
|
-
"moost.route":
|
|
274
|
+
"moost.route": cc?.route,
|
|
258
275
|
"moost.event_type": this.getEventType()
|
|
259
276
|
}
|
|
260
277
|
};
|
|
@@ -272,10 +289,7 @@ function readHandlerOtelMeta(controller, method) {
|
|
|
272
289
|
const chm = this.getControllerHandlerMeta();
|
|
273
290
|
const span = getSpan();
|
|
274
291
|
if (span) {
|
|
275
|
-
if (this.getEventType() === httpKind.
|
|
276
|
-
const req = this.getRequest();
|
|
277
|
-
span.updateName(`${req?.method || ""} ${req?.url}`);
|
|
278
|
-
}
|
|
292
|
+
if (this.getEventType() === httpKind.name) span.updateName(this.getRequest()?.method || "HTTP");
|
|
279
293
|
}
|
|
280
294
|
this.startEventMetrics(chm.attrs, route);
|
|
281
295
|
} else if (name === "Controller:registered") {
|
|
@@ -285,7 +299,7 @@ function readHandlerOtelMeta(controller, method) {
|
|
|
285
299
|
const span = getSpan();
|
|
286
300
|
if (span) {
|
|
287
301
|
span.setAttributes(chm.attrs);
|
|
288
|
-
if (chm.attrs["moost.event_type"] === httpKind.
|
|
302
|
+
if (chm.attrs["moost.event_type"] === httpKind.name) span.updateName(`${this.getRequest()?.method || ""} ${_route || "<unresolved>"}`);
|
|
289
303
|
else span.updateName(`${chm.attrs["moost.event_type"]} ${_route || "<unresolved>"}`);
|
|
290
304
|
}
|
|
291
305
|
}
|
|
@@ -320,8 +334,7 @@ function readHandlerOtelMeta(controller, method) {
|
|
|
320
334
|
"moost.event_type": a["moost.event_type"],
|
|
321
335
|
"moost.is_error": error ? 1 : 0
|
|
322
336
|
};
|
|
323
|
-
if (a["moost.event_type"] === httpKind.
|
|
324
|
-
if (!attrs.route) attrs.route = this.getRequest()?.url || "";
|
|
337
|
+
if (a["moost.event_type"] === httpKind.name) {
|
|
325
338
|
attrs["http.status_code"] = this.getResponse()?._statusCode || 0;
|
|
326
339
|
attrs["moost.is_error"] = attrs["moost.is_error"] || attrs["http.status_code"] > 399 ? 1 : 0;
|
|
327
340
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moostjs/otel",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.50",
|
|
4
4
|
"description": "@moostjs/otel",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"composables",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"vitest": "3.2.7"
|
|
46
46
|
},
|
|
47
47
|
"peerDependencies": {
|
|
48
|
-
"@wooksjs/event-core": "^0.7.
|
|
49
|
-
"@moostjs/event-http": "^0.6.
|
|
50
|
-
"moost": "^0.6.
|
|
48
|
+
"@wooksjs/event-core": "^0.7.28",
|
|
49
|
+
"@moostjs/event-http": "^0.6.50",
|
|
50
|
+
"moost": "^0.6.50"
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|
|
53
53
|
"pub": "pnpm publish --access public",
|