@generazioneai/telemetry 0.0.1 → 0.1.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/CHANGELOG.md +8 -0
- package/README.md +43 -1
- package/dist/attributes.d.ts +13 -0
- package/dist/attributes.d.ts.map +1 -0
- package/dist/attributes.js +115 -0
- package/dist/attributes.js.map +1 -0
- package/dist/config.d.ts +20 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +39 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/log-context.d.ts +8 -0
- package/dist/log-context.d.ts.map +1 -0
- package/dist/log-context.js +13 -0
- package/dist/log-context.js.map +1 -0
- package/dist/logger/index.d.ts +10 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/index.js +23 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/logger/json-logger.d.ts +39 -0
- package/dist/logger/json-logger.d.ts.map +1 -0
- package/dist/logger/json-logger.js +127 -0
- package/dist/logger/json-logger.js.map +1 -0
- package/dist/nats.interceptor.d.ts +18 -0
- package/dist/nats.interceptor.d.ts.map +1 -0
- package/dist/nats.interceptor.js +124 -0
- package/dist/nats.interceptor.js.map +1 -0
- package/dist/propagation.d.ts +18 -0
- package/dist/propagation.d.ts.map +1 -0
- package/dist/propagation.js +37 -0
- package/dist/propagation.js.map +1 -0
- package/dist/redaction.d.ts +13 -0
- package/dist/redaction.d.ts.map +1 -0
- package/dist/redaction.js +133 -0
- package/dist/redaction.js.map +1 -0
- package/dist/register.d.ts +2 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +10 -0
- package/dist/register.js.map +1 -0
- package/dist/sanitizing-exporter.d.ts +13 -0
- package/dist/sanitizing-exporter.d.ts.map +1 -0
- package/dist/sanitizing-exporter.js +45 -0
- package/dist/sanitizing-exporter.js.map +1 -0
- package/dist/sdk.d.ts +18 -0
- package/dist/sdk.d.ts.map +1 -0
- package/dist/sdk.js +94 -0
- package/dist/sdk.js.map +1 -0
- package/dist/telemetry.module.d.ts +26 -0
- package/dist/telemetry.module.d.ts.map +1 -0
- package/dist/telemetry.module.js +78 -0
- package/dist/telemetry.module.js.map +1 -0
- package/package.json +92 -4
|
@@ -0,0 +1,124 @@
|
|
|
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.NatsTelemetryInterceptor = void 0;
|
|
10
|
+
exports.resolveCmd = resolveCmd;
|
|
11
|
+
exports.pickJuridicalId = pickJuridicalId;
|
|
12
|
+
require("reflect-metadata");
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const api_1 = require("@opentelemetry/api");
|
|
15
|
+
const rxjs_1 = require("rxjs");
|
|
16
|
+
const log_context_1 = require("./log-context");
|
|
17
|
+
const propagation_1 = require("./propagation");
|
|
18
|
+
const PATTERN_METADATA = 'microservices:pattern';
|
|
19
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
20
|
+
/** Il nome del comando di un handler `@MessagePattern({ cmd: 'x.y' })` (o `@EventPattern`), altrimenti il subject NATS. */
|
|
21
|
+
function resolveCmd(handler, subject) {
|
|
22
|
+
const patterns = typeof handler === 'function' ? Reflect.getMetadata(PATTERN_METADATA, handler) : undefined;
|
|
23
|
+
const first = patterns?.[0];
|
|
24
|
+
if (typeof first === 'string')
|
|
25
|
+
return first.slice(0, 120);
|
|
26
|
+
if (first && typeof first === 'object' && typeof first.cmd === 'string') {
|
|
27
|
+
return first.cmd.slice(0, 120);
|
|
28
|
+
}
|
|
29
|
+
if (first !== undefined)
|
|
30
|
+
return JSON.stringify(first).slice(0, 120);
|
|
31
|
+
return (subject ?? 'unknown').slice(0, 120);
|
|
32
|
+
}
|
|
33
|
+
function uuidOrUndefined(v) {
|
|
34
|
+
return typeof v === 'string' && UUID.test(v) ? v : undefined;
|
|
35
|
+
}
|
|
36
|
+
/** L'azienda del messaggio, solo se è un UUID: dall'intestazione `Gen-Tenant` o dall'`auth`/dal payload. Mai altri campi. */
|
|
37
|
+
function pickJuridicalId(headers, data) {
|
|
38
|
+
const fromHeader = uuidOrUndefined(headers?.get('Gen-Tenant'));
|
|
39
|
+
if (fromHeader)
|
|
40
|
+
return fromHeader;
|
|
41
|
+
const d = (data ?? {});
|
|
42
|
+
return uuidOrUndefined(d.auth?.juridicalId) ?? uuidOrUndefined(d.auth?.tenantId) ?? uuidOrUndefined(d.juridicalId) ?? uuidOrUndefined(d.dto?.juridicalId);
|
|
43
|
+
}
|
|
44
|
+
const meter = api_1.metrics.getMeter('@generazioneai/telemetry');
|
|
45
|
+
const requests = meter.createCounter('nats_server_requests_total', { description: 'Comandi NATS gestiti dal servizio, per comando ed esito' });
|
|
46
|
+
const durations = meter.createHistogram('nats_server_request_duration_seconds', {
|
|
47
|
+
description: 'Durata dei comandi NATS gestiti dal servizio',
|
|
48
|
+
unit: 's',
|
|
49
|
+
advice: { explicitBucketBoundaries: [0.005, 0.025, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30] },
|
|
50
|
+
});
|
|
51
|
+
/**
|
|
52
|
+
* Lato servizio: per ogni messaggio NATS apre lo span `nats.server <cmd>` figlio del `traceparent` negli header, mette `cmd`
|
|
53
|
+
* e `juridicalId` nel contesto dei log del comando e conta durata ed esito. Non tocca mai il payload: negli span entrano
|
|
54
|
+
* solo gli attributi a lista bianca. Gli altri tipi di contesto (HTTP) passano senza cambiamenti.
|
|
55
|
+
*/
|
|
56
|
+
let NatsTelemetryInterceptor = class NatsTelemetryInterceptor {
|
|
57
|
+
constructor() {
|
|
58
|
+
this.tracer = api_1.trace.getTracer('@generazioneai/telemetry');
|
|
59
|
+
}
|
|
60
|
+
intercept(execution, next) {
|
|
61
|
+
if (execution.getType() !== 'rpc')
|
|
62
|
+
return next.handle();
|
|
63
|
+
const rpc = execution.switchToRpc();
|
|
64
|
+
const nats = rpc.getContext();
|
|
65
|
+
const headers = typeof nats?.getHeaders === 'function' ? nats.getHeaders() : undefined;
|
|
66
|
+
const subject = typeof nats?.getSubject === 'function' ? nats.getSubject() : undefined;
|
|
67
|
+
const cmd = resolveCmd(execution.getHandler(), subject);
|
|
68
|
+
const juridicalId = pickJuridicalId(headers, rpc.getData());
|
|
69
|
+
const parent = (0, propagation_1.extractTraceContext)(headers);
|
|
70
|
+
return new rxjs_1.Observable((subscriber) => {
|
|
71
|
+
const started = process.hrtime.bigint();
|
|
72
|
+
const span = this.tracer.startSpan(`nats.server ${cmd}`, {
|
|
73
|
+
kind: api_1.SpanKind.CONSUMER,
|
|
74
|
+
attributes: {
|
|
75
|
+
'messaging.system': 'nats',
|
|
76
|
+
'messaging.operation': 'process',
|
|
77
|
+
...(subject ? { 'messaging.destination.name': subject.slice(0, 120) } : {}),
|
|
78
|
+
cmd,
|
|
79
|
+
...(juridicalId ? { juridicalId } : {}),
|
|
80
|
+
},
|
|
81
|
+
}, parent);
|
|
82
|
+
let done = false;
|
|
83
|
+
const finish = (outcome, error) => {
|
|
84
|
+
if (done)
|
|
85
|
+
return;
|
|
86
|
+
done = true;
|
|
87
|
+
const seconds = Number(process.hrtime.bigint() - started) / 1e9;
|
|
88
|
+
span.setAttribute('outcome', outcome);
|
|
89
|
+
span.setAttribute('duration_ms', Math.round(seconds * 1000));
|
|
90
|
+
if (outcome === 'error') {
|
|
91
|
+
// Niente messaggio dell'errore: può citare dati personali.
|
|
92
|
+
span.setAttribute('error.type', error instanceof Error ? error.name : 'Error');
|
|
93
|
+
span.setStatus({ code: api_1.SpanStatusCode.ERROR });
|
|
94
|
+
}
|
|
95
|
+
span.end();
|
|
96
|
+
requests.add(1, { cmd, outcome });
|
|
97
|
+
durations.record(seconds, { cmd });
|
|
98
|
+
};
|
|
99
|
+
let inner;
|
|
100
|
+
api_1.context.with(api_1.trace.setSpan(parent, span), () => (0, log_context_1.runWithLogContext)({ cmd, juridicalId }, () => {
|
|
101
|
+
inner = next.handle().subscribe({
|
|
102
|
+
next: (v) => subscriber.next(v),
|
|
103
|
+
error: (e) => {
|
|
104
|
+
finish('error', e);
|
|
105
|
+
subscriber.error(e);
|
|
106
|
+
},
|
|
107
|
+
complete: () => {
|
|
108
|
+
finish('ok');
|
|
109
|
+
subscriber.complete();
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
}));
|
|
113
|
+
return () => {
|
|
114
|
+
inner?.unsubscribe();
|
|
115
|
+
finish('ok');
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
exports.NatsTelemetryInterceptor = NatsTelemetryInterceptor;
|
|
121
|
+
exports.NatsTelemetryInterceptor = NatsTelemetryInterceptor = __decorate([
|
|
122
|
+
(0, common_1.Injectable)()
|
|
123
|
+
], NatsTelemetryInterceptor);
|
|
124
|
+
//# sourceMappingURL=nats.interceptor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nats.interceptor.js","sourceRoot":"","sources":["../src/nats.interceptor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type Context } from '@opentelemetry/api';
|
|
2
|
+
/** La parte di `MsgHdrs` (`@nats-io/nats-core`) che serve: `get`/`set`/`has`. */
|
|
3
|
+
export interface HeadersLike {
|
|
4
|
+
get(key: string): string;
|
|
5
|
+
set(key: string, value: string): void;
|
|
6
|
+
}
|
|
7
|
+
export interface ReadableHeadersLike {
|
|
8
|
+
get(key: string): string;
|
|
9
|
+
}
|
|
10
|
+
/** Firma del hook che `@generazioneai/authz` ≥ 0.7 chiama prima di ogni invio NATS (`setNatsHeadersHook`). `ctx` è il contesto di authz. */
|
|
11
|
+
export type NatsHeadersHook = (headers: HeadersLike, ctx?: unknown) => void;
|
|
12
|
+
/** Scrive `traceparent` (e `tracestate`) dallo span attivo negli header. Senza span attivo non scrive nulla. */
|
|
13
|
+
export declare function injectTraceContext(headers: HeadersLike, ctx?: Context): void;
|
|
14
|
+
/** Il contesto remoto dagli header NATS (o il contesto attivo se `traceparent` manca). */
|
|
15
|
+
export declare function extractTraceContext(headers: ReadableHeadersLike | undefined | null, base?: Context): Context;
|
|
16
|
+
/** Da passare ad `authz.setNatsHeadersHook(traceparentHeadersHook)` (lo fa `TelemetryModule.forRoot` se il pacchetto lo espone). */
|
|
17
|
+
export declare const traceparentHeadersHook: NatsHeadersHook;
|
|
18
|
+
//# sourceMappingURL=propagation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"propagation.d.ts","sourceRoot":"","sources":["../src/propagation.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,KAAK,OAAO,EAA0C,MAAM,oBAAoB,CAAC;AAEvH,iFAAiF;AACjF,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACvC;AACD,MAAM,WAAW,mBAAmB;IAClC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1B;AAED,4IAA4I;AAC5I,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;AAW5E,gHAAgH;AAChH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,GAAE,OAA0B,GAAG,IAAI,CAG9F;AAED,0FAA0F;AAC1F,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,GAAG,SAAS,GAAG,IAAI,EAAE,IAAI,GAAE,OAA0B,GAAG,OAAO,CAG9H;AAED,oIAAoI;AACpI,eAAO,MAAM,sBAAsB,EAAE,eAMpC,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.traceparentHeadersHook = void 0;
|
|
4
|
+
exports.injectTraceContext = injectTraceContext;
|
|
5
|
+
exports.extractTraceContext = extractTraceContext;
|
|
6
|
+
const api_1 = require("@opentelemetry/api");
|
|
7
|
+
const setter = { set: (h, k, v) => h.set(k, v) };
|
|
8
|
+
const getter = {
|
|
9
|
+
keys: () => ['traceparent', 'tracestate'],
|
|
10
|
+
get: (h, k) => {
|
|
11
|
+
const v = h?.get(k);
|
|
12
|
+
return v ? v : undefined;
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
/** Scrive `traceparent` (e `tracestate`) dallo span attivo negli header. Senza span attivo non scrive nulla. */
|
|
16
|
+
function injectTraceContext(headers, ctx = api_1.context.active()) {
|
|
17
|
+
if (!api_1.trace.getSpan(ctx)?.spanContext())
|
|
18
|
+
return;
|
|
19
|
+
api_1.propagation.inject(ctx, headers, setter);
|
|
20
|
+
}
|
|
21
|
+
/** Il contesto remoto dagli header NATS (o il contesto attivo se `traceparent` manca). */
|
|
22
|
+
function extractTraceContext(headers, base = api_1.context.active()) {
|
|
23
|
+
if (!headers)
|
|
24
|
+
return base;
|
|
25
|
+
return api_1.propagation.extract(base, headers, getter);
|
|
26
|
+
}
|
|
27
|
+
/** Da passare ad `authz.setNatsHeadersHook(traceparentHeadersHook)` (lo fa `TelemetryModule.forRoot` se il pacchetto lo espone). */
|
|
28
|
+
const traceparentHeadersHook = (headers) => {
|
|
29
|
+
try {
|
|
30
|
+
injectTraceContext(headers);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
/* la telemetria non deve mai rompere un invio */
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
exports.traceparentHeadersHook = traceparentHeadersHook;
|
|
37
|
+
//# sourceMappingURL=propagation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"propagation.js","sourceRoot":"","sources":["../src/propagation.ts"],"names":[],"mappings":";;;AAwBA,gDAGC;AAGD,kDAGC;AAjCD,4CAAuH;AAcvH,MAAM,MAAM,GAA+B,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;AAC7E,MAAM,MAAM,GAAmD;IAC7D,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,aAAa,EAAE,YAAY,CAAC;IACzC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACZ,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;QACpB,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3B,CAAC;CACF,CAAC;AAEF,gHAAgH;AAChH,SAAgB,kBAAkB,CAAC,OAAoB,EAAE,MAAe,aAAO,CAAC,MAAM,EAAE;IACtF,IAAI,CAAC,WAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,WAAW,EAAE;QAAE,OAAO;IAC/C,iBAAW,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAC3C,CAAC;AAED,0FAA0F;AAC1F,SAAgB,mBAAmB,CAAC,OAA+C,EAAE,OAAgB,aAAO,CAAC,MAAM,EAAE;IACnH,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,OAAO,iBAAW,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AACpD,CAAC;AAED,oIAAoI;AAC7H,MAAM,sBAAsB,GAAoB,CAAC,OAAO,EAAE,EAAE;IACjE,IAAI,CAAC;QACH,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,iDAAiD;IACnD,CAAC;AACH,CAAC,CAAC;AANW,QAAA,sBAAsB,0BAMjC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redazione dei dati personali (decisione 35). Due livelli:
|
|
3
|
+
* - chiavi: ciò che per nome porta dati personali o segreti (`Authorization`, `cookie`, corpi, email, nomi, codici fiscali…)
|
|
4
|
+
* perde il valore;
|
|
5
|
+
* - testo: ogni stringa ha email, codici fiscali, IBAN, JWT e `Bearer …` mascherati, anche se la chiave è innocua.
|
|
6
|
+
*/
|
|
7
|
+
export declare const REDACTED = "[redacted]";
|
|
8
|
+
export declare function isSensitiveKey(key: string): boolean;
|
|
9
|
+
/** Maschera nel testo ciò che sembra email, codice fiscale, IBAN, JWT o credenziale. */
|
|
10
|
+
export declare function maskString(text: string): string;
|
|
11
|
+
/** Copia ripulita di un valore qualsiasi (log, eccezioni, attributi). Non modifica l'originale. */
|
|
12
|
+
export declare function redact(value: unknown, depth?: number, seen?: WeakSet<object>): unknown;
|
|
13
|
+
//# sourceMappingURL=redaction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redaction.d.ts","sourceRoot":"","sources":["../src/redaction.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,eAAe,CAAC;AAsErC,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAKnD;AAED,wFAAwF;AACxF,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI/C;AAED,mGAAmG;AACnG,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,SAAI,EAAE,IAAI,GAAE,OAAO,CAAC,MAAM,CAAiB,GAAG,OAAO,CA6BhG"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.REDACTED = void 0;
|
|
4
|
+
exports.isSensitiveKey = isSensitiveKey;
|
|
5
|
+
exports.maskString = maskString;
|
|
6
|
+
exports.redact = redact;
|
|
7
|
+
/**
|
|
8
|
+
* Redazione dei dati personali (decisione 35). Due livelli:
|
|
9
|
+
* - chiavi: ciò che per nome porta dati personali o segreti (`Authorization`, `cookie`, corpi, email, nomi, codici fiscali…)
|
|
10
|
+
* perde il valore;
|
|
11
|
+
* - testo: ogni stringa ha email, codici fiscali, IBAN, JWT e `Bearer …` mascherati, anche se la chiave è innocua.
|
|
12
|
+
*/
|
|
13
|
+
exports.REDACTED = '[redacted]';
|
|
14
|
+
const EMAIL = /[A-Za-z0-9._%+'-]+@[A-Za-z0-9-]+(?:\.[A-Za-z0-9-]+)+/g;
|
|
15
|
+
// Codice fiscale italiano, con le lettere dell'omocodia al posto delle cifre.
|
|
16
|
+
const FISCAL_CODE = /\b[A-Za-z]{6}[0-9LMNPQRSTUVlmnpqrstuv]{2}[A-Za-z][0-9LMNPQRSTUVlmnpqrstuv]{2}[A-Za-z][0-9LMNPQRSTUVlmnpqrstuv]{3}[A-Za-z]\b/g;
|
|
17
|
+
const IBAN = /\b[A-Z]{2}\d{2}[A-Z0-9]{11,30}\b/g;
|
|
18
|
+
const JWT = /\beyJ[A-Za-z0-9_-]{5,}\.[A-Za-z0-9_-]{5,}\.[A-Za-z0-9_-]*\b/g;
|
|
19
|
+
const BEARER = /\b(Bearer|Basic)\s+[A-Za-z0-9._~+/=-]{8,}/gi;
|
|
20
|
+
const MAX_STRING = 2000;
|
|
21
|
+
const MAX_DEPTH = 6;
|
|
22
|
+
const MAX_ITEMS = 50;
|
|
23
|
+
/** Chiavi (normalizzate: minuscole, senza `-` `_` `.`) che non portano mai il valore. */
|
|
24
|
+
const SENSITIVE_EXACT = new Set([
|
|
25
|
+
'authorization',
|
|
26
|
+
'proxyauthorization',
|
|
27
|
+
'cookie',
|
|
28
|
+
'setcookie',
|
|
29
|
+
'xapikey',
|
|
30
|
+
'apikey',
|
|
31
|
+
'password',
|
|
32
|
+
'passwd',
|
|
33
|
+
'pwd',
|
|
34
|
+
'secret',
|
|
35
|
+
'clientsecret',
|
|
36
|
+
'token',
|
|
37
|
+
'accesstoken',
|
|
38
|
+
'refreshtoken',
|
|
39
|
+
'idtoken',
|
|
40
|
+
'otp',
|
|
41
|
+
'pin',
|
|
42
|
+
'body',
|
|
43
|
+
'rawbody',
|
|
44
|
+
'payload',
|
|
45
|
+
'data',
|
|
46
|
+
'dto',
|
|
47
|
+
'snapshot',
|
|
48
|
+
'headers',
|
|
49
|
+
'email',
|
|
50
|
+
'mail',
|
|
51
|
+
'pec',
|
|
52
|
+
'phone',
|
|
53
|
+
'telefono',
|
|
54
|
+
'cellulare',
|
|
55
|
+
'mobile',
|
|
56
|
+
'iban',
|
|
57
|
+
'address',
|
|
58
|
+
'indirizzo',
|
|
59
|
+
'birthdate',
|
|
60
|
+
'birthplace',
|
|
61
|
+
'dateofbirth',
|
|
62
|
+
'datanascita',
|
|
63
|
+
'cf',
|
|
64
|
+
'taxcode',
|
|
65
|
+
'vatnumber',
|
|
66
|
+
'partitaiva',
|
|
67
|
+
'name',
|
|
68
|
+
'nome',
|
|
69
|
+
'cognome',
|
|
70
|
+
'surname',
|
|
71
|
+
]);
|
|
72
|
+
const SENSITIVE_SUFFIX = ['name', 'nome', 'email', 'secret', 'password', 'token', 'fiscalcode', 'codicefiscale', 'iban', 'cookie'];
|
|
73
|
+
/** Chiavi tecniche che finiscono in `name` ma non sono persone. */
|
|
74
|
+
const NOT_PERSONAL = new Set(['servicename', 'hostname', 'filename', 'loggername', 'consumername', 'jobname', 'queuename', 'streamname', 'cmd', 'contextname']);
|
|
75
|
+
function normalize(key) {
|
|
76
|
+
return key.toLowerCase().replace(/[-_.\s]/g, '');
|
|
77
|
+
}
|
|
78
|
+
function isSensitiveKey(key) {
|
|
79
|
+
const k = normalize(key);
|
|
80
|
+
if (NOT_PERSONAL.has(k))
|
|
81
|
+
return false;
|
|
82
|
+
if (SENSITIVE_EXACT.has(k))
|
|
83
|
+
return true;
|
|
84
|
+
return SENSITIVE_SUFFIX.some((s) => k.endsWith(s));
|
|
85
|
+
}
|
|
86
|
+
/** Maschera nel testo ciò che sembra email, codice fiscale, IBAN, JWT o credenziale. */
|
|
87
|
+
function maskString(text) {
|
|
88
|
+
let out = text.length > MAX_STRING ? `${text.slice(0, MAX_STRING)}…` : text;
|
|
89
|
+
out = out.replace(BEARER, '$1 [redacted]').replace(JWT, '[jwt]').replace(EMAIL, '[email]').replace(IBAN, '[iban]').replace(FISCAL_CODE, '[cf]');
|
|
90
|
+
return out;
|
|
91
|
+
}
|
|
92
|
+
/** Copia ripulita di un valore qualsiasi (log, eccezioni, attributi). Non modifica l'originale. */
|
|
93
|
+
function redact(value, depth = 0, seen = new WeakSet()) {
|
|
94
|
+
if (value === null || value === undefined)
|
|
95
|
+
return value;
|
|
96
|
+
if (typeof value === 'string')
|
|
97
|
+
return maskString(value);
|
|
98
|
+
if (typeof value === 'number' || typeof value === 'boolean')
|
|
99
|
+
return value;
|
|
100
|
+
if (typeof value === 'bigint')
|
|
101
|
+
return value.toString();
|
|
102
|
+
if (typeof value === 'function' || typeof value === 'symbol')
|
|
103
|
+
return undefined;
|
|
104
|
+
if (value instanceof Date)
|
|
105
|
+
return value.toISOString();
|
|
106
|
+
if (Buffer.isBuffer(value) || value instanceof Uint8Array)
|
|
107
|
+
return `[binary ${value.byteLength} bytes]`;
|
|
108
|
+
if (value instanceof Error) {
|
|
109
|
+
return { type: value.name, message: maskString(value.message), stack: value.stack ? maskString(value.stack) : undefined };
|
|
110
|
+
}
|
|
111
|
+
if (typeof value !== 'object')
|
|
112
|
+
return String(value);
|
|
113
|
+
if (depth >= MAX_DEPTH)
|
|
114
|
+
return '[truncated]';
|
|
115
|
+
if (seen.has(value))
|
|
116
|
+
return '[circular]';
|
|
117
|
+
seen.add(value);
|
|
118
|
+
if (Array.isArray(value)) {
|
|
119
|
+
const items = value.slice(0, MAX_ITEMS).map((v) => redact(v, depth + 1, seen));
|
|
120
|
+
return value.length > MAX_ITEMS ? [...items, `[+${value.length - MAX_ITEMS}]`] : items;
|
|
121
|
+
}
|
|
122
|
+
const out = {};
|
|
123
|
+
let n = 0;
|
|
124
|
+
for (const [k, v] of Object.entries(value)) {
|
|
125
|
+
if (n++ >= MAX_ITEMS) {
|
|
126
|
+
out['[+]'] = true;
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
out[k] = isSensitiveKey(k) ? exports.REDACTED : redact(v, depth + 1, seen);
|
|
130
|
+
}
|
|
131
|
+
return out;
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=redaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redaction.js","sourceRoot":"","sources":["../src/redaction.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,SAAS,wCAAmB,CAAC"}
|
package/dist/register.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.telemetry = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* `import '@generazioneai/telemetry/register';` come PRIMA riga di `main.ts`. Con `TELEMETRY_MODE=off` (di serie) non fa nulla.
|
|
6
|
+
* Non installa gestori di segnali: lo spegnimento ordinato lo fa `TelemetryModule` (o `beforeExit`).
|
|
7
|
+
*/
|
|
8
|
+
const sdk_1 = require("./sdk");
|
|
9
|
+
exports.telemetry = (0, sdk_1.startTelemetry)();
|
|
10
|
+
//# sourceMappingURL=register.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register.js","sourceRoot":"","sources":["../src/register.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACH,+BAAuC;AAE1B,QAAA,SAAS,GAAG,IAAA,oBAAc,GAAE,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ExportResult } from '@opentelemetry/core';
|
|
2
|
+
import type { ReadableSpan, SpanExporter } from '@opentelemetry/sdk-trace-base';
|
|
3
|
+
/** Copia di uno span con gli attributi (anche di eventi e link) ripuliti dalla lista bianca. */
|
|
4
|
+
export declare function sanitizeSpan(span: ReadableSpan): ReadableSpan;
|
|
5
|
+
/** Avvolge un esportatore: ciò che esce dal processo è già ripulito (il collector rifà il controllo, ma non è l'unica barriera). */
|
|
6
|
+
export declare class SanitizingSpanExporter implements SpanExporter {
|
|
7
|
+
private readonly inner;
|
|
8
|
+
constructor(inner: SpanExporter);
|
|
9
|
+
export(spans: ReadableSpan[], resultCallback: (result: ExportResult) => void): void;
|
|
10
|
+
shutdown(): Promise<void>;
|
|
11
|
+
forceFlush(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=sanitizing-exporter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizing-exporter.d.ts","sourceRoot":"","sources":["../src/sanitizing-exporter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAIhF,gGAAgG;AAChG,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,YAAY,CAoB7D;AAED,oIAAoI;AACpI,qBAAa,sBAAuB,YAAW,YAAY;IAC7C,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,YAAY;IAEhD,MAAM,CAAC,KAAK,EAAE,YAAY,EAAE,EAAE,cAAc,EAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAI,GAAG,IAAI;IAInF,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAG5B"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SanitizingSpanExporter = void 0;
|
|
4
|
+
exports.sanitizeSpan = sanitizeSpan;
|
|
5
|
+
const attributes_1 = require("./attributes");
|
|
6
|
+
const redaction_1 = require("./redaction");
|
|
7
|
+
/** Copia di uno span con gli attributi (anche di eventi e link) ripuliti dalla lista bianca. */
|
|
8
|
+
function sanitizeSpan(span) {
|
|
9
|
+
return {
|
|
10
|
+
name: (0, redaction_1.maskString)(span.name),
|
|
11
|
+
kind: span.kind,
|
|
12
|
+
spanContext: () => span.spanContext(),
|
|
13
|
+
parentSpanContext: span.parentSpanContext,
|
|
14
|
+
startTime: span.startTime,
|
|
15
|
+
endTime: span.endTime,
|
|
16
|
+
status: { code: span.status.code }, // il messaggio di stato può citare dati
|
|
17
|
+
attributes: (0, attributes_1.sanitizeAttributes)(span.attributes),
|
|
18
|
+
links: span.links.map((l) => ({ context: l.context, attributes: (0, attributes_1.sanitizeAttributes)(l.attributes) })),
|
|
19
|
+
events: span.events.map((e) => ({ name: e.name, time: e.time, attributes: (0, attributes_1.sanitizeAttributes)(e.attributes) })),
|
|
20
|
+
duration: span.duration,
|
|
21
|
+
ended: span.ended,
|
|
22
|
+
resource: span.resource,
|
|
23
|
+
instrumentationScope: span.instrumentationScope,
|
|
24
|
+
droppedAttributesCount: span.droppedAttributesCount,
|
|
25
|
+
droppedEventsCount: span.droppedEventsCount,
|
|
26
|
+
droppedLinksCount: span.droppedLinksCount,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** Avvolge un esportatore: ciò che esce dal processo è già ripulito (il collector rifà il controllo, ma non è l'unica barriera). */
|
|
30
|
+
class SanitizingSpanExporter {
|
|
31
|
+
constructor(inner) {
|
|
32
|
+
this.inner = inner;
|
|
33
|
+
}
|
|
34
|
+
export(spans, resultCallback) {
|
|
35
|
+
this.inner.export(spans.map(sanitizeSpan), resultCallback);
|
|
36
|
+
}
|
|
37
|
+
shutdown() {
|
|
38
|
+
return this.inner.shutdown();
|
|
39
|
+
}
|
|
40
|
+
forceFlush() {
|
|
41
|
+
return this.inner.forceFlush?.() ?? Promise.resolve();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.SanitizingSpanExporter = SanitizingSpanExporter;
|
|
45
|
+
//# sourceMappingURL=sanitizing-exporter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sanitizing-exporter.js","sourceRoot":"","sources":["../src/sanitizing-exporter.ts"],"names":[],"mappings":";;;AAMA,oCAoBC;AAxBD,6CAAkD;AAClD,2CAAyC;AAEzC,gGAAgG;AAChG,SAAgB,YAAY,CAAC,IAAkB;IAC7C,OAAO;QACL,IAAI,EAAE,IAAA,sBAAU,EAAC,IAAI,CAAC,IAAI,CAAC;QAC3B,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE;QACrC,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;QACzC,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,MAAM,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,wCAAwC;QAC5E,UAAU,EAAE,IAAA,+BAAkB,EAAC,IAAI,CAAC,UAAU,CAAC;QAC/C,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,UAAU,EAAE,IAAA,+BAAkB,EAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACpG,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,UAAU,EAAE,IAAA,+BAAkB,EAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAC9G,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,oBAAoB,EAAE,IAAI,CAAC,oBAAoB;QAC/C,sBAAsB,EAAE,IAAI,CAAC,sBAAsB;QACnD,kBAAkB,EAAE,IAAI,CAAC,kBAAkB;QAC3C,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;KAC1C,CAAC;AACJ,CAAC;AAED,oIAAoI;AACpI,MAAa,sBAAsB;IACjC,YAA6B,KAAmB;QAAnB,UAAK,GAAL,KAAK,CAAc;IAAG,CAAC;IAEpD,MAAM,CAAC,KAAqB,EAAE,cAA8C;QAC1E,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,cAAc,CAAC,CAAC;IAC7D,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC/B,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IACxD,CAAC;CACF;AAdD,wDAcC"}
|
package/dist/sdk.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { MeterProvider } from '@opentelemetry/sdk-metrics';
|
|
2
|
+
import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node';
|
|
3
|
+
import { type TelemetryConfig } from './config';
|
|
4
|
+
export interface TelemetryHandle {
|
|
5
|
+
config: TelemetryConfig;
|
|
6
|
+
tracerProvider: NodeTracerProvider;
|
|
7
|
+
meterProvider: MeterProvider;
|
|
8
|
+
shutdown(): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Avvia l'SDK se la configurazione lo chiede (`TELEMETRY_MODE=on` e un endpoint). Idempotente. Va chiamato prima che
|
|
12
|
+
* l'applicazione carichi `http`, `pg`, `ioredis`: per questo `@generazioneai/telemetry/register` è il primo import di `main.ts`.
|
|
13
|
+
* Tutti gli span passano dal `SanitizingSpanExporter` (lista bianca degli attributi) prima di uscire.
|
|
14
|
+
*/
|
|
15
|
+
export declare function startTelemetry(env?: NodeJS.ProcessEnv): TelemetryHandle | null;
|
|
16
|
+
export declare function getTelemetry(): TelemetryHandle | null;
|
|
17
|
+
export declare function shutdownTelemetry(): Promise<void>;
|
|
18
|
+
//# sourceMappingURL=sdk.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,aAAa,EAAiC,MAAM,4BAA4B,CAAC;AAE1F,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,UAAU,CAAC;AAG5D,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,eAAe,CAAC;IACxB,cAAc,EAAE,kBAAkB,CAAC;IACnC,aAAa,EAAE,aAAa,CAAC;IAC7B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAeD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,eAAe,GAAG,IAAI,CAwD3F;AAED,wBAAgB,YAAY,IAAI,eAAe,GAAG,IAAI,CAErD;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAEvD"}
|
package/dist/sdk.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.startTelemetry = startTelemetry;
|
|
4
|
+
exports.getTelemetry = getTelemetry;
|
|
5
|
+
exports.shutdownTelemetry = shutdownTelemetry;
|
|
6
|
+
const api_1 = require("@opentelemetry/api");
|
|
7
|
+
const exporter_metrics_otlp_http_1 = require("@opentelemetry/exporter-metrics-otlp-http");
|
|
8
|
+
const exporter_trace_otlp_http_1 = require("@opentelemetry/exporter-trace-otlp-http");
|
|
9
|
+
const instrumentation_1 = require("@opentelemetry/instrumentation");
|
|
10
|
+
const instrumentation_http_1 = require("@opentelemetry/instrumentation-http");
|
|
11
|
+
const resources_1 = require("@opentelemetry/resources");
|
|
12
|
+
const sdk_metrics_1 = require("@opentelemetry/sdk-metrics");
|
|
13
|
+
const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base");
|
|
14
|
+
const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node");
|
|
15
|
+
const config_1 = require("./config");
|
|
16
|
+
const sanitizing_exporter_1 = require("./sanitizing-exporter");
|
|
17
|
+
let handle = null;
|
|
18
|
+
const QUIET_PATHS = /^\/(?:api\/)?(?:health|metrics|ready|live)/;
|
|
19
|
+
/** Strumentazioni opzionali: se il pacchetto manca o non si carica, si va avanti senza. */
|
|
20
|
+
function optional(load) {
|
|
21
|
+
try {
|
|
22
|
+
return [load()];
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Avvia l'SDK se la configurazione lo chiede (`TELEMETRY_MODE=on` e un endpoint). Idempotente. Va chiamato prima che
|
|
30
|
+
* l'applicazione carichi `http`, `pg`, `ioredis`: per questo `@generazioneai/telemetry/register` è il primo import di `main.ts`.
|
|
31
|
+
* Tutti gli span passano dal `SanitizingSpanExporter` (lista bianca degli attributi) prima di uscire.
|
|
32
|
+
*/
|
|
33
|
+
function startTelemetry(env = process.env) {
|
|
34
|
+
if (handle)
|
|
35
|
+
return handle;
|
|
36
|
+
const config = (0, config_1.readConfig)(env);
|
|
37
|
+
if (!config.enabled)
|
|
38
|
+
return null;
|
|
39
|
+
const resource = (0, resources_1.resourceFromAttributes)({
|
|
40
|
+
'service.name': config.serviceName,
|
|
41
|
+
...(config.environment ? { 'deployment.environment': config.environment } : {}),
|
|
42
|
+
...(config.serviceVersion ? { 'service.version': config.serviceVersion } : {}),
|
|
43
|
+
});
|
|
44
|
+
const tracerProvider = new sdk_trace_node_1.NodeTracerProvider({
|
|
45
|
+
resource,
|
|
46
|
+
sampler: new sdk_trace_base_1.ParentBasedSampler({
|
|
47
|
+
root: config.sampleRatio >= 1 ? new sdk_trace_base_1.AlwaysOnSampler() : new sdk_trace_base_1.TraceIdRatioBasedSampler(config.sampleRatio),
|
|
48
|
+
}),
|
|
49
|
+
spanProcessors: [new sdk_trace_base_1.BatchSpanProcessor(new sanitizing_exporter_1.SanitizingSpanExporter(new exporter_trace_otlp_http_1.OTLPTraceExporter({ url: `${config.endpoint}/v1/traces` })))],
|
|
50
|
+
});
|
|
51
|
+
tracerProvider.register();
|
|
52
|
+
const meterProvider = new sdk_metrics_1.MeterProvider({
|
|
53
|
+
resource,
|
|
54
|
+
readers: [
|
|
55
|
+
new sdk_metrics_1.PeriodicExportingMetricReader({
|
|
56
|
+
exporter: new exporter_metrics_otlp_http_1.OTLPMetricExporter({ url: `${config.endpoint}/v1/metrics` }),
|
|
57
|
+
exportIntervalMillis: config.metricIntervalMs,
|
|
58
|
+
}),
|
|
59
|
+
],
|
|
60
|
+
});
|
|
61
|
+
api_1.metrics.setGlobalMeterProvider(meterProvider);
|
|
62
|
+
const instrumentations = [
|
|
63
|
+
new instrumentation_http_1.HttpInstrumentation({
|
|
64
|
+
ignoreIncomingRequestHook: (req) => QUIET_PATHS.test(req.url ?? ''),
|
|
65
|
+
// Nessuna intestazione e nessun corpo negli span: l'esportatore tiene comunque solo la lista bianca.
|
|
66
|
+
requireParentforOutgoingSpans: true,
|
|
67
|
+
}),
|
|
68
|
+
...optional(() => new (require('@opentelemetry/instrumentation-pg').PgInstrumentation)({ enhancedDatabaseReporting: false })),
|
|
69
|
+
...optional(() => new (require('@opentelemetry/instrumentation-ioredis').IORedisInstrumentation)({ dbStatementSerializer: (cmdName) => cmdName })),
|
|
70
|
+
...optional(() => new (require('@prisma/instrumentation').PrismaInstrumentation)()),
|
|
71
|
+
];
|
|
72
|
+
(0, instrumentation_1.registerInstrumentations)({ tracerProvider, meterProvider, instrumentations });
|
|
73
|
+
let closed = false;
|
|
74
|
+
handle = {
|
|
75
|
+
config,
|
|
76
|
+
tracerProvider,
|
|
77
|
+
meterProvider,
|
|
78
|
+
async shutdown() {
|
|
79
|
+
if (closed)
|
|
80
|
+
return;
|
|
81
|
+
closed = true;
|
|
82
|
+
await Promise.allSettled([tracerProvider.shutdown(), meterProvider.shutdown()]);
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
process.once('beforeExit', () => void handle?.shutdown());
|
|
86
|
+
return handle;
|
|
87
|
+
}
|
|
88
|
+
function getTelemetry() {
|
|
89
|
+
return handle;
|
|
90
|
+
}
|
|
91
|
+
async function shutdownTelemetry() {
|
|
92
|
+
await handle?.shutdown();
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=sdk.js.map
|
package/dist/sdk.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk.js","sourceRoot":"","sources":["../src/sdk.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { DynamicModule, OnApplicationShutdown, OnModuleInit } from '@nestjs/common';
|
|
2
|
+
import { type NatsHeadersHook } from './propagation';
|
|
3
|
+
export interface TelemetryModuleOptions {
|
|
4
|
+
/** Nome del servizio (`id`, `hr`, `gateway`…): campo `service` dei log. */
|
|
5
|
+
service: string;
|
|
6
|
+
/**
|
|
7
|
+
* Il modulo di authz che espone `setNatsHeadersHook` (≥ 0.7). Di serie lo cerca da solo (`require('@generazioneai/authz')`);
|
|
8
|
+
* con authz più vecchio non fa nulla e il `traceparent` non parte negli header.
|
|
9
|
+
*/
|
|
10
|
+
authz?: {
|
|
11
|
+
setNatsHeadersHook?: (hook: NatsHeadersHook) => void;
|
|
12
|
+
} | false;
|
|
13
|
+
}
|
|
14
|
+
export declare const TELEMETRY_OPTIONS: unique symbol;
|
|
15
|
+
export declare class TelemetryService implements OnModuleInit, OnApplicationShutdown {
|
|
16
|
+
private readonly options;
|
|
17
|
+
private readonly logger;
|
|
18
|
+
constructor(options: TelemetryModuleOptions);
|
|
19
|
+
onModuleInit(): void;
|
|
20
|
+
onApplicationShutdown(): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
export declare class TelemetryModule {
|
|
23
|
+
/** `TelemetryModule.forRoot({ service: 'hr' })` nell'AppModule: interceptor `nats.server <cmd>` globale, hook del traceparent, spegnimento. */
|
|
24
|
+
static forRoot(options: TelemetryModuleOptions): DynamicModule;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=telemetry.module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"telemetry.module.d.ts","sourceRoot":"","sources":["../src/telemetry.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAsC,qBAAqB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAIxH,OAAO,EAA0B,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAG7E,MAAM,WAAW,sBAAsB;IACrC,2EAA2E;IAC3E,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,KAAK,CAAC,EAAE;QAAE,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAA;KAAE,GAAG,KAAK,CAAC;CAC1E;AAED,eAAO,MAAM,iBAAiB,eAA8B,CAAC;AAE7D,qBACa,gBAAiB,YAAW,YAAY,EAAE,qBAAqB;IAGnC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAF/D,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2B;gBAEM,OAAO,EAAE,sBAAsB;IAEvF,YAAY,IAAI,IAAI;IAkBd,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;CAG7C;AAED,qBACa,eAAe;IAC1B,+IAA+I;IAC/I,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,sBAAsB,GAAG,aAAa;CAY/D"}
|