@vendure/telemetry-plugin 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.md ADDED
@@ -0,0 +1,42 @@
1
+ # License
2
+ Copyright (C) Vendure GmbH
3
+
4
+ This software is available under two different licenses:
5
+ * GNU General Public License version 3 (GPLv3) as Vendure Community Edition
6
+ * Vendure Commercial License (VCL)
7
+
8
+ The default Vendure license, without a valid Vendure Commercial License agreement, is the Open-Source GPLv3 license.
9
+
10
+ ## GNU General Public License version 3 (GPLv3)
11
+
12
+ If you decide to choose the GPLv3 license, you must comply with the following terms:
13
+
14
+ This program is free software: you can redistribute it and/or modify
15
+ it under the terms of the GNU General Public License as published by
16
+ the Free Software Foundation, either version 3 of the License, or
17
+ (at your option) any later version.
18
+
19
+ This program is distributed in the hope that it will be useful,
20
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
21
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
+ GNU General Public License for more details.
23
+
24
+ You should have received a copy of the GNU General Public License
25
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
26
+
27
+ Additional permission under GNU GPL version 3 section 7:
28
+
29
+ An additional exception under section 7 of the GPL is included in the plugin-exception.txt file,
30
+ which allows you to distribute Vendure plugins (i.e. extensions) under a different license.
31
+
32
+ ## Vendure Commercial License (VCL)
33
+
34
+ Alternatively, commercial and supported versions of the program - also known as
35
+ Commercial Distributions - must be used in accordance with the terms and conditions
36
+ contained in a separate written agreement between you and Vendure GmbH.
37
+ For more information about the Vendure Commercial License (VCL) please contact contact@vendure.io.
38
+
39
+ Please see also:
40
+
41
+ - [Licensing FAQ - license-faq.md](license/license-faq.md)
42
+ - [GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 - gpl-3.0.txt](license/gpl-3.0.txt)
@@ -0,0 +1,2 @@
1
+ import { CacheService, EventBus, JobQueue, JobQueueService } from '@vendure/core';
2
+ export declare const defaultMethodHooks: (import("..").MethodHookConfig<CacheService> | import("..").MethodHookConfig<EventBus> | import("..").MethodHookConfig<JobQueueService> | import("..").MethodHookConfig<JobQueue<import("@vendure/core").JsonCompatible<any>>>)[];
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultMethodHooks = void 0;
4
+ const core_1 = require("@vendure/core");
5
+ const javascript_stringify_1 = require("javascript-stringify");
6
+ const method_hooks_service_1 = require("../service/method-hooks.service");
7
+ exports.defaultMethodHooks = [
8
+ (0, method_hooks_service_1.registerMethodHooks)(core_1.CacheService, {
9
+ get: {
10
+ pre: ({ args: [key], span }) => {
11
+ span.setAttribute('cache.key', key);
12
+ },
13
+ post: ({ args: [key], result: hit, span }) => {
14
+ span.setAttribute('cache.hit', !!hit);
15
+ if (hit) {
16
+ span.addEvent('cache.hit', { key });
17
+ }
18
+ else {
19
+ span.addEvent('cache.miss', { key });
20
+ }
21
+ },
22
+ },
23
+ set: {
24
+ pre: ({ args: [key], span }) => {
25
+ span.setAttribute('cache.key', key);
26
+ },
27
+ },
28
+ delete: {
29
+ pre: ({ args: [key], span }) => {
30
+ span.setAttribute('cache.key', key);
31
+ },
32
+ },
33
+ invalidateTags: {
34
+ pre: ({ args: [tags], span }) => {
35
+ span.setAttribute('cache.tags', tags.join(', '));
36
+ },
37
+ },
38
+ }),
39
+ (0, method_hooks_service_1.registerMethodHooks)(core_1.EventBus, {
40
+ publish: {
41
+ pre: ({ args: [event], span }) => {
42
+ span.setAttribute('event', event.constructor.name);
43
+ span.setAttribute('event.timestamp', event.createdAt.toISOString());
44
+ },
45
+ },
46
+ }),
47
+ (0, method_hooks_service_1.registerMethodHooks)(core_1.JobQueueService, {
48
+ createQueue: {
49
+ pre: ({ args: [options], span }) => {
50
+ span.setAttribute('job-queue.name', options.name);
51
+ },
52
+ },
53
+ }),
54
+ (0, method_hooks_service_1.registerMethodHooks)(core_1.JobQueue, {
55
+ start: {
56
+ pre: ({ instance, span }) => {
57
+ span.setAttribute('job-queue.name', instance.name);
58
+ },
59
+ },
60
+ add: {
61
+ pre: ({ args: [data, options], span, instance }) => {
62
+ var _a, _b;
63
+ span.setAttribute('job.queueName', instance.name);
64
+ span.setAttribute('job.data', (_a = (0, javascript_stringify_1.stringify)(data, null, 2, {
65
+ maxDepth: 3,
66
+ })) !== null && _a !== void 0 ? _a : '');
67
+ span.setAttribute('job.retries', (_b = options === null || options === void 0 ? void 0 : options.retries) !== null && _b !== void 0 ? _b : 0);
68
+ },
69
+ post({ result, span }) {
70
+ span.setAttribute('job.buffered', result.id === 'buffered');
71
+ },
72
+ },
73
+ }),
74
+ ];
75
+ //# sourceMappingURL=default-method-hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-method-hooks.js","sourceRoot":"","sources":["../../src/config/default-method-hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { Injector, InstrumentationStrategy, WrappedMethodArgs } from '@vendure/core';
2
+ export declare const tracer: import("@opentelemetry/api").Tracer;
3
+ export declare class OtelInstrumentationStrategy implements InstrumentationStrategy {
4
+ private spanAttributeService;
5
+ init(injector: Injector): void;
6
+ wrapMethod({ instance, target, methodName, args, applyOriginalFunction }: WrappedMethodArgs): any;
7
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OtelInstrumentationStrategy = exports.tracer = void 0;
4
+ const api_1 = require("@opentelemetry/api");
5
+ const core_1 = require("@vendure/core");
6
+ const method_hooks_service_1 = require("../service/method-hooks.service");
7
+ exports.tracer = api_1.trace.getTracer('@vendure/core', core_1.VENDURE_VERSION);
8
+ const recordException = (span, error) => {
9
+ span.recordException(error);
10
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
11
+ };
12
+ class OtelInstrumentationStrategy {
13
+ init(injector) {
14
+ this.spanAttributeService = injector.get(method_hooks_service_1.MethodHooksService);
15
+ }
16
+ wrapMethod({ instance, target, methodName, args, applyOriginalFunction }) {
17
+ const spanName = `${String(target.name)}.${String(methodName)}`;
18
+ return exports.tracer.startActiveSpan(spanName, {}, span => {
19
+ var _a, _b;
20
+ const hooks = (_a = this.spanAttributeService) === null || _a === void 0 ? void 0 : _a.getHooks(target, methodName);
21
+ (_b = hooks === null || hooks === void 0 ? void 0 : hooks.pre) === null || _b === void 0 ? void 0 : _b.call(hooks, { args, span, instance });
22
+ if (applyOriginalFunction.constructor.name === 'AsyncFunction') {
23
+ return (applyOriginalFunction()
24
+ .then((result) => {
25
+ if (hooks === null || hooks === void 0 ? void 0 : hooks.post) {
26
+ hooks.post({ args, result, span, instance });
27
+ }
28
+ return result;
29
+ })
30
+ // @ts-expect-error
31
+ .catch(error => {
32
+ recordException(span, error);
33
+ // Throw error to propagate it further
34
+ throw error;
35
+ })
36
+ .finally(() => {
37
+ span.end();
38
+ }));
39
+ }
40
+ try {
41
+ const result = applyOriginalFunction();
42
+ if (hooks === null || hooks === void 0 ? void 0 : hooks.post) {
43
+ hooks.post({ args, result, span, instance });
44
+ }
45
+ return result;
46
+ }
47
+ catch (error) {
48
+ recordException(span, error);
49
+ // throw for further propagation
50
+ throw error;
51
+ }
52
+ finally {
53
+ span.end();
54
+ }
55
+ });
56
+ }
57
+ }
58
+ exports.OtelInstrumentationStrategy = OtelInstrumentationStrategy;
59
+ //# sourceMappingURL=otel-instrumentation-strategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otel-instrumentation-strategy.js","sourceRoot":"","sources":["../../src/config/otel-instrumentation-strategy.ts"],"names":[],"mappings":";;;AAAA,4CAA4E;AAC5E,wCAAsG;AAEtG,0EAAqE;AAExD,QAAA,MAAM,GAAG,WAAK,CAAC,SAAS,CAAC,eAAe,EAAE,sBAAe,CAAC,CAAC;AAExE,MAAM,eAAe,GAAG,CAAC,IAAa,EAAE,KAAU,EAAE,EAAE;IAClD,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAC5B,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,oBAAc,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;AAC3E,CAAC,CAAC;AAEF,MAAa,2BAA2B;IAGpC,IAAI,CAAC,QAAkB;QACnB,IAAI,CAAC,oBAAoB,GAAG,QAAQ,CAAC,GAAG,CAAC,yCAAkB,CAAC,CAAC;IACjE,CAAC;IAED,UAAU,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,qBAAqB,EAAqB;QACvF,MAAM,QAAQ,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;QAEhE,OAAO,cAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE;;YAC/C,MAAM,KAAK,GAAG,MAAA,IAAI,CAAC,oBAAoB,0CAAE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YACtE,MAAA,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,GAAG,sDAAG,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YACvC,IAAI,qBAAqB,CAAC,WAAW,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;gBAC7D,OAAO,CACH,qBAAqB,EAAE;qBAClB,IAAI,CAAC,CAAC,MAAW,EAAE,EAAE;oBAClB,IAAI,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,IAAI,EAAE,CAAC;wBACd,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;oBACjD,CAAC;oBACD,OAAO,MAAM,CAAC;gBAClB,CAAC,CAAC;oBACF,mBAAmB;qBAClB,KAAK,CAAC,KAAK,CAAC,EAAE;oBACX,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;oBAC7B,sCAAsC;oBACtC,MAAM,KAAK,CAAC;gBAChB,CAAC,CAAC;qBACD,OAAO,CAAC,GAAG,EAAE;oBACV,IAAI,CAAC,GAAG,EAAE,CAAC;gBACf,CAAC,CAAC,CACT,CAAC;YACN,CAAC;YAED,IAAI,CAAC;gBACD,MAAM,MAAM,GAAG,qBAAqB,EAAE,CAAC;gBACvC,IAAI,KAAK,aAAL,KAAK,uBAAL,KAAK,CAAE,IAAI,EAAE,CAAC;oBACd,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;gBACjD,CAAC;gBACD,OAAO,MAAM,CAAC;YAClB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACb,eAAe,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBAE7B,gCAAgC;gBAChC,MAAM,KAAK,CAAC;YAChB,CAAC;oBAAS,CAAC;gBACP,IAAI,CAAC,GAAG,EAAE,CAAC;YACf,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC;CACJ;AAlDD,kEAkDC"}
@@ -0,0 +1,51 @@
1
+ import { LogLevel, VendureLogger } from '@vendure/core';
2
+ export declare const otelLogger: import("@opentelemetry/api-logs").Logger;
3
+ /**
4
+ * @description
5
+ * Options for the OtelLogger.
6
+ *
7
+ * @since 3.3.0
8
+ * @docsCategory core plugins/TelemetryPlugin
9
+ * @docsPage OtelLogger
10
+ */
11
+ export interface OtelLoggerOptions {
12
+ /**
13
+ * @description
14
+ * If set to a LogLevel, the logger will also log to the console.
15
+ * This can be useful for local development or debugging.
16
+ *
17
+ * @example
18
+ * ```ts
19
+ * import { LogLevel } from '@vendure/core';
20
+ * import { TelemetryPlugin } from '@vendure/telemetry-plugin';
21
+ *
22
+ * // ...
23
+ *
24
+ * TelemetryPlugin.init({
25
+ * loggerOptions: {
26
+ * logToConsole: LogLevel.Verbose,
27
+ * },
28
+ * });
29
+ * ```
30
+ */
31
+ logToConsole?: LogLevel;
32
+ }
33
+ /**
34
+ * @description
35
+ * A logger that emits logs to OpenTelemetry and optionally to the console.
36
+ *
37
+ * @since 3.3.0
38
+ * @docsCategory core plugins/TelemetryPlugin
39
+ * @docsPage OtelLogger
40
+ * @docsWeight 0
41
+ */
42
+ export declare class OtelLogger implements VendureLogger {
43
+ private defaultLogger?;
44
+ constructor(options: OtelLoggerOptions);
45
+ debug(message: string, context?: string): void;
46
+ warn(message: string, context?: string): void;
47
+ info(message: string, context?: string): void;
48
+ error(message: string, context?: string): void;
49
+ verbose(message: string, context?: string): void;
50
+ private emitLog;
51
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OtelLogger = exports.otelLogger = void 0;
4
+ const api_logs_1 = require("@opentelemetry/api-logs");
5
+ const core_1 = require("@vendure/core");
6
+ exports.otelLogger = api_logs_1.logs.getLogger('@vendure/core', core_1.VENDURE_VERSION);
7
+ /**
8
+ * @description
9
+ * A logger that emits logs to OpenTelemetry and optionally to the console.
10
+ *
11
+ * @since 3.3.0
12
+ * @docsCategory core plugins/TelemetryPlugin
13
+ * @docsPage OtelLogger
14
+ * @docsWeight 0
15
+ */
16
+ class OtelLogger {
17
+ constructor(options) {
18
+ if (options.logToConsole) {
19
+ this.defaultLogger = new core_1.DefaultLogger({
20
+ level: options.logToConsole,
21
+ timestamp: false,
22
+ });
23
+ }
24
+ }
25
+ debug(message, context) {
26
+ var _a;
27
+ this.emitLog(api_logs_1.SeverityNumber.DEBUG, message, context);
28
+ (_a = this.defaultLogger) === null || _a === void 0 ? void 0 : _a.debug(message, context);
29
+ }
30
+ warn(message, context) {
31
+ var _a;
32
+ this.emitLog(api_logs_1.SeverityNumber.WARN, message, context);
33
+ (_a = this.defaultLogger) === null || _a === void 0 ? void 0 : _a.warn(message, context);
34
+ }
35
+ info(message, context) {
36
+ var _a;
37
+ this.emitLog(api_logs_1.SeverityNumber.INFO, message, context);
38
+ (_a = this.defaultLogger) === null || _a === void 0 ? void 0 : _a.info(message, context);
39
+ }
40
+ error(message, context) {
41
+ var _a;
42
+ this.emitLog(api_logs_1.SeverityNumber.ERROR, message, context);
43
+ (_a = this.defaultLogger) === null || _a === void 0 ? void 0 : _a.error(message, context);
44
+ }
45
+ verbose(message, context) {
46
+ var _a;
47
+ this.emitLog(api_logs_1.SeverityNumber.DEBUG, message, context);
48
+ (_a = this.defaultLogger) === null || _a === void 0 ? void 0 : _a.verbose(message, context);
49
+ }
50
+ emitLog(severityNumber, message, context, label) {
51
+ exports.otelLogger.emit({
52
+ severityNumber,
53
+ body: message,
54
+ attributes: Object.assign({ context, service_name: 'vendure' }, (label ? { label } : {})),
55
+ });
56
+ }
57
+ }
58
+ exports.OtelLogger = OtelLogger;
59
+ //# sourceMappingURL=otel-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otel-logger.js","sourceRoot":"","sources":["../../src/config/otel-logger.ts"],"names":[],"mappings":";;;AAAA,sDAA+D;AAC/D,wCAAwF;AAE3E,QAAA,UAAU,GAAG,eAAI,CAAC,SAAS,CAAC,eAAe,EAAE,sBAAe,CAAC,CAAC;AAiC3E;;;;;;;;GAQG;AACH,MAAa,UAAU;IAGnB,YAAY,OAA0B;QAClC,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;YACvB,IAAI,CAAC,aAAa,GAAG,IAAI,oBAAa,CAAC;gBACnC,KAAK,EAAE,OAAO,CAAC,YAAY;gBAC3B,SAAS,EAAE,KAAK;aACnB,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,OAAgB;;QACnC,IAAI,CAAC,OAAO,CAAC,yBAAc,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACrD,MAAA,IAAI,CAAC,aAAa,0CAAE,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,OAAgB;;QAClC,IAAI,CAAC,OAAO,CAAC,yBAAc,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACpD,MAAA,IAAI,CAAC,aAAa,0CAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;IAED,IAAI,CAAC,OAAe,EAAE,OAAgB;;QAClC,IAAI,CAAC,OAAO,CAAC,yBAAc,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACpD,MAAA,IAAI,CAAC,aAAa,0CAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,OAAe,EAAE,OAAgB;;QACnC,IAAI,CAAC,OAAO,CAAC,yBAAc,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACrD,MAAA,IAAI,CAAC,aAAa,0CAAE,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAChD,CAAC;IAED,OAAO,CAAC,OAAe,EAAE,OAAgB;;QACrC,IAAI,CAAC,OAAO,CAAC,yBAAc,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACrD,MAAA,IAAI,CAAC,aAAa,0CAAE,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAClD,CAAC;IAEO,OAAO,CAAC,cAA8B,EAAE,OAAe,EAAE,OAAgB,EAAE,KAAc;QAC7F,kBAAU,CAAC,IAAI,CAAC;YACZ,cAAc;YACd,IAAI,EAAE,OAAO;YACb,UAAU,kBACN,OAAO,EACP,YAAY,EAAE,SAAS,IACpB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAC9B;SACJ,CAAC,CAAC;IACP,CAAC;CACJ;AAhDD,gCAgDC"}
@@ -0,0 +1 @@
1
+ export declare const TELEMETRY_PLUGIN_OPTIONS: unique symbol;
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TELEMETRY_PLUGIN_OPTIONS = void 0;
4
+ exports.TELEMETRY_PLUGIN_OPTIONS = Symbol('TELEMETRY_PLUGIN_OPTIONS');
5
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,wBAAwB,GAAG,MAAM,CAAC,0BAA0B,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ export * from './config/default-method-hooks';
2
+ export * from './config/otel-instrumentation-strategy';
3
+ export * from './config/otel-logger';
4
+ export * from './service/method-hooks.service';
5
+ export * from './telemetry.plugin';
6
+ export * from './types';
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./config/default-method-hooks"), exports);
18
+ __exportStar(require("./config/otel-instrumentation-strategy"), exports);
19
+ __exportStar(require("./config/otel-logger"), exports);
20
+ __exportStar(require("./service/method-hooks.service"), exports);
21
+ __exportStar(require("./telemetry.plugin"), exports);
22
+ __exportStar(require("./types"), exports);
23
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gEAA8C;AAC9C,yEAAuD;AACvD,uDAAqC;AACrC,iEAA+C;AAC/C,qDAAmC;AACnC,0CAAwB"}
@@ -0,0 +1,70 @@
1
+ import { NodeSDKConfiguration } from '@opentelemetry/sdk-node';
2
+ /**
3
+ * @description
4
+ * Options for configuring the OpenTelemetry Node SDK.
5
+ *
6
+ * @docsCategory core plugins/TelemetryPlugin
7
+ * @docsPage getSdkConfiguration
8
+ */
9
+ export interface SdkConfigurationOptions {
10
+ /**
11
+ * @description
12
+ * When set to `true`, the SDK will log spans to the console instead of sending them to an
13
+ * exporter. This should just be used for debugging purposes.
14
+ *
15
+ * @default false
16
+ */
17
+ logToConsole?: boolean;
18
+ /**
19
+ * @description
20
+ * The configuration object for the OpenTelemetry Node SDK.
21
+ */
22
+ config: Partial<NodeSDKConfiguration>;
23
+ }
24
+ /**
25
+ * @description
26
+ * Creates a configuration object for the OpenTelemetry Node SDK. This is used to set up a custom
27
+ * preload script which must be run before the main Vendure server is loaded by means of the
28
+ * Node.js `--require` flag.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * // instrumentation.ts
33
+ * import { OTLPLogExporter } from '\@opentelemetry/exporter-logs-otlp-proto';
34
+ * import { OTLPTraceExporter } from '\@opentelemetry/exporter-trace-otlp-http';
35
+ * import { BatchLogRecordProcessor } from '\@opentelemetry/sdk-logs';
36
+ * import { NodeSDK } from '\@opentelemetry/sdk-node';
37
+ * import { BatchSpanProcessor } from '\@opentelemetry/sdk-trace-base';
38
+ * import { getSdkConfiguration } from '\@vendure/telemetry-plugin/preload';
39
+ *
40
+ * process.env.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://localhost:3100/otlp';
41
+ * process.env.OTEL_LOGS_EXPORTER = 'otlp';
42
+ * process.env.OTEL_RESOURCE_ATTRIBUTES = 'service.name=vendure-dev-server';
43
+ *
44
+ * const traceExporter = new OTLPTraceExporter({
45
+ * url: 'http://localhost:4318/v1/traces',
46
+ * });
47
+ * const logExporter = new OTLPLogExporter();
48
+ *
49
+ * const config = getSdkConfiguration({
50
+ * config: {
51
+ * spanProcessors: [new BatchSpanProcessor(traceExporter)],
52
+ * logRecordProcessors: [new BatchLogRecordProcessor(logExporter)],
53
+ * },
54
+ * });
55
+ *
56
+ * const sdk = new NodeSDK(config);
57
+ *
58
+ * sdk.start();
59
+ * ```
60
+ *
61
+ * This would them be run as:
62
+ * ```bash
63
+ * node --require ./dist/instrumentation.js ./dist/server.js
64
+ * ```
65
+ *
66
+ * @docsCategory core plugins/TelemetryPlugin
67
+ * @docsPage getSdkConfiguration
68
+ * @docsWeight 0
69
+ */
70
+ export declare function getSdkConfiguration(options?: SdkConfigurationOptions): Partial<NodeSDKConfiguration>;
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.getSdkConfiguration = getSdkConfiguration;
15
+ const auto_instrumentations_node_1 = require("@opentelemetry/auto-instrumentations-node");
16
+ const context_async_hooks_1 = require("@opentelemetry/context-async-hooks");
17
+ const exporter_logs_otlp_proto_1 = require("@opentelemetry/exporter-logs-otlp-proto");
18
+ const exporter_trace_otlp_http_1 = require("@opentelemetry/exporter-trace-otlp-http");
19
+ const resources_1 = require("@opentelemetry/resources");
20
+ const sdk_logs_1 = require("@opentelemetry/sdk-logs");
21
+ const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base");
22
+ // Deep import is intentional: otherwise unwanted code (such as instrumented classes) will get
23
+ // loaded too early before the Otel instrumentation has had a chance to do its thing.
24
+ const instrument_decorator_1 = require("@vendure/core/dist/common/instrument-decorator");
25
+ const traceExporter = new exporter_trace_otlp_http_1.OTLPTraceExporter();
26
+ const logExporter = new exporter_logs_otlp_proto_1.OTLPLogExporter();
27
+ /**
28
+ * @description
29
+ * Creates a configuration object for the OpenTelemetry Node SDK. This is used to set up a custom
30
+ * preload script which must be run before the main Vendure server is loaded by means of the
31
+ * Node.js `--require` flag.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * // instrumentation.ts
36
+ * import { OTLPLogExporter } from '\@opentelemetry/exporter-logs-otlp-proto';
37
+ * import { OTLPTraceExporter } from '\@opentelemetry/exporter-trace-otlp-http';
38
+ * import { BatchLogRecordProcessor } from '\@opentelemetry/sdk-logs';
39
+ * import { NodeSDK } from '\@opentelemetry/sdk-node';
40
+ * import { BatchSpanProcessor } from '\@opentelemetry/sdk-trace-base';
41
+ * import { getSdkConfiguration } from '\@vendure/telemetry-plugin/preload';
42
+ *
43
+ * process.env.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://localhost:3100/otlp';
44
+ * process.env.OTEL_LOGS_EXPORTER = 'otlp';
45
+ * process.env.OTEL_RESOURCE_ATTRIBUTES = 'service.name=vendure-dev-server';
46
+ *
47
+ * const traceExporter = new OTLPTraceExporter({
48
+ * url: 'http://localhost:4318/v1/traces',
49
+ * });
50
+ * const logExporter = new OTLPLogExporter();
51
+ *
52
+ * const config = getSdkConfiguration({
53
+ * config: {
54
+ * spanProcessors: [new BatchSpanProcessor(traceExporter)],
55
+ * logRecordProcessors: [new BatchLogRecordProcessor(logExporter)],
56
+ * },
57
+ * });
58
+ *
59
+ * const sdk = new NodeSDK(config);
60
+ *
61
+ * sdk.start();
62
+ * ```
63
+ *
64
+ * This would them be run as:
65
+ * ```bash
66
+ * node --require ./dist/instrumentation.js ./dist/server.js
67
+ * ```
68
+ *
69
+ * @docsCategory core plugins/TelemetryPlugin
70
+ * @docsPage getSdkConfiguration
71
+ * @docsWeight 0
72
+ */
73
+ function getSdkConfiguration(options) {
74
+ var _a;
75
+ // This environment variable is used to enable instrumentation in the Vendure core code.
76
+ // Without setting this env var, no instrumentation will be applied to any Vendure classes.
77
+ process.env[instrument_decorator_1.ENABLE_INSTRUMENTATION_ENV_VAR] = 'true';
78
+ const _b = (_a = options === null || options === void 0 ? void 0 : options.config) !== null && _a !== void 0 ? _a : {}, { spanProcessors, logRecordProcessors } = _b, rest = __rest(_b, ["spanProcessors", "logRecordProcessors"]);
79
+ const devModeAwareConfig = (options === null || options === void 0 ? void 0 : options.logToConsole)
80
+ ? {
81
+ spanProcessors: [new sdk_trace_base_1.SimpleSpanProcessor(new sdk_trace_base_1.ConsoleSpanExporter())],
82
+ logRecordProcessors: [new sdk_logs_1.SimpleLogRecordProcessor(new sdk_logs_1.ConsoleLogRecordExporter())],
83
+ }
84
+ : {
85
+ spanProcessors: spanProcessors !== null && spanProcessors !== void 0 ? spanProcessors : [new sdk_trace_base_1.BatchSpanProcessor(traceExporter)],
86
+ logRecordProcessors: logRecordProcessors !== null && logRecordProcessors !== void 0 ? logRecordProcessors : [new sdk_logs_1.BatchLogRecordProcessor(logExporter)],
87
+ };
88
+ return Object.assign(Object.assign(Object.assign({ resource: (0, resources_1.resourceFromAttributes)({
89
+ 'service.name': 'vendure',
90
+ 'service.namespace': 'vendure',
91
+ 'service.environment': process.env.NODE_ENV || 'development',
92
+ }) }, devModeAwareConfig), { contextManager: new context_async_hooks_1.AsyncLocalStorageContextManager(), instrumentations: [(0, auto_instrumentations_node_1.getNodeAutoInstrumentations)()] }), rest);
93
+ }
94
+ //# sourceMappingURL=instrumentation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instrumentation.js","sourceRoot":"","sources":["../src/instrumentation.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAwFA,kDA2BC;AAnHD,0FAAwF;AACxF,4EAAqF;AACrF,sFAA0E;AAC1E,sFAA4E;AAC5E,wDAAkE;AAClE,sDAIiC;AAEjC,kEAA6G;AAC7G,8FAA8F;AAC9F,qFAAqF;AACrF,yFAAgG;AAEhG,MAAM,aAAa,GAAG,IAAI,4CAAiB,EAAE,CAAC;AAC9C,MAAM,WAAW,GAAG,IAAI,0CAAe,EAAE,CAAC;AAyB1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,SAAgB,mBAAmB,CAAC,OAAiC;;IACjE,wFAAwF;IACxF,2FAA2F;IAC3F,OAAO,CAAC,GAAG,CAAC,qDAA8B,CAAC,GAAG,MAAM,CAAC;IACrD,MAAM,KAAmD,MAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,MAAM,mCAAI,EAAE,EAAxE,EAAE,cAAc,EAAE,mBAAmB,OAAmC,EAA9B,IAAI,cAA9C,yCAAgD,CAAwB,CAAC;IAE/E,MAAM,kBAAkB,GAAkC,CAAA,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,YAAY;QAC3E,CAAC,CAAC;YACI,cAAc,EAAE,CAAC,IAAI,oCAAmB,CAAC,IAAI,oCAAmB,EAAE,CAAC,CAAC;YACpE,mBAAmB,EAAE,CAAC,IAAI,mCAAwB,CAAC,IAAI,mCAAwB,EAAE,CAAC,CAAC;SACtF;QACH,CAAC,CAAC;YACI,cAAc,EAAE,cAAc,aAAd,cAAc,cAAd,cAAc,GAAI,CAAC,IAAI,mCAAkB,CAAC,aAAa,CAAC,CAAC;YACzE,mBAAmB,EAAE,mBAAmB,aAAnB,mBAAmB,cAAnB,mBAAmB,GAAI,CAAC,IAAI,kCAAuB,CAAC,WAAW,CAAC,CAAC;SACzF,CAAC;IAER,mDACI,QAAQ,EAAE,IAAA,kCAAsB,EAAC;YAC7B,cAAc,EAAE,SAAS;YACzB,mBAAmB,EAAE,SAAS;YAC9B,qBAAqB,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,aAAa;SAC/D,CAAC,IACC,kBAAkB,KACrB,cAAc,EAAE,IAAI,qDAA+B,EAAE,EACrD,gBAAgB,EAAE,CAAC,IAAA,wDAA2B,GAAE,CAAC,KAC9C,IAAI,EACT;AACN,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { Span } from '@opentelemetry/api';
2
+ import { Type } from '@vendure/common/lib/shared-types';
3
+ import { MethodHookConfig } from '../types';
4
+ /**
5
+ * Extracts only the method names from a class type T
6
+ */
7
+ export type MethodNames<T> = {
8
+ [K in keyof T]: T[K] extends Function ? K : never;
9
+ }[keyof T];
10
+ export type Unwrap<T> = T extends Promise<infer U> ? U : T;
11
+ type MethodType<T, K extends keyof T> = T[K] extends (...args: any[]) => any ? T[K] : never;
12
+ export interface InstrumentedMethodHooks<T, Method extends MethodNames<T>> {
13
+ pre?: (input: {
14
+ instance: T;
15
+ args: Parameters<MethodType<T, Method>>;
16
+ span: Span;
17
+ }) => void;
18
+ post?: (input: {
19
+ instance: T;
20
+ args: Parameters<MethodType<T, Method>>;
21
+ result: Unwrap<ReturnType<MethodType<T, Method>>>;
22
+ span: Span;
23
+ }) => void;
24
+ }
25
+ export type MethodHooksForType<T> = {
26
+ [K in MethodNames<T>]?: InstrumentedMethodHooks<T, K>;
27
+ };
28
+ /**
29
+ * @description
30
+ * Allows you to register hooks for a specific method of an instrumented class.
31
+ * These hooks allow extra telemetry actions to be performed on the method.
32
+ *
33
+ * They can then be passed to the {@link TelemetryPlugin} via the {@link TelemetryPluginOptions}.
34
+ *
35
+ * @example
36
+ * ```typescript
37
+ * const productServiceHooks = registerMethodHooks(ProductService, {
38
+ * findOne: {
39
+ * // This will be called before the method is executed
40
+ * pre: ({ args: [ctx, productId], span }) => {
41
+ * span.setAttribute('productId', productId);
42
+ * },
43
+ * // This will be called after the method is executed
44
+ * post: ({ result, span }) => {
45
+ * span.setAttribute('found', !!result);
46
+ * },
47
+ * },
48
+ * });
49
+ * ```
50
+ *
51
+ * @since 3.3.0
52
+ * @docsCategory core plugins/TelemetryPlugin
53
+ */
54
+ export declare function registerMethodHooks<T>(target: Type<T>, hooks: MethodHooksForType<T>): MethodHookConfig<T>;
55
+ export declare class MethodHooksService {
56
+ private hooksMap;
57
+ registerHooks<T>(target: Type<T>, hooks: MethodHooksForType<T>): void;
58
+ getHooks<T>(target: T, methodName: string): InstrumentedMethodHooks<T, any> | undefined;
59
+ }
60
+ export {};
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.MethodHooksService = void 0;
10
+ exports.registerMethodHooks = registerMethodHooks;
11
+ const common_1 = require("@nestjs/common");
12
+ const core_1 = require("@vendure/core");
13
+ /**
14
+ * @description
15
+ * Allows you to register hooks for a specific method of an instrumented class.
16
+ * These hooks allow extra telemetry actions to be performed on the method.
17
+ *
18
+ * They can then be passed to the {@link TelemetryPlugin} via the {@link TelemetryPluginOptions}.
19
+ *
20
+ * @example
21
+ * ```typescript
22
+ * const productServiceHooks = registerMethodHooks(ProductService, {
23
+ * findOne: {
24
+ * // This will be called before the method is executed
25
+ * pre: ({ args: [ctx, productId], span }) => {
26
+ * span.setAttribute('productId', productId);
27
+ * },
28
+ * // This will be called after the method is executed
29
+ * post: ({ result, span }) => {
30
+ * span.setAttribute('found', !!result);
31
+ * },
32
+ * },
33
+ * });
34
+ * ```
35
+ *
36
+ * @since 3.3.0
37
+ * @docsCategory core plugins/TelemetryPlugin
38
+ */
39
+ function registerMethodHooks(target, hooks) {
40
+ return {
41
+ target,
42
+ hooks,
43
+ };
44
+ }
45
+ let MethodHooksService = class MethodHooksService {
46
+ constructor() {
47
+ this.hooksMap = new Map();
48
+ }
49
+ registerHooks(target, hooks) {
50
+ const instrumentedClassTarget = (0, core_1.getInstrumentedClassTarget)(target);
51
+ if (!instrumentedClassTarget) {
52
+ core_1.Logger.error(`Cannot register hooks for non-instrumented class: ${target.name}`);
53
+ return;
54
+ }
55
+ const existingHooks = this.hooksMap.get(instrumentedClassTarget);
56
+ const combinedHooks = Object.assign(Object.assign({}, existingHooks), hooks);
57
+ this.hooksMap.set(instrumentedClassTarget, combinedHooks);
58
+ }
59
+ getHooks(target, methodName) {
60
+ var _a;
61
+ return (_a = this.hooksMap.get(target)) === null || _a === void 0 ? void 0 : _a[methodName];
62
+ }
63
+ };
64
+ exports.MethodHooksService = MethodHooksService;
65
+ exports.MethodHooksService = MethodHooksService = __decorate([
66
+ (0, common_1.Injectable)()
67
+ ], MethodHooksService);
68
+ //# sourceMappingURL=method-hooks.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"method-hooks.service.js","sourceRoot":"","sources":["../../src/service/method-hooks.service.ts"],"names":[],"mappings":";;;;;;;;;AA2DA,kDAKC;AAhED,2CAA4C;AAG5C,wCAAmE;AA8BnE;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,SAAgB,mBAAmB,CAAI,MAAe,EAAE,KAA4B;IAChF,OAAO;QACH,MAAM;QACN,KAAK;KACR,CAAC;AACN,CAAC;AAGM,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAAxB;QACK,aAAQ,GAAG,IAAI,GAAG,EAAoE,CAAC;IAmBnG,CAAC;IAjBG,aAAa,CAAI,MAAe,EAAE,KAA4B;QAC1D,MAAM,uBAAuB,GAAG,IAAA,iCAA0B,EAAC,MAAM,CAAC,CAAC;QACnE,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAC3B,aAAM,CAAC,KAAK,CAAC,qDAAqD,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YACjF,OAAO;QACX,CAAC;QACD,MAAM,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;QACjE,MAAM,aAAa,mCACZ,aAAa,GACb,KAAK,CACX,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,uBAAuB,EAAE,aAAa,CAAC,CAAC;IAC9D,CAAC;IAED,QAAQ,CAAI,MAAS,EAAE,UAAkB;;QACrC,OAAO,MAAA,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,0CAAG,UAAU,CAAC,CAAC;IACnD,CAAC;CACJ,CAAA;AApBY,gDAAkB;6BAAlB,kBAAkB;IAD9B,IAAA,mBAAU,GAAE;GACA,kBAAkB,CAoB9B"}
@@ -0,0 +1,103 @@
1
+ import { MethodHooksService } from './service/method-hooks.service';
2
+ import { TelemetryPluginOptions } from './types';
3
+ /**
4
+ * @description
5
+ * The TelemetryPlugin is used to instrument the Vendure application and collect telemetry data using
6
+ * [OpenTelemetry](https://opentelemetry.io/).
7
+ *
8
+ * ## Installation
9
+ *
10
+ * ```
11
+ * npm install \@vendure/telemetry-plugin
12
+ * ```
13
+ *
14
+ * :::info
15
+ * For a complete guide to setting up and working with Open Telemetry, see
16
+ * the [Implementing Open Telemetry guide](/guides/how-to/telemetry/).
17
+ * :::
18
+ *
19
+ * ## Configuration
20
+ *
21
+ * The plugin is configured via the `TelemetryPlugin.init()` method. This method accepts an options object
22
+ * which defines the OtelLogger options and method hooks.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import { VendureConfig } from '\@vendure/core';
27
+ * import { TelemetryPlugin, registerMethodHooks } from '\@vendure/telemetry-plugin';
28
+ *
29
+ * export const config: VendureConfig = {
30
+ * // ...
31
+ * plugins: [
32
+ * TelemetryPlugin.init({
33
+ * loggerOptions: {
34
+ * // Log to the console at the verbose level
35
+ * console: LogLevel.Verbose,
36
+ * },
37
+ * }),
38
+ * ],
39
+ * };
40
+ * ```
41
+ *
42
+ * ## Preloading the SDK
43
+ *
44
+ * In order to use the OpenTelemetry SDK, you must preload it before the Vendure server is started.
45
+ * This is done by using the `--require` flag when starting the server with a custom preload script.
46
+ *
47
+ * Create a file named `instrumentation.ts` in the root of your project and add the following code:
48
+ *
49
+ * ```ts
50
+ * import { OTLPLogExporter } from '\@opentelemetry/exporter-logs-otlp-proto';
51
+ * import { OTLPTraceExporter } from '\@opentelemetry/exporter-trace-otlp-http';
52
+ * import { BatchLogRecordProcessor } from '\@opentelemetry/sdk-logs';
53
+ * import { NodeSDK } from '\@opentelemetry/sdk-node';
54
+ * import { BatchSpanProcessor } from '\@opentelemetry/sdk-trace-base';
55
+ * import { getSdkConfiguration } from '\@vendure/telemetry-plugin/preload';
56
+ *
57
+ * // In this example we are using Loki as the OTLP endpoint for logging
58
+ * process.env.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://localhost:3100/otlp';
59
+ * process.env.OTEL_LOGS_EXPORTER = 'otlp';
60
+ * process.env.OTEL_RESOURCE_ATTRIBUTES = 'service.name=vendure-dev-server';
61
+ *
62
+ * // We are using Jaeger as the OTLP endpoint for tracing
63
+ * const traceExporter = new OTLPTraceExporter({
64
+ * url: 'http://localhost:4318/v1/traces',
65
+ * });
66
+ * const logExporter = new OTLPLogExporter();
67
+ *
68
+ * // The getSdkConfiguration method returns a configuration object for the OpenTelemetry Node SDK.
69
+ * // It also performs other configuration tasks such as setting a special environment variable
70
+ * // to enable instrumentation in the Vendure core code.
71
+ * const config = getSdkConfiguration({
72
+ * config: {
73
+ * // Pass in any custom configuration options for the Node SDK here
74
+ * spanProcessors: [new BatchSpanProcessor(traceExporter)],
75
+ * logRecordProcessors: [new BatchLogRecordProcessor(logExporter)],
76
+ * },
77
+ * });
78
+ *
79
+ * const sdk = new NodeSDK(config);
80
+ *
81
+ * sdk.start();
82
+ * ```
83
+ *
84
+ * The server would then be started with the following command:
85
+ *
86
+ * ```bash
87
+ * node --require ./dist/instrumentation.js ./dist/server.js
88
+ * ```
89
+ *
90
+ * or for development with ts-node:
91
+ *
92
+ * ```bash
93
+ * npx ts-node --require ./src/instrumentation.ts ./src/server.ts
94
+ * ```
95
+ *
96
+ * @since 3.3.0
97
+ * @docsCategory core plugins/TelemetryPlugin
98
+ */
99
+ export declare class TelemetryPlugin {
100
+ static options: TelemetryPluginOptions;
101
+ constructor(methodHooksService: MethodHooksService, options: TelemetryPluginOptions);
102
+ static init(options: TelemetryPluginOptions): typeof TelemetryPlugin;
103
+ }
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var TelemetryPlugin_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.TelemetryPlugin = void 0;
17
+ const common_1 = require("@nestjs/common");
18
+ const core_1 = require("@vendure/core");
19
+ const default_method_hooks_1 = require("./config/default-method-hooks");
20
+ const otel_instrumentation_strategy_1 = require("./config/otel-instrumentation-strategy");
21
+ const otel_logger_1 = require("./config/otel-logger");
22
+ const constants_1 = require("./constants");
23
+ const method_hooks_service_1 = require("./service/method-hooks.service");
24
+ /**
25
+ * @description
26
+ * The TelemetryPlugin is used to instrument the Vendure application and collect telemetry data using
27
+ * [OpenTelemetry](https://opentelemetry.io/).
28
+ *
29
+ * ## Installation
30
+ *
31
+ * ```
32
+ * npm install \@vendure/telemetry-plugin
33
+ * ```
34
+ *
35
+ * :::info
36
+ * For a complete guide to setting up and working with Open Telemetry, see
37
+ * the [Implementing Open Telemetry guide](/guides/how-to/telemetry/).
38
+ * :::
39
+ *
40
+ * ## Configuration
41
+ *
42
+ * The plugin is configured via the `TelemetryPlugin.init()` method. This method accepts an options object
43
+ * which defines the OtelLogger options and method hooks.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * import { VendureConfig } from '\@vendure/core';
48
+ * import { TelemetryPlugin, registerMethodHooks } from '\@vendure/telemetry-plugin';
49
+ *
50
+ * export const config: VendureConfig = {
51
+ * // ...
52
+ * plugins: [
53
+ * TelemetryPlugin.init({
54
+ * loggerOptions: {
55
+ * // Log to the console at the verbose level
56
+ * console: LogLevel.Verbose,
57
+ * },
58
+ * }),
59
+ * ],
60
+ * };
61
+ * ```
62
+ *
63
+ * ## Preloading the SDK
64
+ *
65
+ * In order to use the OpenTelemetry SDK, you must preload it before the Vendure server is started.
66
+ * This is done by using the `--require` flag when starting the server with a custom preload script.
67
+ *
68
+ * Create a file named `instrumentation.ts` in the root of your project and add the following code:
69
+ *
70
+ * ```ts
71
+ * import { OTLPLogExporter } from '\@opentelemetry/exporter-logs-otlp-proto';
72
+ * import { OTLPTraceExporter } from '\@opentelemetry/exporter-trace-otlp-http';
73
+ * import { BatchLogRecordProcessor } from '\@opentelemetry/sdk-logs';
74
+ * import { NodeSDK } from '\@opentelemetry/sdk-node';
75
+ * import { BatchSpanProcessor } from '\@opentelemetry/sdk-trace-base';
76
+ * import { getSdkConfiguration } from '\@vendure/telemetry-plugin/preload';
77
+ *
78
+ * // In this example we are using Loki as the OTLP endpoint for logging
79
+ * process.env.OTEL_EXPORTER_OTLP_ENDPOINT = 'http://localhost:3100/otlp';
80
+ * process.env.OTEL_LOGS_EXPORTER = 'otlp';
81
+ * process.env.OTEL_RESOURCE_ATTRIBUTES = 'service.name=vendure-dev-server';
82
+ *
83
+ * // We are using Jaeger as the OTLP endpoint for tracing
84
+ * const traceExporter = new OTLPTraceExporter({
85
+ * url: 'http://localhost:4318/v1/traces',
86
+ * });
87
+ * const logExporter = new OTLPLogExporter();
88
+ *
89
+ * // The getSdkConfiguration method returns a configuration object for the OpenTelemetry Node SDK.
90
+ * // It also performs other configuration tasks such as setting a special environment variable
91
+ * // to enable instrumentation in the Vendure core code.
92
+ * const config = getSdkConfiguration({
93
+ * config: {
94
+ * // Pass in any custom configuration options for the Node SDK here
95
+ * spanProcessors: [new BatchSpanProcessor(traceExporter)],
96
+ * logRecordProcessors: [new BatchLogRecordProcessor(logExporter)],
97
+ * },
98
+ * });
99
+ *
100
+ * const sdk = new NodeSDK(config);
101
+ *
102
+ * sdk.start();
103
+ * ```
104
+ *
105
+ * The server would then be started with the following command:
106
+ *
107
+ * ```bash
108
+ * node --require ./dist/instrumentation.js ./dist/server.js
109
+ * ```
110
+ *
111
+ * or for development with ts-node:
112
+ *
113
+ * ```bash
114
+ * npx ts-node --require ./src/instrumentation.ts ./src/server.ts
115
+ * ```
116
+ *
117
+ * @since 3.3.0
118
+ * @docsCategory core plugins/TelemetryPlugin
119
+ */
120
+ let TelemetryPlugin = TelemetryPlugin_1 = class TelemetryPlugin {
121
+ constructor(methodHooksService, options) {
122
+ var _a;
123
+ if (process.env[core_1.ENABLE_INSTRUMENTATION_ENV_VAR]) {
124
+ const allMethodHooks = [...default_method_hooks_1.defaultMethodHooks, ...((_a = options.methodHooks) !== null && _a !== void 0 ? _a : [])];
125
+ for (const methodHook of allMethodHooks) {
126
+ methodHooksService.registerHooks(methodHook.target, methodHook.hooks);
127
+ }
128
+ }
129
+ }
130
+ static init(options) {
131
+ TelemetryPlugin_1.options = options;
132
+ return TelemetryPlugin_1;
133
+ }
134
+ };
135
+ exports.TelemetryPlugin = TelemetryPlugin;
136
+ TelemetryPlugin.options = {};
137
+ exports.TelemetryPlugin = TelemetryPlugin = TelemetryPlugin_1 = __decorate([
138
+ (0, core_1.VendurePlugin)({
139
+ imports: [core_1.PluginCommonModule],
140
+ providers: [
141
+ method_hooks_service_1.MethodHooksService,
142
+ {
143
+ provide: constants_1.TELEMETRY_PLUGIN_OPTIONS,
144
+ useFactory: () => TelemetryPlugin.options,
145
+ },
146
+ ],
147
+ configuration: config => {
148
+ var _a;
149
+ config.systemOptions.instrumentationStrategy = new otel_instrumentation_strategy_1.OtelInstrumentationStrategy();
150
+ config.logger = new otel_logger_1.OtelLogger((_a = TelemetryPlugin.options.loggerOptions) !== null && _a !== void 0 ? _a : {});
151
+ return config;
152
+ },
153
+ compatibility: '>3.3.0',
154
+ }),
155
+ __param(1, (0, common_1.Inject)(constants_1.TELEMETRY_PLUGIN_OPTIONS)),
156
+ __metadata("design:paramtypes", [method_hooks_service_1.MethodHooksService, Object])
157
+ ], TelemetryPlugin);
158
+ //# sourceMappingURL=telemetry.plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.plugin.js","sourceRoot":"","sources":["../src/telemetry.plugin.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAwC;AACxC,wCAAkG;AAElG,wEAAmE;AACnE,0FAAqF;AACrF,sDAAkD;AAClD,2CAAuD;AACvD,yEAAoE;AAGpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+FG;AAiBI,IAAM,eAAe,uBAArB,MAAM,eAAe;IAGxB,YACI,kBAAsC,EACJ,OAA+B;;QAEjE,IAAI,OAAO,CAAC,GAAG,CAAC,qCAA8B,CAAC,EAAE,CAAC;YAC9C,MAAM,cAAc,GAAG,CAAC,GAAG,yCAAkB,EAAE,GAAG,CAAC,MAAA,OAAO,CAAC,WAAW,mCAAI,EAAE,CAAC,CAAC,CAAC;YAC/E,KAAK,MAAM,UAAU,IAAI,cAAc,EAAE,CAAC;gBACtC,kBAAkB,CAAC,aAAa,CAAC,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC;YAC1E,CAAC;QACL,CAAC;IACL,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,OAA+B;QACvC,iBAAe,CAAC,OAAO,GAAG,OAAO,CAAC;QAClC,OAAO,iBAAe,CAAC;IAC3B,CAAC;;AAlBQ,0CAAe;AACjB,uBAAO,GAA2B,EAAE,AAA7B,CAA8B;0BADnC,eAAe;IAhB3B,IAAA,oBAAa,EAAC;QACX,OAAO,EAAE,CAAC,yBAAkB,CAAC;QAC7B,SAAS,EAAE;YACP,yCAAkB;YAClB;gBACI,OAAO,EAAE,oCAAwB;gBACjC,UAAU,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,OAAO;aAC5C;SACJ;QACD,aAAa,EAAE,MAAM,CAAC,EAAE;;YACpB,MAAM,CAAC,aAAa,CAAC,uBAAuB,GAAG,IAAI,2DAA2B,EAAE,CAAC;YACjF,MAAM,CAAC,MAAM,GAAG,IAAI,wBAAU,CAAC,MAAA,eAAe,CAAC,OAAO,CAAC,aAAa,mCAAI,EAAE,CAAC,CAAC;YAC5E,OAAO,MAAM,CAAC;QAClB,CAAC;QACD,aAAa,EAAE,QAAQ;KAC1B,CAAC;IAMO,WAAA,IAAA,eAAM,EAAC,oCAAwB,CAAC,CAAA;qCADb,yCAAkB;GAJjC,eAAe,CAmB3B"}
@@ -0,0 +1,69 @@
1
+ import { Type } from '@vendure/common/lib/shared-types';
2
+ import { OtelLoggerOptions } from './config/otel-logger';
3
+ import { MethodHooksForType } from './service/method-hooks.service';
4
+ export interface MethodHookConfig<T> {
5
+ target: Type<T>;
6
+ hooks: MethodHooksForType<T>;
7
+ }
8
+ /**
9
+ * @description
10
+ * Configuration options for the TelemetryPlugin.
11
+ *
12
+ * @since 3.3.0
13
+ * @docsCategory core plugins/TelemetryPlugin
14
+ */
15
+ export interface TelemetryPluginOptions {
16
+ /**
17
+ * @description
18
+ * The options for the OtelLogger.
19
+ *
20
+ * For example, to also include logging to the console, you can use the following:
21
+ * ```ts
22
+ * import { LogLevel } from '\@vendure/core';
23
+ * import { TelemetryPlugin } from '\@vendure/telemetry-plugin';
24
+ *
25
+ * TelemetryPlugin.init({
26
+ * loggerOptions: {
27
+ * console: LogLevel.Verbose,
28
+ * },
29
+ * });
30
+ * ```
31
+ */
32
+ loggerOptions?: OtelLoggerOptions;
33
+ /**
34
+ * @description
35
+ * **Status: Developer Preview**
36
+ *
37
+ * This API may change in a future release.
38
+ *
39
+ * Method hooks allow you to add extra telemetry actions to specific methods.
40
+ * To define hooks on a method, use the {@link registerMethodHooks} function.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * import { TelemetryPlugin, registerMethodHooks } from '\@vendure/telemetry-plugin';
45
+ *
46
+ * TelemetryPlugin.init({
47
+ * methodHooks: [
48
+ * registerMethodHooks(ProductService, {
49
+ *
50
+ * // Define some hooks for the `findOne` method
51
+ * findOne: {
52
+ * // This will be called before the method is executed
53
+ * pre: ({ args: [ctx, productId], span }) => {
54
+ * span.setAttribute('productId', productId);
55
+ * },
56
+ * // This will be called after the method is executed
57
+ * post: ({ result, span }) => {
58
+ * span.setAttribute('found', !!result);
59
+ * },
60
+ * },
61
+ * }),
62
+ * ],
63
+ * });
64
+ * ```
65
+ *
66
+ * @experimental
67
+ */
68
+ methodHooks?: Array<MethodHookConfig<any>>;
69
+ }
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@vendure/telemetry-plugin",
3
+ "version": "3.3.0",
4
+ "description": "Telemetry for Vendure",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/vendure-ecommerce/vendure/"
8
+ },
9
+ "homepage": "https://www.vendure.io",
10
+ "funding": "https://github.com/sponsors/michaelbromley",
11
+ "private": false,
12
+ "license": "GPL-3.0-or-later",
13
+ "type": "commonjs",
14
+ "scripts": {
15
+ "build": "rimraf dist && tsc -p ./tsconfig.build.json",
16
+ "watch": "tsc -p ./tsconfig.build.json --watch"
17
+ },
18
+ "publishConfig": {
19
+ "access": "public"
20
+ },
21
+ "main": "dist/index.js",
22
+ "types": "dist/index.d.ts",
23
+ "files": [
24
+ "dist/**/*"
25
+ ],
26
+ "exports": {
27
+ ".": {
28
+ "types": "./dist/index.d.ts",
29
+ "default": "./dist/index.js"
30
+ },
31
+ "./preload": {
32
+ "types": "./dist/instrumentation.d.ts",
33
+ "default": "./dist/instrumentation.js"
34
+ }
35
+ },
36
+ "dependencies": {
37
+ "@opentelemetry/api": "^1.9.0",
38
+ "@opentelemetry/auto-instrumentations-node": "^0.58.0",
39
+ "@opentelemetry/context-async-hooks": "^2.0.0",
40
+ "@opentelemetry/exporter-logs-otlp-proto": "^0.200.0",
41
+ "@opentelemetry/exporter-trace-otlp-http": "^0.200.0",
42
+ "@opentelemetry/resources": "^2.0.0",
43
+ "@opentelemetry/sdk-logs": "^0.200.0",
44
+ "@opentelemetry/sdk-node": "^0.200.0",
45
+ "javascript-stringify": "^2.1.0"
46
+ },
47
+ "devDependencies": {
48
+ "@vendure/common": "3.3.0",
49
+ "@vendure/core": "3.3.0",
50
+ "typescript": "5.8.2"
51
+ },
52
+ "gitHead": "a4c56359ec831b0c54dd01eab14fb75455c43ab7"
53
+ }