@athenna/logger 5.17.0 → 5.19.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@athenna/logger",
3
- "version": "5.17.0",
3
+ "version": "5.19.0",
4
4
  "description": "The Athenna logging solution. Log in stdout, files and buckets.",
5
5
  "license": "MIT",
6
6
  "author": "João Lenon <lenon@athenna.io>",
@@ -63,7 +63,6 @@
63
63
  },
64
64
  "dependencies": {
65
65
  "@aws-lambda-powertools/logger": "^1.18.1",
66
- "@opentelemetry/api": "^1.9.0",
67
66
  "@opentelemetry/api-logs": "^0.213.0",
68
67
  "cls-rtracer": "^2.6.3",
69
68
  "telegraf": "^4.16.3"
@@ -74,7 +73,8 @@
74
73
  "@athenna/ioc": "^5.2.0",
75
74
  "@athenna/test": "^5.5.0",
76
75
  "@athenna/tsconfig": "^5.0.0",
77
- "@opentelemetry/context-async-hooks": "^2.6.0",
76
+ "@opentelemetry/api": "^1.9.1",
77
+ "@opentelemetry/context-async-hooks": "^2.7.0",
78
78
  "@typescript-eslint/eslint-plugin": "^8.38.0",
79
79
  "@typescript-eslint/parser": "^8.38.0",
80
80
  "commitizen": "^4.3.1",
@@ -6,6 +6,7 @@
6
6
  * For the full copyright and license information, please view the LICENSE
7
7
  * file that was distributed with this source code.
8
8
  */
9
+ import type { Context as OtelContext } from '@opentelemetry/api';
9
10
  export declare abstract class Formatter {
10
11
  /**
11
12
  * Holds the configuration object of formatter.
@@ -39,6 +40,10 @@ export declare abstract class Formatter {
39
40
  * Get the span id for formatter.
40
41
  */
41
42
  spanId(): string | null;
43
+ /**
44
+ * Resolve configured context bindings using the active OpenTelemetry context.
45
+ */
46
+ contextBindings(activeContext?: OtelContext): Record<string, any>;
42
47
  /**
43
48
  * Create the timestamp for formatter.
44
49
  */
@@ -8,8 +8,8 @@
8
8
  */
9
9
  import rTracer from 'cls-rtracer';
10
10
  import { hostname } from 'node:os';
11
- import { trace } from '@opentelemetry/api';
12
- import { Is, Color } from '@athenna/common';
11
+ import { Is, Color, Module } from '@athenna/common';
12
+ const otelApi = await Module.safeImport('@opentelemetry/api');
13
13
  export class Formatter {
14
14
  constructor() {
15
15
  /**
@@ -46,14 +46,37 @@ export class Formatter {
46
46
  * Get the trace id for formatter.
47
47
  */
48
48
  traceId() {
49
- return (trace.getActiveSpan()?.spanContext().traceId ||
50
- (rTracer.id() || null));
49
+ if (otelApi?.trace?.getActiveSpan()?.spanContext().traceId) {
50
+ return otelApi?.trace?.getActiveSpan()?.spanContext().traceId;
51
+ }
52
+ return (rTracer.id() || null);
51
53
  }
52
54
  /**
53
55
  * Get the span id for formatter.
54
56
  */
55
57
  spanId() {
56
- return trace.getActiveSpan()?.spanContext().spanId || null;
58
+ return otelApi?.trace?.getActiveSpan()?.spanContext().spanId || null;
59
+ }
60
+ /**
61
+ * Resolve configured context bindings using the active OpenTelemetry context.
62
+ */
63
+ contextBindings(activeContext) {
64
+ if (!otelApi) {
65
+ throw new Error('The package @opentelemetry/api is not installed');
66
+ }
67
+ if (!activeContext) {
68
+ activeContext = otelApi.context.active();
69
+ }
70
+ const contextBindings = this.configs.contextBindings || [];
71
+ const resolved = {};
72
+ for (const binding of contextBindings) {
73
+ const value = binding.resolve(activeContext);
74
+ if (Is.Undefined(value)) {
75
+ continue;
76
+ }
77
+ resolved[binding.field] = value;
78
+ }
79
+ return resolved;
57
80
  }
58
81
  /**
59
82
  * Create the timestamp for formatter.
@@ -13,11 +13,13 @@ export class JsonFormatter extends Formatter {
13
13
  const base = {
14
14
  ...(this.configs.defaults || {}),
15
15
  level: this.level(),
16
- time: Date.now(),
16
+ date: new Date().toISOString(),
17
+ timestamp: Date.now(),
17
18
  pid: this.pid(),
18
19
  hostname: this.hostname(),
19
20
  traceId: this.traceId(),
20
- spanId: this.spanId()
21
+ spanId: this.spanId(),
22
+ ...this.contextBindings(),
21
23
  };
22
24
  if (Is.String(message)) {
23
25
  base.msg = message;
@@ -21,6 +21,17 @@ export class RequestFormatter extends Formatter {
21
21
  if (!this.configs.asJson) {
22
22
  return this.clean(`${method}${status} ${ctx.request.baseUrl} - ${date} - ${responseTimeMs}`);
23
23
  }
24
+ const base = {
25
+ ...(this.configs.defaults || {}),
26
+ level: this.level(),
27
+ date,
28
+ timestamp: Date.now(),
29
+ pid: this.pid(),
30
+ hostname: this.hostname(),
31
+ traceId: this.traceId(),
32
+ spanId: this.spanId(),
33
+ ...this.contextBindings()
34
+ };
24
35
  const metadata = {
25
36
  method: ctx.request.method,
26
37
  duration: responseTimeMs,
@@ -28,9 +39,6 @@ export class RequestFormatter extends Formatter {
28
39
  statusCode,
29
40
  url: ctx.request.hostUrl,
30
41
  path: ctx.request.baseUrl,
31
- createdAt: Date.now(),
32
- traceId: this.traceId(),
33
- spanId: this.spanId(),
34
42
  data: ctx.data
35
43
  };
36
44
  const request = {
@@ -45,6 +53,6 @@ export class RequestFormatter extends Formatter {
45
53
  body: ctx.response.body,
46
54
  headers: ctx.response.headers
47
55
  };
48
- return JSON.stringify({ request, response, metadata }, this.getCircularReplacer());
56
+ return JSON.stringify({ ...base, request, response, metadata }, this.getCircularReplacer());
49
57
  }
50
58
  }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @athenna/logger
3
+ *
4
+ * (c) João Lenon <lenon@athenna.io>
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+ import type { Context } from '@opentelemetry/api';
10
+ export type ContextBinding = {
11
+ field: string;
12
+ resolve: (activeContext: Context) => any;
13
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * @athenna/logger
3
+ *
4
+ * (c) João Lenon <lenon@athenna.io>
5
+ *
6
+ * For the full copyright and license information, please view the LICENSE
7
+ * file that was distributed with this source code.
8
+ */
9
+ export {};
@@ -7,3 +7,4 @@
7
7
  * file that was distributed with this source code.
8
8
  */
9
9
  export * from '#src/types/Level';
10
+ export * from '#src/types/ContextBinding';
@@ -7,3 +7,4 @@
7
7
  * file that was distributed with this source code.
8
8
  */
9
9
  export * from '#src/types/Level';
10
+ export * from '#src/types/ContextBinding';