@noony-serverless/core 0.3.3 → 0.4.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/build/core/containerPool.d.ts +129 -26
- package/build/core/containerPool.js +213 -68
- package/build/core/handler.d.ts +2 -2
- package/build/core/handler.js +6 -12
- package/build/core/index.d.ts +1 -0
- package/build/core/index.js +1 -0
- package/build/core/logger.d.ts +89 -1
- package/build/core/logger.js +136 -5
- package/build/core/telemetry/config.d.ts +331 -0
- package/build/core/telemetry/config.js +153 -0
- package/build/core/telemetry/index.d.ts +22 -0
- package/build/core/telemetry/index.js +45 -0
- package/build/core/telemetry/provider.d.ts +203 -0
- package/build/core/telemetry/provider.js +3 -0
- package/build/core/telemetry/providers/console-provider.d.ts +54 -0
- package/build/core/telemetry/providers/console-provider.js +124 -0
- package/build/core/telemetry/providers/index.d.ts +10 -0
- package/build/core/telemetry/providers/index.js +19 -0
- package/build/core/telemetry/providers/noop-provider.d.ts +51 -0
- package/build/core/telemetry/providers/noop-provider.js +67 -0
- package/build/core/telemetry/providers/opentelemetry-provider.d.ts +102 -0
- package/build/core/telemetry/providers/opentelemetry-provider.js +342 -0
- package/build/middlewares/ProcessingMiddleware.d.ts +6 -3
- package/build/middlewares/ProcessingMiddleware.js +3 -0
- package/build/middlewares/dependencyInjectionMiddleware.d.ts +23 -11
- package/build/middlewares/dependencyInjectionMiddleware.js +36 -12
- package/build/middlewares/guards/adapters/CustomTokenVerificationPortAdapter.d.ts +1 -1
- package/build/middlewares/guards/guards/FastAuthGuard.d.ts +5 -5
- package/build/middlewares/guards/guards/FastAuthGuard.js +3 -2
- package/build/middlewares/guards/guards/PermissionGuardFactory.d.ts +7 -9
- package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/ExpressionPermissionResolver.js +1 -1
- package/build/middlewares/guards/resolvers/PermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/PlainPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/resolvers/WildcardPermissionResolver.d.ts +1 -1
- package/build/middlewares/guards/services/FastUserContextService.d.ts +11 -32
- package/build/middlewares/headerVariablesMiddleware.d.ts +8 -4
- package/build/middlewares/headerVariablesMiddleware.js +5 -1
- package/build/middlewares/httpAttributesMiddleware.d.ts +5 -3
- package/build/middlewares/httpAttributesMiddleware.js +3 -1
- package/build/middlewares/index.d.ts +1 -0
- package/build/middlewares/index.js +1 -0
- package/build/middlewares/openTelemetryMiddleware.d.ts +162 -0
- package/build/middlewares/openTelemetryMiddleware.js +359 -0
- package/build/middlewares/rateLimitingMiddleware.d.ts +8 -6
- package/build/middlewares/rateLimitingMiddleware.js +19 -6
- package/build/middlewares/securityAuditMiddleware.d.ts +6 -3
- package/build/middlewares/securityAuditMiddleware.js +3 -0
- package/build/middlewares/securityHeadersMiddleware.d.ts +5 -2
- package/build/middlewares/securityHeadersMiddleware.js +3 -0
- package/build/middlewares/validationMiddleware.d.ts +8 -4
- package/build/middlewares/validationMiddleware.js +5 -1
- package/build/utils/container.utils.js +4 -1
- package/build/utils/fastify-wrapper.d.ts +74 -0
- package/build/utils/fastify-wrapper.js +175 -0
- package/build/utils/index.d.ts +4 -0
- package/build/utils/index.js +23 -1
- package/build/utils/otel.helper.d.ts +122 -0
- package/build/utils/otel.helper.js +258 -0
- package/build/utils/pubsub-trace.utils.d.ts +102 -0
- package/build/utils/pubsub-trace.utils.js +155 -0
- package/build/utils/wrapper-utils.d.ts +177 -0
- package/build/utils/wrapper-utils.js +236 -0
- package/package.json +61 -2
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NoopProvider = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Noop (No-operation) Telemetry Provider
|
|
6
|
+
*
|
|
7
|
+
* This provider does nothing and is used as:
|
|
8
|
+
* 1. Fallback when other providers fail validation
|
|
9
|
+
* 2. Default when telemetry is disabled (NODE_ENV=test)
|
|
10
|
+
* 3. Placeholder when no configuration is provided
|
|
11
|
+
*
|
|
12
|
+
* It implements all TelemetryProvider methods as no-ops to ensure
|
|
13
|
+
* the application continues to work even when telemetry fails.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* // Automatically used as fallback
|
|
17
|
+
* const provider = new NoopProvider();
|
|
18
|
+
* await provider.initialize({ serviceName: 'test' });
|
|
19
|
+
* const span = provider.createSpan(context); // Returns undefined
|
|
20
|
+
*/
|
|
21
|
+
class NoopProvider {
|
|
22
|
+
name = 'noop';
|
|
23
|
+
/**
|
|
24
|
+
* Noop provider is always valid
|
|
25
|
+
*/
|
|
26
|
+
async validate() {
|
|
27
|
+
return { valid: true };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* No-op initialization
|
|
31
|
+
*/
|
|
32
|
+
async initialize(_config) {
|
|
33
|
+
// Do nothing
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Always returns undefined (no span created)
|
|
37
|
+
*/
|
|
38
|
+
createSpan(_context) {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* No-op metric recording
|
|
43
|
+
*/
|
|
44
|
+
recordMetric(_name, _value, _attributes) {
|
|
45
|
+
// Do nothing
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* No-op logging
|
|
49
|
+
*/
|
|
50
|
+
log(_level, _message, _attributes) {
|
|
51
|
+
// Do nothing
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Always ready (does nothing, so always ready)
|
|
55
|
+
*/
|
|
56
|
+
isReady() {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* No-op shutdown
|
|
61
|
+
*/
|
|
62
|
+
async shutdown() {
|
|
63
|
+
// Do nothing
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.NoopProvider = NoopProvider;
|
|
67
|
+
//# sourceMappingURL=noop-provider.js.map
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { Context } from '../../core';
|
|
2
|
+
import { TelemetryProvider, ValidationResult, GenericSpan, TelemetryConfig } from '../provider';
|
|
3
|
+
/**
|
|
4
|
+
* Standard OpenTelemetry SDK 2.0 Provider
|
|
5
|
+
*
|
|
6
|
+
* Implements telemetry using the official OpenTelemetry JavaScript SDK.
|
|
7
|
+
* Supports OTLP exporters for traces, metrics, and logs.
|
|
8
|
+
*
|
|
9
|
+
* Requirements:
|
|
10
|
+
* - Node.js >= 18.19.0 or >= 20.6.0
|
|
11
|
+
* - OTEL_EXPORTER_OTLP_ENDPOINT environment variable
|
|
12
|
+
* - @opentelemetry/sdk-node and related packages installed
|
|
13
|
+
*
|
|
14
|
+
* Auto-selected when OTEL_EXPORTER_OTLP_ENDPOINT is set.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* // Environment setup
|
|
18
|
+
* OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318/v1/traces
|
|
19
|
+
*
|
|
20
|
+
* // Usage
|
|
21
|
+
* const provider = new OpenTelemetryProvider();
|
|
22
|
+
* const validation = await provider.validate();
|
|
23
|
+
* if (validation.valid) {
|
|
24
|
+
* await provider.initialize({
|
|
25
|
+
* serviceName: 'my-service',
|
|
26
|
+
* serviceVersion: '1.0.0'
|
|
27
|
+
* });
|
|
28
|
+
* }
|
|
29
|
+
*/
|
|
30
|
+
export declare class OpenTelemetryProvider implements TelemetryProvider {
|
|
31
|
+
readonly name = "opentelemetry";
|
|
32
|
+
private sdk?;
|
|
33
|
+
private tracer?;
|
|
34
|
+
private meter?;
|
|
35
|
+
private ready;
|
|
36
|
+
/**
|
|
37
|
+
* Validate OpenTelemetry configuration
|
|
38
|
+
*
|
|
39
|
+
* Checks:
|
|
40
|
+
* 1. OTEL_EXPORTER_OTLP_ENDPOINT is set
|
|
41
|
+
* 2. Endpoint is a valid URL
|
|
42
|
+
* 3. Required packages are available (checked lazily during init)
|
|
43
|
+
*/
|
|
44
|
+
validate(): Promise<ValidationResult>;
|
|
45
|
+
/**
|
|
46
|
+
* Initialize OpenTelemetry SDK
|
|
47
|
+
*
|
|
48
|
+
* Sets up:
|
|
49
|
+
* - Resource attributes (service name, version, environment)
|
|
50
|
+
* - OTLP trace exporter
|
|
51
|
+
* - Composite propagator (W3C + Cloud Trace)
|
|
52
|
+
* - Tracer and Meter providers
|
|
53
|
+
*/
|
|
54
|
+
initialize(config: TelemetryConfig): Promise<void>;
|
|
55
|
+
/**
|
|
56
|
+
* Create an OpenTelemetry span
|
|
57
|
+
*
|
|
58
|
+
* Creates a SERVER span with HTTP semantic conventions.
|
|
59
|
+
* Returns undefined if provider is not ready.
|
|
60
|
+
*/
|
|
61
|
+
createSpan(context: Context<unknown, unknown>): GenericSpan | undefined;
|
|
62
|
+
/**
|
|
63
|
+
* Record a metric as a histogram
|
|
64
|
+
*/
|
|
65
|
+
recordMetric(name: string, value: number, attributes?: Record<string, unknown>): void;
|
|
66
|
+
/**
|
|
67
|
+
* Log with trace correlation
|
|
68
|
+
*
|
|
69
|
+
* Adds trace and span IDs to log output when available.
|
|
70
|
+
*/
|
|
71
|
+
log(level: string, message: string, attributes?: Record<string, unknown>): void;
|
|
72
|
+
/**
|
|
73
|
+
* Check if OpenTelemetry provider is ready
|
|
74
|
+
*/
|
|
75
|
+
isReady(): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Shutdown OpenTelemetry SDK
|
|
78
|
+
*
|
|
79
|
+
* Flushes pending telemetry data and closes exporters.
|
|
80
|
+
*/
|
|
81
|
+
shutdown(): Promise<void>;
|
|
82
|
+
/**
|
|
83
|
+
* Create composite propagator based on configuration
|
|
84
|
+
*
|
|
85
|
+
* Supports:
|
|
86
|
+
* - W3C Trace Context (traceparent/tracestate)
|
|
87
|
+
* - Google Cloud Trace Context (X-Cloud-Trace-Context)
|
|
88
|
+
*
|
|
89
|
+
* When running on GCP, both formats are enabled by default for compatibility.
|
|
90
|
+
* This allows trace IDs to be synchronized between Cloud Run Load Balancer
|
|
91
|
+
* and your application.
|
|
92
|
+
*
|
|
93
|
+
* @param config Telemetry configuration
|
|
94
|
+
* @returns Configured propagator (W3C, Cloud Trace, or Composite)
|
|
95
|
+
*/
|
|
96
|
+
private createPropagator;
|
|
97
|
+
/**
|
|
98
|
+
* Detect if running on Google Cloud Platform
|
|
99
|
+
*/
|
|
100
|
+
private isRunningOnGCP;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=opentelemetry-provider.d.ts.map
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OpenTelemetryProvider = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Standard OpenTelemetry SDK 2.0 Provider
|
|
6
|
+
*
|
|
7
|
+
* Implements telemetry using the official OpenTelemetry JavaScript SDK.
|
|
8
|
+
* Supports OTLP exporters for traces, metrics, and logs.
|
|
9
|
+
*
|
|
10
|
+
* Requirements:
|
|
11
|
+
* - Node.js >= 18.19.0 or >= 20.6.0
|
|
12
|
+
* - OTEL_EXPORTER_OTLP_ENDPOINT environment variable
|
|
13
|
+
* - @opentelemetry/sdk-node and related packages installed
|
|
14
|
+
*
|
|
15
|
+
* Auto-selected when OTEL_EXPORTER_OTLP_ENDPOINT is set.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // Environment setup
|
|
19
|
+
* OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318/v1/traces
|
|
20
|
+
*
|
|
21
|
+
* // Usage
|
|
22
|
+
* const provider = new OpenTelemetryProvider();
|
|
23
|
+
* const validation = await provider.validate();
|
|
24
|
+
* if (validation.valid) {
|
|
25
|
+
* await provider.initialize({
|
|
26
|
+
* serviceName: 'my-service',
|
|
27
|
+
* serviceVersion: '1.0.0'
|
|
28
|
+
* });
|
|
29
|
+
* }
|
|
30
|
+
*/
|
|
31
|
+
class OpenTelemetryProvider {
|
|
32
|
+
name = 'opentelemetry';
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34
|
+
sdk; // NodeSDK
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
36
|
+
tracer; // Tracer
|
|
37
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
38
|
+
meter; // Meter
|
|
39
|
+
ready = false;
|
|
40
|
+
/**
|
|
41
|
+
* Validate OpenTelemetry configuration
|
|
42
|
+
*
|
|
43
|
+
* Checks:
|
|
44
|
+
* 1. OTEL_EXPORTER_OTLP_ENDPOINT is set
|
|
45
|
+
* 2. Endpoint is a valid URL
|
|
46
|
+
* 3. Required packages are available (checked lazily during init)
|
|
47
|
+
*/
|
|
48
|
+
async validate() {
|
|
49
|
+
const endpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
|
|
50
|
+
if (!endpoint) {
|
|
51
|
+
return {
|
|
52
|
+
valid: false,
|
|
53
|
+
reason: 'OTEL_EXPORTER_OTLP_ENDPOINT environment variable not set',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
new URL(endpoint);
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return {
|
|
61
|
+
valid: false,
|
|
62
|
+
reason: `OTEL_EXPORTER_OTLP_ENDPOINT is not a valid URL: ${endpoint}`,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return { valid: true };
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Initialize OpenTelemetry SDK
|
|
69
|
+
*
|
|
70
|
+
* Sets up:
|
|
71
|
+
* - Resource attributes (service name, version, environment)
|
|
72
|
+
* - OTLP trace exporter
|
|
73
|
+
* - Composite propagator (W3C + Cloud Trace)
|
|
74
|
+
* - Tracer and Meter providers
|
|
75
|
+
*/
|
|
76
|
+
async initialize(config) {
|
|
77
|
+
try {
|
|
78
|
+
// Dynamic require to avoid compile-time dependency on OTEL packages
|
|
79
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
80
|
+
const otelApi = require('@opentelemetry/api');
|
|
81
|
+
const { trace, metrics } = otelApi;
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
83
|
+
const sdkNode = require('@opentelemetry/sdk-node');
|
|
84
|
+
const { NodeSDK } = sdkNode;
|
|
85
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
86
|
+
const exporterHttp = require('@opentelemetry/exporter-trace-otlp-http');
|
|
87
|
+
const { OTLPTraceExporter } = exporterHttp;
|
|
88
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
89
|
+
const resources = require('@opentelemetry/resources');
|
|
90
|
+
const { Resource } = resources;
|
|
91
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
92
|
+
const semConv = require('@opentelemetry/semantic-conventions');
|
|
93
|
+
const { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } = semConv;
|
|
94
|
+
// Create resource with service metadata
|
|
95
|
+
const resource = new Resource({
|
|
96
|
+
[ATTR_SERVICE_NAME]: config.serviceName,
|
|
97
|
+
[ATTR_SERVICE_VERSION]: config.serviceVersion || '1.0.0',
|
|
98
|
+
environment: config.environment || 'production',
|
|
99
|
+
});
|
|
100
|
+
// Configure trace exporter
|
|
101
|
+
const traceExporter = new OTLPTraceExporter({
|
|
102
|
+
url: config.exporters?.traces?.[0]?.endpoint ||
|
|
103
|
+
process.env.OTEL_EXPORTER_OTLP_ENDPOINT,
|
|
104
|
+
headers: config.exporters?.traces?.[0]?.headers,
|
|
105
|
+
timeoutMillis: config.exporters?.traces?.[0]?.timeout,
|
|
106
|
+
});
|
|
107
|
+
// Configure composite propagator for W3C + Cloud Trace support
|
|
108
|
+
const textMapPropagator = this.createPropagator(config);
|
|
109
|
+
// Initialize SDK
|
|
110
|
+
this.sdk = new NodeSDK({
|
|
111
|
+
resource,
|
|
112
|
+
traceExporter,
|
|
113
|
+
textMapPropagator, // Use composite propagator
|
|
114
|
+
});
|
|
115
|
+
await this.sdk.start();
|
|
116
|
+
// Get tracer and meter
|
|
117
|
+
this.tracer = trace.getTracer(config.serviceName, config.serviceVersion || '1.0.0');
|
|
118
|
+
this.meter = metrics.getMeter(config.serviceName, config.serviceVersion || '1.0.0');
|
|
119
|
+
this.ready = true;
|
|
120
|
+
console.log('[Telemetry] OpenTelemetry provider initialized');
|
|
121
|
+
console.log('[Telemetry] Exporting to:', config.exporters?.traces?.[0]?.endpoint ||
|
|
122
|
+
process.env.OTEL_EXPORTER_OTLP_ENDPOINT);
|
|
123
|
+
}
|
|
124
|
+
catch (error) {
|
|
125
|
+
console.error('[Telemetry] Failed to initialize OpenTelemetry provider:', error);
|
|
126
|
+
this.ready = false;
|
|
127
|
+
// Check if error is due to missing packages
|
|
128
|
+
if (error instanceof Error &&
|
|
129
|
+
error.message.includes('Cannot find module')) {
|
|
130
|
+
console.error('[Telemetry] OpenTelemetry packages not installed. Run:');
|
|
131
|
+
console.error(' npm install @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/exporter-trace-otlp-http @opentelemetry/resources @opentelemetry/semantic-conventions');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Create an OpenTelemetry span
|
|
137
|
+
*
|
|
138
|
+
* Creates a SERVER span with HTTP semantic conventions.
|
|
139
|
+
* Returns undefined if provider is not ready.
|
|
140
|
+
*/
|
|
141
|
+
createSpan(context) {
|
|
142
|
+
if (!this.ready || !this.tracer)
|
|
143
|
+
return undefined;
|
|
144
|
+
try {
|
|
145
|
+
// Dynamic import for SpanKind
|
|
146
|
+
const SpanKind = 1; // SERVER = 1 in OpenTelemetry
|
|
147
|
+
const span = this.tracer.startSpan('http.request', {
|
|
148
|
+
kind: SpanKind,
|
|
149
|
+
attributes: {
|
|
150
|
+
'http.method': context.req.method,
|
|
151
|
+
'http.url': context.req.url || context.req.path,
|
|
152
|
+
'http.target': context.req.path || '/',
|
|
153
|
+
'request.id': context.requestId,
|
|
154
|
+
'http.user_agent': context.req.headers?.['user-agent'] || '',
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
return {
|
|
158
|
+
setAttributes: (attrs) => {
|
|
159
|
+
span.setAttributes(attrs);
|
|
160
|
+
},
|
|
161
|
+
recordException: (error) => {
|
|
162
|
+
span.recordException(error);
|
|
163
|
+
},
|
|
164
|
+
setStatus: (status) => {
|
|
165
|
+
span.setStatus(status);
|
|
166
|
+
},
|
|
167
|
+
end: () => {
|
|
168
|
+
span.end();
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
console.error('[Telemetry] Failed to create span:', error);
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Record a metric as a histogram
|
|
179
|
+
*/
|
|
180
|
+
recordMetric(name, value, attributes) {
|
|
181
|
+
if (!this.ready || !this.meter)
|
|
182
|
+
return;
|
|
183
|
+
try {
|
|
184
|
+
const histogram = this.meter.createHistogram(name, {
|
|
185
|
+
description: `Histogram for ${name}`,
|
|
186
|
+
unit: 'ms',
|
|
187
|
+
});
|
|
188
|
+
histogram.record(value, attributes);
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
console.error('[Telemetry] Failed to record metric:', error);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Log with trace correlation
|
|
196
|
+
*
|
|
197
|
+
* Adds trace and span IDs to log output when available.
|
|
198
|
+
*/
|
|
199
|
+
log(level, message, attributes) {
|
|
200
|
+
if (!this.ready)
|
|
201
|
+
return;
|
|
202
|
+
try {
|
|
203
|
+
// Try to get active span for correlation
|
|
204
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
205
|
+
const { trace } = require('@opentelemetry/api');
|
|
206
|
+
const span = trace.getActiveSpan();
|
|
207
|
+
const traceContext = span
|
|
208
|
+
? {
|
|
209
|
+
traceId: span.spanContext().traceId,
|
|
210
|
+
spanId: span.spanContext().spanId,
|
|
211
|
+
traceFlags: span.spanContext().traceFlags,
|
|
212
|
+
}
|
|
213
|
+
: {};
|
|
214
|
+
console.log(JSON.stringify({
|
|
215
|
+
level,
|
|
216
|
+
message,
|
|
217
|
+
...traceContext,
|
|
218
|
+
...attributes,
|
|
219
|
+
timestamp: new Date().toISOString(),
|
|
220
|
+
}));
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
// Fallback to simple logging
|
|
224
|
+
console.log(JSON.stringify({ level, message, ...attributes }));
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Check if OpenTelemetry provider is ready
|
|
229
|
+
*/
|
|
230
|
+
isReady() {
|
|
231
|
+
return this.ready;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Shutdown OpenTelemetry SDK
|
|
235
|
+
*
|
|
236
|
+
* Flushes pending telemetry data and closes exporters.
|
|
237
|
+
*/
|
|
238
|
+
async shutdown() {
|
|
239
|
+
if (this.ready && this.sdk) {
|
|
240
|
+
try {
|
|
241
|
+
await this.sdk.shutdown();
|
|
242
|
+
console.log('[Telemetry] OpenTelemetry provider shutdown complete');
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
console.error('[Telemetry] Error during shutdown:', error);
|
|
246
|
+
}
|
|
247
|
+
finally {
|
|
248
|
+
this.ready = false;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Create composite propagator based on configuration
|
|
254
|
+
*
|
|
255
|
+
* Supports:
|
|
256
|
+
* - W3C Trace Context (traceparent/tracestate)
|
|
257
|
+
* - Google Cloud Trace Context (X-Cloud-Trace-Context)
|
|
258
|
+
*
|
|
259
|
+
* When running on GCP, both formats are enabled by default for compatibility.
|
|
260
|
+
* This allows trace IDs to be synchronized between Cloud Run Load Balancer
|
|
261
|
+
* and your application.
|
|
262
|
+
*
|
|
263
|
+
* @param config Telemetry configuration
|
|
264
|
+
* @returns Configured propagator (W3C, Cloud Trace, or Composite)
|
|
265
|
+
*/
|
|
266
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
267
|
+
createPropagator(config) {
|
|
268
|
+
try {
|
|
269
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
270
|
+
const propagators = [];
|
|
271
|
+
// Determine which propagators to use
|
|
272
|
+
const useCloudTrace = config.propagation?.cloudTrace ?? this.isRunningOnGCP();
|
|
273
|
+
const useW3C = config.propagation?.w3c ?? true;
|
|
274
|
+
// Add Cloud Trace propagator (priority 1 - reads X-Cloud-Trace-Context from GCP)
|
|
275
|
+
if (useCloudTrace) {
|
|
276
|
+
try {
|
|
277
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
278
|
+
const cloudPropagator = require('@google-cloud/opentelemetry-cloud-trace-propagator');
|
|
279
|
+
const { CloudPropagator } = cloudPropagator;
|
|
280
|
+
propagators.push(new CloudPropagator());
|
|
281
|
+
console.log('[Telemetry] CloudPropagator enabled for GCP trace compatibility');
|
|
282
|
+
}
|
|
283
|
+
catch (error) {
|
|
284
|
+
console.warn('[Telemetry] CloudPropagator requested but package not installed:', error instanceof Error ? error.message : error);
|
|
285
|
+
console.warn('[Telemetry] Install with: npm install @google-cloud/opentelemetry-cloud-trace-propagator');
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
// Add W3C Trace Context propagator (priority 2 - standard traceparent)
|
|
289
|
+
if (useW3C) {
|
|
290
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
291
|
+
const otelCore = require('@opentelemetry/core');
|
|
292
|
+
const { W3CTraceContextPropagator } = otelCore;
|
|
293
|
+
propagators.push(new W3CTraceContextPropagator());
|
|
294
|
+
console.log('[Telemetry] W3CTraceContextPropagator enabled');
|
|
295
|
+
}
|
|
296
|
+
// If multiple propagators, use CompositePropagator
|
|
297
|
+
if (propagators.length > 1) {
|
|
298
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
299
|
+
const otelCore = require('@opentelemetry/core');
|
|
300
|
+
const { CompositePropagator } = otelCore;
|
|
301
|
+
return new CompositePropagator({ propagators });
|
|
302
|
+
}
|
|
303
|
+
// If only one propagator, use it directly
|
|
304
|
+
if (propagators.length === 1) {
|
|
305
|
+
return propagators[0];
|
|
306
|
+
}
|
|
307
|
+
// Fallback to W3C if no propagators configured
|
|
308
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
309
|
+
const otelCore = require('@opentelemetry/core');
|
|
310
|
+
const { W3CTraceContextPropagator } = otelCore;
|
|
311
|
+
return new W3CTraceContextPropagator();
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
console.error('[Telemetry] Failed to create propagator:', error);
|
|
315
|
+
// Return W3C propagator as safe fallback
|
|
316
|
+
try {
|
|
317
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
318
|
+
const otelCore = require('@opentelemetry/core');
|
|
319
|
+
const { W3CTraceContextPropagator } = otelCore;
|
|
320
|
+
return new W3CTraceContextPropagator();
|
|
321
|
+
}
|
|
322
|
+
catch (fallbackError) {
|
|
323
|
+
console.error('[Telemetry] Failed to create fallback propagator:', fallbackError);
|
|
324
|
+
return undefined;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Detect if running on Google Cloud Platform
|
|
330
|
+
*/
|
|
331
|
+
isRunningOnGCP() {
|
|
332
|
+
return !!(process.env.GOOGLE_CLOUD_PROJECT ||
|
|
333
|
+
process.env.GCLOUD_PROJECT ||
|
|
334
|
+
process.env.GCP_PROJECT ||
|
|
335
|
+
process.env.K_SERVICE || // Cloud Run
|
|
336
|
+
process.env.FUNCTION_NAME || // Cloud Functions
|
|
337
|
+
process.env.GAE_APPLICATION // App Engine
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
exports.OpenTelemetryProvider = OpenTelemetryProvider;
|
|
342
|
+
//# sourceMappingURL=opentelemetry-provider.js.map
|
|
@@ -42,7 +42,7 @@ export interface ProcessingMiddlewareConfig {
|
|
|
42
42
|
parser?: BodyParserConfig;
|
|
43
43
|
query?: QueryProcessingConfig;
|
|
44
44
|
attributes?: AttributesConfig;
|
|
45
|
-
skipProcessing?: (context: Context) => boolean;
|
|
45
|
+
skipProcessing?: <TBody, TUser>(context: Context<TBody, TUser>) => boolean;
|
|
46
46
|
}
|
|
47
47
|
/**
|
|
48
48
|
* Consolidated ProcessingMiddleware that combines body parsing, query processing, and attribute extraction.
|
|
@@ -52,6 +52,9 @@ export interface ProcessingMiddlewareConfig {
|
|
|
52
52
|
* - QueryParametersMiddleware
|
|
53
53
|
* - HttpAttributesMiddleware
|
|
54
54
|
*
|
|
55
|
+
* @template TBody - The type of the request body payload (preserves type chain)
|
|
56
|
+
* @template TUser - The type of the authenticated user (preserves type chain)
|
|
57
|
+
*
|
|
55
58
|
* @example
|
|
56
59
|
* Complete processing setup:
|
|
57
60
|
* ```typescript
|
|
@@ -95,10 +98,10 @@ export interface ProcessingMiddlewareConfig {
|
|
|
95
98
|
* }));
|
|
96
99
|
* ```
|
|
97
100
|
*/
|
|
98
|
-
export declare class ProcessingMiddleware implements BaseMiddleware {
|
|
101
|
+
export declare class ProcessingMiddleware<TBody = unknown, TUser = unknown> implements BaseMiddleware<TBody, TUser> {
|
|
99
102
|
private config;
|
|
100
103
|
constructor(config?: ProcessingMiddlewareConfig);
|
|
101
|
-
before(context: Context): Promise<void>;
|
|
104
|
+
before(context: Context<TBody, TUser>): Promise<void>;
|
|
102
105
|
private extractAttributes;
|
|
103
106
|
private processQueryParameters;
|
|
104
107
|
private parseBody;
|
|
@@ -10,6 +10,9 @@ const core_1 = require("../core");
|
|
|
10
10
|
* - QueryParametersMiddleware
|
|
11
11
|
* - HttpAttributesMiddleware
|
|
12
12
|
*
|
|
13
|
+
* @template TBody - The type of the request body payload (preserves type chain)
|
|
14
|
+
* @template TUser - The type of the authenticated user (preserves type chain)
|
|
15
|
+
*
|
|
13
16
|
* @example
|
|
14
17
|
* Complete processing setup:
|
|
15
18
|
* ```typescript
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { BaseMiddleware, Context } from '../core';
|
|
2
|
+
import { ServiceDefinition } from '../core/containerPool';
|
|
2
3
|
/**
|
|
3
4
|
* Middleware to inject dependencies into the request context using typedi.
|
|
4
5
|
* This allows handlers to access shared services or data via context.container.
|
|
5
6
|
*
|
|
6
|
-
* @
|
|
7
|
+
* @template TBody - The type of the request body payload (preserves type chain)
|
|
8
|
+
* @template TUser - The type of the authenticated user (preserves type chain)
|
|
9
|
+
* @implements {BaseMiddleware<TBody, TUser>}
|
|
7
10
|
*
|
|
8
11
|
* @example
|
|
9
12
|
* Basic service injection:
|
|
@@ -145,18 +148,24 @@ import { BaseMiddleware, Context } from '../core';
|
|
|
145
148
|
* });
|
|
146
149
|
* ```
|
|
147
150
|
*/
|
|
148
|
-
export declare class DependencyInjectionMiddleware implements BaseMiddleware {
|
|
151
|
+
export declare class DependencyInjectionMiddleware<TBody = unknown, TUser = unknown> implements BaseMiddleware<TBody, TUser> {
|
|
149
152
|
private services;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
private options?;
|
|
154
|
+
constructor(services?: ServiceDefinition[], options?: {
|
|
155
|
+
/**
|
|
156
|
+
* Service scope: 'global' for process-lifetime, 'local' for request-lifetime
|
|
157
|
+
* @default 'local'
|
|
158
|
+
*/
|
|
159
|
+
scope?: "global" | "local";
|
|
160
|
+
} | undefined);
|
|
161
|
+
before(context: Context<TBody, TUser>): Promise<void>;
|
|
155
162
|
}
|
|
156
163
|
/**
|
|
157
164
|
* Factory function that creates a dependency injection middleware.
|
|
158
165
|
* Creates a new container instance for each request to avoid shared state issues.
|
|
159
166
|
*
|
|
167
|
+
* @template TBody - The type of the request body payload (preserves type chain)
|
|
168
|
+
* @template TUser - The type of the authenticated user (preserves type chain)
|
|
160
169
|
* @param services - Array of service definitions with id and value
|
|
161
170
|
* @returns BaseMiddleware object with dependency injection logic
|
|
162
171
|
*
|
|
@@ -245,8 +254,11 @@ export declare class DependencyInjectionMiddleware implements BaseMiddleware {
|
|
|
245
254
|
* });
|
|
246
255
|
* ```
|
|
247
256
|
*/
|
|
248
|
-
export declare const dependencyInjection: (services?: {
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
257
|
+
export declare const dependencyInjection: <TBody = unknown, TUser = unknown>(services?: ServiceDefinition[], options?: {
|
|
258
|
+
/**
|
|
259
|
+
* Service scope: 'global' for process-lifetime, 'local' for request-lifetime
|
|
260
|
+
* @default 'local'
|
|
261
|
+
*/
|
|
262
|
+
scope?: "global" | "local";
|
|
263
|
+
}) => BaseMiddleware<TBody, TUser>;
|
|
252
264
|
//# sourceMappingURL=dependencyInjectionMiddleware.d.ts.map
|