@vtvlive/interactive-apm 0.0.2

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.
Files changed (36) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +320 -0
  3. package/dist/factories/tracing-provider.factory.d.ts +81 -0
  4. package/dist/factories/tracing-provider.factory.d.ts.map +1 -0
  5. package/dist/factories/tracing-provider.factory.js +93 -0
  6. package/dist/index.d.ts +11 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +35 -0
  9. package/dist/init/elastic-apm-init.d.ts +51 -0
  10. package/dist/init/elastic-apm-init.d.ts.map +1 -0
  11. package/dist/init/elastic-apm-init.js +86 -0
  12. package/dist/init/opentelemetry-init.d.ts +51 -0
  13. package/dist/init/opentelemetry-init.d.ts.map +1 -0
  14. package/dist/init/opentelemetry-init.js +156 -0
  15. package/dist/interfaces/tracing-provider.interface.d.ts +43 -0
  16. package/dist/interfaces/tracing-provider.interface.d.ts.map +1 -0
  17. package/dist/interfaces/tracing-provider.interface.js +2 -0
  18. package/dist/modules/tracing.module.d.ts +96 -0
  19. package/dist/modules/tracing.module.d.ts.map +1 -0
  20. package/dist/modules/tracing.module.js +162 -0
  21. package/dist/providers/elastic-apm.tracing-provider.d.ts +57 -0
  22. package/dist/providers/elastic-apm.tracing-provider.d.ts.map +1 -0
  23. package/dist/providers/elastic-apm.tracing-provider.js +163 -0
  24. package/dist/providers/opentelemetry.tracing-provider.d.ts +68 -0
  25. package/dist/providers/opentelemetry.tracing-provider.d.ts.map +1 -0
  26. package/dist/providers/opentelemetry.tracing-provider.js +288 -0
  27. package/dist/services/tracing.service.d.ts +88 -0
  28. package/dist/services/tracing.service.d.ts.map +1 -0
  29. package/dist/services/tracing.service.js +103 -0
  30. package/dist/types/apm-provider.type.d.ts +47 -0
  31. package/dist/types/apm-provider.type.d.ts.map +1 -0
  32. package/dist/types/apm-provider.type.js +32 -0
  33. package/dist/utils/tracing.helper.d.ts +68 -0
  34. package/dist/utils/tracing.helper.d.ts.map +1 -0
  35. package/dist/utils/tracing.helper.js +115 -0
  36. package/package.json +105 -0
@@ -0,0 +1,103 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TracingService = void 0;
4
+ /**
5
+ * Tracing Service - Wrapper cho ITracingProvider
6
+ * Service này được inject vào controllers/services để sử dụng tracing
7
+ *
8
+ * Provider implementation (OpenTelemetry hoặc Elastic APM) được inject thông qua DI
9
+ *
10
+ * @example
11
+ * // NestJS usage
12
+ * constructor(private readonly tracingService: TracingService) {}
13
+ *
14
+ * someMethod() {
15
+ * const span = this.tracingService.startSpan('my.operation', { 'key': 'value' }, 'SERVER');
16
+ * try {
17
+ * // ... code
18
+ * } finally {
19
+ * span.end();
20
+ * }
21
+ * }
22
+ *
23
+ * @example
24
+ * // Standalone usage
25
+ * const provider = createTracingProvider();
26
+ * const tracingService = new TracingService(provider);
27
+ */
28
+ class TracingService {
29
+ constructor(provider) {
30
+ this.provider = provider;
31
+ }
32
+ /**
33
+ * Bắt đầu một span mới để trace operation
34
+ * @param name Tên của span
35
+ * @param attributes Các attributes metadata
36
+ * @param spanKind Loại span (mặc định: INTERNAL)
37
+ * - INTERNAL: Internal operation
38
+ * - SERVER: Server-side request handler (API endpoints)
39
+ * - CLIENT: Client-side call (outgoing HTTP, database)
40
+ * - PRODUCER: Message producer
41
+ * - CONSUMER: Message consumer
42
+ * @returns Span object - cần gọi end() khi hoàn thành
43
+ *
44
+ * @example
45
+ * const span = this.tracingService.startSpan('my.operation', { 'key': 'value' }, 'SERVER');
46
+ * try {
47
+ * // ... code
48
+ * } finally {
49
+ * span.end();
50
+ * }
51
+ */
52
+ startSpan(name, attributes, spanKind = 'INTERNAL') {
53
+ return this.provider.startSpan(name, attributes, spanKind);
54
+ }
55
+ /**
56
+ * Thực thi function với context tracing (auto-close span)
57
+ * @param name Tên của span
58
+ * @param fn Function cần trace
59
+ * @param attributes Các attributes metadata
60
+ * @returns Kết quả của function
61
+ *
62
+ * @example
63
+ * const result = await this.tracingService.startSpanWithParent(
64
+ * 'my.operation',
65
+ * async (span) => {
66
+ * span.setAttribute('custom', 'value');
67
+ * return await someAsyncOperation();
68
+ * }
69
+ * );
70
+ */
71
+ startSpanWithParent(name, fn, attributes) {
72
+ return this.provider.startSpanWithParent(name, fn, attributes);
73
+ }
74
+ /**
75
+ * Capture error vào active span hiện tại
76
+ * @param error Error object
77
+ */
78
+ captureError(error) {
79
+ this.provider.captureError(error);
80
+ }
81
+ /**
82
+ * Set attribute cho active span hiện tại
83
+ * @param key Tên attribute
84
+ * @param value Giá trị attribute
85
+ */
86
+ setAttribute(key, value) {
87
+ this.provider.setAttribute(key, value);
88
+ }
89
+ /**
90
+ * Kết thúc span manually
91
+ * @param span Span cần end (nếu không truyền, sẽ end active span)
92
+ */
93
+ endSpan(span) {
94
+ this.provider.endSpan(span);
95
+ }
96
+ /**
97
+ * Flush và shutdown APM provider (cho graceful shutdown)
98
+ */
99
+ async shutdown() {
100
+ await this.provider.shutdown();
101
+ }
102
+ }
103
+ exports.TracingService = TracingService;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * APM Provider types
3
+ */
4
+ /**
5
+ * Enum for available APM providers
6
+ */
7
+ export declare enum ApmProvider {
8
+ /** OpenTelemetry with OTLP exporter */
9
+ OPENTELEMETRY = "opentelemetry",
10
+ /** Elastic APM Node.js agent */
11
+ ELASTIC_APM = "elastic-apm"
12
+ }
13
+ /**
14
+ * Span kind types for tracing
15
+ */
16
+ export declare enum SpanKind {
17
+ /** Internal operation */
18
+ INTERNAL = "INTERNAL",
19
+ /** Server-side request handler (API endpoints) */
20
+ SERVER = "SERVER",
21
+ /** Client-side call (outgoing HTTP, database) */
22
+ CLIENT = "CLIENT",
23
+ /** Message producer */
24
+ PRODUCER = "PRODUCER",
25
+ /** Message consumer */
26
+ CONSUMER = "CONSUMER"
27
+ }
28
+ /**
29
+ * APM provider configuration options
30
+ */
31
+ export interface TracingProviderConfig {
32
+ /** Provider type */
33
+ provider?: ApmProvider | string;
34
+ /** Service name for APM */
35
+ serviceName?: string;
36
+ /** Deployment environment */
37
+ environment?: string;
38
+ /** Elastic APM server URL (for elastic-apm provider) */
39
+ serverUrl?: string;
40
+ /** Secret token for authentication */
41
+ secretToken?: string;
42
+ /** OTLP endpoint URL (for opentelemetry provider) */
43
+ otlpEndpoint?: string;
44
+ /** Service version */
45
+ serviceVersion?: string;
46
+ }
47
+ //# sourceMappingURL=apm-provider.type.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apm-provider.type.d.ts","sourceRoot":"","sources":["../../src/types/apm-provider.type.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,oBAAY,WAAW;IACrB,uCAAuC;IACvC,aAAa,kBAAkB;IAC/B,gCAAgC;IAChC,WAAW,gBAAgB;CAC5B;AAED;;GAEG;AACH,oBAAY,QAAQ;IAClB,yBAAyB;IACzB,QAAQ,aAAa;IACrB,kDAAkD;IAClD,MAAM,WAAW;IACjB,iDAAiD;IACjD,MAAM,WAAW;IACjB,uBAAuB;IACvB,QAAQ,aAAa;IACrB,uBAAuB;IACvB,QAAQ,aAAa;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,oBAAoB;IACpB,QAAQ,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IAChC,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6BAA6B;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sBAAsB;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB"}
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ /**
3
+ * APM Provider types
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SpanKind = exports.ApmProvider = void 0;
7
+ /**
8
+ * Enum for available APM providers
9
+ */
10
+ var ApmProvider;
11
+ (function (ApmProvider) {
12
+ /** OpenTelemetry with OTLP exporter */
13
+ ApmProvider["OPENTELEMETRY"] = "opentelemetry";
14
+ /** Elastic APM Node.js agent */
15
+ ApmProvider["ELASTIC_APM"] = "elastic-apm";
16
+ })(ApmProvider || (exports.ApmProvider = ApmProvider = {}));
17
+ /**
18
+ * Span kind types for tracing
19
+ */
20
+ var SpanKind;
21
+ (function (SpanKind) {
22
+ /** Internal operation */
23
+ SpanKind["INTERNAL"] = "INTERNAL";
24
+ /** Server-side request handler (API endpoints) */
25
+ SpanKind["SERVER"] = "SERVER";
26
+ /** Client-side call (outgoing HTTP, database) */
27
+ SpanKind["CLIENT"] = "CLIENT";
28
+ /** Message producer */
29
+ SpanKind["PRODUCER"] = "PRODUCER";
30
+ /** Message consumer */
31
+ SpanKind["CONSUMER"] = "CONSUMER";
32
+ })(SpanKind || (exports.SpanKind = SpanKind = {}));
@@ -0,0 +1,68 @@
1
+ import { Span, SpanKind } from '@opentelemetry/api';
2
+ /**
3
+ * TracingHelper - Static utility class for direct OpenTelemetry usage
4
+ *
5
+ * This class provides direct access to OpenTelemetry tracing without requiring
6
+ * dependency injection or the TracingService wrapper.
7
+ *
8
+ * Note: This requires @opentelemetry/api to be installed.
9
+ *
10
+ * @example
11
+ * import { TracingHelper } from '@vtvlive/interactive-apm';
12
+ *
13
+ * const span = TracingHelper.startSpan('my.operation', { 'key': 'value' }, SpanKind.SERVER);
14
+ * try {
15
+ * // ... code
16
+ * } catch (error) {
17
+ * TracingHelper.captureError(error);
18
+ * throw error;
19
+ * } finally {
20
+ * TracingHelper.endSpan(span);
21
+ * }
22
+ */
23
+ export declare class TracingHelper {
24
+ private static tracer;
25
+ /**
26
+ * Bắt đầu một span mới để trace operation
27
+ * @param name Tên của span
28
+ * @param attributes Các attributes metadata
29
+ * @param spanKind Loại span (mặc định: INTERNAL). Dùng SERVER cho API endpoints
30
+ * @returns Span object
31
+ */
32
+ static startSpan(name: string, attributes?: Record<string, string | number>, spanKind?: SpanKind): Span;
33
+ /**
34
+ * Thực thi function với context tracing (auto-close span)
35
+ * @param name Tên của span
36
+ * @param fn Function cần trace
37
+ * @param attributes Các attributes metadata
38
+ * @returns Kết quả của function
39
+ */
40
+ static startSpanWithParent<T>(name: string, fn: (span: Span) => Promise<T>, attributes?: Record<string, string | number>): Promise<T>;
41
+ /**
42
+ * Capture error vào active span hiện tại
43
+ * @param error Error object
44
+ */
45
+ static captureError(error: Error): void;
46
+ /**
47
+ * Set attribute cho active span hiện tại
48
+ * @param key Tên attribute
49
+ * @param value Giá trị attribute
50
+ */
51
+ static setAttribute(key: string, value: string | number): void;
52
+ /**
53
+ * Kết thúc span manually
54
+ * @param span Span cần end
55
+ */
56
+ static endSpan(span?: Span): void;
57
+ /**
58
+ * Get the current active span
59
+ * @returns The active span or undefined
60
+ */
61
+ static getActiveSpan(): Span | undefined;
62
+ /**
63
+ * Get the current trace ID
64
+ * @returns The trace ID or undefined
65
+ */
66
+ static getTraceId(): string | undefined;
67
+ }
68
+ //# sourceMappingURL=tracing.helper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tracing.helper.d.ts","sourceRoot":"","sources":["../../src/utils/tracing.helper.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,IAAI,EAAkB,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAEpF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAsC;IAE3D;;;;;;OAMG;IACH,MAAM,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,EAAE,QAAQ,GAAE,QAA4B,GAAG,IAAI;IAa1H;;;;;;OAMG;IACH,MAAM,CAAC,mBAAmB,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAiBrI;;;OAGG;IACH,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI;IAQvC;;;;OAIG;IACH,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAO9D;;;OAGG;IACH,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,IAAI;IAOjC;;;OAGG;IACH,MAAM,CAAC,aAAa,IAAI,IAAI,GAAG,SAAS;IAIxC;;;OAGG;IACH,MAAM,CAAC,UAAU,IAAI,MAAM,GAAG,SAAS;CAIxC"}
@@ -0,0 +1,115 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TracingHelper = void 0;
4
+ // @ts-ignore - Optional peer dependency
5
+ const api_1 = require("@opentelemetry/api");
6
+ /**
7
+ * TracingHelper - Static utility class for direct OpenTelemetry usage
8
+ *
9
+ * This class provides direct access to OpenTelemetry tracing without requiring
10
+ * dependency injection or the TracingService wrapper.
11
+ *
12
+ * Note: This requires @opentelemetry/api to be installed.
13
+ *
14
+ * @example
15
+ * import { TracingHelper } from '@vtvlive/interactive-apm';
16
+ *
17
+ * const span = TracingHelper.startSpan('my.operation', { 'key': 'value' }, SpanKind.SERVER);
18
+ * try {
19
+ * // ... code
20
+ * } catch (error) {
21
+ * TracingHelper.captureError(error);
22
+ * throw error;
23
+ * } finally {
24
+ * TracingHelper.endSpan(span);
25
+ * }
26
+ */
27
+ class TracingHelper {
28
+ /**
29
+ * Bắt đầu một span mới để trace operation
30
+ * @param name Tên của span
31
+ * @param attributes Các attributes metadata
32
+ * @param spanKind Loại span (mặc định: INTERNAL). Dùng SERVER cho API endpoints
33
+ * @returns Span object
34
+ */
35
+ static startSpan(name, attributes, spanKind = api_1.SpanKind.INTERNAL) {
36
+ const span = this.tracer.startSpan(name, {
37
+ attributes,
38
+ kind: spanKind,
39
+ }, api_1.context.active());
40
+ return span;
41
+ }
42
+ /**
43
+ * Thực thi function với context tracing (auto-close span)
44
+ * @param name Tên của span
45
+ * @param fn Function cần trace
46
+ * @param attributes Các attributes metadata
47
+ * @returns Kết quả của function
48
+ */
49
+ static startSpanWithParent(name, fn, attributes) {
50
+ return api_1.context.with(api_1.trace.setSpan(api_1.context.active(), TracingHelper.startSpan(name, attributes)), async () => {
51
+ const span = api_1.trace.getActiveSpan();
52
+ try {
53
+ const result = await fn(span);
54
+ return result;
55
+ }
56
+ catch (error) {
57
+ span?.recordException(error);
58
+ span?.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
59
+ throw error;
60
+ }
61
+ finally {
62
+ span?.end();
63
+ }
64
+ });
65
+ }
66
+ /**
67
+ * Capture error vào active span hiện tại
68
+ * @param error Error object
69
+ */
70
+ static captureError(error) {
71
+ const span = api_1.trace.getActiveSpan();
72
+ if (span) {
73
+ span.recordException(error);
74
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
75
+ }
76
+ }
77
+ /**
78
+ * Set attribute cho active span hiện tại
79
+ * @param key Tên attribute
80
+ * @param value Giá trị attribute
81
+ */
82
+ static setAttribute(key, value) {
83
+ const span = api_1.trace.getActiveSpan();
84
+ if (span) {
85
+ span.setAttribute(key, value);
86
+ }
87
+ }
88
+ /**
89
+ * Kết thúc span manually
90
+ * @param span Span cần end
91
+ */
92
+ static endSpan(span) {
93
+ const activeSpan = span || api_1.trace.getActiveSpan();
94
+ if (activeSpan) {
95
+ activeSpan.end();
96
+ }
97
+ }
98
+ /**
99
+ * Get the current active span
100
+ * @returns The active span or undefined
101
+ */
102
+ static getActiveSpan() {
103
+ return api_1.trace.getActiveSpan();
104
+ }
105
+ /**
106
+ * Get the current trace ID
107
+ * @returns The trace ID or undefined
108
+ */
109
+ static getTraceId() {
110
+ const span = api_1.trace.getActiveSpan();
111
+ return span?.spanContext().traceId;
112
+ }
113
+ }
114
+ exports.TracingHelper = TracingHelper;
115
+ TracingHelper.tracer = api_1.trace.getTracer('interactive-apm');
package/package.json ADDED
@@ -0,0 +1,105 @@
1
+ {
2
+ "name": "@vtvlive/interactive-apm",
3
+ "version": "0.0.2",
4
+ "description": "APM integration package supporting both Elastic APM and OpenTelemetry with NestJS integration",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": "./dist/index.js",
8
+ "keywords": [
9
+ "apm",
10
+ "elastic-apm",
11
+ "opentelemetry",
12
+ "otel",
13
+ "tracing",
14
+ "monitoring",
15
+ "nestjs",
16
+ "observability"
17
+ ],
18
+ "author": {
19
+ "name": "VTVLive"
20
+ },
21
+ "license": "MIT",
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "build:watch": "tsc --watch",
25
+ "prepublishOnly": "npm run build",
26
+ "clean": "rm -rf dist",
27
+ "test": "jest",
28
+ "test:watch": "jest --watch",
29
+ "test:coverage": "jest --coverage",
30
+ "test:unit": "jest __tests__/unit",
31
+ "test:integration": "jest __tests__/integration"
32
+ },
33
+ "peerDependencies": {
34
+ "@nestjs/common": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0",
35
+ "@nestjs/config": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0",
36
+ "@opentelemetry/api": "^1.0.0",
37
+ "@opentelemetry/exporter-trace-otlp-http": ">=0.200.0",
38
+ "@opentelemetry/instrumentation-express": ">=0.50.0",
39
+ "@opentelemetry/instrumentation-http": ">=0.200.0",
40
+ "@opentelemetry/resources": ">=1.0.0",
41
+ "@opentelemetry/sdk-node": ">=0.200.0",
42
+ "@opentelemetry/sdk-trace-base": ">=1.0.0",
43
+ "@opentelemetry/semantic-conventions": ">=1.0.0",
44
+ "elastic-apm-node": ">=3.0.0"
45
+ },
46
+ "peerDependenciesMeta": {
47
+ "@nestjs/common": {
48
+ "optional": true
49
+ },
50
+ "@nestjs/config": {
51
+ "optional": true
52
+ },
53
+ "@opentelemetry/api": {
54
+ "optional": true
55
+ },
56
+ "@opentelemetry/exporter-trace-otlp-http": {
57
+ "optional": true
58
+ },
59
+ "@opentelemetry/instrumentation-express": {
60
+ "optional": true
61
+ },
62
+ "@opentelemetry/instrumentation-http": {
63
+ "optional": true
64
+ },
65
+ "@opentelemetry/resources": {
66
+ "optional": true
67
+ },
68
+ "@opentelemetry/sdk-node": {
69
+ "optional": true
70
+ },
71
+ "@opentelemetry/sdk-trace-base": {
72
+ "optional": true
73
+ },
74
+ "@opentelemetry/semantic-conventions": {
75
+ "optional": true
76
+ },
77
+ "elastic-apm-node": {
78
+ "optional": true
79
+ }
80
+ },
81
+ "devDependencies": {
82
+ "@nestjs/common": "^11.1.17",
83
+ "@nestjs/config": "^4.0.3",
84
+ "@opentelemetry/api": "^1.9.0",
85
+ "@opentelemetry/exporter-trace-otlp-http": "^0.213.0",
86
+ "@opentelemetry/instrumentation-express": "^0.61.0",
87
+ "@opentelemetry/instrumentation-http": "^0.213.0",
88
+ "@opentelemetry/resources": "^2.6.0",
89
+ "@opentelemetry/sdk-node": "^0.213.0",
90
+ "@opentelemetry/sdk-trace-base": "^1.22.0",
91
+ "@opentelemetry/semantic-conventions": "^1.40.0",
92
+ "@types/jest": "^29.5.0",
93
+ "@types/node": "^20.0.0",
94
+ "elastic-apm-node": "^4.15.0",
95
+ "jest": "^29.7.0",
96
+ "ts-jest": "^29.1.0",
97
+ "typescript": "^5.3.0"
98
+ },
99
+ "engines": {
100
+ "node": ">=14.0.0"
101
+ },
102
+ "files": [
103
+ "dist"
104
+ ]
105
+ }