@moostjs/otel 0.4.15 → 0.4.17

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 CHANGED
@@ -117,6 +117,53 @@ function getMoostMetrics() {
117
117
  return moostMetrics;
118
118
  }
119
119
 
120
+ function withSpan(span, cb, postProcess) {
121
+ const _span = typeof span.name === 'string' && !span.spanContext
122
+ ? span
123
+ : api.trace
124
+ .getTracer('default')
125
+ .startSpan(span.name, span.options);
126
+ let result = undefined;
127
+ const finalizeSpan = (e, r) => {
128
+ if (e) {
129
+ _span.recordException(e);
130
+ _span.setStatus({
131
+ code: api.SpanStatusCode.ERROR,
132
+ message: e.message || 'Unknown Error',
133
+ });
134
+ }
135
+ if (postProcess) {
136
+ postProcess(_span, e, r);
137
+ }
138
+ else {
139
+ _span.end();
140
+ }
141
+ };
142
+ api.context.with(api.trace.setSpan(api.context.active(), _span), () => {
143
+ try {
144
+ result = cb();
145
+ }
146
+ catch (error) {
147
+ finalizeSpan(error, undefined);
148
+ throw error;
149
+ }
150
+ if (result instanceof Promise) {
151
+ result
152
+ .then(r => {
153
+ finalizeSpan(undefined, r);
154
+ return r;
155
+ })
156
+ .catch(error => {
157
+ finalizeSpan(error, undefined);
158
+ });
159
+ }
160
+ else {
161
+ finalizeSpan(undefined, result);
162
+ }
163
+ });
164
+ return result;
165
+ }
166
+
120
167
  const tracer = api.trace.getTracer('moost-tracer');
121
168
  class SpanInjector extends moost.ContextInjector {
122
169
  constructor() {
@@ -135,10 +182,11 @@ class SpanInjector extends moost.ContextInjector {
135
182
  }
136
183
  else {
137
184
  const span = tracer.startSpan(name, {
185
+ kind: api.SpanKind.INTERNAL,
138
186
  attributes: attrs,
139
187
  });
140
188
  return this.withSpan(span, fn, {
141
- rootSpan: false,
189
+ withMetrics: false,
142
190
  endSpan: true,
143
191
  });
144
192
  }
@@ -174,7 +222,7 @@ class SpanInjector extends moost.ContextInjector {
174
222
  if (span) {
175
223
  registerSpan(span);
176
224
  return this.withSpan(span, cb, {
177
- rootSpan: true,
225
+ withMetrics: true,
178
226
  endSpan: eventType !== 'HTTP',
179
227
  });
180
228
  }
@@ -252,48 +300,20 @@ class SpanInjector extends moost.ContextInjector {
252
300
  }
253
301
  }
254
302
  withSpan(span, cb, opts) {
255
- let result;
256
- let exception;
257
- const endSpan = (error) => {
258
- if (error) {
259
- span.recordException(error);
303
+ return withSpan(span, cb, (_span, exception, result) => {
304
+ if (result instanceof Error) {
305
+ _span.recordException(result);
260
306
  }
261
- if (opts.rootSpan) {
307
+ if (opts.withMetrics) {
262
308
  const chm = this.getControllerHandlerMeta();
263
309
  if (!chm.ignoreMeter) {
264
- this.endEventMetrics(chm.attrs, error);
310
+ this.endEventMetrics(chm.attrs, result instanceof Error ? result : exception);
265
311
  }
266
312
  }
267
313
  if (opts.endSpan) {
268
- span.end();
269
- }
270
- };
271
- api.context.with(api.trace.setSpan(api.context.active(), span), () => {
272
- try {
273
- result = cb();
274
- }
275
- catch (error) {
276
- exception = error;
277
- endSpan(exception);
314
+ _span.end();
278
315
  }
279
316
  });
280
- const ret = result;
281
- if (!exception) {
282
- if (ret && ret instanceof Promise) {
283
- ret
284
- .then(r => {
285
- endSpan(r instanceof Error ? r : undefined);
286
- return r;
287
- })
288
- .catch(error => {
289
- endSpan(error);
290
- });
291
- }
292
- else {
293
- endSpan(ret instanceof Error ? ret : undefined);
294
- }
295
- }
296
- return ret;
297
317
  }
298
318
  startEventMetrics(a, route) {
299
319
  if (a['moost.event_type'] === 'HTTP') {
@@ -1220,3 +1240,4 @@ exports.useOtelContext = useOtelContext;
1220
1240
  exports.useOtelPropagation = useOtelPropagation;
1221
1241
  exports.useSpan = useSpan;
1222
1242
  exports.useTrace = useTrace;
1243
+ exports.withSpan = withSpan;
package/dist/index.d.ts CHANGED
@@ -230,7 +230,7 @@ declare class SpanInjector extends ContextInjector<TContextInjectorHook> {
230
230
  };
231
231
  hook(method: string, name: 'Handler:not_found' | 'Handler:routed' | 'Controller:registered', route?: string): void;
232
232
  withSpan<T>(span: Span, cb: () => T, opts: {
233
- rootSpan: boolean;
233
+ withMetrics: boolean;
234
234
  endSpan: boolean;
235
235
  }): T;
236
236
  startEventMetrics(a: Record<string, string | number | boolean | undefined>, route?: string): void;
@@ -242,4 +242,23 @@ declare class SpanInjector extends ContextInjector<TContextInjectorHook> {
242
242
  }) | undefined;
243
243
  }
244
244
 
245
- export { MoostBatchSpanProcessor, MoostSimpleSpanProcessor, OtelIgnoreMeter, OtelIgnoreSpan, SpanInjector, type TOtelContext, type TOtelMate, enableOtelForMoost, getOtelMate, shouldSpanBeIgnored, useOtelContext, useOtelPropagation, useSpan, useTrace };
245
+ type TPostSpanProcessFn<T> = (span: Span, exception: Error | undefined, result: Awaited<T> | undefined) => void;
246
+ interface TSpanInput {
247
+ name: string;
248
+ options?: SpanOptions;
249
+ }
250
+ /**
251
+ * Starts or continues a span, executes the callback within the span's context,
252
+ * and handles span completion and error recording. Supports both synchronous and asynchronous callbacks.
253
+ * An optional post-processing callback can be used to enrich the span before it ends.
254
+ *
255
+ * @template T
256
+ * @param {TSpanInput | Span} span - The span input containing name and options, or an existing span.
257
+ * @param {() => T} cb - The callback function to execute within the span's context.
258
+ * @param {TPostSpanProcessFn<T>=} postProcess - An optional post-processing callback to enrich the span before it ends. **CAUTION: When used, you must end the span yourself `span.end()`.**
259
+ * @returns {T} The result of the callback function.
260
+ * @throws {Error} Will throw an error if the callback function throws.
261
+ */
262
+ declare function withSpan<T>(span: TSpanInput | Span, cb: () => T, postProcess?: TPostSpanProcessFn<T>): T;
263
+
264
+ export { MoostBatchSpanProcessor, MoostSimpleSpanProcessor, OtelIgnoreMeter, OtelIgnoreSpan, SpanInjector, type TOtelContext, type TOtelMate, type TPostSpanProcessFn, type TSpanInput, enableOtelForMoost, getOtelMate, shouldSpanBeIgnored, useOtelContext, useOtelPropagation, useSpan, useTrace, withSpan };
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { trace, context, metrics } from '@opentelemetry/api';
1
+ import { trace, context, metrics, SpanStatusCode, SpanKind } from '@opentelemetry/api';
2
2
  import { useAsyncEventContext as useAsyncEventContext$1, ContextInjector, useControllerContext, getConstructor as getConstructor$2, replaceContextInjector } from 'moost';
3
3
  import { randomUUID } from 'crypto';
4
4
  import { AsyncLocalStorage } from 'node:async_hooks';
@@ -115,6 +115,53 @@ function getMoostMetrics() {
115
115
  return moostMetrics;
116
116
  }
117
117
 
118
+ function withSpan(span, cb, postProcess) {
119
+ const _span = typeof span.name === 'string' && !span.spanContext
120
+ ? span
121
+ : trace
122
+ .getTracer('default')
123
+ .startSpan(span.name, span.options);
124
+ let result = undefined;
125
+ const finalizeSpan = (e, r) => {
126
+ if (e) {
127
+ _span.recordException(e);
128
+ _span.setStatus({
129
+ code: SpanStatusCode.ERROR,
130
+ message: e.message || 'Unknown Error',
131
+ });
132
+ }
133
+ if (postProcess) {
134
+ postProcess(_span, e, r);
135
+ }
136
+ else {
137
+ _span.end();
138
+ }
139
+ };
140
+ context.with(trace.setSpan(context.active(), _span), () => {
141
+ try {
142
+ result = cb();
143
+ }
144
+ catch (error) {
145
+ finalizeSpan(error, undefined);
146
+ throw error;
147
+ }
148
+ if (result instanceof Promise) {
149
+ result
150
+ .then(r => {
151
+ finalizeSpan(undefined, r);
152
+ return r;
153
+ })
154
+ .catch(error => {
155
+ finalizeSpan(error, undefined);
156
+ });
157
+ }
158
+ else {
159
+ finalizeSpan(undefined, result);
160
+ }
161
+ });
162
+ return result;
163
+ }
164
+
118
165
  const tracer = trace.getTracer('moost-tracer');
119
166
  class SpanInjector extends ContextInjector {
120
167
  constructor() {
@@ -133,10 +180,11 @@ class SpanInjector extends ContextInjector {
133
180
  }
134
181
  else {
135
182
  const span = tracer.startSpan(name, {
183
+ kind: SpanKind.INTERNAL,
136
184
  attributes: attrs,
137
185
  });
138
186
  return this.withSpan(span, fn, {
139
- rootSpan: false,
187
+ withMetrics: false,
140
188
  endSpan: true,
141
189
  });
142
190
  }
@@ -172,7 +220,7 @@ class SpanInjector extends ContextInjector {
172
220
  if (span) {
173
221
  registerSpan(span);
174
222
  return this.withSpan(span, cb, {
175
- rootSpan: true,
223
+ withMetrics: true,
176
224
  endSpan: eventType !== 'HTTP',
177
225
  });
178
226
  }
@@ -250,48 +298,20 @@ class SpanInjector extends ContextInjector {
250
298
  }
251
299
  }
252
300
  withSpan(span, cb, opts) {
253
- let result;
254
- let exception;
255
- const endSpan = (error) => {
256
- if (error) {
257
- span.recordException(error);
301
+ return withSpan(span, cb, (_span, exception, result) => {
302
+ if (result instanceof Error) {
303
+ _span.recordException(result);
258
304
  }
259
- if (opts.rootSpan) {
305
+ if (opts.withMetrics) {
260
306
  const chm = this.getControllerHandlerMeta();
261
307
  if (!chm.ignoreMeter) {
262
- this.endEventMetrics(chm.attrs, error);
308
+ this.endEventMetrics(chm.attrs, result instanceof Error ? result : exception);
263
309
  }
264
310
  }
265
311
  if (opts.endSpan) {
266
- span.end();
267
- }
268
- };
269
- context.with(trace.setSpan(context.active(), span), () => {
270
- try {
271
- result = cb();
272
- }
273
- catch (error) {
274
- exception = error;
275
- endSpan(exception);
312
+ _span.end();
276
313
  }
277
314
  });
278
- const ret = result;
279
- if (!exception) {
280
- if (ret && ret instanceof Promise) {
281
- ret
282
- .then(r => {
283
- endSpan(r instanceof Error ? r : undefined);
284
- return r;
285
- })
286
- .catch(error => {
287
- endSpan(error);
288
- });
289
- }
290
- else {
291
- endSpan(ret instanceof Error ? ret : undefined);
292
- }
293
- }
294
- return ret;
295
315
  }
296
316
  startEventMetrics(a, route) {
297
317
  if (a['moost.event_type'] === 'HTTP') {
@@ -1206,4 +1226,4 @@ class MoostSimpleSpanProcessor extends SimpleSpanProcessor {
1206
1226
  }
1207
1227
  }
1208
1228
 
1209
- export { MoostBatchSpanProcessor, MoostSimpleSpanProcessor, OtelIgnoreMeter, OtelIgnoreSpan, SpanInjector, enableOtelForMoost, getOtelMate, shouldSpanBeIgnored, useOtelContext, useOtelPropagation, useSpan, useTrace };
1229
+ export { MoostBatchSpanProcessor, MoostSimpleSpanProcessor, OtelIgnoreMeter, OtelIgnoreSpan, SpanInjector, enableOtelForMoost, getOtelMate, shouldSpanBeIgnored, useOtelContext, useOtelPropagation, useSpan, useTrace, withSpan };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@moostjs/otel",
3
- "version": "0.4.15",
3
+ "version": "0.4.17",
4
4
  "description": "@moostjs/otel",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.mjs",
@@ -39,6 +39,6 @@
39
39
  "dependencies": {
40
40
  "@opentelemetry/api": "^1.9.0",
41
41
  "@opentelemetry/sdk-trace-base": "^1.25.1",
42
- "moost": "0.4.15"
42
+ "moost": "0.4.17"
43
43
  }
44
44
  }