Skip to content

Commit 3844769

Browse files
committed
feat: add core dimensional models and service inventory report
- Add dim_otel_resources for resource attribute deduplication - Add fct_otel_* views joining staging with resource dimension - Add rpt_otel_service_inventory for service discovery - Update staging models with resource_id foreign key - Refresh test parquet files with consistent resource data
1 parent 35335ea commit 3844769

25 files changed

+726
-102
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
A dbt package for transforming OpenTelemetry (OTLP) data into queryable, analytics-ready schemas.
44

5-
[![CI](https://github.com/smithclay/dbt-opentelemetry/actions/workflows/ci.yml/badge.svg)](https://github.com/smithclay/dbt-opentelemetry/actions/workflows/ci.yml)
5+
[![CI](https://github.com/smithclay/dbt-opentelemetry/actions/workflows/ci.yml/badge.svg)](https://github.com/smithclay/dbt_opentelemetry/actions/workflows/ci.yml)
66
[![dbt Hub](https://img.shields.io/badge/dbt%20Hub-dbt__opentelemetry-orange)](https://hub.getdbt.com/)
77
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
88

dbt_project.yml

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,33 @@ model-paths: ["models"]
88
macro-paths: ["macros"]
99

1010
vars:
11-
# Source configuration - override these to match your data location
12-
# otel_database: defaults to target.database (handled in sources.yml)
13-
otel_schema: "raw"
14-
otel_logs_table: "logs"
15-
otel_spans_table: "spans"
16-
otel_gauge_table: "gauge"
17-
otel_sum_table: "sum"
11+
# Source configuration - override these to match your data location
12+
# otel_database: defaults to target.database (handled in sources.yml)
13+
otel_schema: "raw"
14+
otel_logs_table: "logs"
15+
otel_spans_table: "spans"
16+
otel_gauge_table: "gauge"
17+
otel_sum_table: "sum"
1818

19-
# Feature flags for optional domain models
20-
# Set to true in your dbt_project.yml to enable
21-
otel_enable_k8s: false
22-
otel_enable_ai_agents: false
23-
otel_enable_apm: false
19+
# Feature flags for optional domain models
20+
# Set to true in your dbt_project.yml to enable
21+
otel_enable_k8s: false
22+
otel_enable_ai_agents: false
23+
otel_enable_apm: false
2424

2525
models:
26-
dbt_opentelemetry:
27-
staging:
28-
+materialized: view
29-
k8s:
30-
+materialized: table
31-
ai_agents:
32-
+materialized: table
33-
apm:
34-
+materialized: table
26+
dbt_opentelemetry:
27+
staging:
28+
+materialized: view
29+
core:
30+
+materialized: view
31+
dim_otel_resources:
32+
+materialized: incremental
33+
reporting:
34+
+materialized: table
35+
k8s:
36+
+materialized: table
37+
ai_agents:
38+
+materialized: table
39+
apm:
40+
+materialized: table

integration_tests/macros/test_helpers.sql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
{{ log("Created table " ~ logs_table, info=True) }}
3131

3232
{# Spans table - transform to OTLP schema #}
33+
{# Note: end_time computed from start + duration since parquet end_timestamp units vary #}
3334
{% set spans_table = schema_name ~ '.' ~ var('otel_spans_table', 'spans') %}
3435
{{ log("Creating table " ~ spans_table ~ "...", info=True) }}
3536
{% set spans_sql %}
@@ -42,7 +43,7 @@
4243
span_name as name,
4344
span_kind as kind,
4445
epoch_ns(timestamp) as start_time_unix_nano,
45-
end_timestamp as end_time_unix_nano,
46+
epoch_ns(timestamp) + duration as end_time_unix_nano,
4647
resource_attributes,
4748
scope_name,
4849
scope_version,
839 Bytes
Binary file not shown.
-134 Bytes
Binary file not shown.
346 Bytes
Binary file not shown.
1.03 KB
Binary file not shown.

macros/attributes.sql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
$."{{ key | replace('"', '\\"') }}"
33
{%- endmacro %}
44

5+
{% macro resource_hash(json_col) -%}
6+
md5({{ json_col }}::varchar)
7+
{%- endmacro %}
8+
59
{% macro attr_str(json_col, key, default=None) -%}
610
coalesce(
711
json_extract_string({{ json_col }}::json, '{{ dbt_opentelemetry.json_path(key) }}'),
Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,52 @@
11
{{ config(enabled=var('otel_enable_ai_agents', false)) }}
22

3+
-- AI agent events with resource fields already promoted from dim_otel_resources
4+
35
with logs as (
46
select *
5-
from {{ ref('stg_otel_logs') }}
7+
from {{ ref('fct_otel_logs') }}
68
)
79

810
select
9-
logs.*,
10-
{{ dbt_opentelemetry.coalesce_attr_str(['resource_attributes', 'attributes'], 'agent.id') }} as agent_id,
11-
{{ dbt_opentelemetry.coalesce_attr_str(['resource_attributes', 'attributes'], 'agent.session_id') }} as session_id,
12-
{{ dbt_opentelemetry.coalesce_attr_str(['resource_attributes', 'attributes'], 'tool.name') }} as tool_name,
13-
{{ dbt_opentelemetry.coalesce_attr_str(['resource_attributes', 'attributes'], 'llm.model') }} as llm_model,
14-
{{ dbt_opentelemetry.attr_int('attributes', 'llm.tokens_in') }} as tokens_in,
15-
{{ dbt_opentelemetry.attr_int('attributes', 'llm.tokens_out') }} as tokens_out,
16-
{{ dbt_opentelemetry.attr_double('attributes', 'llm.cost_usd') }} as cost_usd
11+
-- Core log fields
12+
resource_id,
13+
trace_id,
14+
span_id,
15+
logged_at,
16+
observed_at,
17+
event_ts,
18+
severity_number,
19+
severity_text,
20+
severity_class,
21+
is_error,
22+
body,
23+
scope_name,
24+
attributes,
25+
26+
-- Service identity (from resource dimension)
27+
service_name,
28+
service_namespace,
29+
service_version,
30+
31+
-- Agent-specific fields (typically in attributes)
32+
{{ coalesce_attr_str(['resource_attributes', 'attributes'], 'agent.id') }} as agent_id,
33+
{{ coalesce_attr_str(['resource_attributes', 'attributes'], 'agent.session_id') }} as session_id,
34+
{{ coalesce_attr_str(['resource_attributes', 'attributes'], 'agent.name') }} as agent_name,
35+
{{ attr_str('attributes', 'agent.event.type') }} as event_type,
36+
37+
-- Tool usage
38+
{{ attr_str('attributes', 'tool.name') }} as tool_name,
39+
{{ attr_str('attributes', 'tool.result') }} as tool_result,
40+
41+
-- LLM usage
42+
{{ coalesce_attr_str(['resource_attributes', 'attributes'], 'llm.model') }} as llm_model,
43+
{{ attr_str('attributes', 'llm.provider') }} as llm_provider,
44+
{{ attr_int('attributes', 'llm.tokens_in') }} as tokens_in,
45+
{{ attr_int('attributes', 'llm.tokens_out') }} as tokens_out,
46+
{{ attr_double('attributes', 'llm.cost_usd') }} as cost_usd,
47+
{{ attr_double('attributes', 'llm.latency_ms') }} as llm_latency_ms,
48+
49+
-- Full resource blob
50+
resource_attributes
51+
1752
from logs

models/ai_agents/marts_agent_session_summary.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,18 @@ with events as (
99
select
1010
session_id,
1111
max(agent_id) as agent_id,
12+
max(agent_name) as agent_name,
13+
max(service_name) as service_name,
1214
min(event_ts) as session_start_ts,
1315
max(event_ts) as session_end_ts,
16+
extract(epoch from max(event_ts) - min(event_ts)) as session_duration_seconds,
1417
count(*) as event_count,
18+
count(distinct tool_name) filter (where tool_name is not null) as unique_tools_used,
19+
count(*) filter (where tool_name is not null) as tool_invocations,
20+
count(*) filter (where is_error) as error_count,
1521
sum(coalesce(tokens_in, 0)) as tokens_in_total,
1622
sum(coalesce(tokens_out, 0)) as tokens_out_total,
23+
sum(coalesce(tokens_in, 0) + coalesce(tokens_out, 0)) as tokens_total,
1724
sum(coalesce(cost_usd, 0)) as cost_usd_total
1825
from events
1926
group by 1

0 commit comments

Comments
 (0)