Skip to content

Commit b37168c

Browse files
petrotiurinclaude
andcommitted
feat(cipx): add query_source to cipx_spends for the AI-spend model-switch lever
ai-cost-backend's "switch default model" savings estimate needs to scope to the main conversation loop only (subagent/auxiliary calls aren't affected by the default-model setting), but query_source was dropped when cipx_spends moved from spans.metadata JSON to typed columns. Re-adds it as its own typed column, extracted the same way as the other cipx.call fields. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 285ddb6 commit b37168c

2 files changed

Lines changed: 21 additions & 5 deletions

File tree

apps/opik-backend/src/main/java/com/comet/opik/domain/CipxSpendDAO.java

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ public record SpanRow(
5353
long uInput,
5454
long uCacheRead,
5555
long uCacheCreation,
56-
long uOutput) {
56+
long uOutput,
57+
@NonNull String querySource) {
5758

5859
public static SpanRow from(UUID spanId, UUID traceId, UUID projectId, JsonNode metadata, Instant startTime) {
5960
JsonNode call = metadata.path("cipx").path("call");
@@ -68,6 +69,7 @@ public static SpanRow from(UUID spanId, UUID traceId, UUID projectId, JsonNode m
6869
.uCacheRead(usage.path("cache_read_input_tokens").asLong(0))
6970
.uCacheCreation(usage.path("cache_creation_input_tokens").asLong(0))
7071
.uOutput(usage.path("output_tokens").asLong(0))
72+
.querySource(call.path("query_source").asText(""))
7173
.build();
7274
}
7375
}
@@ -77,7 +79,7 @@ public static SpanRow from(UUID spanId, UUID traceId, UUID projectId, JsonNode m
7779
private static final String INSERT = """
7880
INSERT INTO cipx_spends
7981
(workspace_id, project_id, trace_id, span_id, start_time, model,
80-
u_input, u_cache_read, u_cache_creation, u_output)
82+
u_input, u_cache_read, u_cache_creation, u_output, query_source)
8183
SETTINGS log_comment = '<log_comment>'
8284
FORMAT Values
8385
<items:{item |
@@ -91,7 +93,8 @@ public static SpanRow from(UUID spanId, UUID traceId, UUID projectId, JsonNode m
9193
:u_input<item.index>,
9294
:u_cache_read<item.index>,
9395
:u_cache_creation<item.index>,
94-
:u_output<item.index>
96+
:u_output<item.index>,
97+
:query_source<item.index>
9598
)
9699
<if(item.hasNext)>,<endif>
97100
}>
@@ -120,7 +123,7 @@ private Publisher<? extends Result> insert(List<SpanRow> rows, String workspaceI
120123
// Positional binds: the driver resolves named binds with a linear indexOf over the statement's
121124
// parameter list (quadratic per statement), while bind(int) is a direct array write. Indices
122125
// follow the placeholders' first-appearance order in the rendered SQL: workspace_id once at 0
123-
// (repeats dedup), then 9 parameters per row tuple in template order.
126+
// (repeats dedup), then 10 parameters per row tuple in template order.
124127
statement.bind(0, workspaceId);
125128
int index = 1;
126129
for (SpanRow row : rows) {
@@ -132,7 +135,8 @@ private Publisher<? extends Result> insert(List<SpanRow> rows, String workspaceI
132135
.bind(index++, row.uInput())
133136
.bind(index++, row.uCacheRead())
134137
.bind(index++, row.uCacheCreation())
135-
.bind(index++, row.uOutput());
138+
.bind(index++, row.uOutput())
139+
.bind(index++, row.querySource());
136140
}
137141

138142
return statement.execute();
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--liquibase formatted sql
2+
--changeset petrotiurin:000101_add_query_source_to_cipx_spend
3+
--comment: Add query_source (cipx.call.query_source) to cipx_spends so AI-spend levers can scope to the main conversation loop
4+
5+
-- cipx emits metadata.cipx.call.query_source ('main' for the primary conversation loop, something
6+
-- else for subagent/auxiliary calls). The "switch default model" savings lever needs to scope to
7+
-- 'main' only -- subagent calls aren't affected by changing the default model setting -- so this
8+
-- needs its own typed column rather than being folded into an existing one.
9+
ALTER TABLE ${ANALYTICS_DB_DATABASE_NAME}.cipx_spends ON CLUSTER '{cluster}'
10+
ADD COLUMN IF NOT EXISTS query_source LowCardinality(String) DEFAULT '';
11+
12+
--rollback ALTER TABLE ${ANALYTICS_DB_DATABASE_NAME}.cipx_spends ON CLUSTER '{cluster}' DROP COLUMN IF EXISTS query_source;

0 commit comments

Comments
 (0)