@primafuture/telemetry-stack 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.
package/README.md CHANGED
@@ -197,20 +197,28 @@ curl -sS -X POST http://localhost:4318/v1/logs \
197
197
  \"body\": {\"stringValue\": \"hello from telemetry-stack smoke test\"},
198
198
  \"attributes\": [
199
199
  {
200
- \"key\": \"log_type\",
200
+ \"key\": \"app.value.log_type\",
201
201
  \"value\": {\"stringValue\": \"smoke_test\"}
202
202
  },
203
203
  {
204
- \"key\": \"route\",
204
+ \"key\": \"app.value.route\",
205
205
  \"value\": {\"stringValue\": \"/smoke\"}
206
206
  },
207
207
  {
208
- \"key\": \"count\",
208
+ \"key\": \"app.value.count\",
209
209
  \"value\": {\"intValue\": \"3\"}
210
210
  },
211
211
  {
212
- \"key\": \"parallel\",
212
+ \"key\": \"app.value.parallel\",
213
213
  \"value\": {\"boolValue\": true}
214
+ },
215
+ {
216
+ \"key\": \"app.type.deletedAt\",
217
+ \"value\": {\"stringValue\": \"null\"}
218
+ },
219
+ {
220
+ \"key\": \"app.meta.json\",
221
+ \"value\": {\"stringValue\": \"{\\\"log_type\\\":\\\"smoke_test\\\",\\\"route\\\":\\\"/smoke\\\",\\\"count\\\":3,\\\"parallel\\\":true,\\\"deletedAt\\\":null}\"}
214
222
  }
215
223
  ]
216
224
  }]
@@ -236,21 +244,30 @@ curl -G 'http://localhost:3100/loki/api/v1/query_range' \
236
244
  --data-urlencode 'limit=5'
237
245
  ```
238
246
 
239
- The returned log should expose application metadata under `app_*`, for example
240
- `app_log_type`, `app_route`, `app_count`, and `app_parallel`. OpenTelemetry
241
- metadata should be under `otel_*`, for example `otel_resource_service_name` and
242
- `otel_scope_name`.
247
+ The returned log should expose application metadata under structured names such
248
+ as `app_value_log_type`, `app_value_route`, `app_value_count`,
249
+ `app_value_parallel`, `app_type_deletedAt`, and `app_meta_json`.
250
+ OpenTelemetry metadata should be under `otel_*`, for example
251
+ `otel_resource_service_name` and `otel_scope_name`.
243
252
 
244
253
  ## Log Metadata in Loki
245
254
 
246
- Applications can log plain metadata such as `count`, `parallel`, or `route`.
247
- Alloy normalizes those fields before Loki receives them, so application code does
248
- not need to add prefixes itself.
255
+ PrimaFuture telemetry libraries encode application metadata before export. The
256
+ query-friendly view uses `app.value.*` for values, `app.type.*` for type markers
257
+ such as `null` or `undefined`, and `app.meta.json` for the JSON representation.
258
+ Loki displays those dotted names as underscore names such as `app_value_route`.
259
+
260
+ Legacy applications can still log plain metadata such as `count`, `parallel`, or
261
+ `route`. Alloy wraps only those unprefixed legacy fields into `app.*`; it leaves
262
+ already namespaced `app.*` metadata untouched.
249
263
 
250
264
  The stack uses these names:
251
265
 
252
266
  ```text
253
- app_* application log attributes
267
+ app_value_* query-friendly application metadata values
268
+ app_type_* application metadata type markers
269
+ app_meta_json JSON application metadata representation
270
+ app_* legacy application log attributes wrapped by Alloy
254
271
  otel_resource_* OpenTelemetry resource attributes
255
272
  otel_scope_* OpenTelemetry instrumentation scope attributes
256
273
  otel_log_* OpenTelemetry log record fields
@@ -261,8 +278,10 @@ service_name legacy compatibility label for Grafana trace-to-logs
261
278
  Examples:
262
279
 
263
280
  ```text
264
- count -> app_count
265
- route -> app_route
281
+ count -> app_value_count
282
+ route -> app_value_route
283
+ deletedAt: null -> app_type_deletedAt = "null"
284
+ metadata JSON -> app_meta_json
266
285
  service.name -> otel_resource_service_name
267
286
  instrumentation scope -> otel_scope_name
268
287
  trace id -> otel_log_trace_id
@@ -276,7 +295,7 @@ not as index labels. Query them after selecting a stream:
276
295
  ```logql
277
296
  {loki_service_name="telemetry-dice-roller-example"}
278
297
  | trace_id="0242ac120002"
279
- | app_route="/roll"
298
+ | app_value_route="/roll"
280
299
  ```
281
300
 
282
301
  Current Loki versions return structured metadata merged into the `stream` labels
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@primafuture/telemetry-stack",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "description": "Reusable PrimaFuture telemetry stack launcher powered by Docker Compose.",
6
6
  "author": "PrimaFuture.cz s.r.o. <dev@primafuture.cz>",
@@ -9,8 +9,10 @@ otelcol.processor.transform "loki_labels" {
9
9
  log_statements {
10
10
  context = "log"
11
11
  statements = [
12
- // Copy application log attributes into app.* without requiring apps to prefix anything themselves.
12
+ // Copy legacy application log attributes into app.* without wrapping already namespaced app.* fields again.
13
13
  `merge_maps(log.cache, log.attributes, "upsert")`,
14
+ `delete_matching_keys(log.cache, "^app[.].*")`,
15
+ `delete_matching_keys(log.cache, "^otel[.].*")`,
14
16
  `flatten(log.cache, "app", resolveConflicts=true)`,
15
17
  `merge_maps(log.attributes, log.cache, "upsert")`,
16
18
  `delete_matching_keys(log.cache, ".*")`,
@@ -39,7 +41,11 @@ otelcol.processor.transform "loki_labels" {
39
41
  // Build explicit Loki labels from original values. Loki will normalize dots to underscores.
40
42
  `set(resource.attributes["loki.service.name"], resource.attributes["service.name"]) where resource.attributes["service.name"] != nil`,
41
43
  `set(resource.attributes["loki.log.type"], log.attributes["log_type"]) where log.attributes["log_type"] != nil`,
44
+ `set(resource.attributes["loki.log.type"], log.attributes["value.log_type"]) where resource.attributes["loki.log.type"] == nil and log.attributes["value.log_type"] != nil`,
45
+ `set(resource.attributes["loki.log.type"], log.attributes["app.value.log_type"]) where resource.attributes["loki.log.type"] == nil and log.attributes["app.value.log_type"] != nil`,
42
46
  `set(resource.attributes["loki.log.file.path"], log.attributes["log.file.path"]) where log.attributes["log.file.path"] != nil`,
47
+ `set(resource.attributes["loki.log.file.path"], log.attributes["value.log.file.path"]) where resource.attributes["loki.log.file.path"] == nil and log.attributes["value.log.file.path"] != nil`,
48
+ `set(resource.attributes["loki.log.file.path"], log.attributes["app.value.log.file.path"]) where resource.attributes["loki.log.file.path"] == nil and log.attributes["app.value.log.file.path"] != nil`,
43
49
 
44
50
  // Keep only namespaced structured metadata, explicit Loki label resource attributes, and the legacy service.name label.
45
51
  `keep_matching_keys(log.attributes, "^(app|otel)[.]")`,