@dumanarge/xssrv-shared-lib 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/auth/tenant.middleware.d.ts +6 -1
  2. package/dist/auth/tenant.middleware.js +10 -3
  3. package/dist/auth/tenant.middleware.js.map +1 -1
  4. package/dist/context/index.d.ts +3 -0
  5. package/dist/context/index.js +11 -0
  6. package/dist/context/index.js.map +1 -0
  7. package/dist/context/observability-context.d.ts +23 -0
  8. package/dist/context/observability-context.js +71 -0
  9. package/dist/context/observability-context.js.map +1 -0
  10. package/dist/context/observability.interceptor.d.ts +5 -0
  11. package/dist/context/observability.interceptor.js +72 -0
  12. package/dist/context/observability.interceptor.js.map +1 -0
  13. package/dist/context/observability.middleware.d.ts +5 -0
  14. package/dist/context/observability.middleware.js +36 -0
  15. package/dist/context/observability.middleware.js.map +1 -0
  16. package/dist/errors/app-error.d.ts +22 -0
  17. package/dist/errors/app-error.js +94 -0
  18. package/dist/errors/app-error.js.map +1 -0
  19. package/dist/errors/app-error.types.d.ts +44 -0
  20. package/dist/errors/app-error.types.js +3 -0
  21. package/dist/errors/app-error.types.js.map +1 -0
  22. package/dist/errors/error-category.d.ts +22 -0
  23. package/dist/errors/error-category.js +42 -0
  24. package/dist/errors/error-category.js.map +1 -0
  25. package/dist/errors/error-registry.d.ts +5 -0
  26. package/dist/errors/error-registry.js +26 -0
  27. package/dist/errors/error-registry.js.map +1 -0
  28. package/dist/errors/index.d.ts +4 -0
  29. package/dist/errors/index.js +14 -0
  30. package/dist/errors/index.js.map +1 -0
  31. package/dist/filters/grpc-app-exception.filter.d.ts +11 -0
  32. package/dist/filters/grpc-app-exception.filter.js +177 -0
  33. package/dist/filters/grpc-app-exception.filter.js.map +1 -0
  34. package/dist/filters/http-app-exception.filter.d.ts +7 -0
  35. package/dist/filters/http-app-exception.filter.js +196 -0
  36. package/dist/filters/http-app-exception.filter.js.map +1 -0
  37. package/dist/filters/index.d.ts +3 -0
  38. package/dist/filters/index.js +13 -0
  39. package/dist/filters/index.js.map +1 -0
  40. package/dist/filters/severity.d.ts +7 -0
  41. package/dist/filters/severity.js +51 -0
  42. package/dist/filters/severity.js.map +1 -0
  43. package/dist/index.d.ts +8 -0
  44. package/dist/index.js +28 -1
  45. package/dist/index.js.map +1 -1
  46. package/dist/logging/http-exception.filter.d.ts +1 -0
  47. package/dist/logging/http-exception.filter.js +6 -0
  48. package/dist/logging/http-exception.filter.js.map +1 -0
  49. package/dist/logging/logging.module.d.ts +22 -5
  50. package/dist/logging/logging.module.js +39 -10
  51. package/dist/logging/logging.module.js.map +1 -1
  52. package/dist/logging/request-logging.interceptor.d.ts +5 -0
  53. package/dist/logging/request-logging.interceptor.js +59 -0
  54. package/dist/logging/request-logging.interceptor.js.map +1 -0
  55. package/dist/metrics/index.d.ts +1 -0
  56. package/dist/metrics/index.js +9 -0
  57. package/dist/metrics/index.js.map +1 -0
  58. package/dist/metrics/metrics.d.ts +17 -0
  59. package/dist/metrics/metrics.js +31 -0
  60. package/dist/metrics/metrics.js.map +1 -0
  61. package/dist/observability/error-observability.d.ts +32 -0
  62. package/dist/observability/error-observability.js +146 -0
  63. package/dist/observability/error-observability.js.map +1 -0
  64. package/dist/observability/otel-log-emitter.d.ts +10 -0
  65. package/dist/observability/otel-log-emitter.js +47 -0
  66. package/dist/observability/otel-log-emitter.js.map +1 -0
  67. package/dist/observability/request-context.d.ts +12 -0
  68. package/dist/observability/request-context.js +49 -0
  69. package/dist/observability/request-context.js.map +1 -0
  70. package/dist/tracing/tracing.js +22 -0
  71. package/dist/tracing/tracing.js.map +1 -1
  72. package/package.json +24 -1
@@ -17,7 +17,11 @@ export declare const PINO_LOGGER_CONFIG: {
17
17
  url: any;
18
18
  headers: {
19
19
  'x-request-id': any;
20
+ 'x-correlation-id': any;
20
21
  'x-tenant-id': any;
22
+ 'x-user-id': any;
23
+ 'x-account-id': any;
24
+ 'x-user-email': any;
21
25
  'user-agent': any;
22
26
  };
23
27
  };
@@ -25,14 +29,27 @@ export declare const PINO_LOGGER_CONFIG: {
25
29
  statusCode: any;
26
30
  };
27
31
  };
28
- customProps: () => {
32
+ customProps: (req: any) => {
33
+ requestId: any;
34
+ correlationId: any;
35
+ tenantId: string;
36
+ userId: string;
37
+ accountId: string;
38
+ userEmail: string;
39
+ origin: "http" | "grpc" | "rabbitmq" | "cron" | "system";
40
+ operation: string;
41
+ } | {
29
42
  traceId: string;
30
43
  spanId: string;
31
44
  traceFlags: number;
32
- } | {
33
- traceId?: undefined;
34
- spanId?: undefined;
35
- traceFlags?: undefined;
45
+ requestId: any;
46
+ correlationId: any;
47
+ tenantId: string;
48
+ userId: string;
49
+ accountId: string;
50
+ userEmail: string;
51
+ origin: "http" | "grpc" | "rabbitmq" | "cron" | "system";
52
+ operation: string;
36
53
  };
37
54
  redact: {
38
55
  paths: string[];
@@ -10,6 +10,19 @@ exports.LoggingModule = exports.PINO_LOGGER_CONFIG = void 0;
10
10
  const common_1 = require("@nestjs/common");
11
11
  const nestjs_pino_1 = require("nestjs-pino");
12
12
  const api_1 = require("@opentelemetry/api");
13
+ const crypto_1 = require("crypto");
14
+ const observability_context_1 = require("../context/observability-context");
15
+ const isProduction = process.env.NODE_ENV === 'production';
16
+ const redactPaths = [
17
+ 'req.headers.authorization',
18
+ 'req.headers.cookie',
19
+ 'req.body.password',
20
+ 'req.body.secret',
21
+ 'req.body.token',
22
+ ];
23
+ if (isProduction) {
24
+ redactPaths.push('req.headers.x-user-email', 'req.body.email', 'email', 'user.email');
25
+ }
13
26
  exports.PINO_LOGGER_CONFIG = {
14
27
  pinoHttp: {
15
28
  level: process.env.LOG_LEVEL || 'info',
@@ -27,7 +40,11 @@ exports.PINO_LOGGER_CONFIG = {
27
40
  url: req.url,
28
41
  headers: {
29
42
  'x-request-id': req.headers['x-request-id'],
43
+ 'x-correlation-id': req.headers['x-correlation-id'],
30
44
  'x-tenant-id': req.headers['x-tenant-id'],
45
+ 'x-user-id': req.headers['x-user-id'],
46
+ 'x-account-id': req.headers['x-account-id'],
47
+ 'x-user-email': req.headers['x-user-email'],
31
48
  'user-agent': req.headers['user-agent'],
32
49
  },
33
50
  }),
@@ -35,30 +52,42 @@ exports.PINO_LOGGER_CONFIG = {
35
52
  statusCode: res.statusCode,
36
53
  }),
37
54
  },
38
- customProps: () => {
55
+ customProps: (req) => {
39
56
  const activeSpan = api_1.trace.getActiveSpan();
57
+ const contextData = observability_context_1.ObservabilityContext.get();
58
+ const requestId = contextData?.requestId ?? req?.id ?? req?.headers?.['x-request-id'];
59
+ const correlationId = contextData?.correlationId ?? req?.headers?.['x-correlation-id'] ?? requestId;
60
+ const baseProps = {
61
+ requestId,
62
+ correlationId,
63
+ tenantId: contextData?.tenantId,
64
+ userId: contextData?.userId,
65
+ accountId: contextData?.accountId,
66
+ userEmail: contextData?.userEmail,
67
+ origin: contextData?.origin,
68
+ operation: contextData?.operation,
69
+ };
40
70
  if (activeSpan) {
41
71
  const spanContext = activeSpan.spanContext();
72
+ observability_context_1.ObservabilityContext.set({
73
+ traceId: spanContext.traceId,
74
+ spanId: spanContext.spanId,
75
+ });
42
76
  return {
77
+ ...baseProps,
43
78
  traceId: spanContext.traceId,
44
79
  spanId: spanContext.spanId,
45
80
  traceFlags: spanContext.traceFlags,
46
81
  };
47
82
  }
48
- return {};
83
+ return baseProps;
49
84
  },
50
85
  redact: {
51
- paths: [
52
- 'req.headers.authorization',
53
- 'req.headers.cookie',
54
- 'req.body.password',
55
- 'req.body.secret',
56
- 'req.body.token',
57
- ],
86
+ paths: redactPaths,
58
87
  censor: '[REDACTED]',
59
88
  },
60
89
  genReqId: (req) => {
61
- return req.headers['x-request-id'] || crypto.randomUUID();
90
+ return req.headers['x-request-id'] || (0, crypto_1.randomUUID)();
62
91
  },
63
92
  },
64
93
  };
@@ -1 +1 @@
1
- {"version":3,"file":"logging.module.js","sourceRoot":"","sources":["../../src/logging/logging.module.ts"],"names":[],"mappings":";;;;;;;;;AAUA,2CAAwC;AACxC,6CAA+D;AAC/D,4CAAoD;AAEvC,QAAA,kBAAkB,GAAG;IAChC,QAAQ,EAAE;QACR,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,MAAM;QACtC,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;YAC/C,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE;YAC1E,CAAC,CAAC,SAAS;QACb,WAAW,EAAE;YACX,MAAM,EAAE,CAAC,GAAQ,EAAE,EAAE;gBAEnB,OAAO,GAAG,CAAC,GAAG,KAAK,cAAc,IAAI,GAAG,CAAC,GAAG,KAAK,eAAe,IAAI,GAAG,CAAC,GAAG,KAAK,UAAU,CAAC;YAC7F,CAAC;SACF;QACD,WAAW,EAAE;YACX,GAAG,EAAE,CAAC,GAAQ,EAAE,EAAE,CAAC,CAAC;gBAClB,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,GAAG,EAAE,GAAG,CAAC,GAAG;gBACZ,OAAO,EAAE;oBACP,cAAc,EAAE,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC;oBAC3C,aAAa,EAAE,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;oBACzC,YAAY,EAAE,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC;iBACxC;aACF,CAAC;YACF,GAAG,EAAE,CAAC,GAAQ,EAAE,EAAE,CAAC,CAAC;gBAClB,UAAU,EAAE,GAAG,CAAC,UAAU;aAC3B,CAAC;SACH;QACD,WAAW,EAAE,GAAG,EAAE;YAChB,MAAM,UAAU,GAAG,WAAK,CAAC,aAAa,EAAE,CAAC;YACzC,IAAI,UAAU,EAAE,CAAC;gBACf,MAAM,WAAW,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;gBAC7C,OAAO;oBACL,OAAO,EAAE,WAAW,CAAC,OAAO;oBAC5B,MAAM,EAAE,WAAW,CAAC,MAAM;oBAC1B,UAAU,EAAE,WAAW,CAAC,UAAU;iBACnC,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,EAAE;YACN,KAAK,EAAE;gBACL,2BAA2B;gBAC3B,oBAAoB;gBACpB,mBAAmB;gBACnB,iBAAiB;gBACjB,gBAAgB;aACjB;YACD,MAAM,EAAE,YAAY;SACrB;QACD,QAAQ,EAAE,CAAC,GAAQ,EAAE,EAAE;YACrB,OAAO,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QAC5D,CAAC;KACF;CACF,CAAC;AAMK,IAAM,aAAa,GAAnB,MAAM,aAAa;CAAG,CAAA;AAAhB,sCAAa;wBAAb,aAAa;IAJzB,IAAA,eAAM,EAAC;QACN,OAAO,EAAE,CAAC,0BAAgB,CAAC,OAAO,CAAC,0BAAkB,CAAC,CAAC;QACvD,OAAO,EAAE,CAAC,0BAAgB,CAAC;KAC5B,CAAC;GACW,aAAa,CAAG"}
1
+ {"version":3,"file":"logging.module.js","sourceRoot":"","sources":["../../src/logging/logging.module.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { CallHandler, ExecutionContext, NestInterceptor } from '@nestjs/common';
2
+ import { Observable } from 'rxjs';
3
+ export declare class RequestLoggingInterceptor implements NestInterceptor {
4
+ intercept(context: ExecutionContext, next: CallHandler): Observable<unknown>;
5
+ }
@@ -0,0 +1,59 @@
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.RequestLoggingInterceptor = void 0;
10
+ const common_1 = require("@nestjs/common");
11
+ const crypto_1 = require("crypto");
12
+ const rxjs_1 = require("rxjs");
13
+ const request_context_1 = require("../observability/request-context");
14
+ const metrics_1 = require("../metrics");
15
+ let RequestLoggingInterceptor = class RequestLoggingInterceptor {
16
+ intercept(context, next) {
17
+ if (context.getType() !== 'http') {
18
+ return next.handle();
19
+ }
20
+ const http = context.switchToHttp();
21
+ const request = http.getRequest();
22
+ const response = http.getResponse();
23
+ const ctx = (0, request_context_1.createHttpObservabilityContext)(request);
24
+ const requestId = ctx.requestId ?? request.id ?? (0, crypto_1.randomUUID)();
25
+ const correlationId = ctx.correlationId ?? requestId;
26
+ const startedAt = Date.now();
27
+ request.__requestStartedAt = startedAt;
28
+ if (response.setHeader) {
29
+ response.setHeader('x-request-id', requestId);
30
+ response.setHeader('x-correlation-id', correlationId);
31
+ }
32
+ return new rxjs_1.Observable((subscriber) => {
33
+ request_context_1.ObservabilityContextStorage.run({
34
+ ...ctx,
35
+ requestId,
36
+ correlationId,
37
+ }, () => {
38
+ next.handle().subscribe({
39
+ next: (value) => subscriber.next(value),
40
+ error: (error) => subscriber.error(error),
41
+ complete: () => {
42
+ (0, metrics_1.recordRequestDurationMetric)(Date.now() - startedAt, {
43
+ service: process.env.SERVICE_NAME ?? 'unknown-service',
44
+ transport: 'http',
45
+ operation: String(request.url ?? 'unknown'),
46
+ statusCode: response.statusCode,
47
+ });
48
+ subscriber.complete();
49
+ },
50
+ });
51
+ });
52
+ });
53
+ }
54
+ };
55
+ exports.RequestLoggingInterceptor = RequestLoggingInterceptor;
56
+ exports.RequestLoggingInterceptor = RequestLoggingInterceptor = __decorate([
57
+ (0, common_1.Injectable)()
58
+ ], RequestLoggingInterceptor);
59
+ //# sourceMappingURL=request-logging.interceptor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-logging.interceptor.js","sourceRoot":"","sources":["../../src/logging/request-logging.interceptor.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAKwB;AACxB,mCAAoC;AACpC,+BAAkC;AAClC,sEAG0C;AAC1C,wCAAyD;AAGlD,IAAM,yBAAyB,GAA/B,MAAM,yBAAyB;IACpC,SAAS,CAAC,OAAyB,EAAE,IAAiB;QACpD,IAAI,OAAO,CAAC,OAAO,EAAE,KAAK,MAAM,EAAE,CAAC;YACjC,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,CAAC;QAED,MAAM,IAAI,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;QACpC,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAI3B,CAAC;QACL,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAwD,CAAC;QAE1F,MAAM,GAAG,GAAG,IAAA,gDAA8B,EAAC,OAAO,CAAC,CAAC;QACpD,MAAM,SAAS,GAAG,GAAG,CAAC,SAAS,IAAI,OAAO,CAAC,EAAE,IAAI,IAAA,mBAAU,GAAE,CAAC;QAC9D,MAAM,aAAa,GAAG,GAAG,CAAC,aAAa,IAAI,SAAS,CAAC;QACrD,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC5B,OAAmC,CAAC,kBAAkB,GAAG,SAAS,CAAC;QAEpE,IAAI,QAAQ,CAAC,SAAS,EAAE,CAAC;YACvB,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;YAC9C,QAAQ,CAAC,SAAS,CAAC,kBAAkB,EAAE,aAAa,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,IAAI,iBAAU,CAAC,CAAC,UAAU,EAAE,EAAE;YACnC,6CAA2B,CAAC,GAAG,CAC7B;gBACE,GAAG,GAAG;gBACN,SAAS;gBACT,aAAa;aACd,EACD,GAAG,EAAE;gBACH,IAAI,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC;oBACtB,IAAI,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC;oBACvC,KAAK,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC;oBACzC,QAAQ,EAAE,GAAG,EAAE;wBACb,IAAA,qCAA2B,EAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,EAAE;4BAClD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,iBAAiB;4BACtD,SAAS,EAAE,MAAM;4BACjB,SAAS,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,SAAS,CAAC;4BAC3C,UAAU,EAAG,QAAoC,CAAC,UAAgC;yBACnF,CAAC,CAAC;wBACH,UAAU,CAAC,QAAQ,EAAE,CAAC;oBACxB,CAAC;iBACF,CAAC,CAAC;YACL,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACF,CAAA;AAlDY,8DAAyB;oCAAzB,yBAAyB;IADrC,IAAA,mBAAU,GAAE;GACA,yBAAyB,CAkDrC"}
@@ -0,0 +1 @@
1
+ export { appErrorsCounter, requestDurationHistogram, recordAppErrorMetric, recordRequestDurationMetric, type AppMetricSeverity, type AppErrorMetricInput, type RequestDurationMetricInput, } from './metrics';
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.recordRequestDurationMetric = exports.recordAppErrorMetric = exports.requestDurationHistogram = exports.appErrorsCounter = void 0;
4
+ var metrics_1 = require("./metrics");
5
+ Object.defineProperty(exports, "appErrorsCounter", { enumerable: true, get: function () { return metrics_1.appErrorsCounter; } });
6
+ Object.defineProperty(exports, "requestDurationHistogram", { enumerable: true, get: function () { return metrics_1.requestDurationHistogram; } });
7
+ Object.defineProperty(exports, "recordAppErrorMetric", { enumerable: true, get: function () { return metrics_1.recordAppErrorMetric; } });
8
+ Object.defineProperty(exports, "recordRequestDurationMetric", { enumerable: true, get: function () { return metrics_1.recordRequestDurationMetric; } });
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":";;;AAAA,qCAQmB;AAPjB,2GAAA,gBAAgB,OAAA;AAChB,mHAAA,wBAAwB,OAAA;AACxB,+GAAA,oBAAoB,OAAA;AACpB,sHAAA,2BAA2B,OAAA"}
@@ -0,0 +1,17 @@
1
+ export type AppMetricSeverity = 'info' | 'warn' | 'error' | 'fatal';
2
+ export interface AppErrorMetricInput {
3
+ service: string;
4
+ category: string;
5
+ code: string;
6
+ severity: AppMetricSeverity;
7
+ }
8
+ export interface RequestDurationMetricInput {
9
+ service: string;
10
+ transport: 'http' | 'grpc' | 'rabbitmq' | 'system';
11
+ operation: string;
12
+ statusCode?: number;
13
+ }
14
+ export declare const appErrorsCounter: import("@opentelemetry/api").Counter<import("@opentelemetry/api").Attributes>;
15
+ export declare const requestDurationHistogram: import("@opentelemetry/api").Histogram<import("@opentelemetry/api").Attributes>;
16
+ export declare function recordAppErrorMetric(input: AppErrorMetricInput): void;
17
+ export declare function recordRequestDurationMetric(durationMs: number, input: RequestDurationMetricInput): void;
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.requestDurationHistogram = exports.appErrorsCounter = void 0;
4
+ exports.recordAppErrorMetric = recordAppErrorMetric;
5
+ exports.recordRequestDurationMetric = recordRequestDurationMetric;
6
+ const api_1 = require("@opentelemetry/api");
7
+ const meter = api_1.metrics.getMeter('xenonsmart-backend');
8
+ exports.appErrorsCounter = meter.createCounter('app_errors_total', {
9
+ description: 'Total application errors by service/category/code/severity',
10
+ });
11
+ exports.requestDurationHistogram = meter.createHistogram('app_request_duration_ms', {
12
+ description: 'Application request duration in milliseconds',
13
+ unit: 'ms',
14
+ });
15
+ function recordAppErrorMetric(input) {
16
+ exports.appErrorsCounter.add(1, {
17
+ service: input.service,
18
+ category: input.category,
19
+ code: input.code,
20
+ severity: input.severity,
21
+ });
22
+ }
23
+ function recordRequestDurationMetric(durationMs, input) {
24
+ exports.requestDurationHistogram.record(durationMs, {
25
+ service: input.service,
26
+ transport: input.transport,
27
+ operation: input.operation,
28
+ status_code: input.statusCode ? String(input.statusCode) : 'unknown',
29
+ });
30
+ }
31
+ //# sourceMappingURL=metrics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../src/metrics/metrics.ts"],"names":[],"mappings":";;;AA6BA,oDAOC;AAED,kEAUC;AAhDD,4CAA6C;AAkB7C,MAAM,KAAK,GAAG,aAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;AAExC,QAAA,gBAAgB,GAAG,KAAK,CAAC,aAAa,CAAC,kBAAkB,EAAE;IACtE,WAAW,EAAE,4DAA4D;CAC1E,CAAC,CAAC;AAEU,QAAA,wBAAwB,GAAG,KAAK,CAAC,eAAe,CAAC,yBAAyB,EAAE;IACvF,WAAW,EAAE,8CAA8C;IAC3D,IAAI,EAAE,IAAI;CACX,CAAC,CAAC;AAEH,SAAgB,oBAAoB,CAAC,KAA0B;IAC7D,wBAAgB,CAAC,GAAG,CAAC,CAAC,EAAE;QACtB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,2BAA2B,CACzC,UAAkB,EAClB,KAAiC;IAEjC,gCAAwB,CAAC,MAAM,CAAC,UAAU,EAAE;QAC1C,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,WAAW,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS;KACrE,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,32 @@
1
+ export type AppErrorSeverity = 'info' | 'warn' | 'error';
2
+ export type AppErrorLogPayload = {
3
+ service: string;
4
+ transport: 'http' | 'grpc' | 'rabbitmq' | 'system';
5
+ errorKey: string;
6
+ messageKey?: string;
7
+ category?: string;
8
+ retryable?: boolean;
9
+ httpCode?: number;
10
+ grpcCode?: number;
11
+ requestId?: string;
12
+ userId?: string;
13
+ accountId?: string;
14
+ email?: string;
15
+ details?: Record<string, unknown>;
16
+ fields?: Array<{
17
+ field?: string;
18
+ code?: string;
19
+ message?: string;
20
+ }>;
21
+ timestamp?: string;
22
+ };
23
+ export declare function resolveErrorSeverity(payload: AppErrorLogPayload): AppErrorSeverity;
24
+ export declare function emitAppErrorObservability(payload: AppErrorLogPayload, options?: {
25
+ logger?: {
26
+ error?: (payload: unknown, message?: string) => void;
27
+ warn?: (payload: unknown, message?: string) => void;
28
+ info?: (payload: unknown, message?: string) => void;
29
+ log?: (payload: unknown, message?: string) => void;
30
+ };
31
+ severity?: AppErrorSeverity;
32
+ }): AppErrorSeverity;
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveErrorSeverity = resolveErrorSeverity;
4
+ exports.emitAppErrorObservability = emitAppErrorObservability;
5
+ const api_1 = require("@opentelemetry/api");
6
+ const meter = api_1.metrics.getMeter('xssrv-shared-observability');
7
+ const appErrorLogCounter = meter.createCounter('app_error_log_total', {
8
+ description: 'Application error logs grouped by severity and error identity.',
9
+ });
10
+ function normalizeHttpCode(httpCode) {
11
+ if (typeof httpCode !== 'number' || Number.isNaN(httpCode)) {
12
+ return 'unknown';
13
+ }
14
+ return String(httpCode);
15
+ }
16
+ function readString(input) {
17
+ if (typeof input !== 'string') {
18
+ return undefined;
19
+ }
20
+ const value = input.trim();
21
+ return value.length > 0 ? value : undefined;
22
+ }
23
+ function firstValidationField(fields) {
24
+ if (!Array.isArray(fields) || fields.length === 0) {
25
+ return undefined;
26
+ }
27
+ const first = fields[0];
28
+ if (!first) {
29
+ return undefined;
30
+ }
31
+ return {
32
+ field: readString(first.field),
33
+ code: readString(first.code),
34
+ message: readString(first.message),
35
+ };
36
+ }
37
+ function firstDetailsValidation(details) {
38
+ const validationErrors = details
39
+ ?.validationErrors;
40
+ if (!Array.isArray(validationErrors) || validationErrors.length === 0) {
41
+ return undefined;
42
+ }
43
+ const first = validationErrors[0];
44
+ if (!first) {
45
+ return undefined;
46
+ }
47
+ const field = readString(first.property);
48
+ const constraints = first.constraints;
49
+ const constraintKey = constraints ? Object.keys(constraints)[0] : undefined;
50
+ const rule = readString(constraintKey);
51
+ const message = constraints && constraintKey ? readString(constraints[constraintKey]) : undefined;
52
+ return { field, rule, message };
53
+ }
54
+ function resolveErrorSeverity(payload) {
55
+ const category = payload.category?.toUpperCase();
56
+ const httpCode = payload.httpCode;
57
+ const grpcCode = payload.grpcCode;
58
+ if (httpCode === 503 || httpCode === 504) {
59
+ return 'warn';
60
+ }
61
+ if (typeof httpCode === 'number' && httpCode >= 500) {
62
+ return 'error';
63
+ }
64
+ if (grpcCode === 14 || grpcCode === 4) {
65
+ return 'warn';
66
+ }
67
+ if (grpcCode === 13 || grpcCode === 2 || grpcCode === 15) {
68
+ return 'error';
69
+ }
70
+ if (category === 'UNAVAILABLE' || category === 'TIMEOUT' || category === 'DEPENDENCY') {
71
+ return 'warn';
72
+ }
73
+ if (category === 'INTERNAL') {
74
+ return 'error';
75
+ }
76
+ return 'info';
77
+ }
78
+ function emitAppErrorObservability(payload, options) {
79
+ const severity = options?.severity ?? resolveErrorSeverity(payload);
80
+ const details = payload.details ?? {};
81
+ const validationField = firstValidationField(payload.fields);
82
+ const detailsValidation = firstDetailsValidation(details);
83
+ const source = details;
84
+ const targetService = readString(source.unavailableService) ??
85
+ readString(source.dependency) ??
86
+ readString(source.source);
87
+ const operation = readString(source.operation);
88
+ appErrorLogCounter.add(1, {
89
+ service: payload.service,
90
+ level: severity,
91
+ error_key: payload.errorKey,
92
+ category: payload.category ?? 'UNKNOWN',
93
+ transport: payload.transport,
94
+ http_code: normalizeHttpCode(payload.httpCode),
95
+ });
96
+ const logPayload = {
97
+ event: 'app_error',
98
+ level: severity,
99
+ service: payload.service,
100
+ sourceService: payload.service,
101
+ targetService,
102
+ operation,
103
+ transport: payload.transport,
104
+ errorKey: payload.errorKey,
105
+ messageKey: payload.messageKey,
106
+ category: payload.category,
107
+ retryable: payload.retryable,
108
+ status: {
109
+ http: payload.httpCode,
110
+ grpc: payload.grpcCode,
111
+ },
112
+ validation: validationField || detailsValidation
113
+ ? {
114
+ field: validationField?.field ?? detailsValidation?.field,
115
+ code: validationField?.code,
116
+ rule: detailsValidation?.rule,
117
+ message: validationField?.message ?? detailsValidation?.message,
118
+ }
119
+ : undefined,
120
+ user: {
121
+ userId: payload.userId,
122
+ accountId: payload.accountId,
123
+ email: payload.email,
124
+ },
125
+ requestId: payload.requestId,
126
+ details: payload.details,
127
+ timestamp: payload.timestamp ?? new Date().toISOString(),
128
+ };
129
+ const logger = options?.logger;
130
+ if (severity === 'error') {
131
+ logger?.error?.(logPayload, 'Application error observed');
132
+ }
133
+ else if (severity === 'warn') {
134
+ logger?.warn?.(logPayload, 'Application warning observed');
135
+ }
136
+ else {
137
+ if (logger?.info) {
138
+ logger.info(logPayload, 'Application info observed');
139
+ }
140
+ else {
141
+ logger?.log?.(logPayload, 'Application info observed');
142
+ }
143
+ }
144
+ return severity;
145
+ }
146
+ //# sourceMappingURL=error-observability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-observability.js","sourceRoot":"","sources":["../../src/observability/error-observability.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ type OTelSeverity = 'info' | 'warn' | 'error' | 'fatal';
2
+ type OTelLogInput = {
3
+ service: string;
4
+ severity: OTelSeverity;
5
+ message: string;
6
+ attributes?: Record<string, unknown>;
7
+ body?: Record<string, unknown>;
8
+ };
9
+ export declare function emitOtelLog(input: OTelLogInput): void;
10
+ export {};
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.emitOtelLog = emitOtelLog;
4
+ let cachedLogger;
5
+ function toSeverityNumber(level) {
6
+ switch (level) {
7
+ case 'fatal':
8
+ return 21;
9
+ case 'error':
10
+ return 17;
11
+ case 'warn':
12
+ return 13;
13
+ default:
14
+ return 9;
15
+ }
16
+ }
17
+ function getLogger() {
18
+ if (cachedLogger !== undefined) {
19
+ return cachedLogger;
20
+ }
21
+ try {
22
+ const apiLogs = require('@opentelemetry/api-logs');
23
+ cachedLogger = apiLogs.logs.getLogger('xenonsmart-backend');
24
+ }
25
+ catch {
26
+ cachedLogger = null;
27
+ }
28
+ return cachedLogger;
29
+ }
30
+ function emitOtelLog(input) {
31
+ const logger = getLogger();
32
+ if (!logger) {
33
+ return;
34
+ }
35
+ const severityText = input.severity.toUpperCase();
36
+ logger.emit({
37
+ severityNumber: toSeverityNumber(input.severity),
38
+ severityText,
39
+ body: input.body ?? { message: input.message },
40
+ attributes: {
41
+ service: input.service,
42
+ severity: input.severity,
43
+ ...input.attributes,
44
+ },
45
+ });
46
+ }
47
+ //# sourceMappingURL=otel-log-emitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otel-log-emitter.js","sourceRoot":"","sources":["../../src/observability/otel-log-emitter.ts"],"names":[],"mappings":";;AAmDA,kCAkBC;AAlDD,IAAI,YAA+C,CAAC;AAEpD,SAAS,gBAAgB,CAAC,KAAmB;IAC3C,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,OAAO;YACV,OAAO,EAAE,CAAC;QACZ,KAAK,OAAO;YACV,OAAO,EAAE,CAAC;QACZ,KAAK,MAAM;YACT,OAAO,EAAE,CAAC;QACZ;YACE,OAAO,CAAC,CAAC;IACb,CAAC;AACH,CAAC;AAED,SAAS,SAAS;IAChB,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,OAAO,CAAC,yBAAyB,CAEhD,CAAC;QACF,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;IAC9D,CAAC;IAAC,MAAM,CAAC;QACP,YAAY,GAAG,IAAI,CAAC;IACtB,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,SAAgB,WAAW,CAAC,KAAmB;IAC7C,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;IACT,CAAC;IAED,MAAM,YAAY,GAAG,KAAK,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;IAElD,MAAM,CAAC,IAAI,CAAC;QACV,cAAc,EAAE,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC;QAChD,YAAY;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE;QAC9C,UAAU,EAAE;YACV,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,GAAG,KAAK,CAAC,UAAU;SACpB;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { createHttpObservabilityContext, type ObservabilityContextData as BaseObservabilityContextData } from '../context/observability-context';
2
+ export interface ObservabilityContextData extends BaseObservabilityContextData {
3
+ email?: string;
4
+ source?: BaseObservabilityContextData['origin'];
5
+ }
6
+ export declare class ObservabilityContextStorage {
7
+ static run<T>(context: ObservabilityContextData, callback: () => T): T;
8
+ static get(): ObservabilityContextData | undefined;
9
+ static patch(input: Partial<ObservabilityContextData>): void;
10
+ static toLogMeta(): Record<string, string | undefined>;
11
+ }
12
+ export { createHttpObservabilityContext };
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createHttpObservabilityContext = exports.ObservabilityContextStorage = void 0;
4
+ const observability_context_1 = require("../context/observability-context");
5
+ Object.defineProperty(exports, "createHttpObservabilityContext", { enumerable: true, get: function () { return observability_context_1.createHttpObservabilityContext; } });
6
+ class ObservabilityContextStorage {
7
+ static run(context, callback) {
8
+ return observability_context_1.ObservabilityContext.run({
9
+ ...context,
10
+ userEmail: context.userEmail ?? context.email,
11
+ origin: context.origin ?? context.source,
12
+ }, callback);
13
+ }
14
+ static get() {
15
+ const current = observability_context_1.ObservabilityContext.get();
16
+ if (!current) {
17
+ return undefined;
18
+ }
19
+ return {
20
+ ...current,
21
+ email: current.userEmail,
22
+ source: current.origin,
23
+ };
24
+ }
25
+ static patch(input) {
26
+ observability_context_1.ObservabilityContext.set({
27
+ ...input,
28
+ userEmail: input.userEmail ?? input.email,
29
+ origin: input.origin ?? input.source,
30
+ });
31
+ }
32
+ static toLogMeta() {
33
+ const context = ObservabilityContextStorage.get();
34
+ return {
35
+ requestId: context?.requestId,
36
+ correlationId: context?.correlationId,
37
+ tenantId: context?.tenantId,
38
+ userId: context?.userId,
39
+ accountId: context?.accountId,
40
+ email: context?.email,
41
+ source: context?.source,
42
+ operation: context?.operation,
43
+ traceId: context?.traceId,
44
+ spanId: context?.spanId,
45
+ };
46
+ }
47
+ }
48
+ exports.ObservabilityContextStorage = ObservabilityContextStorage;
49
+ //# sourceMappingURL=request-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-context.js","sourceRoot":"","sources":["../../src/observability/request-context.ts"],"names":[],"mappings":";;;AAAA,4EAI0C;AAwDjC,+GA3DP,sDAA8B,OA2DO;AAjDvC,MAAa,2BAA2B;IACtC,MAAM,CAAC,GAAG,CAAI,OAAiC,EAAE,QAAiB;QAChE,OAAO,4CAAoB,CAAC,GAAG,CAC7B;YACE,GAAG,OAAO;YACV,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,KAAK;YAC7C,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM;SACzC,EACD,QAAQ,CACT,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,GAAG;QACR,MAAM,OAAO,GAAG,4CAAoB,CAAC,GAAG,EAAE,CAAC;QAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO;YACL,GAAG,OAAO;YACV,KAAK,EAAE,OAAO,CAAC,SAAS;YACxB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,KAAwC;QACnD,4CAAoB,CAAC,GAAG,CAAC;YACvB,GAAG,KAAK;YACR,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,KAAK;YACzC,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,MAAM;SACrC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,SAAS;QACd,MAAM,OAAO,GAAG,2BAA2B,CAAC,GAAG,EAAE,CAAC;QAClD,OAAO;YACL,SAAS,EAAE,OAAO,EAAE,SAAS;YAC7B,aAAa,EAAE,OAAO,EAAE,aAAa;YACrC,QAAQ,EAAE,OAAO,EAAE,QAAQ;YAC3B,MAAM,EAAE,OAAO,EAAE,MAAM;YACvB,SAAS,EAAE,OAAO,EAAE,SAAS;YAC7B,KAAK,EAAE,OAAO,EAAE,KAAK;YACrB,MAAM,EAAE,OAAO,EAAE,MAAM;YACvB,SAAS,EAAE,OAAO,EAAE,SAAS;YAC7B,OAAO,EAAE,OAAO,EAAE,OAAO;YACzB,MAAM,EAAE,OAAO,EAAE,MAAM;SACxB,CAAC;IACJ,CAAC;CACF;AA/CD,kEA+CC"}
@@ -28,6 +28,24 @@ const metricReader = new sdk_metrics_1.PeriodicExportingMetricReader({
28
28
  exporter: new exporter_metrics_otlp_grpc_1.OTLPMetricExporter({ url: otelEndpoint }),
29
29
  exportIntervalMillis: 15000,
30
30
  });
31
+ let logProvider = null;
32
+ function setupOtelLogs() {
33
+ try {
34
+ const sdkLogs = require('@opentelemetry/sdk-logs');
35
+ const exporterLogs = require('@opentelemetry/exporter-logs-otlp-grpc');
36
+ const apiLogs = require('@opentelemetry/api-logs');
37
+ const provider = new sdkLogs.LoggerProvider({ resource });
38
+ const exporter = new exporterLogs.OTLPLogExporter({ url: otelEndpoint });
39
+ provider.addLogRecordProcessor(new sdkLogs.BatchLogRecordProcessor(exporter));
40
+ apiLogs.logs.setGlobalLoggerProvider(provider);
41
+ logProvider = provider;
42
+ }
43
+ catch (error) {
44
+ if (process.env.OTEL_DEBUG === 'true') {
45
+ console.warn('OpenTelemetry logs SDK is not available. Install @opentelemetry/sdk-logs, @opentelemetry/api-logs and @opentelemetry/exporter-logs-otlp-grpc.', error);
46
+ }
47
+ }
48
+ }
31
49
  const sdk = new sdk_node_1.NodeSDK({
32
50
  resource,
33
51
  traceExporter,
@@ -46,10 +64,14 @@ const sdk = new sdk_node_1.NodeSDK({
46
64
  ],
47
65
  });
48
66
  exports.sdk = sdk;
67
+ setupOtelLogs();
49
68
  sdk.start();
50
69
  const shutdown = async () => {
51
70
  try {
52
71
  await sdk.shutdown();
72
+ if (logProvider) {
73
+ await logProvider.shutdown();
74
+ }
53
75
  console.log('OpenTelemetry SDK shut down successfully');
54
76
  }
55
77
  catch (err) {