@vtvlive/interactive-apm 0.0.13 → 0.0.15

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.
@@ -1,4 +1,4 @@
1
- import { ISpan, SpanKind } from "../types/apm.types";
1
+ import { ISpan, SpanAttributes, SpanAttributeValue, SpanKind } from "../types/apm.types";
2
2
  /**
3
3
  * Interface chung cho APM Tracing Provider
4
4
  * Cho phép switch giữa OpenTelemetry và Elastic APM thông qua DI
@@ -16,7 +16,7 @@ export interface ITracingProvider {
16
16
  * @param spanKind Loại span (INTERNAL, SERVER, CLIENT, PRODUCER, CONSUMER, WEBSOCKET, OTHER)
17
17
  * @returns Span object - cần gọi end() khi hoàn thành
18
18
  */
19
- startSpan(name: string, attributes?: Record<string, string | number>, spanKind?: SpanKind): ISpan | null;
19
+ startSpan(name: string, attributes?: SpanAttributes, spanKind?: SpanKind): ISpan | null;
20
20
  /**
21
21
  * Thực thi function với context tracing (auto-close span)
22
22
  * @param name Tên của span
@@ -24,7 +24,7 @@ export interface ITracingProvider {
24
24
  * @param attributes Các attributes metadata
25
25
  * @returns Kết quả của function
26
26
  */
27
- startSpanWithParent<T>(name: string, fn: (span: ISpan | null) => Promise<T>, attributes?: Record<string, string | number>): Promise<T>;
27
+ startSpanWithParent<T>(name: string, fn: (span: ISpan | null) => Promise<T>, attributes?: SpanAttributes): Promise<T>;
28
28
  /**
29
29
  * Capture error vào active span hiện tại
30
30
  * @param error Error object
@@ -35,7 +35,13 @@ export interface ITracingProvider {
35
35
  * @param key Tên attribute
36
36
  * @param value Giá trị attribute
37
37
  */
38
- setAttribute(key: string, value: string | number): void;
38
+ setAttribute(key: string, value: SpanAttributeValue): void;
39
+ /**
40
+ * Set label/attribute cho active transaction hiện tại
41
+ * @param key Tên label
42
+ * @param value Giá trị label
43
+ */
44
+ setTransactionLabel(key: string, value: SpanAttributeValue): void;
39
45
  /**
40
46
  * Force flush all pending spans
41
47
  */
@@ -1 +1 @@
1
- {"version":3,"file":"tracing-provider.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/tracing-provider.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,UAAU,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7C;;;;;;OAMG;IACH,SAAS,CACP,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,EAC5C,QAAQ,CAAC,EAAE,QAAQ,GAClB,KAAK,GAAG,IAAI,CAAC;IAEhB;;;;;;OAMG;IACH,mBAAmB,CAAC,CAAC,EACnB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAC3C,OAAO,CAAC,CAAC,CAAC,CAAC;IAEd;;;OAGG;IACH,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAEjC;;;;OAIG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAExD;;OAEG;IACH,UAAU,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7B;;;OAGG;IACH,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAErD;;OAEG;IACH,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B"}
1
+ {"version":3,"file":"tracing-provider.interface.d.ts","sourceRoot":"","sources":["../../src/interfaces/tracing-provider.interface.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEzF;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,UAAU,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7C;;;;;;OAMG;IACH,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,IAAI,CAAC;IAExF;;;;;;OAMG;IACH,mBAAmB,CAAC,CAAC,EACnB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,UAAU,CAAC,EAAE,cAAc,GAC1B,OAAO,CAAC,CAAC,CAAC,CAAC;IAEd;;;OAGG;IACH,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IAEjC;;;;OAIG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAE3D;;;;OAIG;IACH,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAElE;;OAEG;IACH,UAAU,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7B;;;OAGG;IACH,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAErD;;OAEG;IACH,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B"}
@@ -1,12 +1,12 @@
1
1
  import { SpanKind } from "../types/apm-provider.type";
2
2
  import { ITracingProvider } from "../interfaces/tracing-provider.interface";
3
- import { ISpan } from "../types/apm.types";
3
+ import { ISpan, SpanAttributes, SpanAttributeValue } from "../types/apm.types";
4
4
  /**
5
5
  * Elastic APM specific span interface
6
6
  */
7
7
  export interface IElasticApmSpan extends ISpan {
8
8
  /** Set a label on the span */
9
- setLabel(key: string, value: string): void;
9
+ setLabel(key: string, value: string | number | boolean, stringify?: boolean): void;
10
10
  /** Set the span type */
11
11
  setType(type: string): void;
12
12
  /** Set the outcome (success, failure) */
@@ -22,6 +22,8 @@ export declare class ElasticApmTracingProvider implements ITracingProvider {
22
22
  private apm;
23
23
  private readonly serviceName;
24
24
  private readonly environment;
25
+ private static isElasticLabelValue;
26
+ private static setElasticLabel;
25
27
  constructor(config?: {
26
28
  serviceName?: string;
27
29
  environment?: string;
@@ -43,19 +45,23 @@ export declare class ElasticApmTracingProvider implements ITracingProvider {
43
45
  /**
44
46
  * Bắt đầu một span mới
45
47
  */
46
- startSpan(name: string, attributes?: Record<string, string | number>, spanKind?: SpanKind): IElasticApmSpan | null;
48
+ startSpan(name: string, attributes?: SpanAttributes, spanKind?: SpanKind): IElasticApmSpan | null;
47
49
  /**
48
50
  * Thực thi function với tracing context
49
51
  */
50
- startSpanWithParent<T>(name: string, fn: (span: ISpan | null) => Promise<T>, attributes?: Record<string, string | number>): Promise<T>;
52
+ startSpanWithParent<T>(name: string, fn: (span: ISpan | null) => Promise<T>, attributes?: SpanAttributes): Promise<T>;
51
53
  /**
52
54
  * Capture error vào APM
53
55
  */
54
56
  captureError(error: Error): void;
55
57
  /**
56
- * Set label cho current transaction/span
58
+ * Set label cho current span
57
59
  */
58
- setAttribute(key: string, value: string | number): void;
60
+ setAttribute(key: string, value: SpanAttributeValue): void;
61
+ /**
62
+ * Set label cho current transaction
63
+ */
64
+ setTransactionLabel(key: string, value: SpanAttributeValue): void;
59
65
  /**
60
66
  * End span manually
61
67
  */
@@ -1 +1 @@
1
- {"version":3,"file":"elastic-apm.tracing-provider.d.ts","sourceRoot":"","sources":["../../src/providers/elastic-apm.tracing-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAU3C;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,KAAK;IAC5C,8BAA8B;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAE3C,wBAAwB;IACxB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5B,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,mBAAmB;IACnB,GAAG,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CAC7B;AA0BD;;;GAGG;AACH,qBAAa,yBAA0B,YAAW,gBAAgB;IAChE,OAAO,CAAC,GAAG,CAAiC;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAGnC,MAAM,GAAE;QACN,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,cAAc,CAAC,EAAE,MAAM,CAAC;KACpB;IAOR;;;OAGG;IACG,UAAU,CAAC,MAAM,CAAC,EAAE;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,GAAG,OAAO,CAAC,IAAI,CAAC;IAiDjB;;OAEG;IACH,SAAS,CACP,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,EAC5C,QAAQ,GAAE,QAA4B,GACrC,eAAe,GAAG,IAAI;IAiHzB;;OAEG;IACG,mBAAmB,CAAC,CAAC,EACzB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAC3C,OAAO,CAAC,CAAC,CAAC;IAsBb;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAMhC;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAOvD;;OAEG;IACH,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI;IAOpD;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB/B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAmBzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAe5B"}
1
+ {"version":3,"file":"elastic-apm.tracing-provider.d.ts","sourceRoot":"","sources":["../../src/providers/elastic-apm.tracing-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAU/E;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,KAAK;IAC5C,8BAA8B;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,SAAS,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAEnF,wBAAwB;IACxB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5B,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,mBAAmB;IACnB,GAAG,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CAC7B;AA2BD;;;GAGG;AACH,qBAAa,yBAA0B,YAAW,gBAAgB;IAChE,OAAO,CAAC,GAAG,CAAiC;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IAErC,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAMlC,OAAO,CAAC,MAAM,CAAC,eAAe;gBAkB5B,MAAM,GAAE;QACN,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,cAAc,CAAC,EAAE,MAAM,CAAC;KACpB;IAOR;;;OAGG;IACG,UAAU,CAAC,MAAM,CAAC,EAAE;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,GAAG,OAAO,CAAC,IAAI,CAAC;IAiDjB;;OAEG;IACH,SAAS,CACP,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,cAAc,EAC3B,QAAQ,GAAE,QAA4B,GACrC,eAAe,GAAG,IAAI;IAoHzB;;OAEG;IACG,mBAAmB,CAAC,CAAC,EACzB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,UAAU,CAAC,EAAE,cAAc,GAC1B,OAAO,CAAC,CAAC,CAAC;IAsBb;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAMhC;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAO1D;;OAEG;IACH,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAOjE;;OAEG;IACH,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI;IAOpD;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAgB/B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAmBzB;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAe5B"}
@@ -9,6 +9,19 @@ const elastic_apm_compat_1 = require("../utils/elastic-apm-compat");
9
9
  * Sử dụng elastic-apm-node agent để gửi traces về Elastic APM server
10
10
  */
11
11
  class ElasticApmTracingProvider {
12
+ static isElasticLabelValue(value) {
13
+ return value !== undefined && !Array.isArray(value);
14
+ }
15
+ static setElasticLabel(target, key, value) {
16
+ if (!ElasticApmTracingProvider.isElasticLabelValue(value)) {
17
+ return;
18
+ }
19
+ if (typeof value === "number" || typeof value === "boolean") {
20
+ target.setLabel(key, value, false);
21
+ return;
22
+ }
23
+ target.setLabel(key, value);
24
+ }
12
25
  constructor(config = {}) {
13
26
  this.apm = null;
14
27
  this.serviceName =
@@ -93,7 +106,7 @@ class ElasticApmTracingProvider {
93
106
  // Set labels từ attributes
94
107
  if (attributes) {
95
108
  for (const [key, value] of Object.entries(attributes)) {
96
- span.setLabel(key, String(value));
109
+ ElasticApmTracingProvider.setElasticLabel(span, key, value);
97
110
  }
98
111
  }
99
112
  // Set span type dựa trên kind
@@ -112,7 +125,10 @@ class ElasticApmTracingProvider {
112
125
  }
113
126
  return;
114
127
  }
115
- originalSetLabel(key, value);
128
+ if (!ElasticApmTracingProvider.isElasticLabelValue(value)) {
129
+ return;
130
+ }
131
+ ElasticApmTracingProvider.setElasticLabel({ setLabel: originalSetLabel }, key, value);
116
132
  };
117
133
  // Override setAttribute (if it exists, maps to setLabel)
118
134
  if (typeof span.setAttribute === "function") {
@@ -188,12 +204,21 @@ class ElasticApmTracingProvider {
188
204
  }
189
205
  }
190
206
  /**
191
- * Set label cho current transaction/span
207
+ * Set label cho current span
192
208
  */
193
209
  setAttribute(key, value) {
194
210
  const span = this.apm?.currentSpan;
195
211
  if (span) {
196
- span.setLabel(key, String(value));
212
+ ElasticApmTracingProvider.setElasticLabel(span, key, value);
213
+ }
214
+ }
215
+ /**
216
+ * Set label cho current transaction
217
+ */
218
+ setTransactionLabel(key, value) {
219
+ const transaction = this.apm?.currentTransaction;
220
+ if (transaction) {
221
+ ElasticApmTracingProvider.setElasticLabel(transaction, key, value);
197
222
  }
198
223
  }
199
224
  /**
@@ -1,6 +1,6 @@
1
1
  import { ITracingProvider } from "../interfaces/tracing-provider.interface";
2
2
  import { OtlpTransport } from "../types/otlp-transport.type";
3
- import { ISpan, SpanKind } from "../types/apm.types";
3
+ import { ISpan, SpanAttributes, SpanAttributeValue, SpanKind } from "../types/apm.types";
4
4
  /**
5
5
  * OpenTelemetry Tracing Provider Implementation
6
6
  * Sử dụng OpenTelemetry SDK với OTLP exporter để gửi traces về Elastic APM
@@ -40,14 +40,15 @@ export declare class OpenTelemetryTracingProvider implements ITracingProvider {
40
40
  enableConsoleExporter?: boolean;
41
41
  environment?: string;
42
42
  }): Promise<void>;
43
+ private getTransactionSpanFromContext;
43
44
  /**
44
45
  * Bắt đầu một span mới
45
46
  */
46
- startSpan(name: string, attributes?: Record<string, string | number>, spanKind?: SpanKind): ISpan | null;
47
+ startSpan(name: string, attributes?: SpanAttributes, spanKind?: SpanKind): ISpan | null;
47
48
  /**
48
49
  * Thực thi function với tracing context
49
50
  */
50
- startSpanWithParent<T>(name: string, fn: (span: ISpan | null) => Promise<T>, attributes?: Record<string, string | number>): Promise<T>;
51
+ startSpanWithParent<T>(name: string, fn: (span: ISpan | null) => Promise<T>, attributes?: SpanAttributes): Promise<T>;
51
52
  /**
52
53
  * Capture error vào active span
53
54
  */
@@ -55,7 +56,11 @@ export declare class OpenTelemetryTracingProvider implements ITracingProvider {
55
56
  /**
56
57
  * Set attribute cho active span
57
58
  */
58
- setAttribute(key: string, value: string | number): void;
59
+ setAttribute(key: string, value: SpanAttributeValue): void;
60
+ /**
61
+ * Set transaction label on the root request span when available
62
+ */
63
+ setTransactionLabel(key: string, value: SpanAttributeValue): void;
59
64
  /**
60
65
  * Force flush all pending spans
61
66
  */
@@ -1 +1 @@
1
- {"version":3,"file":"opentelemetry.tracing-provider.d.ts","sourceRoot":"","sources":["../../src/providers/opentelemetry.tracing-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAyGrD;;;GAGG;AACH,qBAAa,4BAA6B,YAAW,gBAAgB;IACnE,OAAO,CAAC,GAAG,CAAiB;IAC5B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyB;IACrD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAU;IAChD,OAAO,CAAC,WAAW,CAAS;gBAG1B,MAAM,GAAE;QACN,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,aAAa,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;QACvC,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,qBAAqB,CAAC,EAAE,OAAO,CAAC;KAC5B;IA6BR;;;OAGG;IACG,UAAU,CAAC,MAAM,CAAC,EAAE;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,qBAAqB,CAAC,EAAE,OAAO,CAAC;QAChC,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+NjB;;OAEG;IACH,SAAS,CACP,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,EAC5C,QAAQ,GAAE,QAA4B,GACrC,KAAK,GAAG,IAAI;IA+Gf;;OAEG;IACG,mBAAmB,CAAC,CAAC,EACzB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAC3C,OAAO,CAAC,CAAC,CAAC;IAmCb;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAiBhC;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAavD;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAajC;;OAEG;IACH,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI;IAapD;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAM/B;;OAEG;IACH,OAAO,CAAC,WAAW;CAmBpB"}
1
+ {"version":3,"file":"opentelemetry.tracing-provider.d.ts","sourceRoot":"","sources":["../../src/providers/opentelemetry.tracing-provider.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AA8GzF;;;GAGG;AACH,qBAAa,4BAA6B,YAAW,gBAAgB;IACnE,OAAO,CAAC,GAAG,CAAiB;IAC5B,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAC9C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAyB;IACrD,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAU;IAChD,OAAO,CAAC,WAAW,CAAS;gBAG1B,MAAM,GAAE;QACN,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,aAAa,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;QACvC,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,qBAAqB,CAAC,EAAE,OAAO,CAAC;KAC5B;IA6BR;;;OAGG;IACG,UAAU,CAAC,MAAM,CAAC,EAAE;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrC,qBAAqB,CAAC,EAAE,OAAO,CAAC;QAChC,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,GAAG,OAAO,CAAC,IAAI,CAAC;IA+NjB,OAAO,CAAC,6BAA6B;IAuBrC;;OAEG;IACH,SAAS,CACP,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,cAAc,EAC3B,QAAQ,GAAE,QAA4B,GACrC,KAAK,GAAG,IAAI;IA4If;;OAEG;IACG,mBAAmB,CAAC,CAAC,EACzB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,UAAU,CAAC,EAAE,cAAc,GAC1B,OAAO,CAAC,CAAC,CAAC;IA4Cb;;OAEG;IACH,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAiBhC;;OAEG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAa1D;;OAEG;IACH,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAWjE;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAajC;;OAEG;IACH,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI;IAapD;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAM/B;;OAEG;IACH,OAAO,CAAC,WAAW;CAmBpB"}
@@ -38,6 +38,7 @@ const otlp_transport_type_1 = require("../types/otlp-transport.type");
38
38
  const apm_types_1 = require("../types/apm.types");
39
39
  const debug_logger_1 = require("../utils/debug-logger");
40
40
  const debug_exporter_wrapper_1 = require("../utils/debug-exporter-wrapper");
41
+ const opentelemetry_transaction_context_1 = require("../utils/opentelemetry-transaction-context");
41
42
  /**
42
43
  * Transaction Name Processor for OpenTelemetry
43
44
  * Sets transaction names to format: "GET /api/healthcheck/ping"
@@ -339,6 +340,20 @@ class OpenTelemetryTracingProvider {
339
340
  throw error;
340
341
  }
341
342
  }
343
+ getTransactionSpanFromContext() {
344
+ // @ts-ignore - Optional peer dependency
345
+ const { context, trace } = require("@opentelemetry/api");
346
+ const activeContext = context.active();
347
+ const transactionSpan = activeContext?.getValue?.(opentelemetry_transaction_context_1.transactionSpanContextKey);
348
+ if (transactionSpan) {
349
+ return transactionSpan;
350
+ }
351
+ const activeSpan = trace.getActiveSpan();
352
+ if (activeSpan?.[opentelemetry_transaction_context_1.transactionSpanRef]) {
353
+ return activeSpan[opentelemetry_transaction_context_1.transactionSpanRef] ?? null;
354
+ }
355
+ return null;
356
+ }
342
357
  /**
343
358
  * Bắt đầu một span mới
344
359
  */
@@ -350,8 +365,10 @@ class OpenTelemetryTracingProvider {
350
365
  return null;
351
366
  }
352
367
  // @ts-ignore - Optional peer dependency
353
- const { context } = require("@opentelemetry/api");
368
+ const { context, trace } = require("@opentelemetry/api");
354
369
  const tracer = this.tracer;
370
+ const activeContext = context.active();
371
+ const activeTransactionSpan = this.getTransactionSpanFromContext();
355
372
  const span = tracer.startSpan(name, {
356
373
  attributes,
357
374
  kind: this.mapSpanKind(spanKind),
@@ -360,6 +377,21 @@ class OpenTelemetryTracingProvider {
360
377
  if (span) {
361
378
  const spanForLog = { name, kind: this.mapSpanKind(spanKind) };
362
379
  (0, debug_logger_1.logSpan)("OpenTelemetry", spanForLog);
380
+ const transactionSpan = spanKind === apm_types_1.SpanKind.SERVER ? span : activeTransactionSpan;
381
+ if (transactionSpan) {
382
+ span[opentelemetry_transaction_context_1.transactionSpanRef] = transactionSpan;
383
+ let transactionContext;
384
+ if (typeof activeContext.setValue === "function") {
385
+ transactionContext = activeContext.setValue(opentelemetry_transaction_context_1.transactionSpanContextKey, transactionSpan);
386
+ }
387
+ else {
388
+ if ((0, debug_logger_1.isDebugEnabled)()) {
389
+ console.warn("[OpenTelemetry] activeContext.setValue is unavailable; falling back to trace.setSpan for transaction span propagation");
390
+ }
391
+ transactionContext = trace.setSpan(context.active(), transactionSpan);
392
+ }
393
+ span[opentelemetry_transaction_context_1.spanExecutionContextRef] = transactionContext;
394
+ }
363
395
  }
364
396
  // Add end protection to prevent operations on ended span
365
397
  if (span) {
@@ -412,7 +444,7 @@ class OpenTelemetryTracingProvider {
412
444
  // Override end to prevent duplicate ends
413
445
  if (typeof span.end === "function") {
414
446
  const originalEnd = span.end.bind(span);
415
- span.end = () => {
447
+ span.end = (result) => {
416
448
  if (isEnded) {
417
449
  if ((0, debug_logger_1.isDebugEnabled)()) {
418
450
  console.warn(`[OpenTelemetry] Span "${name}" has already been ended. Ignoring duplicate end().`);
@@ -420,7 +452,7 @@ class OpenTelemetryTracingProvider {
420
452
  return;
421
453
  }
422
454
  isEnded = true;
423
- originalEnd();
455
+ originalEnd(result);
424
456
  };
425
457
  }
426
458
  }
@@ -432,16 +464,21 @@ class OpenTelemetryTracingProvider {
432
464
  async startSpanWithParent(name, fn, attributes) {
433
465
  // @ts-ignore - Optional peer dependency
434
466
  const { context, trace, SpanStatusCode } = require("@opentelemetry/api");
435
- return context.with(trace.setSpan(context.active(), this.startSpan(name, attributes)), async () => {
436
- const span = trace.getActiveSpan();
467
+ const span = this.startSpan(name, attributes);
468
+ const spanContext = span?.[opentelemetry_transaction_context_1.spanExecutionContextRef] ??
469
+ context.active();
470
+ const executionContext = span ? trace.setSpan(spanContext, span) : spanContext;
471
+ return context.with(executionContext, async () => {
472
+ const activeSpan = trace.getActiveSpan();
473
+ const currentSpan = activeSpan ?? span;
437
474
  try {
438
- const result = await fn(span);
475
+ const result = await fn(currentSpan);
439
476
  return result;
440
477
  }
441
478
  catch (error) {
442
- if (span) {
443
- span.recordException(error);
444
- span.setStatus({
479
+ if (currentSpan) {
480
+ currentSpan.recordException(error);
481
+ currentSpan.setStatus({
445
482
  code: SpanStatusCode.ERROR,
446
483
  message: error.message,
447
484
  });
@@ -452,7 +489,7 @@ class OpenTelemetryTracingProvider {
452
489
  throw error;
453
490
  }
454
491
  finally {
455
- span?.end();
492
+ currentSpan?.end();
456
493
  }
457
494
  });
458
495
  }
@@ -478,7 +515,7 @@ class OpenTelemetryTracingProvider {
478
515
  * Set attribute cho active span
479
516
  */
480
517
  setAttribute(key, value) {
481
- if (!this.initialized) {
518
+ if (!this.initialized || value === undefined) {
482
519
  return;
483
520
  }
484
521
  // @ts-ignore - Optional peer dependency
@@ -488,6 +525,18 @@ class OpenTelemetryTracingProvider {
488
525
  span.setAttribute(key, value);
489
526
  }
490
527
  }
528
+ /**
529
+ * Set transaction label on the root request span when available
530
+ */
531
+ setTransactionLabel(key, value) {
532
+ if (!this.initialized || value === undefined || Array.isArray(value)) {
533
+ return;
534
+ }
535
+ const transactionSpan = this.getTransactionSpanFromContext();
536
+ if (transactionSpan) {
537
+ transactionSpan.setAttribute(key, value);
538
+ }
539
+ }
491
540
  /**
492
541
  * Force flush all pending spans
493
542
  */
@@ -1,5 +1,5 @@
1
1
  import { ITracingProvider } from "../interfaces/tracing-provider.interface";
2
- import { ISpan, SpanKind } from "../types/apm.types";
2
+ import { ISpan, SpanAttributes, SpanAttributeValue, SpanKind } from "../types/apm.types";
3
3
  /**
4
4
  * Tracing Service - Wrapper cho ITracingProvider
5
5
  * Service này được inject vào controllers/services để sử dụng tracing
@@ -47,7 +47,7 @@ export declare class TracingService {
47
47
  * span.end();
48
48
  * }
49
49
  */
50
- startSpan(name: string, attributes?: Record<string, string | number>, spanKind?: SpanKind): ISpan | null;
50
+ startSpan(name: string, attributes?: SpanAttributes, spanKind?: SpanKind): ISpan | null;
51
51
  /**
52
52
  * Thực thi function với context tracing (auto-close span)
53
53
  * @param name Tên của span
@@ -64,7 +64,7 @@ export declare class TracingService {
64
64
  * }
65
65
  * );
66
66
  */
67
- startSpanWithParent<T>(name: string, fn: (span: ISpan | null) => Promise<T>, attributes?: Record<string, string | number>): Promise<T>;
67
+ startSpanWithParent<T>(name: string, fn: (span: ISpan | null) => Promise<T>, attributes?: SpanAttributes): Promise<T>;
68
68
  /**
69
69
  * Capture error vào active span hiện tại
70
70
  * @param error Error object
@@ -75,7 +75,13 @@ export declare class TracingService {
75
75
  * @param key Tên attribute
76
76
  * @param value Giá trị attribute
77
77
  */
78
- setAttribute(key: string, value: string | number): void;
78
+ setAttribute(key: string, value: SpanAttributeValue): void;
79
+ /**
80
+ * Set label/attribute cho active transaction hiện tại
81
+ * @param key Tên label
82
+ * @param value Giá trị label
83
+ */
84
+ setTransactionLabel(key: string, value: SpanAttributeValue): void;
79
85
  /**
80
86
  * Kết thúc span manually
81
87
  * @param span Span cần end (nếu không truyền, sẽ end active span)
@@ -1 +1 @@
1
- {"version":3,"file":"tracing.service.d.ts","sourceRoot":"","sources":["../../src/services/tracing.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,gBAAgB;IAEvD;;;;;;;;;;;;;;;;;;;OAmBG;IACH,SAAS,CACP,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,EAC5C,QAAQ,GAAE,QAA4B,GACrC,KAAK,GAAG,IAAI;IAIf;;;;;;;;;;;;;;;OAeG;IACH,mBAAmB,CAAC,CAAC,EACnB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAC3C,OAAO,CAAC,CAAC,CAAC;IAIb;;;OAGG;IACH,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAIhC;;;;OAIG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAIvD;;;OAGG;IACH,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI;IAI7C;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAGhC"}
1
+ {"version":3,"file":"tracing.service.d.ts","sourceRoot":"","sources":["../../src/services/tracing.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAC5E,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEzF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBAAa,cAAc;IACb,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAAR,QAAQ,EAAE,gBAAgB;IAEvD;;;;;;;;;;;;;;;;;;;OAmBG;IACH,SAAS,CACP,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,cAAc,EAC3B,QAAQ,GAAE,QAA4B,GACrC,KAAK,GAAG,IAAI;IAIf;;;;;;;;;;;;;;;OAeG;IACH,mBAAmB,CAAC,CAAC,EACnB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EACtC,UAAU,CAAC,EAAE,cAAc,GAC1B,OAAO,CAAC,CAAC,CAAC;IAIb;;;OAGG;IACH,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAIhC;;;;OAIG;IACH,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAI1D;;;;OAIG;IACH,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAIjE;;;OAGG;IACH,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI;IAI7C;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAGhC"}
@@ -87,6 +87,14 @@ class TracingService {
87
87
  setAttribute(key, value) {
88
88
  this.provider.setAttribute(key, value);
89
89
  }
90
+ /**
91
+ * Set label/attribute cho active transaction hiện tại
92
+ * @param key Tên label
93
+ * @param value Giá trị label
94
+ */
95
+ setTransactionLabel(key, value) {
96
+ this.provider.setTransactionLabel(key, value);
97
+ }
90
98
  /**
91
99
  * Kết thúc span manually
92
100
  * @param span Span cần end (nếu không truyền, sẽ end active span)
@@ -10,13 +10,15 @@ export { ApmProvider, type ApmProviderType, SpanKind, OtlpTransport, type OtlpTr
10
10
  /**
11
11
  * Common Span interface - works with both Elastic APM and OpenTelemetry
12
12
  */
13
+ export type SpanAttributeValue = string | number | boolean | string[] | undefined;
14
+ export type SpanAttributes = Record<string, SpanAttributeValue>;
13
15
  export interface ISpan {
14
16
  /** Span name */
15
17
  name: string;
16
18
  /** End the span */
17
19
  end(result?: unknown): void;
18
20
  /** Set an attribute on the span */
19
- setAttribute(key: string, value: string | number | boolean | string[] | undefined): void;
21
+ setAttribute(key: string, value: SpanAttributeValue): void;
20
22
  /** Add an event to the span */
21
23
  addEvent?(name: string, attributes?: Record<string, unknown>): void;
22
24
  /** Set the span status */
@@ -47,7 +49,7 @@ export interface ITracer {
47
49
  */
48
50
  export interface SpanOptions {
49
51
  /** Span attributes */
50
- attributes?: Record<string, string | number | boolean>;
52
+ attributes?: SpanAttributes;
51
53
  /** Span kind (server, client, internal, etc.) */
52
54
  kind?: SpanKind;
53
55
  /** Parent span context */
@@ -1 +1 @@
1
- {"version":3,"file":"apm.types.d.ts","sourceRoot":"","sources":["../../src/types/apm.types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAClF,OAAO,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAG9E,OAAO,EAAE,WAAW,EAAE,KAAK,eAAe,EAAE,QAAQ,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,CAAC;AAE9F;;GAEG;AACH,MAAM,WAAW,KAAK;IACpB,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IAEb,mBAAmB;IACnB,GAAG,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAE5B,mCAAmC;IACnC,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,GAAG,IAAI,CAAC;IAEzF,+BAA+B;IAC/B,QAAQ,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAEpE,0BAA0B;IAC1B,SAAS,CAAC,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAErC,sCAAsC;IACtC,eAAe,CAAC,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,GAAG,IAAI,CAAC;CAChD;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,uBAAuB;IACvB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC;IAEtD,oCAAoC;IACpC,aAAa,CAAC,IAAI,KAAK,GAAG,SAAS,CAAC;IAEpC,yCAAyC;IACzC,mBAAmB,CAAC,CAAC,CAAC,EACpB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EACnC,OAAO,CAAC,EAAE,WAAW,GACpB,OAAO,CAAC,CAAC,CAAC,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,sBAAsB;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IAEvD,iDAAiD;IACjD,IAAI,CAAC,EAAE,QAAQ,CAAC;IAEhB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,KAAK,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,mBAAmB;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,kBAAkB;IAC3D,qBAAqB;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,mBAAmB;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,cAAc;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,qCAAqC;IACrC,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,+BAA+B;IAC/B,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,kBAAkB;IAC9D,wBAAwB;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,8CAA8C;IAC9C,aAAa,CAAC,EAAE,aAAa,GAAG,MAAM,CAAC;IAEvC,sBAAsB;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,mBAAmB;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAErC,8BAA8B;IAC9B,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,yDAAyD;IACzD,IAAI,EAAE,MAAM,CAAC;IAEb,6BAA6B;IAC7B,KAAK,CAAC,EAAE,KAAK,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,oCAAoC;IACpC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,aAAa,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAEpD,kCAAkC;IAClC,KAAK,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC;IAEzB,oCAAoC;IACpC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE5B,6BAA6B;IAC7B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,mBAAmB;IACnB,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,GAAG,IAAI,CAAC;IAExE,4BAA4B;IAC5B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1B,6BAA6B;IAC7B,UAAU,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B"}
1
+ {"version":3,"file":"apm.types.d.ts","sourceRoot":"","sources":["../../src/types/apm.types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare const transactionSpanContextKey: symbol;
2
+ export declare const transactionSpanRef: unique symbol;
3
+ export declare const spanExecutionContextRef: unique symbol;
4
+ //# sourceMappingURL=opentelemetry-transaction-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"opentelemetry-transaction-context.d.ts","sourceRoot":"","sources":["../../src/utils/opentelemetry-transaction-context.ts"],"names":[],"mappings":"AAiBA,eAAO,MAAM,yBAAyB,QAErC,CAAC;AAEF,eAAO,MAAM,kBAAkB,eAAiD,CAAC;AACjF,eAAO,MAAM,uBAAuB,eAA8C,CAAC"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.spanExecutionContextRef = exports.transactionSpanRef = exports.transactionSpanContextKey = void 0;
4
+ const resolveCreateContextKey = () => {
5
+ try {
6
+ // @ts-ignore - Optional peer dependency
7
+ const { createContextKey } = require("@opentelemetry/api");
8
+ if (typeof createContextKey === "function") {
9
+ return createContextKey;
10
+ }
11
+ }
12
+ catch {
13
+ // Ignore when optional dependency is unavailable
14
+ }
15
+ return (description) => Symbol(description);
16
+ };
17
+ exports.transactionSpanContextKey = resolveCreateContextKey()("interactive-apm.transaction-span");
18
+ exports.transactionSpanRef = Symbol("interactive-apm.transaction-span-ref");
19
+ exports.spanExecutionContextRef = Symbol("interactive-apm.execution-context");
@@ -1,4 +1,4 @@
1
- import { Span } from "@opentelemetry/api";
1
+ import { ISpan, SpanAttributes, SpanAttributeValue } from "../types/apm.types";
2
2
  import { SpanKind } from "../types/apm-provider.type";
3
3
  /**
4
4
  * TracingHelper - Static utility class for unified APM usage
@@ -19,10 +19,13 @@ import { SpanKind } from "../types/apm-provider.type";
19
19
  export declare class TracingHelper {
20
20
  private static tracer;
21
21
  private static apmProvider;
22
+ private static isElasticLabelValue;
23
+ private static setElasticLabel;
22
24
  /**
23
25
  * Get the current APM provider (cached)
24
26
  */
25
27
  private static getProvider;
28
+ private static getTransactionSpanFromContext;
26
29
  /**
27
30
  * Reset cached provider (useful for testing)
28
31
  */
@@ -34,7 +37,7 @@ export declare class TracingHelper {
34
37
  * @param spanKind Loại span (mặc định: INTERNAL). Dùng SERVER cho API endpoints
35
38
  * @returns Span object
36
39
  */
37
- static startSpan(name: string, attributes?: Record<string, string | number>, spanKind?: SpanKind): Span;
40
+ static startSpan(name: string, attributes?: SpanAttributes, spanKind?: SpanKind): ISpan;
38
41
  private static mapSpanKindToOtlpSpanKind;
39
42
  /**
40
43
  * Start span using OpenTelemetry API
@@ -63,7 +66,7 @@ export declare class TracingHelper {
63
66
  * @param attributes Các attributes metadata
64
67
  * @returns Kết quả của function
65
68
  */
66
- static startSpanWithParent<T>(name: string, fn: (span: Span | undefined) => Promise<T>, attributes?: Record<string, string | number>): Promise<T>;
69
+ static startSpanWithParent<T>(name: string, fn: (span: ISpan | undefined) => Promise<T>, attributes?: SpanAttributes): Promise<T>;
67
70
  /**
68
71
  * Capture error vào active span hiện tại
69
72
  * @param error Error object
@@ -74,17 +77,21 @@ export declare class TracingHelper {
74
77
  * @param key Tên attribute
75
78
  * @param value Giá trị attribute
76
79
  */
77
- static setAttribute(key: string, value: string | number): void;
80
+ static setAttribute(key: string, value: SpanAttributeValue): void;
81
+ /**
82
+ * Set label/attribute cho active transaction hiện tại
83
+ */
84
+ static setTransactionLabel(key: string, value: SpanAttributeValue): void;
78
85
  /**
79
86
  * Kết thúc span manually
80
87
  * @param span Span cần end
81
88
  */
82
- static endSpan(span?: Span, result?: unknown): void;
89
+ static endSpan(span?: ISpan, result?: unknown): void;
83
90
  /**
84
91
  * Get the current active span
85
92
  * @returns The active span or undefined
86
93
  */
87
- static getActiveSpan(): Span | undefined;
94
+ static getActiveSpan(): ISpan | undefined;
88
95
  /**
89
96
  * Get the current trace ID
90
97
  * @returns The trace ID or undefined
@@ -1 +1 @@
1
- {"version":3,"file":"tracing.helper.d.ts","sourceRoot":"","sources":["../../src/utils/tracing.helper.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,IAAI,EAA4C,MAAM,oBAAoB,CAAC;AACpG,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAwCtD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAsC;IAC3D,OAAO,CAAC,MAAM,CAAC,WAAW,CAAoD;IAE9E;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAO1B;;OAEG;IACH,MAAM,CAAC,kBAAkB,IAAI,IAAI;IAIjC;;;;;;OAMG;IACH,MAAM,CAAC,SAAS,CACd,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,EAC5C,QAAQ,GAAE,QAA4B,GACrC,IAAI;IAWP,OAAO,CAAC,MAAM,CAAC,yBAAyB;IAiBxC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAiBrC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IA2FlC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,4BAA4B;IAqB3C;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAsBpC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAe7B;;;;;;OAMG;WACU,mBAAmB,CAAC,CAAC,EAChC,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,EAC1C,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAC3C,OAAO,CAAC,CAAC,CAAC;IA2Cb;;;OAGG;IACH,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAsBvC;;;;OAIG;IACH,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAwB9D;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI;IA2BnD;;;OAGG;IACH,MAAM,CAAC,aAAa,IAAI,IAAI,GAAG,SAAS;IAqBxC;;;OAGG;IACH,MAAM,CAAC,UAAU,IAAI,MAAM,GAAG,SAAS;CAqBxC"}
1
+ {"version":3,"file":"tracing.helper.d.ts","sourceRoot":"","sources":["../../src/utils/tracing.helper.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAkDtD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAsC;IAC3D,OAAO,CAAC,MAAM,CAAC,WAAW,CAAoD;IAE9E,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAMlC,OAAO,CAAC,MAAM,CAAC,eAAe;IAiB9B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,WAAW;IAO1B,OAAO,CAAC,MAAM,CAAC,6BAA6B;IAqB5C;;OAEG;IACH,MAAM,CAAC,kBAAkB,IAAI,IAAI;IAIjC;;;;;;OAMG;IACH,MAAM,CAAC,SAAS,CACd,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,cAAc,EAC3B,QAAQ,GAAE,QAA4B,GACrC,KAAK;IAWR,OAAO,CAAC,MAAM,CAAC,yBAAyB;IAiBxC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAmCrC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAgGlC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,4BAA4B;IAqB3C;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,qBAAqB;IAsBpC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAoB7B;;;;;;OAMG;WACU,mBAAmB,CAAC,CAAC,EAChC,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,CAAC,IAAI,EAAE,KAAK,GAAG,SAAS,KAAK,OAAO,CAAC,CAAC,CAAC,EAC3C,UAAU,CAAC,EAAE,cAAc,GAC1B,OAAO,CAAC,CAAC,CAAC;IAyDb;;;OAGG;IACH,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAsBvC;;;;OAIG;IACH,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAwBjE;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,IAAI;IA2BxE;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI;IA2BpD;;;OAGG;IACH,MAAM,CAAC,aAAa,IAAI,KAAK,GAAG,SAAS;IAqBzC;;;OAGG;IACH,MAAM,CAAC,UAAU,IAAI,MAAM,GAAG,SAAS;CAqBxC"}
@@ -4,6 +4,7 @@ exports.TracingHelper = void 0;
4
4
  // @ts-ignore - Optional peer dependency
5
5
  const api_1 = require("@opentelemetry/api");
6
6
  const apm_provider_type_1 = require("../types/apm-provider.type");
7
+ const opentelemetry_transaction_context_1 = require("./opentelemetry-transaction-context");
7
8
  /**
8
9
  * Get the current APM provider type
9
10
  */
@@ -52,6 +53,19 @@ function getApmProvider() {
52
53
  * }
53
54
  */
54
55
  class TracingHelper {
56
+ static isElasticLabelValue(value) {
57
+ return value !== undefined && !Array.isArray(value);
58
+ }
59
+ static setElasticLabel(target, key, value) {
60
+ if (!TracingHelper.isElasticLabelValue(value)) {
61
+ return;
62
+ }
63
+ if (typeof value === "number" || typeof value === "boolean") {
64
+ target.setLabel(key, value, false);
65
+ return;
66
+ }
67
+ target.setLabel(key, value);
68
+ }
55
69
  /**
56
70
  * Get the current APM provider (cached)
57
71
  */
@@ -61,6 +75,18 @@ class TracingHelper {
61
75
  }
62
76
  return this.apmProvider;
63
77
  }
78
+ static getTransactionSpanFromContext() {
79
+ const activeContext = api_1.context.active();
80
+ const transactionSpan = activeContext?.getValue?.(opentelemetry_transaction_context_1.transactionSpanContextKey);
81
+ if (transactionSpan) {
82
+ return transactionSpan;
83
+ }
84
+ const activeSpan = api_1.trace.getActiveSpan();
85
+ if (activeSpan?.[opentelemetry_transaction_context_1.transactionSpanRef]) {
86
+ return activeSpan[opentelemetry_transaction_context_1.transactionSpanRef] ?? null;
87
+ }
88
+ return activeSpan ?? null;
89
+ }
64
90
  /**
65
91
  * Reset cached provider (useful for testing)
66
92
  */
@@ -102,10 +128,18 @@ class TracingHelper {
102
128
  * Start span using OpenTelemetry API
103
129
  */
104
130
  static startSpanOpenTelemetry(name, attributes, spanKind = apm_provider_type_1.SpanKind.INTERNAL) {
131
+ const activeContext = api_1.context.active();
132
+ const activeTransactionSpan = this.getTransactionSpanFromContext();
105
133
  const span = this.tracer.startSpan(name, {
106
134
  attributes,
107
135
  kind: this.mapSpanKindToOtlpSpanKind(spanKind),
108
136
  }, api_1.context.active());
137
+ const transactionSpan = spanKind === apm_provider_type_1.SpanKind.SERVER ? span : activeTransactionSpan;
138
+ if (transactionSpan) {
139
+ span[opentelemetry_transaction_context_1.transactionSpanRef] = transactionSpan;
140
+ const transactionContext = activeContext.setValue?.(opentelemetry_transaction_context_1.transactionSpanContextKey, transactionSpan);
141
+ span[opentelemetry_transaction_context_1.spanExecutionContextRef] = transactionContext ?? api_1.context.active();
142
+ }
109
143
  return span;
110
144
  }
111
145
  /**
@@ -139,7 +173,7 @@ class TracingHelper {
139
173
  // Set attributes as labels
140
174
  if (attributes) {
141
175
  for (const [key, value] of Object.entries(attributes)) {
142
- apmSpan.setLabel(key, String(value));
176
+ TracingHelper.setElasticLabel(apmSpan, key, value);
143
177
  }
144
178
  }
145
179
  // Set span type
@@ -153,14 +187,14 @@ class TracingHelper {
153
187
  // Add setAttribute method that maps to setLabel
154
188
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
155
189
  span.setAttribute = (key, value) => {
156
- originalSetLabel(key, String(value));
190
+ TracingHelper.setElasticLabel({ setLabel: originalSetLabel }, key, value);
157
191
  return span; // Return span for chaining
158
192
  };
159
193
  // Add setAttributes method for batch setting
160
194
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
161
195
  span.setAttributes = (attrs) => {
162
196
  for (const [k, v] of Object.entries(attrs)) {
163
- originalSetLabel(k, String(v));
197
+ TracingHelper.setElasticLabel({ setLabel: originalSetLabel }, k, v);
164
198
  }
165
199
  return span; // Return span for chaining
166
200
  };
@@ -235,18 +269,23 @@ class TracingHelper {
235
269
  * Create a no-op span that does nothing
236
270
  */
237
271
  static createNoOpSpan(name) {
238
- return {
272
+ const noOpSpan = {
239
273
  name,
240
- kind: apm_provider_type_1.SpanKind.INTERNAL,
241
- spanContext: () => ({ traceId: "noop", spanId: "noop" }),
242
- setAttribute: () => ({}),
243
- setAttributes: () => ({}),
244
- addEvent: () => ({}),
245
- recordException: () => ({}),
246
- setStatus: () => ({}),
247
- end: () => ({}),
248
- isRecording: () => false,
274
+ setAttribute: function () {
275
+ return this;
276
+ },
277
+ addEvent: function () {
278
+ return this;
279
+ },
280
+ recordException: function () {
281
+ return this;
282
+ },
283
+ setStatus: function () {
284
+ return this;
285
+ },
286
+ end: () => { },
249
287
  };
288
+ return noOpSpan;
250
289
  }
251
290
  /**
252
291
  * Thực thi function với context tracing (auto-close span)
@@ -271,23 +310,33 @@ class TracingHelper {
271
310
  }
272
311
  }
273
312
  // OpenTelemetry with context propagation
274
- return api_1.context.with(api_1.trace.setSpan(api_1.context.active(), TracingHelper.startSpan(name, attributes)), async () => {
275
- const span = api_1.trace.getActiveSpan();
313
+ const span = TracingHelper.startSpan(name, attributes);
314
+ const spanContext = span?.[opentelemetry_transaction_context_1.spanExecutionContextRef] ??
315
+ api_1.context.active();
316
+ const executionContext = span
317
+ ? api_1.trace.setSpan(spanContext, span)
318
+ : api_1.context.active();
319
+ return api_1.context.with(executionContext, async () => {
320
+ const activeSpan = api_1.trace.getActiveSpan();
321
+ const currentSpan = activeSpan ?? span;
276
322
  // If no active span, throw an error - this should not happen if the span was just started
277
- if (!span) {
323
+ if (!currentSpan) {
278
324
  throw new Error(`Failed to get active span for "${name}". The OpenTelemetry context may not be properly initialized.`);
279
325
  }
280
326
  try {
281
- const result = await fn(span);
327
+ const result = await fn(currentSpan);
282
328
  return result;
283
329
  }
284
330
  catch (error) {
285
- span.recordException(error);
286
- span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
331
+ currentSpan.recordException(error);
332
+ currentSpan.setStatus({
333
+ code: api_1.SpanStatusCode.ERROR,
334
+ message: error.message,
335
+ });
287
336
  throw error;
288
337
  }
289
338
  finally {
290
- span.end();
339
+ currentSpan.end();
291
340
  }
292
341
  });
293
342
  }
@@ -328,7 +377,7 @@ class TracingHelper {
328
377
  const apm = require("elastic-apm-node");
329
378
  const span = apm.currentSpan;
330
379
  if (span) {
331
- span.setLabel(key, String(value));
380
+ TracingHelper.setElasticLabel(span, key, value);
332
381
  }
333
382
  }
334
383
  catch {
@@ -338,10 +387,37 @@ class TracingHelper {
338
387
  }
339
388
  // OpenTelemetry
340
389
  const span = api_1.trace.getActiveSpan();
341
- if (span) {
390
+ if (span && value !== undefined) {
342
391
  span.setAttribute(key, value);
343
392
  }
344
393
  }
394
+ /**
395
+ * Set label/attribute cho active transaction hiện tại
396
+ */
397
+ static setTransactionLabel(key, value) {
398
+ const provider = this.getProvider();
399
+ if (provider === "elastic-apm") {
400
+ try {
401
+ // @ts-ignore - Optional dependency
402
+ const apm = require("elastic-apm-node");
403
+ const transaction = apm.currentTransaction;
404
+ if (transaction) {
405
+ TracingHelper.setElasticLabel(transaction, key, value);
406
+ }
407
+ }
408
+ catch {
409
+ // Ignore if elastic-apm is not available
410
+ }
411
+ return;
412
+ }
413
+ if (value === undefined || Array.isArray(value)) {
414
+ return;
415
+ }
416
+ const transactionSpan = this.getTransactionSpanFromContext();
417
+ if (transactionSpan) {
418
+ transactionSpan.setAttribute(key, value);
419
+ }
420
+ }
345
421
  /**
346
422
  * Kết thúc span manually
347
423
  * @param span Span cần end
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtvlive/interactive-apm",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "description": "APM integration package supporting both Elastic APM and OpenTelemetry with NestJS integration",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",