Scenario B: Observability logs and OpenTelemetry¶
Part of Streaming Transformations › Scenarios.
Goal¶
Logs and OpenTelemetry data arrive in high volume, and much of it is debug noise. Attributes are nested in arrays, which makes them hard to query. Teams want to keep only the useful records, turn attributes into rows, attach the owning team, and keep a few views of the same stream current, for example errors only and counts per service.
Transformations used¶
- Stream filtering on stream columns: drop debug-level and other noisy records.
- Lateral Flatten on the stream: expand resource or span attributes into rows.
- Stream enrichment: attach the owning team and service metadata.
- Insert-triggered materialized views: keep several views on the same target table, for example errors only and counts per service and severity.
Source data¶
Stream¶
The example uses these four log records. Each record carries its resource attributes as an array:
Dimension table¶
The PIPE joins this dimension table, refreshed periodically:
Target table¶
The PIPE lands transformed and filtered rows in this target table, with one row per record and attribute:
Transformation¶
The PIPE synchronously lands data in materialized views and the target table. Record attributes are flattened, and rows are enriched by joining the owning team and service metadata from the dimension table. Noisy records are dropped by filtering on a stream column.
Result¶
Target table¶
Querying the target table returns rows like these:
| EVENT_TS | SERVICE_NAME | SEVERITY | TRACE_ID | MESSAGE | ATTR_KEY | ATTR_VALUE | OWNING_TEAM | TIER |
|---|---|---|---|---|---|---|---|---|
| 2026-10-09 08:00:01 | checkout | WARN | 4bf92f3577b34da6 | payment retry 1 | host.name | node-a | payments-team | tier-1 |
| 2026-10-09 08:00:01 | checkout | WARN | 4bf92f3577b34da6 | payment retry 1 | k8s.pod | checkout-7f9c | payments-team | tier-1 |
| 2026-10-09 08:00:03 | inventory | ERROR | a3ce929d0e0e4736 | stock lookup timed out | host.name | node-b | supply-team | tier-2 |
| 2026-10-09 08:00:03 | inventory | ERROR | a3ce929d0e0e4736 | stock lookup timed out | k8s.pod | inventory-5d2e | supply-team | tier-2 |
The DEBUG and INFO records are dropped. Each remaining record lands as one row per attribute, with the owning team and tier of its service.
Insert-triggered materialized views¶
The PIPE keeps both insert-triggered materialized views up to date synchronously as it lands rows in the target table.
Querying otel_errors returns the records with severity ERROR:
| EVENT_TS | SERVICE_NAME | TRACE_ID | MESSAGE | ATTR_KEY | ATTR_VALUE | OWNING_TEAM |
|---|---|---|---|---|---|---|
| 2026-10-09 08:00:03 | inventory | a3ce929d0e0e4736 | stock lookup timed out | host.name | node-b | supply-team |
| 2026-10-09 08:00:03 | inventory | a3ce929d0e0e4736 | stock lookup timed out | k8s.pod | inventory-5d2e | supply-team |
Querying otel_counts_by_service returns the number of landed rows per service and severity:
| SERVICE_NAME | SEVERITY | RECORD_COUNT |
|---|---|---|
| checkout | WARN | 2 |
| inventory | ERROR | 2 |
The counts are per landed row, so a record with two attributes counts twice.
Considerations¶
- Dimension data is a snapshot that refreshes periodically, so updates can take several minutes to appear. This works well for slow-moving reference data. Dynamic tables can be used as dimension tables.
- Create the materialized views before the pipe. Rows ingested before a view exists aren’t backfilled into it.
ERROR_LOGGINGcurrently can’t be enabled on the target table of a pipe that usesLATERAL FLATTEN.
See also¶
See Stream filtering, Stream enrichment, Lateral Flatten, and Insert-triggered materialized views for more information on the transformations used in this scenario.
Previous: Scenario A: AI agent observability · Next: Scenario C: Industrial IoT telemetry