@vtvlive/interactive-apm 0.0.14 → 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.
@@ -36,6 +36,12 @@ export interface ITracingProvider {
36
36
  * @param value Giá trị attribute
37
37
  */
38
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,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;;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"}
@@ -6,7 +6,7 @@ import { ISpan, SpanAttributes, SpanAttributeValue } from "../types/apm.types";
6
6
  */
7
7
  export interface IElasticApmSpan extends ISpan {
8
8
  /** Set a label on the span */
9
- setLabel(key: string, value: string | number | boolean): 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) */
@@ -23,6 +23,7 @@ export declare class ElasticApmTracingProvider implements ITracingProvider {
23
23
  private readonly serviceName;
24
24
  private readonly environment;
25
25
  private static isElasticLabelValue;
26
+ private static setElasticLabel;
26
27
  constructor(config?: {
27
28
  serviceName?: string;
28
29
  environment?: string;
@@ -54,9 +55,13 @@ export declare class ElasticApmTracingProvider implements ITracingProvider {
54
55
  */
55
56
  captureError(error: Error): void;
56
57
  /**
57
- * Set label cho current transaction/span
58
+ * Set label cho current span
58
59
  */
59
60
  setAttribute(key: string, value: SpanAttributeValue): void;
61
+ /**
62
+ * Set label cho current transaction
63
+ */
64
+ setTransactionLabel(key: string, value: SpanAttributeValue): void;
60
65
  /**
61
66
  * End span manually
62
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,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,GAAG,IAAI,CAAC;IAE9D,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;IAErC,OAAO,CAAC,MAAM,CAAC,mBAAmB;gBAOhC,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;IAsHzB;;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,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"}
@@ -12,6 +12,16 @@ class ElasticApmTracingProvider {
12
12
  static isElasticLabelValue(value) {
13
13
  return value !== undefined && !Array.isArray(value);
14
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
+ }
15
25
  constructor(config = {}) {
16
26
  this.apm = null;
17
27
  this.serviceName =
@@ -96,9 +106,7 @@ class ElasticApmTracingProvider {
96
106
  // Set labels từ attributes
97
107
  if (attributes) {
98
108
  for (const [key, value] of Object.entries(attributes)) {
99
- if (ElasticApmTracingProvider.isElasticLabelValue(value)) {
100
- span.setLabel(key, value);
101
- }
109
+ ElasticApmTracingProvider.setElasticLabel(span, key, value);
102
110
  }
103
111
  }
104
112
  // Set span type dựa trên kind
@@ -120,7 +128,7 @@ class ElasticApmTracingProvider {
120
128
  if (!ElasticApmTracingProvider.isElasticLabelValue(value)) {
121
129
  return;
122
130
  }
123
- originalSetLabel(key, value);
131
+ ElasticApmTracingProvider.setElasticLabel({ setLabel: originalSetLabel }, key, value);
124
132
  };
125
133
  // Override setAttribute (if it exists, maps to setLabel)
126
134
  if (typeof span.setAttribute === "function") {
@@ -196,12 +204,21 @@ class ElasticApmTracingProvider {
196
204
  }
197
205
  }
198
206
  /**
199
- * Set label cho current transaction/span
207
+ * Set label cho current span
200
208
  */
201
209
  setAttribute(key, value) {
202
210
  const span = this.apm?.currentSpan;
203
- if (span && ElasticApmTracingProvider.isElasticLabelValue(value)) {
204
- span.setLabel(key, value);
211
+ if (span) {
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);
205
222
  }
206
223
  }
207
224
  /**
@@ -40,6 +40,7 @@ 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
  */
@@ -56,6 +57,10 @@ export declare class OpenTelemetryTracingProvider implements ITracingProvider {
56
57
  * Set attribute cho active span
57
58
  */
58
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,cAAc,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAyGzF;;;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,cAAc,EAC3B,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,cAAc,GAC1B,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,kBAAkB,GAAG,IAAI;IAa1D;;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
  }
@@ -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
  */
@@ -76,6 +76,12 @@ export declare class TracingService {
76
76
  * @param value Giá trị attribute
77
77
  */
78
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,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;;;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)
@@ -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");
@@ -20,10 +20,12 @@ export declare class TracingHelper {
20
20
  private static tracer;
21
21
  private static apmProvider;
22
22
  private static isElasticLabelValue;
23
+ private static setElasticLabel;
23
24
  /**
24
25
  * Get the current APM provider (cached)
25
26
  */
26
27
  private static getProvider;
28
+ private static getTransactionSpanFromContext;
27
29
  /**
28
30
  * Reset cached provider (useful for testing)
29
31
  */
@@ -76,6 +78,10 @@ export declare class TracingHelper {
76
78
  * @param value Giá trị attribute
77
79
  */
78
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;
79
85
  /**
80
86
  * Kết thúc span manually
81
87
  * @param span Span cần end
@@ -1 +1 @@
1
- {"version":3,"file":"tracing.helper.d.ts","sourceRoot":"","sources":["../../src/utils/tracing.helper.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC/E,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,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAMlC;;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,cAAc,EAC3B,QAAQ,GAAE,QAA4B,GACrC,KAAK;IAWR,OAAO,CAAC,MAAM,CAAC,yBAAyB;IAiBxC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAiBrC;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,mBAAmB;IAsGlC;;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;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,kBAAkB,GAAG,IAAI;IAwBjE;;;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"}
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
  */
@@ -55,6 +56,16 @@ class TracingHelper {
55
56
  static isElasticLabelValue(value) {
56
57
  return value !== undefined && !Array.isArray(value);
57
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
+ }
58
69
  /**
59
70
  * Get the current APM provider (cached)
60
71
  */
@@ -64,6 +75,18 @@ class TracingHelper {
64
75
  }
65
76
  return this.apmProvider;
66
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
+ }
67
90
  /**
68
91
  * Reset cached provider (useful for testing)
69
92
  */
@@ -105,10 +128,18 @@ class TracingHelper {
105
128
  * Start span using OpenTelemetry API
106
129
  */
107
130
  static startSpanOpenTelemetry(name, attributes, spanKind = apm_provider_type_1.SpanKind.INTERNAL) {
131
+ const activeContext = api_1.context.active();
132
+ const activeTransactionSpan = this.getTransactionSpanFromContext();
108
133
  const span = this.tracer.startSpan(name, {
109
134
  attributes,
110
135
  kind: this.mapSpanKindToOtlpSpanKind(spanKind),
111
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
+ }
112
143
  return span;
113
144
  }
114
145
  /**
@@ -142,9 +173,7 @@ class TracingHelper {
142
173
  // Set attributes as labels
143
174
  if (attributes) {
144
175
  for (const [key, value] of Object.entries(attributes)) {
145
- if (TracingHelper.isElasticLabelValue(value)) {
146
- apmSpan.setLabel(key, value);
147
- }
176
+ TracingHelper.setElasticLabel(apmSpan, key, value);
148
177
  }
149
178
  }
150
179
  // Set span type
@@ -158,18 +187,14 @@ class TracingHelper {
158
187
  // Add setAttribute method that maps to setLabel
159
188
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
160
189
  span.setAttribute = (key, value) => {
161
- if (TracingHelper.isElasticLabelValue(value)) {
162
- originalSetLabel(key, value);
163
- }
190
+ TracingHelper.setElasticLabel({ setLabel: originalSetLabel }, key, value);
164
191
  return span; // Return span for chaining
165
192
  };
166
193
  // Add setAttributes method for batch setting
167
194
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
168
195
  span.setAttributes = (attrs) => {
169
196
  for (const [k, v] of Object.entries(attrs)) {
170
- if (TracingHelper.isElasticLabelValue(v)) {
171
- originalSetLabel(k, v);
172
- }
197
+ TracingHelper.setElasticLabel({ setLabel: originalSetLabel }, k, v);
173
198
  }
174
199
  return span; // Return span for chaining
175
200
  };
@@ -285,23 +310,33 @@ class TracingHelper {
285
310
  }
286
311
  }
287
312
  // OpenTelemetry with context propagation
288
- return api_1.context.with(api_1.trace.setSpan(api_1.context.active(), TracingHelper.startSpan(name, attributes)), async () => {
289
- 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;
290
322
  // If no active span, throw an error - this should not happen if the span was just started
291
- if (!span) {
323
+ if (!currentSpan) {
292
324
  throw new Error(`Failed to get active span for "${name}". The OpenTelemetry context may not be properly initialized.`);
293
325
  }
294
326
  try {
295
- const result = await fn(span);
327
+ const result = await fn(currentSpan);
296
328
  return result;
297
329
  }
298
330
  catch (error) {
299
- span.recordException(error);
300
- 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
+ });
301
336
  throw error;
302
337
  }
303
338
  finally {
304
- span.end();
339
+ currentSpan.end();
305
340
  }
306
341
  });
307
342
  }
@@ -341,8 +376,8 @@ class TracingHelper {
341
376
  // @ts-ignore - Optional dependency
342
377
  const apm = require("elastic-apm-node");
343
378
  const span = apm.currentSpan;
344
- if (span && TracingHelper.isElasticLabelValue(value)) {
345
- span.setLabel(key, value);
379
+ if (span) {
380
+ TracingHelper.setElasticLabel(span, key, value);
346
381
  }
347
382
  }
348
383
  catch {
@@ -356,6 +391,33 @@ class TracingHelper {
356
391
  span.setAttribute(key, value);
357
392
  }
358
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
+ }
359
421
  /**
360
422
  * Kết thúc span manually
361
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.14",
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",