@ogcio/o11y-sdk-node 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/README.md +158 -13
  3. package/dist/lib/config-manager.d.ts +3 -0
  4. package/dist/lib/config-manager.js +11 -0
  5. package/dist/lib/exporter/console.js +3 -4
  6. package/dist/lib/exporter/grpc.js +14 -13
  7. package/dist/lib/exporter/http.d.ts +1 -1
  8. package/dist/lib/exporter/http.js +14 -13
  9. package/dist/lib/exporter/pii-exporter-decorator.d.ts +20 -0
  10. package/dist/lib/exporter/pii-exporter-decorator.js +103 -0
  11. package/dist/lib/exporter/processor-config.d.ts +5 -0
  12. package/dist/lib/exporter/processor-config.js +16 -0
  13. package/dist/lib/index.d.ts +18 -4
  14. package/dist/lib/instrumentation.node.js +13 -11
  15. package/dist/lib/internals/hooks.d.ts +3 -0
  16. package/dist/lib/internals/hooks.js +12 -0
  17. package/dist/lib/internals/pii-detection.d.ts +17 -0
  18. package/dist/lib/internals/pii-detection.js +116 -0
  19. package/dist/lib/internals/shared-metrics.d.ts +7 -0
  20. package/dist/lib/internals/shared-metrics.js +18 -0
  21. package/dist/lib/traces.d.ts +20 -1
  22. package/dist/lib/traces.js +47 -1
  23. package/dist/package.json +3 -2
  24. package/dist/vitest.config.js +7 -1
  25. package/lib/config-manager.ts +16 -0
  26. package/lib/exporter/console.ts +6 -4
  27. package/lib/exporter/grpc.ts +34 -21
  28. package/lib/exporter/http.ts +33 -20
  29. package/lib/exporter/pii-exporter-decorator.ts +152 -0
  30. package/lib/exporter/processor-config.ts +23 -0
  31. package/lib/index.ts +19 -4
  32. package/lib/instrumentation.node.ts +16 -16
  33. package/lib/internals/hooks.ts +14 -0
  34. package/lib/internals/pii-detection.ts +145 -0
  35. package/lib/internals/shared-metrics.ts +34 -0
  36. package/lib/traces.ts +74 -1
  37. package/package.json +3 -2
  38. package/test/config-manager.test.ts +34 -0
  39. package/test/exporter/pii-exporter-decorator.test.ts +139 -0
  40. package/test/integration/{integration.test.ts → http-tracing.integration.test.ts} +0 -2
  41. package/test/integration/pii.integration.test.ts +68 -0
  42. package/test/integration/run.sh +2 -2
  43. package/test/internals/hooks.test.ts +45 -0
  44. package/test/internals/pii-detection.test.ts +141 -0
  45. package/test/internals/shared-metrics.test.ts +34 -0
  46. package/test/node-config.test.ts +59 -14
  47. package/test/processor/enrich-span-processor.test.ts +2 -54
  48. package/test/traces/active-span.test.ts +28 -0
  49. package/test/traces/with-span.test.ts +340 -0
  50. package/test/utils/alloy-log-parser.ts +7 -0
  51. package/test/utils/mock-signals.ts +144 -0
  52. package/vitest.config.ts +7 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,67 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.0](https://github.com/ogcio/o11y/compare/@ogcio/o11y-sdk-node@v0.2.0...@ogcio/o11y-sdk-node@v0.3.0) (2025-07-28)
4
+
5
+
6
+ ### Features
7
+
8
+ * add custom log processor for span enrich ([#102](https://github.com/ogcio/o11y/issues/102)) ([bbf8334](https://github.com/ogcio/o11y/commit/bbf83340940ed651dff63bbe7aaa52881d1e8c8c))
9
+ * add opentelemetry sampler ([#66](https://github.com/ogcio/o11y/issues/66)) ([48a1761](https://github.com/ogcio/o11y/commit/48a1761d68fbccf7b63e4232a62376caecf01fbc))
10
+ * april depedency upgrade AB[#27200](https://github.com/ogcio/o11y/issues/27200) ([#116](https://github.com/ogcio/o11y/issues/116)) ([d792fe5](https://github.com/ogcio/o11y/commit/d792fe5a783b0b495912b5bef2babfe11ef5e01d))
11
+ * june deps update ([#147](https://github.com/ogcio/o11y/issues/147)) ([b365a40](https://github.com/ogcio/o11y/commit/b365a4099cdfd8533ffa4948620d29f0044bbd70))
12
+ * late june deps update ([#154](https://github.com/ogcio/o11y/issues/154)) ([a772622](https://github.com/ogcio/o11y/commit/a7726225a59b2dbcd4326919323d935843b2f93f))
13
+ * may deps update ([#136](https://github.com/ogcio/o11y/issues/136)) ([3edd8b1](https://github.com/ogcio/o11y/commit/3edd8b1d823740d555fc4d93be427e9dc1438a95))
14
+ * o11y sdk repo setup ([#15](https://github.com/ogcio/o11y/issues/15)) ([c5816ba](https://github.com/ogcio/o11y/commit/c5816baff1454353f12539949959e84964ed6401))
15
+ * o11y showcase AB[#25895](https://github.com/ogcio/o11y/issues/25895) ([#84](https://github.com/ogcio/o11y/issues/84)) ([f8f10af](https://github.com/ogcio/o11y/commit/f8f10af97d9f5c188e3e65f7d62d5c673edce25a))
16
+ * remove pnpm test on prepublishOnly script ([#68](https://github.com/ogcio/o11y/issues/68)) ([41f6f57](https://github.com/ogcio/o11y/commit/41f6f57fa415c4f7adc29f49f983539274ef7320))
17
+ * **sdk-node:** add span customization AB[#25358](https://github.com/ogcio/o11y/issues/25358) ([46ba97b](https://github.com/ogcio/o11y/commit/46ba97bac4004ff326a954592f45213ce0e4d683))
18
+ * **sdk-node:** custom metrics ([#53](https://github.com/ogcio/o11y/issues/53)) ([3cb40b1](https://github.com/ogcio/o11y/commit/3cb40b1add3d80615c8d123d233724094559c7ff))
19
+ * **sdk-node:** pii detection on traces and logs ([#176](https://github.com/ogcio/o11y/issues/176)) ([3d72f94](https://github.com/ogcio/o11y/commit/3d72f941b1854278105e7c6d4c4c20248037ecd3))
20
+ * **sdk-node:** renaming MetricsParams interface properties AB[#26188](https://github.com/ogcio/o11y/issues/26188) ([#96](https://github.com/ogcio/o11y/issues/96)) ([244aee0](https://github.com/ogcio/o11y/commit/244aee01ae6e7f319ae7f9fdeff27eb40ee3c863))
21
+ * **sdk-node:** traces and span wrapping utility AB[#29532](https://github.com/ogcio/o11y/issues/29532) ([#175](https://github.com/ogcio/o11y/issues/175)) ([22398d8](https://github.com/ogcio/o11y/commit/22398d8663519e7b2152ebc8766c64bf36a709e7))
22
+ * update AWS secrets manager connection AB[#29565](https://github.com/ogcio/o11y/issues/29565) ([#166](https://github.com/ogcio/o11y/issues/166)) ([962c03d](https://github.com/ogcio/o11y/commit/962c03de2da4060a81aa603c355f3d60cafe3c30))
23
+ * upgrade to opentelemetry 2 AB[#25863](https://github.com/ogcio/o11y/issues/25863) ([#106](https://github.com/ogcio/o11y/issues/106)) ([3ff0314](https://github.com/ogcio/o11y/commit/3ff0314fef9f4d7b5db76da3b94e9035801384c7))
24
+
25
+
26
+ ### Bug Fixes
27
+
28
+ * add readme file inside submodule ([#27](https://github.com/ogcio/o11y/issues/27)) ([dc518d5](https://github.com/ogcio/o11y/commit/dc518d5dde573368443bc0f8619e80e331880c78))
29
+ * default attributes in resource ([#112](https://github.com/ogcio/o11y/issues/112)) ([f0f0b9d](https://github.com/ogcio/o11y/commit/f0f0b9d555ef321d31f7171e25dc4b8a5b044522))
30
+ * improve getMetric attributes types ([#76](https://github.com/ogcio/o11y/issues/76)) ([243649c](https://github.com/ogcio/o11y/commit/243649c4bfe750687a729fbd836772cce16e0cb1))
31
+ * prepublishOnly hook ([#60](https://github.com/ogcio/o11y/issues/60)) ([9fbd3ad](https://github.com/ogcio/o11y/commit/9fbd3ad0b45a1604cf2eccc26b2f8855640417a1))
32
+ * **sdk-node:** add waitForReady for grpc-client to handle transient init connection errors AB[#28329](https://github.com/ogcio/o11y/issues/28329) ([#144](https://github.com/ogcio/o11y/issues/144)) ([6f260da](https://github.com/ogcio/o11y/commit/6f260da15fcbcd2c629ec6d4bb9fb3592803f399))
33
+ * **sdk-node:** allow graceful shutdown of instrumentation on SIGTERM AB[#28329](https://github.com/ogcio/o11y/issues/28329) ([#151](https://github.com/ogcio/o11y/issues/151)) ([991ee15](https://github.com/ogcio/o11y/commit/991ee1559898b721823cb9d1e0490e2ad82e6d0a))
34
+ * **sdk-node:** update sdk init examples AB[#28329](https://github.com/ogcio/o11y/issues/28329) ([#146](https://github.com/ogcio/o11y/issues/146)) ([81de295](https://github.com/ogcio/o11y/commit/81de2957a7bef7430a46c6677f3c876255ef7c88))
35
+
36
+
37
+ ### Miscellaneous Chores
38
+
39
+ * **auto-release:** release @ogcio/o11y-sdk-node 0.1.0-beta.10 ([#113](https://github.com/ogcio/o11y/issues/113)) ([5474a1d](https://github.com/ogcio/o11y/commit/5474a1dd715dcfcd1da7ec46ea17da3b369529ac))
40
+ * **auto-release:** release @ogcio/o11y-sdk-node 0.1.0-beta.11 ([#137](https://github.com/ogcio/o11y/issues/137)) ([90e42ba](https://github.com/ogcio/o11y/commit/90e42ba5b76d7bd89cbffd011f5a2fda1b3e4fe0))
41
+ * **auto-release:** release @ogcio/o11y-sdk-node 0.1.0-beta.12 ([#148](https://github.com/ogcio/o11y/issues/148)) ([d495182](https://github.com/ogcio/o11y/commit/d495182d04312a62298b3e5fb18d55c32743c14e))
42
+ * **auto-release:** release @ogcio/o11y-sdk-node 0.1.0-beta.13 ([#152](https://github.com/ogcio/o11y/issues/152)) ([5903e22](https://github.com/ogcio/o11y/commit/5903e22c7da8219661c6b9f78a2b3c330bc51823))
43
+ * **auto-release:** release @ogcio/o11y-sdk-node 0.1.0-beta.3 ([#30](https://github.com/ogcio/o11y/issues/30)) ([842da9b](https://github.com/ogcio/o11y/commit/842da9b6500c03b0c3a11165a78168724bd0a0f5))
44
+ * **auto-release:** release @ogcio/o11y-sdk-node 0.1.0-beta.4 ([#61](https://github.com/ogcio/o11y/issues/61)) ([770873e](https://github.com/ogcio/o11y/commit/770873e7c7d08289e7a8ab46bc801294e9d055bf))
45
+ * **auto-release:** release @ogcio/o11y-sdk-node 0.1.0-beta.5 ([#67](https://github.com/ogcio/o11y/issues/67)) ([8ffc453](https://github.com/ogcio/o11y/commit/8ffc45380b76cf59dcbdd86c6f0501b4526948e7))
46
+ * **auto-release:** release @ogcio/o11y-sdk-node 0.1.0-beta.6 ([#70](https://github.com/ogcio/o11y/issues/70)) ([32308de](https://github.com/ogcio/o11y/commit/32308de75b80db1b2def63d2b5fcf80328278712))
47
+ * **auto-release:** release @ogcio/o11y-sdk-node 0.1.0-beta.7 ([#75](https://github.com/ogcio/o11y/issues/75)) ([5598269](https://github.com/ogcio/o11y/commit/55982690a5a21a18120572a8760f6630aeda2bd1))
48
+ * **auto-release:** release @ogcio/o11y-sdk-node 0.1.0-beta.8 ([#86](https://github.com/ogcio/o11y/issues/86)) ([c0956d4](https://github.com/ogcio/o11y/commit/c0956d4eceabb415d72addf5e2b6f5efd5423f62))
49
+ * **auto-release:** release @ogcio/o11y-sdk-node 0.1.0-beta.9 ([#105](https://github.com/ogcio/o11y/issues/105)) ([51e854e](https://github.com/ogcio/o11y/commit/51e854e55753bcca33bdc5bc489e9abe2bdee21c))
50
+ * **auto-release:** release @ogcio/o11y-sdk-node 0.2.0-beta.13 ([#155](https://github.com/ogcio/o11y/issues/155)) ([a918198](https://github.com/ogcio/o11y/commit/a91819823da965d160dc0a9a302cd0fea88e68d2))
51
+ * **deps-dev:** bump @types/node to `24` AB[#29294](https://github.com/ogcio/o11y/issues/29294) ([3c74c28](https://github.com/ogcio/o11y/commit/3c74c28af41af8403220368ac72a90e40c3e15ae))
52
+ * **deps-dev:** bump the root-deps group across 1 directory with 3 updates ([#150](https://github.com/ogcio/o11y/issues/150)) ([9d574d1](https://github.com/ogcio/o11y/commit/9d574d1af0964fc4af991d677b443015921d93f6))
53
+ * **deps:** bump the root-deps group across 1 directory with 6 updates ([#31](https://github.com/ogcio/o11y/issues/31)) ([591e15f](https://github.com/ogcio/o11y/commit/591e15fcfd8f633f7809de7ca0bfe179251609e7))
54
+ * **deps:** bump the root-deps group across 3 directories with 10 updates ([#64](https://github.com/ogcio/o11y/issues/64)) ([bde04e3](https://github.com/ogcio/o11y/commit/bde04e3d67a6b860a11eca0229dc76e7bbaad13a))
55
+ * **deps:** bump the root-deps group across 3 directories with 28 updates ([#74](https://github.com/ogcio/o11y/issues/74)) ([b67190c](https://github.com/ogcio/o11y/commit/b67190c18c175770c1661c1c70dcf9990c9cb275))
56
+ * dx improvements ([#22](https://github.com/ogcio/o11y/issues/22)) ([1698662](https://github.com/ogcio/o11y/commit/1698662cb2a96220f36959c30480db06a1be2e61))
57
+ * migrate from node:test to vitest ([#20](https://github.com/ogcio/o11y/issues/20)) ([fd1300b](https://github.com/ogcio/o11y/commit/fd1300b1a72c5fac972ccd42b7b05ad125d6e33e))
58
+ * packages updates ([#44](https://github.com/ogcio/o11y/issues/44)) ([11ecc75](https://github.com/ogcio/o11y/commit/11ecc75e7a4e8983dd0f8a9f499e8cb8c21b00ee))
59
+ * **release:** release @ogcio/o11y-sdk-node 0.1.0-beta.1 ([#25](https://github.com/ogcio/o11y/issues/25)) ([0c17f98](https://github.com/ogcio/o11y/commit/0c17f980cf782ab02e1b5243a50e5d37772a590d))
60
+ * **release:** release @ogcio/o11y-sdk-node 0.1.0-beta.2 ([#28](https://github.com/ogcio/o11y/issues/28)) ([1468e48](https://github.com/ogcio/o11y/commit/1468e4832ad757a733e54d2f110d85345904ec50))
61
+ * removed deprecated dep is-url from react-sdk ([#77](https://github.com/ogcio/o11y/issues/77)) ([4ef27d3](https://github.com/ogcio/o11y/commit/4ef27d3a5d01323ea1abdd7659900d4a2a31adce))
62
+ * update dependencies ([#91](https://github.com/ogcio/o11y/issues/91)) ([a16a8cd](https://github.com/ogcio/o11y/commit/a16a8cd1b072f7f6906f8a77b9bab2a4dad9fdee))
63
+ * update integration tests and docs ([#171](https://github.com/ogcio/o11y/issues/171)) ([d03b2a5](https://github.com/ogcio/o11y/commit/d03b2a54d1832aa160b9e8ed3cc28fc72005475c))
64
+
3
65
  ## [0.2.0](https://github.com/ogcio/o11y/compare/@ogcio/o11y-sdk-node@v0.1.0-beta.13...@ogcio/o11y-sdk-node@v0.2.0) (2025-06-24)
4
66
 
5
67
 
package/README.md CHANGED
@@ -56,6 +56,8 @@ Or setup inside your package.json
56
56
  }
57
57
  ```
58
58
 
59
+ # Traces
60
+
59
61
  ## Span Customization
60
62
 
61
63
  It is possible to customize spans such as traces and logs globally or in a single code statement using predefined functions.
@@ -85,27 +87,170 @@ instrumentNode({
85
87
  });
86
88
  ```
87
89
 
88
- ### Edit Active Span
90
+ ### PII Detection
91
+
92
+ By default the sdk detect and redact email PII from traces and logs
93
+
94
+ example:
89
95
 
90
- Using `getActiveSpan` function, you can access to current transaction span and customize it.
96
+ ```
97
+ input: user access: name.lastname@domain.com
98
+ output: user access: [REDACTED EMAIL]
99
+ ```
91
100
 
92
- You can use the function everywhere in your code, and set some custom attributes that are enabled for that single span
101
+ You can disable PII detection with `detection` object inside `NodeSDKConfig`
93
102
 
94
103
  ```typescript
95
- import { getActiveSpan } from "@ogcio/o11y-sdk-node";
104
+ instrumentNode({
105
+ detection: {
106
+ email: false,
107
+ },
108
+ });
109
+ ```
96
110
 
97
- async function routes(app: FastifyInstance) {
98
- app.get("/", async (req, reply) => {
99
- // validation and business logic
111
+ ### PII Detection
100
112
 
101
- // set span attribute
102
- getActiveSpan()?.setAttribute("business.info", "dummy");
113
+ By default the sdk detect and redact email PII from traces and logs
103
114
 
104
- reply.status(200).send(response);
105
- });
106
- }
115
+ example:
116
+
117
+ ```
118
+ input: user acces: name.lastname@domain.com
119
+ output: user access: [REDACTED EMAIL]
120
+ ```
121
+
122
+ You can disable PII detection with `detection` object inside `NodeSDKConfig`
123
+
124
+ ```typescript
125
+ instrumentNode({
126
+ detection: {
127
+ email: false,
128
+ },
129
+ });
107
130
  ```
108
131
 
132
+ ## Utils:
133
+
134
+ - ## `withSpan`:
135
+
136
+ ### Key Features
137
+ - **Automatic Span Management**: Spans are automatically started, ended, and their status is set based on execution success or failure
138
+ - **Exception Recording**: Errors are automatically recorded with proper span status codes
139
+ - **Flexible Configuration**: Support for custom tracer names, span options, and attributes
140
+ - **Promise Support**: Works seamlessly with both synchronous and asynchronous functions
141
+ - **Nested Tracing**: Spans created within existing trace contexts automatically become child spans
142
+
143
+ ### Usage:
144
+
145
+ ```ts
146
+ import { SpanOptions } from "@opentelemetry/api";
147
+
148
+ export type WithSpanParams<T> = {
149
+ /**
150
+ * The name of the trace the span should belong to.
151
+ * NOTE: If you want the new span to belong to an already existing trace, you should provide the same tracer name
152
+ */
153
+ traceName?: string;
154
+ spanName: string;
155
+ spanOptions?: SpanOptions;
156
+ /** A function defining the task you want to be wrapped by this span */
157
+ fn: (span: Span) => T | Promise<T>;
158
+ };
159
+ ```
160
+
161
+ ### examples:
162
+
163
+ ### **Creating a Top-Level Trace (e.g. Worker Job)**
164
+
165
+ Use to create a top-level trace for background jobs, workers, or any standalone operations: `withSpan`
166
+
167
+ ```ts
168
+ import { withSpan } from "@ogcio/o11y-sdk-node";
169
+
170
+ async function processEmailQueue() {
171
+ return withSpan({
172
+ traceName: "email-worker",
173
+ spanName: "process-email-queue",
174
+ fn: async (span) => {
175
+ // Your worker logic here
176
+ const emails = await fetchPendingEmails();
177
+ span.setAttributes({
178
+ "email.count": emails.length,
179
+ "worker.batch.id": generateBatchId(),
180
+ });
181
+
182
+ for (const email of emails) {
183
+ await sendEmail(email);
184
+ }
185
+
186
+ return { processed: emails.length };
187
+ },
188
+ });
189
+ }
190
+ ```
191
+
192
+ ### **Nesting Spans Inside Existing Traces**
193
+
194
+ Create child spans within existing trace contexts to provide detailed operation breakdown:
195
+
196
+ ```typescript
197
+ async function orderProcessing(orderId: string) {
198
+ return withSpan({
199
+ spanName: "process-order",
200
+ fn: async (parentSpan) => {
201
+ // Child span for validation
202
+ const validation = await withSpan({
203
+ spanName: "validate-order",
204
+ fn: async (span) => {
205
+ span.setAttribute("order.id", orderId);
206
+ return await validateOrder(orderId);
207
+ },
208
+ });
209
+ // Child span for payment
210
+ const payment = await withSpan({
211
+ spanName: "process-payment",
212
+ fn: async (span) => {
213
+ span.setAttribute("payment.amount", validation.amount);
214
+ return await processPayment(orderId, validation.amount);
215
+ },
216
+ });
217
+
218
+ parentSpan.setAttributes({
219
+ "order.status": "completed",
220
+ "order.total": payment.amount,
221
+ });
222
+
223
+ return { orderId, status: "completed" };
224
+ },
225
+ });
226
+ }
227
+ ```
228
+
229
+ - ## `getActiveSpan`:
230
+
231
+ Using `getActiveSpan` function, you can access to current transaction span and customize it.
232
+
233
+ ### Examples:
234
+
235
+ ### **Edit Active Span**
236
+
237
+ You can use the function everywhere in your code, and set some custom attributes that are enabled for that single span
238
+
239
+ ```typescript
240
+ import { getActiveSpan } from "@ogcio/o11y-sdk-node";
241
+
242
+ async function routes(app: FastifyInstance) {
243
+ app.get("/", async (req, reply) => {
244
+ // validation and business logic
245
+
246
+ // set span attribute
247
+ getActiveSpan()?.setAttribute("business.info", "dummy");
248
+
249
+ reply.status(200).send(response);
250
+ });
251
+ }
252
+ ```
253
+
109
254
  ## Sending Custom Metrics
110
255
 
111
256
  This package gives the possibility to send custom metrics and define them as desired in the code, you can choose between sync metrics and observable async metrics.
@@ -199,7 +344,7 @@ protocol is a string parameter used to define how to send signals to observabili
199
344
 
200
345
  #### Shared Types
201
346
 
202
- ```ts
347
+ ```typescript
203
348
  export type SDKLogLevel =
204
349
  | "NONE"
205
350
  | "ERROR"
@@ -0,0 +1,3 @@
1
+ import { NodeSDKConfig } from "./index.js";
2
+ export declare const setNodeSdkConfig: (config: NodeSDKConfig) => void;
3
+ export declare const getNodeSdkConfig: () => NodeSDKConfig;
@@ -0,0 +1,11 @@
1
+ let nodeSDKConfig;
2
+ export const setNodeSdkConfig = (config) => {
3
+ nodeSDKConfig = config;
4
+ };
5
+ export const getNodeSdkConfig = () => {
6
+ if (!nodeSDKConfig) {
7
+ throw new Error("Node SDK Config was not initialized.");
8
+ }
9
+ // Ensure getters do not edit config.
10
+ return JSON.parse(JSON.stringify(nodeSDKConfig));
11
+ };
@@ -1,19 +1,18 @@
1
1
  import { ConsoleLogRecordExporter, SimpleLogRecordProcessor, } from "@opentelemetry/sdk-logs";
2
2
  import { metrics } from "@opentelemetry/sdk-node";
3
3
  import { ConsoleSpanExporter, SimpleSpanProcessor, } from "@opentelemetry/sdk-trace-base";
4
- import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
5
- import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
4
+ import { _logsProcessorConfig, _spansProcessorConfig, } from "./processor-config.js";
6
5
  export default function buildConsoleExporters(config) {
7
6
  return {
8
7
  spans: [
9
8
  new SimpleSpanProcessor(new ConsoleSpanExporter()),
10
- new EnrichSpanProcessor(config.spanAttributes),
9
+ ..._spansProcessorConfig(config),
11
10
  ],
12
11
  metrics: new metrics.PeriodicExportingMetricReader({
13
12
  exporter: new metrics.ConsoleMetricExporter(),
14
13
  }),
15
14
  logs: [
16
- new EnrichLogProcessor(config.spanAttributes),
15
+ ..._logsProcessorConfig(config),
17
16
  new SimpleLogRecordProcessor(new ConsoleLogRecordExporter()),
18
17
  ],
19
18
  };
@@ -1,11 +1,12 @@
1
- import { metrics } from "@opentelemetry/sdk-node";
2
- import { CompressionAlgorithm } from "@opentelemetry/otlp-exporter-base";
3
- import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc";
4
1
  import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-grpc";
5
2
  import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-grpc";
3
+ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-grpc";
4
+ import { CompressionAlgorithm } from "@opentelemetry/otlp-exporter-base";
5
+ import { metrics } from "@opentelemetry/sdk-node";
6
6
  import { LogRecordProcessorMap, SpanProcessorMap } from "../utils.js";
7
- import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
8
- import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
7
+ import { _logsProcessorConfig, _spansProcessorConfig, } from "./processor-config.js";
8
+ import { getNodeSdkConfig } from "../config-manager.js";
9
+ import { PIIExporterDecorator } from "./pii-exporter-decorator.js";
9
10
  async function defaultMetadata() {
10
11
  const { Metadata } = await import("@grpc/grpc-js");
11
12
  return new Metadata({
@@ -15,27 +16,27 @@ async function defaultMetadata() {
15
16
  export default async function buildGrpcExporters(config) {
16
17
  return {
17
18
  spans: [
18
- new SpanProcessorMap[config.collectorMode ?? "batch"](new OTLPTraceExporter({
19
+ new SpanProcessorMap[config.collectorMode ?? "batch"](new PIIExporterDecorator(new OTLPTraceExporter({
19
20
  url: `${config.collectorUrl}`,
20
21
  compression: CompressionAlgorithm.GZIP,
21
22
  metadata: config.grpcMetadata ?? (await defaultMetadata()),
22
- })),
23
- new EnrichSpanProcessor(config.spanAttributes),
23
+ }), getNodeSdkConfig())),
24
+ ..._spansProcessorConfig(config),
24
25
  ],
25
26
  metrics: new metrics.PeriodicExportingMetricReader({
26
- exporter: new OTLPMetricExporter({
27
+ exporter: new PIIExporterDecorator(new OTLPMetricExporter({
27
28
  url: `${config.collectorUrl}`,
28
29
  compression: CompressionAlgorithm.GZIP,
29
30
  metadata: config.grpcMetadata ?? (await defaultMetadata()),
30
- }),
31
+ }), getNodeSdkConfig()),
31
32
  }),
32
33
  logs: [
33
- new EnrichLogProcessor(config.spanAttributes),
34
- new LogRecordProcessorMap[config.collectorMode ?? "batch"](new OTLPLogExporter({
34
+ ..._logsProcessorConfig(config),
35
+ new LogRecordProcessorMap[config.collectorMode ?? "batch"](new PIIExporterDecorator(new OTLPLogExporter({
35
36
  url: `${config.collectorUrl}`,
36
37
  compression: CompressionAlgorithm.GZIP,
37
38
  metadata: config.grpcMetadata ?? (await defaultMetadata()),
38
- })),
39
+ }), getNodeSdkConfig())),
39
40
  ],
40
41
  };
41
42
  }
@@ -1,3 +1,3 @@
1
- import { Exporters } from "./index.js";
2
1
  import { NodeSDKConfig } from "../index.js";
2
+ import { Exporters } from "./index.js";
3
3
  export default function buildHttpExporters(config: NodeSDKConfig): Exporters;
@@ -1,35 +1,36 @@
1
- import { metrics } from "@opentelemetry/sdk-node";
2
- import { CompressionAlgorithm } from "@opentelemetry/otlp-exporter-base";
3
- import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
4
1
  import { OTLPLogExporter } from "@opentelemetry/exporter-logs-otlp-http";
5
2
  import { OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
3
+ import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
4
+ import { CompressionAlgorithm } from "@opentelemetry/otlp-exporter-base";
5
+ import { metrics } from "@opentelemetry/sdk-node";
6
6
  import { LogRecordProcessorMap, SpanProcessorMap } from "../utils.js";
7
- import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
8
- import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
7
+ import { _logsProcessorConfig, _spansProcessorConfig, } from "./processor-config.js";
8
+ import { getNodeSdkConfig } from "../config-manager.js";
9
+ import { PIIExporterDecorator } from "./pii-exporter-decorator.js";
9
10
  export default function buildHttpExporters(config) {
10
11
  if (config.collectorUrl.endsWith("/")) {
11
12
  config.collectorUrl = config.collectorUrl.slice(0, -1);
12
13
  }
13
14
  return {
14
15
  spans: [
15
- new SpanProcessorMap[config.collectorMode ?? "batch"](new OTLPTraceExporter({
16
+ new SpanProcessorMap[config.collectorMode ?? "batch"](new PIIExporterDecorator(new OTLPTraceExporter({
16
17
  url: `${config.collectorUrl}/v1/traces`,
17
18
  compression: CompressionAlgorithm.GZIP,
18
- })),
19
- new EnrichSpanProcessor(config.spanAttributes),
19
+ }), getNodeSdkConfig())),
20
+ ..._spansProcessorConfig(config),
20
21
  ],
21
22
  metrics: new metrics.PeriodicExportingMetricReader({
22
- exporter: new OTLPMetricExporter({
23
+ exporter: new PIIExporterDecorator(new OTLPMetricExporter({
23
24
  url: `${config.collectorUrl}/v1/metrics`,
24
25
  compression: CompressionAlgorithm.GZIP,
25
- }),
26
+ }), getNodeSdkConfig()),
26
27
  }),
27
28
  logs: [
28
- new EnrichLogProcessor(config.spanAttributes),
29
- new LogRecordProcessorMap[config.collectorMode ?? "batch"](new OTLPLogExporter({
29
+ ..._logsProcessorConfig(config),
30
+ new LogRecordProcessorMap[config.collectorMode ?? "batch"](new PIIExporterDecorator(new OTLPLogExporter({
30
31
  url: `${config.collectorUrl}/v1/logs`,
31
32
  compression: CompressionAlgorithm.GZIP,
32
- })),
33
+ }), getNodeSdkConfig())),
33
34
  ],
34
35
  };
35
36
  }
@@ -0,0 +1,20 @@
1
+ import { ExportResult } from "@opentelemetry/core";
2
+ import { OTLPExporterBase } from "@opentelemetry/otlp-exporter-base";
3
+ import { ReadableLogRecord } from "@opentelemetry/sdk-logs";
4
+ import { ReadableSpan, SpanExporter } from "@opentelemetry/sdk-trace-base";
5
+ import { NodeSDKConfig } from "../index.js";
6
+ import { PushMetricExporter, ResourceMetrics } from "@opentelemetry/sdk-metrics";
7
+ export declare class PIIExporterDecorator extends OTLPExporterBase<(ReadableSpan | ReadableLogRecord)[] | ResourceMetrics> implements SpanExporter, PushMetricExporter {
8
+ private readonly _exporter;
9
+ private readonly _config;
10
+ constructor(exporter: OTLPExporterBase<(ReadableSpan | ReadableLogRecord)[] | ResourceMetrics>, config: NodeSDKConfig);
11
+ forceFlush(): Promise<void>;
12
+ shutdown(): Promise<void>;
13
+ export(items: (ReadableSpan | ReadableLogRecord)[] | ResourceMetrics, resultCallback: (result: ExportResult) => void): void;
14
+ private _isReadableSpan;
15
+ private _isReadableLogRecord;
16
+ private _isResourceMetrics;
17
+ private _redactSpan;
18
+ private _redactLogRecord;
19
+ private _redactResourceMetrics;
20
+ }
@@ -0,0 +1,103 @@
1
+ import { OTLPExporterBase } from "@opentelemetry/otlp-exporter-base";
2
+ import { _cleanLogBodyPII, _cleanObjectPII, _cleanStringPII, } from "../internals/pii-detection.js";
3
+ export class PIIExporterDecorator extends OTLPExporterBase {
4
+ _exporter;
5
+ _config;
6
+ constructor(exporter, config) {
7
+ super(exporter["_delegate"]);
8
+ this._exporter = exporter;
9
+ this._config = config;
10
+ }
11
+ forceFlush() {
12
+ return this._exporter.forceFlush();
13
+ }
14
+ shutdown() {
15
+ return this._exporter.shutdown();
16
+ }
17
+ export(items, resultCallback) {
18
+ if (!this._config.detection?.email) {
19
+ this._exporter.export(items, resultCallback);
20
+ return;
21
+ }
22
+ if (Array.isArray(items)) {
23
+ const redactedItem = items.map((item) => {
24
+ if (this._isReadableSpan(item)) {
25
+ this._redactSpan(item);
26
+ }
27
+ else if (this._isReadableLogRecord(item)) {
28
+ this._redactLogRecord(item);
29
+ }
30
+ return item;
31
+ });
32
+ this._exporter.export(redactedItem, resultCallback);
33
+ return;
34
+ }
35
+ if (this._isResourceMetrics(items)) {
36
+ this._redactResourceMetrics(items);
37
+ this._exporter.export(items, resultCallback);
38
+ }
39
+ }
40
+ _isReadableSpan(span) {
41
+ return (typeof span === "object" &&
42
+ span !== null &&
43
+ "name" in span &&
44
+ "kind" in span &&
45
+ "spanContext" in span &&
46
+ "attributes" in span);
47
+ }
48
+ _isReadableLogRecord(span) {
49
+ return (typeof span === "object" &&
50
+ span !== null &&
51
+ "body" in span &&
52
+ "attributes" in span &&
53
+ "severityText" in span &&
54
+ "severityNumber" in span);
55
+ }
56
+ _isResourceMetrics(obj) {
57
+ return (typeof obj === "object" &&
58
+ obj !== null &&
59
+ !Array.isArray(obj) &&
60
+ "resource" in obj &&
61
+ "scopeMetrics" in obj);
62
+ }
63
+ _redactSpan(span) {
64
+ Object.assign(span, {
65
+ name: _cleanStringPII(span.name, "trace"),
66
+ attributes: span.attributes && _cleanObjectPII(span.attributes, "trace"),
67
+ resource: {
68
+ attributes: span?.resource?.attributes &&
69
+ _cleanObjectPII(span.resource.attributes, "trace"),
70
+ },
71
+ links: span?.links?.map((link) => {
72
+ Object.assign(link, {
73
+ attributes: link?.attributes && _cleanObjectPII(link.attributes, "trace"),
74
+ });
75
+ }),
76
+ events: span?.events?.map((event) => {
77
+ Object.assign(event, {
78
+ name: _cleanStringPII(event.name, "trace"),
79
+ attributes: event?.attributes && _cleanObjectPII(event.attributes, "trace"),
80
+ });
81
+ return event;
82
+ }),
83
+ });
84
+ }
85
+ _redactLogRecord(log) {
86
+ Object.assign(log, {
87
+ body: _cleanLogBodyPII(log.body),
88
+ attributes: log.attributes && _cleanObjectPII(log.attributes, "log"),
89
+ resource: {
90
+ attributes: log?.resource?.attributes &&
91
+ _cleanObjectPII(log.resource.attributes, "log"),
92
+ },
93
+ });
94
+ }
95
+ _redactResourceMetrics(metric) {
96
+ Object.assign(metric, {
97
+ resource: {
98
+ attributes: metric?.resource?.attributes &&
99
+ _cleanObjectPII(metric.resource.attributes, "metric"),
100
+ },
101
+ });
102
+ }
103
+ }
@@ -0,0 +1,5 @@
1
+ import { NodeSDKConfig } from "../index.js";
2
+ import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
3
+ import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
4
+ export declare function _spansProcessorConfig(config: NodeSDKConfig): EnrichSpanProcessor[];
5
+ export declare function _logsProcessorConfig(config: NodeSDKConfig): EnrichLogProcessor[];
@@ -0,0 +1,16 @@
1
+ import { EnrichLogProcessor } from "../processor/enrich-logger-processor.js";
2
+ import { EnrichSpanProcessor } from "../processor/enrich-span-processor.js";
3
+ export function _spansProcessorConfig(config) {
4
+ const _processor = [];
5
+ if (config.spanAttributes) {
6
+ _processor.push(new EnrichSpanProcessor(config.spanAttributes));
7
+ }
8
+ return _processor;
9
+ }
10
+ export function _logsProcessorConfig(config) {
11
+ const _processor = [];
12
+ if (config.spanAttributes) {
13
+ _processor.push(new EnrichLogProcessor(config.spanAttributes));
14
+ }
15
+ return _processor;
16
+ }
@@ -2,14 +2,18 @@ import type { Metadata } from "@grpc/grpc-js";
2
2
  export interface NodeSDKConfig {
3
3
  /**
4
4
  * The opentelemetry collector entrypoint GRPC url.
5
- * If the collectoUrl is null or undefined, the instrumentation will not be activated.
5
+ * If the collectorUrl is null or undefined, the instrumentation will not be activated.
6
6
  * @example http://alloy:4317
7
7
  */
8
8
  collectorUrl: string;
9
9
  /**
10
- * Name of your application used for the collector to group logs
10
+ * Name of your application used for the collector to group logs and naming traces
11
11
  */
12
12
  serviceName?: string;
13
+ /**
14
+ * Version of your application used for the collector to group logs and naming traces
15
+ */
16
+ serviceVersion?: string;
13
17
  /**
14
18
  * Diagnostic log level for the internal runtime instrumentation
15
19
  *
@@ -19,7 +23,7 @@ export interface NodeSDKConfig {
19
23
  diagLogLevel?: SDKLogLevel;
20
24
  /**
21
25
  * Collector signals processing mode.
22
- * signle: makes an http/grpc request for each signal and it is immediately processed inside grafana
26
+ * single: makes an http/grpc request for each signal, and it is immediately processed inside grafana
23
27
  * batch: sends multiple signals within a time window, optimized to reduce http/grpc calls in production
24
28
  *
25
29
  * @type string
@@ -34,7 +38,7 @@ export interface NodeSDKConfig {
34
38
  */
35
39
  ignoreUrls?: SamplerCondition[];
36
40
  /**
37
- * Object containing static properties or functions used to evaluate custom attributes for every logs and traces.
41
+ * Object containing static properties or functions used to evaluate custom attributes for all logs and traces.
38
42
  */
39
43
  spanAttributes?: Record<string, SignalAttributeValue | (() => SignalAttributeValue)>;
40
44
  /**
@@ -65,6 +69,16 @@ export interface NodeSDKConfig {
65
69
  * @default { waitForReady: true }
66
70
  */
67
71
  grpcMetadata?: Metadata;
72
+ /**
73
+ * Enable/Disable PII detection for GDPR data
74
+ */
75
+ detection?: {
76
+ /**
77
+ * Redact email address
78
+ * @default true
79
+ */
80
+ email?: boolean;
81
+ };
68
82
  }
69
83
  export interface SamplerCondition {
70
84
  type: "endsWith" | "includes" | "equals";