chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
-- +goose up
|
||||
|
||||
CREATE DATABASE trigger_dev;
|
||||
|
||||
-- +goose down
|
||||
DROP DATABASE trigger_dev;
|
||||
@@ -0,0 +1,11 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE IF NOT EXISTS trigger_dev.smoke_test (
|
||||
id UUID DEFAULT generateUUIDv4(),
|
||||
timestamp DateTime64(3) DEFAULT now64(3),
|
||||
message String,
|
||||
number UInt32
|
||||
) ENGINE = MergeTree()
|
||||
ORDER BY (timestamp, id);
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE IF EXISTS trigger_dev.smoke_test;
|
||||
@@ -0,0 +1,100 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE trigger_dev.task_runs_v1
|
||||
(
|
||||
/* ─── ids & hierarchy ─────────────────────────────────────── */
|
||||
environment_id String,
|
||||
organization_id String,
|
||||
project_id String,
|
||||
run_id String,
|
||||
|
||||
environment_type LowCardinality(String),
|
||||
friendly_id String,
|
||||
attempt UInt8 DEFAULT 1,
|
||||
|
||||
/* ─── enums / status ──────────────────────────────────────── */
|
||||
engine LowCardinality(String),
|
||||
status LowCardinality(String),
|
||||
|
||||
/* ─── queue / concurrency / schedule ─────────────────────── */
|
||||
task_identifier String,
|
||||
queue String,
|
||||
|
||||
schedule_id String,
|
||||
batch_id String,
|
||||
|
||||
/* ─── related runs ─────────────────────────────────────────────── */
|
||||
root_run_id String,
|
||||
parent_run_id String,
|
||||
depth UInt8 DEFAULT 0,
|
||||
|
||||
/* ─── telemetry ─────────────────────────────────────────────── */
|
||||
span_id String,
|
||||
trace_id String,
|
||||
idempotency_key String,
|
||||
|
||||
/* ─── timing ─────────────────────────────────────────────── */
|
||||
created_at DateTime64(3),
|
||||
updated_at DateTime64(3),
|
||||
started_at Nullable(DateTime64(3)),
|
||||
executed_at Nullable(DateTime64(3)),
|
||||
completed_at Nullable(DateTime64(3)),
|
||||
delay_until Nullable(DateTime64(3)),
|
||||
queued_at Nullable(DateTime64(3)),
|
||||
expired_at Nullable(DateTime64(3)),
|
||||
expiration_ttl String,
|
||||
|
||||
/* ─── cost / usage ───────────────────────────────────────── */
|
||||
usage_duration_ms UInt32 DEFAULT 0,
|
||||
cost_in_cents Float64 DEFAULT 0,
|
||||
base_cost_in_cents Float64 DEFAULT 0,
|
||||
|
||||
/* ─── payload & context ──────────────────────────────────── */
|
||||
output JSON(max_dynamic_paths = 1024),
|
||||
error JSON(max_dynamic_paths = 64),
|
||||
|
||||
/* ─── tagging / versions ─────────────────────────────────── */
|
||||
tags Array(String) CODEC(ZSTD(1)),
|
||||
task_version String CODEC(LZ4),
|
||||
sdk_version String CODEC(LZ4),
|
||||
cli_version String CODEC(LZ4),
|
||||
machine_preset LowCardinality(String) CODEC(LZ4),
|
||||
|
||||
is_test UInt8 DEFAULT 0,
|
||||
|
||||
/* ─── commit lsn ─────────────────────────────────────────────── */
|
||||
_version UInt64,
|
||||
_is_deleted UInt8 DEFAULT 0
|
||||
)
|
||||
ENGINE = ReplacingMergeTree(_version, _is_deleted)
|
||||
PARTITION BY toYYYYMM(created_at)
|
||||
ORDER BY (toDate(created_at), environment_id, task_identifier, created_at, run_id)
|
||||
SETTINGS enable_json_type = 1;
|
||||
|
||||
/* Fast tag filtering */
|
||||
ALTER TABLE trigger_dev.task_runs_v1
|
||||
ADD INDEX idx_tags tags TYPE tokenbf_v1(32768, 3, 0) GRANULARITY 4;
|
||||
|
||||
CREATE TABLE trigger_dev.raw_task_runs_payload_v1
|
||||
(
|
||||
run_id String,
|
||||
created_at DateTime64(3),
|
||||
payload JSON(max_dynamic_paths = 1024)
|
||||
)
|
||||
ENGINE = MergeTree
|
||||
PARTITION BY toYYYYMM(created_at)
|
||||
ORDER BY (run_id)
|
||||
SETTINGS enable_json_type = 1;
|
||||
|
||||
CREATE VIEW trigger_dev.tmp_eric_task_runs_full_v1 AS
|
||||
SELECT
|
||||
s.*,
|
||||
p.payload as payload
|
||||
FROM trigger_dev.task_runs_v1 AS s FINAL
|
||||
LEFT JOIN trigger_dev.raw_task_runs_payload_v1 AS p ON s.run_id = p.run_id
|
||||
SETTINGS enable_json_type = 1;
|
||||
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE IF EXISTS trigger_dev.task_runs_v1;
|
||||
DROP TABLE IF EXISTS trigger_dev.raw_task_runs_payload_v1;
|
||||
DROP VIEW IF EXISTS trigger_dev.tmp_eric_task_runs_full_v1;
|
||||
@@ -0,0 +1,94 @@
|
||||
-- +goose Up
|
||||
|
||||
/*
|
||||
This is the second version of the task runs table.
|
||||
The main change is we've added organization_id and project_id to the sort key, and removed the toDate(created_at) and task_identifier columns from the sort key.
|
||||
We will add a skip index for the task_identifier column in a future migration.
|
||||
*/
|
||||
CREATE TABLE trigger_dev.task_runs_v2
|
||||
(
|
||||
/* ─── ids & hierarchy ─────────────────────────────────────── */
|
||||
environment_id String,
|
||||
organization_id String,
|
||||
project_id String,
|
||||
run_id String,
|
||||
|
||||
environment_type LowCardinality(String),
|
||||
friendly_id String,
|
||||
attempt UInt8 DEFAULT 1,
|
||||
|
||||
/* ─── enums / status ──────────────────────────────────────── */
|
||||
engine LowCardinality(String),
|
||||
status LowCardinality(String),
|
||||
|
||||
/* ─── queue / concurrency / schedule ─────────────────────── */
|
||||
task_identifier String,
|
||||
queue String,
|
||||
|
||||
schedule_id String,
|
||||
batch_id String,
|
||||
|
||||
/* ─── related runs ─────────────────────────────────────────────── */
|
||||
root_run_id String,
|
||||
parent_run_id String,
|
||||
depth UInt8 DEFAULT 0,
|
||||
|
||||
/* ─── telemetry ─────────────────────────────────────────────── */
|
||||
span_id String,
|
||||
trace_id String,
|
||||
idempotency_key String,
|
||||
|
||||
/* ─── timing ─────────────────────────────────────────────── */
|
||||
created_at DateTime64(3),
|
||||
updated_at DateTime64(3),
|
||||
started_at Nullable(DateTime64(3)),
|
||||
executed_at Nullable(DateTime64(3)),
|
||||
completed_at Nullable(DateTime64(3)),
|
||||
delay_until Nullable(DateTime64(3)),
|
||||
queued_at Nullable(DateTime64(3)),
|
||||
expired_at Nullable(DateTime64(3)),
|
||||
expiration_ttl String,
|
||||
|
||||
/* ─── cost / usage ───────────────────────────────────────── */
|
||||
usage_duration_ms UInt32 DEFAULT 0,
|
||||
cost_in_cents Float64 DEFAULT 0,
|
||||
base_cost_in_cents Float64 DEFAULT 0,
|
||||
|
||||
/* ─── payload & context ──────────────────────────────────── */
|
||||
output JSON(max_dynamic_paths = 1024),
|
||||
error JSON(max_dynamic_paths = 64),
|
||||
|
||||
/* ─── tagging / versions ─────────────────────────────────── */
|
||||
tags Array(String) CODEC(ZSTD(1)),
|
||||
task_version String CODEC(LZ4),
|
||||
sdk_version String CODEC(LZ4),
|
||||
cli_version String CODEC(LZ4),
|
||||
machine_preset LowCardinality(String) CODEC(LZ4),
|
||||
|
||||
is_test UInt8 DEFAULT 0,
|
||||
|
||||
/* ─── commit lsn ─────────────────────────────────────────────── */
|
||||
_version UInt64,
|
||||
_is_deleted UInt8 DEFAULT 0
|
||||
)
|
||||
ENGINE = ReplacingMergeTree(_version, _is_deleted)
|
||||
PARTITION BY toYYYYMM(created_at)
|
||||
ORDER BY (organization_id, project_id, environment_id, created_at, run_id)
|
||||
SETTINGS enable_json_type = 1;
|
||||
|
||||
/* Fast tag filtering */
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
ADD INDEX idx_tags tags TYPE tokenbf_v1(32768, 3, 0) GRANULARITY 4;
|
||||
|
||||
CREATE VIEW trigger_dev.tmp_eric_task_runs_full_v2 AS
|
||||
SELECT
|
||||
s.*,
|
||||
p.payload as payload
|
||||
FROM trigger_dev.task_runs_v2 AS s FINAL
|
||||
LEFT JOIN trigger_dev.raw_task_runs_payload_v1 AS p ON s.run_id = p.run_id
|
||||
SETTINGS enable_json_type = 1;
|
||||
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE IF EXISTS trigger_dev.task_runs_v2;
|
||||
DROP VIEW IF EXISTS trigger_dev.tmp_eric_task_runs_full_v2
|
||||
@@ -0,0 +1,12 @@
|
||||
-- +goose Up
|
||||
/*
|
||||
Add concurrency_key and bulk_action_group_ids columns with defaults.
|
||||
*/
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
ADD COLUMN concurrency_key String DEFAULT '',
|
||||
ADD COLUMN bulk_action_group_ids Array(String) DEFAULT [];
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
DROP COLUMN concurrency_key,
|
||||
DROP COLUMN bulk_action_group_ids;
|
||||
@@ -0,0 +1,10 @@
|
||||
-- +goose Up
|
||||
/*
|
||||
Add worker_queue column.
|
||||
*/
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
ADD COLUMN worker_queue String DEFAULT '';
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
DROP COLUMN worker_queue;
|
||||
@@ -0,0 +1,52 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE IF NOT EXISTS trigger_dev.task_events_v1
|
||||
(
|
||||
-- This the main "tenant" ID
|
||||
environment_id String,
|
||||
-- The organization ID here so we can do MV rollups of usage
|
||||
organization_id String,
|
||||
-- The project ID here so we can do MV rollups of usage
|
||||
project_id String,
|
||||
-- The task slug (e.g. "my-task")
|
||||
task_identifier String CODEC(ZSTD(1)),
|
||||
-- The non-friendly ID for the run
|
||||
run_id String CODEC(ZSTD(1)),
|
||||
-- nanoseconds since the epoch
|
||||
start_time DateTime64(9) CODEC(Delta(8), ZSTD(1)),
|
||||
trace_id String CODEC(ZSTD(1)),
|
||||
span_id String CODEC(ZSTD(1)),
|
||||
-- will be an empty string for root spans
|
||||
parent_span_id String CODEC(ZSTD(1)),
|
||||
-- Log body, event name, or span name
|
||||
message String CODEC(ZSTD(1)),
|
||||
-- this is the new level column, can be
|
||||
-- SPAN, SPAN_EVENT, DEBUG_EVENT, LOG_DEBUG, LOG_LOG, LOG_SUCCESS, LOG_INFO, LOG_WARN, LOG_ERROR, ANCESTOR_OVERRIDE
|
||||
kind LowCardinality(String) CODEC(ZSTD(1)),
|
||||
-- isError, isPartial, isCancelled will now be in this status column
|
||||
-- OK, ERROR, PARTIAL, CANCELLED
|
||||
status LowCardinality(String) CODEC(ZSTD(1)),
|
||||
-- span/log/event attributes and resource attributes
|
||||
-- includes error attributes, gen_ai attributes, and other attributes
|
||||
attributes JSON CODEC(ZSTD(1)),
|
||||
attributes_text String MATERIALIZED toJSONString(attributes),
|
||||
-- This is the metadata column, includes style for styling the event in the UI
|
||||
-- is a JSON stringified object, e.g. {"style":{"icon":"play","variant":"primary"},"error":{"message":"Error message","attributes":{"error.type":"ErrorType","error.code":"123"}}}
|
||||
metadata String CODEC(ZSTD(1)),
|
||||
-- nanoseconds since the start time, only non-zero for spans
|
||||
duration UInt64 CODEC(ZSTD(1)),
|
||||
-- The TTL for the event, will be deleted 7 days after the event expires
|
||||
expires_at DateTime64(3),
|
||||
|
||||
INDEX idx_run_id run_id TYPE bloom_filter(0.001) GRANULARITY 1,
|
||||
INDEX idx_span_id span_id TYPE bloom_filter(0.001) GRANULARITY 1,
|
||||
INDEX idx_duration duration TYPE minmax GRANULARITY 1,
|
||||
INDEX idx_attributes_text attributes_text TYPE tokenbf_v1(32768, 3, 0) GRANULARITY 8
|
||||
)
|
||||
ENGINE = MergeTree
|
||||
PARTITION BY toDate(start_time)
|
||||
ORDER BY (environment_id, toUnixTimestamp(start_time), trace_id)
|
||||
TTL toDateTime(expires_at) + INTERVAL 7 DAY
|
||||
SETTINGS ttl_only_drop_parts = 1;
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE IF EXISTS trigger_dev.task_events_v1;
|
||||
@@ -0,0 +1,55 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE IF NOT EXISTS trigger_dev.task_event_usage_by_minute_v1
|
||||
(
|
||||
organization_id String,
|
||||
project_id String,
|
||||
environment_id String,
|
||||
bucket_start DateTime,
|
||||
event_count UInt64
|
||||
)
|
||||
ENGINE = SummingMergeTree()
|
||||
PARTITION BY toYYYYMM(bucket_start)
|
||||
ORDER BY (organization_id, project_id, environment_id, bucket_start)
|
||||
TTL bucket_start + INTERVAL 8 DAY;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS trigger_dev.task_event_usage_by_hour_v1
|
||||
(
|
||||
organization_id String,
|
||||
project_id String,
|
||||
environment_id String,
|
||||
bucket_start DateTime,
|
||||
event_count UInt64
|
||||
)
|
||||
ENGINE = SummingMergeTree()
|
||||
PARTITION BY toYYYYMM(bucket_start)
|
||||
ORDER BY (organization_id, project_id, environment_id, bucket_start)
|
||||
TTL bucket_start + INTERVAL 400 DAY;
|
||||
|
||||
CREATE MATERIALIZED VIEW IF NOT EXISTS trigger_dev.mv_task_event_usage_by_minute_v1
|
||||
TO trigger_dev.task_event_usage_by_minute_v1 AS
|
||||
SELECT
|
||||
organization_id,
|
||||
project_id,
|
||||
environment_id,
|
||||
toStartOfMinute(start_time) AS bucket_start,
|
||||
count() AS event_count
|
||||
FROM trigger_dev.task_events_v1
|
||||
GROUP BY organization_id, project_id, environment_id, bucket_start;
|
||||
|
||||
CREATE MATERIALIZED VIEW IF NOT EXISTS trigger_dev.mv_task_event_usage_by_hour_v1
|
||||
TO trigger_dev.task_event_usage_by_hour_v1 AS
|
||||
SELECT
|
||||
organization_id,
|
||||
project_id,
|
||||
environment_id,
|
||||
toStartOfHour(bucket_start) AS bucket_start,
|
||||
sum(event_count) AS event_count
|
||||
FROM trigger_dev.task_event_usage_by_minute_v1
|
||||
GROUP BY organization_id, project_id, environment_id, bucket_start;
|
||||
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE IF EXISTS trigger_dev.mv_task_event_usage_by_minute_v1;
|
||||
DROP TABLE IF EXISTS trigger_dev.mv_task_event_usage_by_hour_v1;
|
||||
DROP TABLE IF EXISTS trigger_dev.task_event_usage_by_hour_v1;
|
||||
DROP TABLE IF EXISTS trigger_dev.task_event_usage_by_minute_v1;
|
||||
@@ -0,0 +1,29 @@
|
||||
-- +goose Up
|
||||
DROP TABLE IF EXISTS trigger_dev.mv_task_event_usage_by_minute_v1;
|
||||
|
||||
CREATE MATERIALIZED VIEW IF NOT EXISTS trigger_dev.mv_task_event_usage_by_minute_v2
|
||||
TO trigger_dev.task_event_usage_by_minute_v1 AS
|
||||
SELECT
|
||||
organization_id,
|
||||
project_id,
|
||||
environment_id,
|
||||
toStartOfMinute(start_time) AS bucket_start,
|
||||
count() AS event_count
|
||||
FROM trigger_dev.task_events_v1
|
||||
WHERE kind != 'DEBUG_EVENT' AND kind != 'ANCESTOR_OVERRIDE' AND status != 'PARTIAL'
|
||||
GROUP BY organization_id, project_id, environment_id, bucket_start;
|
||||
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE IF EXISTS trigger_dev.mv_task_event_usage_by_minute_v2;
|
||||
|
||||
CREATE MATERIALIZED VIEW IF NOT EXISTS trigger_dev.mv_task_event_usage_by_minute_v1
|
||||
TO trigger_dev.task_event_usage_by_minute_v1 AS
|
||||
SELECT
|
||||
organization_id,
|
||||
project_id,
|
||||
environment_id,
|
||||
toStartOfMinute(start_time) AS bucket_start,
|
||||
count() AS event_count
|
||||
FROM trigger_dev.task_events_v1
|
||||
GROUP BY organization_id, project_id, environment_id, bucket_start;
|
||||
@@ -0,0 +1,55 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE IF NOT EXISTS trigger_dev.task_events_v2
|
||||
(
|
||||
-- This the main "tenant" ID
|
||||
environment_id String,
|
||||
-- The organization ID here so we can do MV rollups of usage
|
||||
organization_id String,
|
||||
-- The project ID here so we can do MV rollups of usage
|
||||
project_id String,
|
||||
-- The task slug (e.g. "my-task")
|
||||
task_identifier String CODEC(ZSTD(1)),
|
||||
-- The non-friendly ID for the run
|
||||
run_id String CODEC(ZSTD(1)),
|
||||
-- nanoseconds since the epoch
|
||||
start_time DateTime64(9) CODEC(Delta(8), ZSTD(1)),
|
||||
trace_id String CODEC(ZSTD(1)),
|
||||
span_id String CODEC(ZSTD(1)),
|
||||
-- will be an empty string for root spans
|
||||
parent_span_id String CODEC(ZSTD(1)),
|
||||
-- Log body, event name, or span name
|
||||
message String CODEC(ZSTD(1)),
|
||||
-- this is the new level column, can be
|
||||
-- SPAN, SPAN_EVENT, DEBUG_EVENT, LOG_DEBUG, LOG_LOG, LOG_SUCCESS, LOG_INFO, LOG_WARN, LOG_ERROR, ANCESTOR_OVERRIDE
|
||||
kind LowCardinality(String) CODEC(ZSTD(1)),
|
||||
-- isError, isPartial, isCancelled will now be in this status column
|
||||
-- OK, ERROR, PARTIAL, CANCELLED
|
||||
status LowCardinality(String) CODEC(ZSTD(1)),
|
||||
-- span/log/event attributes and resource attributes
|
||||
-- includes error attributes, gen_ai attributes, and other attributes
|
||||
attributes JSON CODEC(ZSTD(1)),
|
||||
attributes_text String MATERIALIZED toJSONString(attributes),
|
||||
-- This is the metadata column, includes style for styling the event in the UI
|
||||
-- is a JSON stringified object, e.g. {"style":{"icon":"play","variant":"primary"},"error":{"message":"Error message","attributes":{"error.type":"ErrorType","error.code":"123"}}}
|
||||
metadata String CODEC(ZSTD(1)),
|
||||
-- nanoseconds since the start time, only non-zero for spans
|
||||
duration UInt64 CODEC(ZSTD(1)),
|
||||
-- The TTL for the event, will be deleted 7 days after the event expires
|
||||
expires_at DateTime64(3),
|
||||
-- NEW: Insert timestamp for partitioning (avoids "too many parts" errors from late-arriving events)
|
||||
inserted_at DateTime64(3) DEFAULT now64(3),
|
||||
|
||||
INDEX idx_run_id run_id TYPE bloom_filter(0.001) GRANULARITY 1,
|
||||
INDEX idx_span_id span_id TYPE bloom_filter(0.001) GRANULARITY 1,
|
||||
INDEX idx_duration duration TYPE minmax GRANULARITY 1,
|
||||
INDEX idx_attributes_text attributes_text TYPE tokenbf_v1(32768, 3, 0) GRANULARITY 8
|
||||
)
|
||||
ENGINE = MergeTree
|
||||
PARTITION BY toDate(inserted_at)
|
||||
ORDER BY (environment_id, toUnixTimestamp(start_time), trace_id)
|
||||
TTL toDateTime(expires_at) + INTERVAL 7 DAY
|
||||
SETTINGS ttl_only_drop_parts = 1;
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE IF EXISTS trigger_dev.task_events_v2;
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
-- +goose Up
|
||||
-- Create materialized views for task_events_v2 table (partitioned by inserted_at)
|
||||
-- These write to the same target tables as the v1 MVs so usage is aggregated across both tables
|
||||
|
||||
CREATE MATERIALIZED VIEW IF NOT EXISTS trigger_dev.mv_task_event_v2_usage_by_minute
|
||||
TO trigger_dev.task_event_usage_by_minute_v1 AS
|
||||
SELECT
|
||||
organization_id,
|
||||
project_id,
|
||||
environment_id,
|
||||
toStartOfMinute(start_time) AS bucket_start,
|
||||
count() AS event_count
|
||||
FROM trigger_dev.task_events_v2
|
||||
WHERE kind != 'DEBUG_EVENT' AND kind != 'ANCESTOR_OVERRIDE' AND status != 'PARTIAL'
|
||||
GROUP BY organization_id, project_id, environment_id, bucket_start;
|
||||
|
||||
-- +goose Down
|
||||
DROP VIEW IF EXISTS trigger_dev.mv_task_event_v2_usage_by_minute;
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
-- +goose Up
|
||||
/*
|
||||
Add max_duration_in_seconds column.
|
||||
*/
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
ADD COLUMN max_duration_in_seconds Nullable (UInt32) DEFAULT NULL;
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
DROP COLUMN max_duration_in_seconds;
|
||||
@@ -0,0 +1,16 @@
|
||||
-- +goose Up
|
||||
|
||||
-- Add columns for storing user-provided idempotency key and scope for searching
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
ADD COLUMN idempotency_key_user String DEFAULT '';
|
||||
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
ADD COLUMN idempotency_key_scope String DEFAULT '';
|
||||
|
||||
-- +goose Down
|
||||
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
DROP COLUMN idempotency_key_user;
|
||||
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
DROP COLUMN idempotency_key_scope;
|
||||
@@ -0,0 +1,45 @@
|
||||
-- +goose Up
|
||||
-- Update the materialized columns to extract the 'data' field if it exists
|
||||
-- This avoids the {"data": ...} wrapper in the text representation
|
||||
-- Note: Direct JSON path access (output.data) returns null for nested objects,
|
||||
-- so we use JSONExtractRaw on the stringified JSON instead
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
ADD COLUMN output_text String MATERIALIZED if (
|
||||
toJSONString (output) = '{}',
|
||||
'',
|
||||
if (
|
||||
length (JSONExtractRaw (toJSONString (output), 'data')) > 0,
|
||||
JSONExtractRaw (toJSONString (output), 'data'),
|
||||
toJSONString (output)
|
||||
)
|
||||
);
|
||||
|
||||
-- For error: extract error.data if it exists
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
ADD COLUMN error_text String MATERIALIZED if (
|
||||
toJSONString (error) = '{}',
|
||||
'',
|
||||
if (
|
||||
length (JSONExtractRaw (toJSONString (error), 'data')) > 0,
|
||||
JSONExtractRaw (toJSONString (error), 'data'),
|
||||
toJSONString (error)
|
||||
)
|
||||
);
|
||||
|
||||
-- Add the indexes
|
||||
ALTER TABLE trigger_dev.task_runs_v2 ADD INDEX idx_output_text output_text TYPE ngrambf_v1 (3, 131072, 3, 0) GRANULARITY 4;
|
||||
|
||||
ALTER TABLE trigger_dev.task_runs_v2 ADD INDEX idx_error_text error_text TYPE ngrambf_v1 (3, 131072, 3, 0) GRANULARITY 4;
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
DROP INDEX IF EXISTS idx_output_text;
|
||||
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
DROP INDEX IF EXISTS idx_error_text;
|
||||
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
DROP COLUMN IF EXISTS output_text;
|
||||
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
DROP COLUMN IF EXISTS error_text;
|
||||
@@ -0,0 +1,20 @@
|
||||
-- +goose Up
|
||||
|
||||
-- Add indexes for text search on task task_events_v2 tables for message and attributes fields
|
||||
ALTER TABLE trigger_dev.task_events_v2
|
||||
ADD INDEX IF NOT EXISTS idx_attributes_text_search lower(attributes_text)
|
||||
TYPE ngrambf_v1(3, 32768, 2, 0)
|
||||
GRANULARITY 1;
|
||||
|
||||
ALTER TABLE trigger_dev.task_events_v2
|
||||
ADD INDEX IF NOT EXISTS idx_message_text_search lower(message)
|
||||
TYPE ngrambf_v1(3, 32768, 2, 0)
|
||||
GRANULARITY 1;
|
||||
|
||||
-- +goose Down
|
||||
|
||||
ALTER TABLE trigger_dev.task_events_v2
|
||||
DROP INDEX idx_attributes_text_search;
|
||||
|
||||
ALTER TABLE trigger_dev.task_events_v2
|
||||
DROP INDEX idx_message_text_search;
|
||||
@@ -0,0 +1,63 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE IF NOT EXISTS trigger_dev.task_events_search_v1
|
||||
(
|
||||
environment_id String,
|
||||
organization_id String,
|
||||
project_id String,
|
||||
triggered_timestamp DateTime64(9) CODEC(Delta(8), ZSTD(1)),
|
||||
trace_id String CODEC(ZSTD(1)),
|
||||
span_id String CODEC(ZSTD(1)),
|
||||
run_id String CODEC(ZSTD(1)),
|
||||
task_identifier String CODEC(ZSTD(1)),
|
||||
start_time DateTime64(9) CODEC(Delta(8), ZSTD(1)),
|
||||
inserted_at DateTime64(3),
|
||||
message String CODEC(ZSTD(1)),
|
||||
kind LowCardinality(String) CODEC(ZSTD(1)),
|
||||
status LowCardinality(String) CODEC(ZSTD(1)),
|
||||
duration UInt64 CODEC(ZSTD(1)),
|
||||
parent_span_id String CODEC(ZSTD(1)),
|
||||
attributes_text String CODEC(ZSTD(1)),
|
||||
|
||||
INDEX idx_run_id run_id TYPE bloom_filter(0.001) GRANULARITY 1,
|
||||
INDEX idx_message_text_search lower(message) TYPE ngrambf_v1(3, 32768, 2, 0) GRANULARITY 1,
|
||||
INDEX idx_attributes_text_search lower(attributes_text) TYPE ngrambf_v1(3, 32768, 2, 0) GRANULARITY 1
|
||||
)
|
||||
ENGINE = MergeTree
|
||||
PARTITION BY toDate(triggered_timestamp)
|
||||
ORDER BY (organization_id, environment_id, triggered_timestamp, trace_id)
|
||||
--Right now we have maximum retention of up to 30 days based on plan.
|
||||
--We put a logical limit for now, the 90 DAY TTL is just a backup
|
||||
--This might need to be updated for longer retention periods
|
||||
TTL toDateTime(triggered_timestamp) + INTERVAL 90 DAY
|
||||
SETTINGS ttl_only_drop_parts = 1;
|
||||
|
||||
CREATE MATERIALIZED VIEW IF NOT EXISTS trigger_dev.task_events_search_mv_v1
|
||||
TO trigger_dev.task_events_search_v1 AS
|
||||
SELECT
|
||||
environment_id,
|
||||
organization_id,
|
||||
project_id,
|
||||
trace_id,
|
||||
span_id,
|
||||
run_id,
|
||||
task_identifier,
|
||||
start_time,
|
||||
inserted_at,
|
||||
message,
|
||||
kind,
|
||||
status,
|
||||
duration,
|
||||
parent_span_id,
|
||||
attributes_text,
|
||||
fromUnixTimestamp64Nano(toUnixTimestamp64Nano(start_time) + toInt64(duration)) AS triggered_timestamp
|
||||
FROM trigger_dev.task_events_v2
|
||||
WHERE
|
||||
kind != 'DEBUG_EVENT'
|
||||
AND status != 'PARTIAL'
|
||||
AND NOT (kind = 'SPAN_EVENT' AND attributes_text = '{}')
|
||||
AND kind != 'ANCESTOR_OVERRIDE'
|
||||
AND message != 'trigger.dev/start';
|
||||
|
||||
-- +goose Down
|
||||
DROP VIEW IF EXISTS trigger_dev.task_events_search_mv_v1;
|
||||
DROP TABLE IF EXISTS trigger_dev.task_events_search_v1;
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
-- +goose Up
|
||||
-- We drop the existing MV and recreate it with the new filter condition
|
||||
DROP VIEW IF EXISTS trigger_dev.task_events_search_mv_v1;
|
||||
|
||||
CREATE MATERIALIZED VIEW IF NOT EXISTS trigger_dev.task_events_search_mv_v1
|
||||
TO trigger_dev.task_events_search_v1 AS
|
||||
SELECT
|
||||
environment_id,
|
||||
organization_id,
|
||||
project_id,
|
||||
trace_id,
|
||||
span_id,
|
||||
run_id,
|
||||
task_identifier,
|
||||
start_time,
|
||||
inserted_at,
|
||||
message,
|
||||
kind,
|
||||
status,
|
||||
duration,
|
||||
parent_span_id,
|
||||
attributes_text,
|
||||
fromUnixTimestamp64Nano(toUnixTimestamp64Nano(start_time) + toInt64(duration)) AS triggered_timestamp
|
||||
FROM trigger_dev.task_events_v2
|
||||
WHERE
|
||||
trace_id != '' -- New condition added here
|
||||
AND kind != 'DEBUG_EVENT'
|
||||
AND status != 'PARTIAL'
|
||||
AND NOT (kind = 'SPAN_EVENT' AND attributes_text = '{}')
|
||||
AND kind != 'ANCESTOR_OVERRIDE'
|
||||
AND message != 'trigger.dev/start';
|
||||
|
||||
-- +goose Down
|
||||
-- In the down migration, we revert to the previous filter set
|
||||
DROP VIEW IF EXISTS trigger_dev.task_events_search_mv_v1;
|
||||
|
||||
CREATE MATERIALIZED VIEW IF NOT EXISTS trigger_dev.task_events_search_mv_v1
|
||||
TO trigger_dev.task_events_search_v1 AS
|
||||
SELECT
|
||||
environment_id,
|
||||
organization_id,
|
||||
project_id,
|
||||
trace_id,
|
||||
span_id,
|
||||
run_id,
|
||||
task_identifier,
|
||||
start_time,
|
||||
inserted_at,
|
||||
message,
|
||||
kind,
|
||||
status,
|
||||
duration,
|
||||
parent_span_id,
|
||||
attributes_text,
|
||||
fromUnixTimestamp64Nano(toUnixTimestamp64Nano(start_time) + toInt64(duration)) AS triggered_timestamp
|
||||
FROM trigger_dev.task_events_v2
|
||||
WHERE
|
||||
kind != 'DEBUG_EVENT'
|
||||
AND status != 'PARTIAL'
|
||||
AND NOT (kind = 'SPAN_EVENT' AND attributes_text = '{}')
|
||||
AND kind != 'ANCESTOR_OVERRIDE'
|
||||
AND message != 'trigger.dev/start';
|
||||
@@ -0,0 +1,22 @@
|
||||
-- +goose Up
|
||||
|
||||
-- These indexes are not used in any WHERE clause.
|
||||
-- idx_duration: duration is only written/read as a column, never filtered on.
|
||||
-- idx_attributes_text: search queries use the task_events_search_v1 table instead.
|
||||
ALTER TABLE trigger_dev.task_events_v2
|
||||
DROP INDEX IF EXISTS idx_duration;
|
||||
|
||||
ALTER TABLE trigger_dev.task_events_v2
|
||||
DROP INDEX IF EXISTS idx_attributes_text;
|
||||
|
||||
-- +goose Down
|
||||
|
||||
ALTER TABLE trigger_dev.task_events_v2
|
||||
ADD INDEX IF NOT EXISTS idx_duration duration
|
||||
TYPE minmax
|
||||
GRANULARITY 1;
|
||||
|
||||
ALTER TABLE trigger_dev.task_events_v2
|
||||
ADD INDEX IF NOT EXISTS idx_attributes_text attributes_text
|
||||
TYPE tokenbf_v1(32768, 3, 0)
|
||||
GRANULARITY 8;
|
||||
@@ -0,0 +1,44 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE IF NOT EXISTS trigger_dev.metrics_v1
|
||||
(
|
||||
organization_id LowCardinality(String),
|
||||
project_id LowCardinality(String),
|
||||
environment_id String CODEC(ZSTD(1)),
|
||||
metric_name LowCardinality(String),
|
||||
metric_type LowCardinality(String),
|
||||
metric_subject String CODEC(ZSTD(1)),
|
||||
bucket_start DateTime CODEC(Delta(4), ZSTD(1)),
|
||||
value Float64 DEFAULT 0 CODEC(ZSTD(1)),
|
||||
attributes JSON(
|
||||
`trigger.run_id` String,
|
||||
`trigger.task_slug` String,
|
||||
`trigger.attempt_number` Int64,
|
||||
`trigger.environment_type` LowCardinality(String),
|
||||
`trigger.machine_id` String,
|
||||
`trigger.machine_name` LowCardinality(String),
|
||||
`trigger.worker_id` String,
|
||||
`trigger.worker_version` String,
|
||||
`system.cpu.logical_number` String,
|
||||
`system.cpu.state` LowCardinality(String),
|
||||
`system.memory.state` LowCardinality(String),
|
||||
`system.device` String,
|
||||
`system.filesystem.type` LowCardinality(String),
|
||||
`system.filesystem.mountpoint` String,
|
||||
`system.filesystem.mode` LowCardinality(String),
|
||||
`system.filesystem.state` LowCardinality(String),
|
||||
`disk.io.direction` LowCardinality(String),
|
||||
`process.cpu.state` LowCardinality(String),
|
||||
`network.io.direction` LowCardinality(String),
|
||||
max_dynamic_paths=8
|
||||
),
|
||||
INDEX idx_run_id attributes.trigger.run_id TYPE bloom_filter(0.001) GRANULARITY 1,
|
||||
INDEX idx_task_slug attributes.trigger.task_slug TYPE bloom_filter(0.001) GRANULARITY 1
|
||||
)
|
||||
ENGINE = MergeTree()
|
||||
PARTITION BY toDate(bucket_start)
|
||||
ORDER BY (organization_id, project_id, environment_id, metric_name, metric_subject, bucket_start)
|
||||
TTL bucket_start + INTERVAL 60 DAY
|
||||
SETTINGS ttl_only_drop_parts = 1;
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE IF EXISTS trigger_dev.metrics_v1;
|
||||
@@ -0,0 +1,7 @@
|
||||
-- +goose Up
|
||||
ALTER TABLE trigger_dev.task_events_v2
|
||||
ADD COLUMN machine_id String DEFAULT '' CODEC(ZSTD(1));
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE trigger_dev.task_events_v2
|
||||
DROP COLUMN machine_id;
|
||||
@@ -0,0 +1,11 @@
|
||||
-- +goose Up
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
ADD COLUMN error_fingerprint String DEFAULT '';
|
||||
|
||||
-- Bloom filter index for fast error fingerprint lookups
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
ADD INDEX idx_error_fingerprint error_fingerprint TYPE bloom_filter GRANULARITY 4;
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE trigger_dev.task_runs_v2 DROP INDEX idx_error_fingerprint;
|
||||
ALTER TABLE trigger_dev.task_runs_v2 DROP COLUMN error_fingerprint;
|
||||
@@ -0,0 +1,78 @@
|
||||
-- +goose Up
|
||||
|
||||
-- Aggregated error groups table (per task + fingerprint)
|
||||
CREATE TABLE trigger_dev.errors_v1
|
||||
(
|
||||
organization_id String,
|
||||
project_id String,
|
||||
environment_id String,
|
||||
task_identifier String,
|
||||
error_fingerprint String,
|
||||
|
||||
-- Error details (samples from occurrences)
|
||||
error_type String,
|
||||
error_message String,
|
||||
sample_stack_trace String,
|
||||
|
||||
-- SimpleAggregateFunction stores raw values and applies the function during merge,
|
||||
-- avoiding binary state encoding issues with AggregateFunction.
|
||||
last_seen_date SimpleAggregateFunction(max, DateTime),
|
||||
|
||||
first_seen SimpleAggregateFunction(min, DateTime64(3)),
|
||||
last_seen SimpleAggregateFunction(max, DateTime64(3)),
|
||||
occurrence_count AggregateFunction(sum, UInt64),
|
||||
affected_task_versions AggregateFunction(uniq, String),
|
||||
|
||||
-- Samples for debugging
|
||||
sample_run_id AggregateFunction(any, String),
|
||||
sample_friendly_id AggregateFunction(any, String),
|
||||
|
||||
-- Status distribution
|
||||
status_distribution AggregateFunction(sumMap, Array(String), Array(UInt64))
|
||||
)
|
||||
ENGINE = AggregatingMergeTree()
|
||||
ORDER BY (organization_id, project_id, environment_id, task_identifier, error_fingerprint)
|
||||
TTL last_seen_date + INTERVAL 90 DAY
|
||||
SETTINGS index_granularity = 8192;
|
||||
|
||||
-- Materialized view to auto-populate from task_runs_v2
|
||||
CREATE MATERIALIZED VIEW trigger_dev.errors_mv_v1
|
||||
TO trigger_dev.errors_v1
|
||||
AS
|
||||
SELECT
|
||||
organization_id,
|
||||
project_id,
|
||||
environment_id,
|
||||
task_identifier,
|
||||
error_fingerprint,
|
||||
|
||||
any(coalesce(nullIf(toString(error.data.type), ''), nullIf(toString(error.data.name), ''), 'Error')) as error_type,
|
||||
any(coalesce(nullIf(substring(toString(error.data.message), 1, 500), ''), 'Unknown error')) as error_message,
|
||||
any(coalesce(substring(toString(error.data.stack), 1, 2000), '')) as sample_stack_trace,
|
||||
|
||||
toDateTime(max(created_at)) as last_seen_date,
|
||||
|
||||
min(created_at) as first_seen,
|
||||
max(created_at) as last_seen,
|
||||
sumState(toUInt64(1)) as occurrence_count,
|
||||
uniqState(task_version) as affected_task_versions,
|
||||
|
||||
anyState(run_id) as sample_run_id,
|
||||
anyState(friendly_id) as sample_friendly_id,
|
||||
|
||||
sumMapState([status], [toUInt64(1)]) as status_distribution
|
||||
FROM trigger_dev.task_runs_v2
|
||||
WHERE
|
||||
error_fingerprint != ''
|
||||
AND status IN ('SYSTEM_FAILURE', 'CRASHED', 'INTERRUPTED', 'COMPLETED_WITH_ERRORS', 'TIMED_OUT')
|
||||
AND _is_deleted = 0
|
||||
GROUP BY
|
||||
organization_id,
|
||||
project_id,
|
||||
environment_id,
|
||||
task_identifier,
|
||||
error_fingerprint;
|
||||
|
||||
-- +goose Down
|
||||
DROP VIEW IF EXISTS trigger_dev.errors_mv_v1;
|
||||
DROP TABLE IF EXISTS trigger_dev.errors_v1;
|
||||
@@ -0,0 +1,89 @@
|
||||
-- +goose Up
|
||||
-- Per-minute error occurrence counts, keyed by fingerprint + task + version.
|
||||
-- Powers precise time-range filtering and dynamic-granularity occurrence charts.
|
||||
CREATE TABLE
|
||||
trigger_dev.error_occurrences_v1 (
|
||||
organization_id String,
|
||||
project_id String,
|
||||
environment_id String,
|
||||
task_identifier String,
|
||||
error_fingerprint String,
|
||||
task_version String,
|
||||
minute DateTime,
|
||||
error_type String,
|
||||
error_message String,
|
||||
stack_trace String,
|
||||
count UInt64,
|
||||
INDEX idx_error_type_search lower(error_type) TYPE ngrambf_v1 (3, 32768, 2, 0) GRANULARITY 1,
|
||||
INDEX idx_error_message_search lower(error_message) TYPE ngrambf_v1 (3, 32768, 2, 0) GRANULARITY 1
|
||||
) ENGINE = SummingMergeTree (count)
|
||||
PARTITION BY
|
||||
toDate (minute)
|
||||
ORDER BY
|
||||
(
|
||||
organization_id,
|
||||
project_id,
|
||||
environment_id,
|
||||
task_identifier,
|
||||
error_fingerprint,
|
||||
task_version,
|
||||
minute
|
||||
) TTL minute + INTERVAL 90 DAY SETTINGS index_granularity = 8192;
|
||||
|
||||
CREATE MATERIALIZED VIEW trigger_dev.error_occurrences_mv_v1 TO trigger_dev.error_occurrences_v1 AS
|
||||
SELECT
|
||||
organization_id,
|
||||
project_id,
|
||||
environment_id,
|
||||
task_identifier,
|
||||
error_fingerprint,
|
||||
task_version,
|
||||
toStartOfMinute (created_at) as minute,
|
||||
any (
|
||||
coalesce(
|
||||
nullIf(toString (error.data.type), ''),
|
||||
nullIf(toString (error.data.name), ''),
|
||||
'Error'
|
||||
)
|
||||
) as error_type,
|
||||
any (
|
||||
coalesce(
|
||||
nullIf(
|
||||
substring(toString (error.data.message), 1, 500),
|
||||
''
|
||||
),
|
||||
'Unknown error'
|
||||
)
|
||||
) as error_message,
|
||||
any (
|
||||
coalesce(
|
||||
substring(toString (error.data.stack), 1, 2000),
|
||||
''
|
||||
)
|
||||
) as stack_trace,
|
||||
count() as count
|
||||
FROM
|
||||
trigger_dev.task_runs_v2
|
||||
WHERE
|
||||
error_fingerprint != ''
|
||||
AND status IN (
|
||||
'SYSTEM_FAILURE',
|
||||
'CRASHED',
|
||||
'INTERRUPTED',
|
||||
'COMPLETED_WITH_ERRORS',
|
||||
'TIMED_OUT'
|
||||
)
|
||||
AND _is_deleted = 0
|
||||
GROUP BY
|
||||
organization_id,
|
||||
project_id,
|
||||
environment_id,
|
||||
task_identifier,
|
||||
error_fingerprint,
|
||||
task_version,
|
||||
minute;
|
||||
|
||||
-- +goose Down
|
||||
DROP VIEW IF EXISTS trigger_dev.error_occurrences_mv_v1;
|
||||
|
||||
DROP TABLE IF EXISTS trigger_dev.error_occurrences_v1;
|
||||
@@ -0,0 +1,64 @@
|
||||
-- +goose Up
|
||||
CREATE TABLE IF NOT EXISTS trigger_dev.llm_metrics_v1
|
||||
(
|
||||
-- Tenant context
|
||||
organization_id LowCardinality(String),
|
||||
project_id LowCardinality(String),
|
||||
environment_id String CODEC(ZSTD(1)),
|
||||
run_id String CODEC(ZSTD(1)),
|
||||
task_identifier LowCardinality(String),
|
||||
trace_id String CODEC(ZSTD(1)),
|
||||
span_id String CODEC(ZSTD(1)),
|
||||
|
||||
-- Model & provider
|
||||
gen_ai_system LowCardinality(String),
|
||||
request_model String CODEC(ZSTD(1)),
|
||||
response_model String CODEC(ZSTD(1)),
|
||||
matched_model_id String CODEC(ZSTD(1)),
|
||||
operation_id LowCardinality(String),
|
||||
finish_reason LowCardinality(String),
|
||||
cost_source LowCardinality(String),
|
||||
|
||||
-- Pricing
|
||||
pricing_tier_id String CODEC(ZSTD(1)),
|
||||
pricing_tier_name LowCardinality(String),
|
||||
|
||||
-- Token usage
|
||||
input_tokens UInt64 DEFAULT 0,
|
||||
output_tokens UInt64 DEFAULT 0,
|
||||
total_tokens UInt64 DEFAULT 0,
|
||||
usage_details Map(LowCardinality(String), UInt64),
|
||||
|
||||
-- Cost
|
||||
input_cost Decimal64(12) DEFAULT 0,
|
||||
output_cost Decimal64(12) DEFAULT 0,
|
||||
total_cost Decimal64(12) DEFAULT 0,
|
||||
cost_details Map(LowCardinality(String), Decimal64(12)),
|
||||
provider_cost Decimal64(12) DEFAULT 0,
|
||||
|
||||
-- Performance
|
||||
ms_to_first_chunk Float64 DEFAULT 0,
|
||||
tokens_per_second Float64 DEFAULT 0,
|
||||
|
||||
-- Attribution
|
||||
metadata Map(LowCardinality(String), String),
|
||||
|
||||
-- Timing
|
||||
start_time DateTime64(9) CODEC(Delta(8), ZSTD(1)),
|
||||
duration UInt64 DEFAULT 0 CODEC(ZSTD(1)),
|
||||
inserted_at DateTime64(3) DEFAULT now64(3),
|
||||
|
||||
-- Indexes
|
||||
INDEX idx_run_id run_id TYPE bloom_filter(0.001) GRANULARITY 1,
|
||||
INDEX idx_span_id span_id TYPE bloom_filter(0.001) GRANULARITY 1,
|
||||
INDEX idx_response_model response_model TYPE bloom_filter(0.01) GRANULARITY 1,
|
||||
INDEX idx_metadata_keys mapKeys(metadata) TYPE bloom_filter(0.01) GRANULARITY 1
|
||||
)
|
||||
ENGINE = MergeTree
|
||||
PARTITION BY toDate(inserted_at)
|
||||
ORDER BY (organization_id, project_id, environment_id, toDate(inserted_at), run_id)
|
||||
TTL toDateTime(inserted_at) + INTERVAL 365 DAY
|
||||
SETTINGS ttl_only_drop_parts = 1;
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE IF EXISTS trigger_dev.llm_metrics_v1;
|
||||
@@ -0,0 +1,13 @@
|
||||
-- +goose Up
|
||||
ALTER TABLE trigger_dev.llm_metrics_v1
|
||||
ADD COLUMN prompt_slug LowCardinality(String) DEFAULT '';
|
||||
|
||||
ALTER TABLE trigger_dev.llm_metrics_v1
|
||||
ADD COLUMN prompt_version UInt32 DEFAULT 0;
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE trigger_dev.llm_metrics_v1
|
||||
DROP COLUMN prompt_slug;
|
||||
|
||||
ALTER TABLE trigger_dev.llm_metrics_v1
|
||||
DROP COLUMN prompt_version;
|
||||
@@ -0,0 +1,7 @@
|
||||
-- +goose Up
|
||||
ALTER TABLE trigger_dev.llm_metrics_v1
|
||||
ADD COLUMN base_response_model String DEFAULT '' CODEC(ZSTD(1));
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE trigger_dev.llm_metrics_v1
|
||||
DROP COLUMN base_response_model;
|
||||
@@ -0,0 +1,57 @@
|
||||
-- +goose Up
|
||||
|
||||
-- Pre-aggregated model performance metrics with no tenant information.
|
||||
-- Used for cross-tenant model comparisons in the Model Registry.
|
||||
-- Aggregated per minute for high-resolution model performance tracking.
|
||||
CREATE TABLE IF NOT EXISTS trigger_dev.llm_model_aggregates_v1
|
||||
(
|
||||
response_model String,
|
||||
base_response_model String DEFAULT '',
|
||||
gen_ai_system LowCardinality(String),
|
||||
minute DateTime,
|
||||
|
||||
-- Counts & totals (SimpleAggregateFunction for sum)
|
||||
call_count SimpleAggregateFunction(sum, UInt64),
|
||||
total_input_tokens SimpleAggregateFunction(sum, UInt64),
|
||||
total_output_tokens SimpleAggregateFunction(sum, UInt64),
|
||||
total_cost SimpleAggregateFunction(sum, Float64),
|
||||
|
||||
-- Performance quantiles (AggregateFunction for merge across parts)
|
||||
ttfc_quantiles AggregateFunction(quantiles(0.5, 0.9, 0.95, 0.99), Float64),
|
||||
tps_quantiles AggregateFunction(quantiles(0.5, 0.9, 0.95, 0.99), Float64),
|
||||
duration_quantiles AggregateFunction(quantiles(0.5, 0.9, 0.95, 0.99), UInt64),
|
||||
|
||||
-- Finish reason distribution
|
||||
finish_reason_counts SimpleAggregateFunction(sumMap, Map(String, UInt64))
|
||||
)
|
||||
ENGINE = AggregatingMergeTree
|
||||
PARTITION BY toYYYYMM(minute)
|
||||
ORDER BY (response_model, base_response_model, gen_ai_system, minute)
|
||||
TTL toDate(minute) + INTERVAL 365 DAY
|
||||
SETTINGS ttl_only_drop_parts = 1;
|
||||
|
||||
-- Materialized view that feeds the aggregate table from llm_metrics_v1.
|
||||
-- Strips all tenant-specific columns (org, project, env, run, span, trace).
|
||||
-- base_response_model comes from the source table (populated during event enrichment).
|
||||
CREATE MATERIALIZED VIEW IF NOT EXISTS trigger_dev.llm_model_aggregates_mv_v1
|
||||
TO trigger_dev.llm_model_aggregates_v1
|
||||
AS SELECT
|
||||
response_model,
|
||||
base_response_model,
|
||||
gen_ai_system,
|
||||
toStartOfMinute(start_time) AS minute,
|
||||
count() AS call_count,
|
||||
sum(input_tokens) AS total_input_tokens,
|
||||
sum(output_tokens) AS total_output_tokens,
|
||||
sum(total_cost) AS total_cost,
|
||||
quantilesStateIf(0.5, 0.9, 0.95, 0.99)(ms_to_first_chunk, ms_to_first_chunk > 0) AS ttfc_quantiles,
|
||||
quantilesStateIf(0.5, 0.9, 0.95, 0.99)(tokens_per_second, tokens_per_second > 0) AS tps_quantiles,
|
||||
quantilesState(0.5, 0.9, 0.95, 0.99)(duration) AS duration_quantiles,
|
||||
sumMap(map(finish_reason, toUInt64(1))) AS finish_reason_counts
|
||||
FROM trigger_dev.llm_metrics_v1
|
||||
WHERE response_model != ''
|
||||
GROUP BY response_model, base_response_model, gen_ai_system, minute;
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE IF EXISTS trigger_dev.llm_model_aggregates_mv_v1;
|
||||
DROP TABLE IF EXISTS trigger_dev.llm_model_aggregates_v1;
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
-- +goose Up
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
ADD COLUMN trigger_source LowCardinality(String) DEFAULT '';
|
||||
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
ADD COLUMN root_trigger_source LowCardinality(String) DEFAULT '';
|
||||
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
ADD COLUMN is_warm_start Nullable(UInt8) DEFAULT NULL;
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
DROP COLUMN trigger_source;
|
||||
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
DROP COLUMN root_trigger_source;
|
||||
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
DROP COLUMN is_warm_start;
|
||||
@@ -0,0 +1,42 @@
|
||||
-- +goose Up
|
||||
|
||||
CREATE TABLE trigger_dev.sessions_v1
|
||||
(
|
||||
/* ─── identity ─────────────────────────────────────────────── */
|
||||
environment_id String,
|
||||
organization_id String,
|
||||
project_id String,
|
||||
session_id String,
|
||||
|
||||
environment_type LowCardinality(String),
|
||||
friendly_id String,
|
||||
external_id String DEFAULT '',
|
||||
|
||||
/* ─── type discriminator ──────────────────────────────────── */
|
||||
type LowCardinality(String),
|
||||
task_identifier String DEFAULT '',
|
||||
|
||||
/* ─── filtering / free-form ──────────────────────────────── */
|
||||
tags Array(String) CODEC(ZSTD(1)),
|
||||
metadata JSON(max_dynamic_paths = 256),
|
||||
|
||||
/* ─── terminal markers ────────────────────────────────────── */
|
||||
closed_at Nullable(DateTime64(3)),
|
||||
closed_reason String DEFAULT '',
|
||||
expires_at Nullable(DateTime64(3)),
|
||||
|
||||
/* ─── timing ─────────────────────────────────────────────── */
|
||||
created_at DateTime64(3),
|
||||
updated_at DateTime64(3),
|
||||
|
||||
/* ─── commit lsn ────────────────────────────────────────── */
|
||||
_version UInt64,
|
||||
_is_deleted UInt8 DEFAULT 0
|
||||
)
|
||||
ENGINE = ReplacingMergeTree(_version, _is_deleted)
|
||||
PARTITION BY toYYYYMM(created_at)
|
||||
ORDER BY (organization_id, project_id, environment_id, created_at, session_id)
|
||||
SETTINGS enable_json_type = 1;
|
||||
|
||||
-- +goose Down
|
||||
DROP TABLE IF EXISTS trigger_dev.sessions_v1;
|
||||
@@ -0,0 +1,12 @@
|
||||
-- +goose Up
|
||||
-- IF NOT EXISTS is required because this migration was previously numbered
|
||||
-- 029 and may have been applied in environments where goose accepted it
|
||||
-- before 030_create_sessions_v1 advanced the version counter. Renaming to
|
||||
-- 031 makes goose treat this as new everywhere, so the DDL must tolerate
|
||||
-- the column already being present.
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
ADD COLUMN IF NOT EXISTS task_kind LowCardinality(String) DEFAULT '';
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
DROP COLUMN IF EXISTS task_kind;
|
||||
@@ -0,0 +1,7 @@
|
||||
-- +goose Up
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
ADD COLUMN IF NOT EXISTS region String DEFAULT '';
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
DROP COLUMN IF EXISTS region;
|
||||
@@ -0,0 +1,7 @@
|
||||
-- +goose Up
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
ADD COLUMN IF NOT EXISTS plan_type LowCardinality(String) DEFAULT '';
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE trigger_dev.task_runs_v2
|
||||
DROP COLUMN IF EXISTS plan_type;
|
||||
@@ -0,0 +1,11 @@
|
||||
-- +goose Up
|
||||
-- Existing rows default to 0 and are intentionally NOT backfilled: the Sessions
|
||||
-- list reads isTest from Postgres (ClickHouse only supplies session IDs), so the
|
||||
-- UI is correct without it. A backfill is only needed if a ClickHouse-side
|
||||
-- isTest filter/aggregate over sessions_v1 is added later.
|
||||
ALTER TABLE trigger_dev.sessions_v1
|
||||
ADD COLUMN IF NOT EXISTS is_test UInt8 DEFAULT 0;
|
||||
|
||||
-- +goose Down
|
||||
ALTER TABLE trigger_dev.sessions_v1
|
||||
DROP COLUMN IF EXISTS is_test;
|
||||
@@ -0,0 +1,192 @@
|
||||
-- +goose Up
|
||||
-- Fix how the error materialized views derive their display columns from the
|
||||
-- stored error JSON:
|
||||
-- * error_type: use the real class name (or internal code), not the generic
|
||||
-- serialization tag (BUILT_IN_ERROR / STRING_ERROR / ...).
|
||||
-- * error_message: fall back name -> raw before 'Unknown error' so messageless
|
||||
-- errors (tagged errors) and non-Error throws still get a meaningful title.
|
||||
-- * stack trace: read error.data.stackTrace (the stored field), not
|
||||
-- error.data.stack, which was always empty.
|
||||
-- Display-only. Only affects rows inserted after this migration.
|
||||
|
||||
ALTER TABLE trigger_dev.errors_mv_v1 MODIFY QUERY
|
||||
SELECT
|
||||
organization_id,
|
||||
project_id,
|
||||
environment_id,
|
||||
task_identifier,
|
||||
error_fingerprint,
|
||||
|
||||
any(coalesce(nullIf(toString(error.data.name), ''), nullIf(toString(error.data.code), ''), 'Error')) as error_type,
|
||||
any(coalesce(
|
||||
nullIf(substring(toString(error.data.message), 1, 500), ''),
|
||||
nullIf(toString(error.data.name), ''),
|
||||
nullIf(substring(toString(error.data.raw), 1, 500), ''),
|
||||
'Unknown error'
|
||||
)) as error_message,
|
||||
any(coalesce(substring(toString(error.data.stackTrace), 1, 2000), '')) as sample_stack_trace,
|
||||
|
||||
toDateTime(max(created_at)) as last_seen_date,
|
||||
|
||||
min(created_at) as first_seen,
|
||||
max(created_at) as last_seen,
|
||||
sumState(toUInt64(1)) as occurrence_count,
|
||||
uniqState(task_version) as affected_task_versions,
|
||||
|
||||
anyState(run_id) as sample_run_id,
|
||||
anyState(friendly_id) as sample_friendly_id,
|
||||
|
||||
sumMapState([status], [toUInt64(1)]) as status_distribution
|
||||
FROM trigger_dev.task_runs_v2
|
||||
WHERE
|
||||
error_fingerprint != ''
|
||||
AND status IN ('SYSTEM_FAILURE', 'CRASHED', 'INTERRUPTED', 'COMPLETED_WITH_ERRORS', 'TIMED_OUT')
|
||||
AND _is_deleted = 0
|
||||
GROUP BY
|
||||
organization_id,
|
||||
project_id,
|
||||
environment_id,
|
||||
task_identifier,
|
||||
error_fingerprint;
|
||||
|
||||
ALTER TABLE trigger_dev.error_occurrences_mv_v1 MODIFY QUERY
|
||||
SELECT
|
||||
organization_id,
|
||||
project_id,
|
||||
environment_id,
|
||||
task_identifier,
|
||||
error_fingerprint,
|
||||
task_version,
|
||||
toStartOfMinute (created_at) as minute,
|
||||
any (
|
||||
coalesce(
|
||||
nullIf(toString (error.data.name), ''),
|
||||
nullIf(toString (error.data.code), ''),
|
||||
'Error'
|
||||
)
|
||||
) as error_type,
|
||||
any (
|
||||
coalesce(
|
||||
nullIf(substring(toString (error.data.message), 1, 500), ''),
|
||||
nullIf(toString (error.data.name), ''),
|
||||
nullIf(substring(toString (error.data.raw), 1, 500), ''),
|
||||
'Unknown error'
|
||||
)
|
||||
) as error_message,
|
||||
any (
|
||||
coalesce(
|
||||
substring(toString (error.data.stackTrace), 1, 2000),
|
||||
''
|
||||
)
|
||||
) as stack_trace,
|
||||
count() as count
|
||||
FROM
|
||||
trigger_dev.task_runs_v2
|
||||
WHERE
|
||||
error_fingerprint != ''
|
||||
AND status IN (
|
||||
'SYSTEM_FAILURE',
|
||||
'CRASHED',
|
||||
'INTERRUPTED',
|
||||
'COMPLETED_WITH_ERRORS',
|
||||
'TIMED_OUT'
|
||||
)
|
||||
AND _is_deleted = 0
|
||||
GROUP BY
|
||||
organization_id,
|
||||
project_id,
|
||||
environment_id,
|
||||
task_identifier,
|
||||
error_fingerprint,
|
||||
task_version,
|
||||
minute;
|
||||
|
||||
-- +goose Down
|
||||
|
||||
ALTER TABLE trigger_dev.errors_mv_v1 MODIFY QUERY
|
||||
SELECT
|
||||
organization_id,
|
||||
project_id,
|
||||
environment_id,
|
||||
task_identifier,
|
||||
error_fingerprint,
|
||||
|
||||
any(coalesce(nullIf(toString(error.data.type), ''), nullIf(toString(error.data.name), ''), 'Error')) as error_type,
|
||||
any(coalesce(nullIf(substring(toString(error.data.message), 1, 500), ''), 'Unknown error')) as error_message,
|
||||
any(coalesce(substring(toString(error.data.stack), 1, 2000), '')) as sample_stack_trace,
|
||||
|
||||
toDateTime(max(created_at)) as last_seen_date,
|
||||
|
||||
min(created_at) as first_seen,
|
||||
max(created_at) as last_seen,
|
||||
sumState(toUInt64(1)) as occurrence_count,
|
||||
uniqState(task_version) as affected_task_versions,
|
||||
|
||||
anyState(run_id) as sample_run_id,
|
||||
anyState(friendly_id) as sample_friendly_id,
|
||||
|
||||
sumMapState([status], [toUInt64(1)]) as status_distribution
|
||||
FROM trigger_dev.task_runs_v2
|
||||
WHERE
|
||||
error_fingerprint != ''
|
||||
AND status IN ('SYSTEM_FAILURE', 'CRASHED', 'INTERRUPTED', 'COMPLETED_WITH_ERRORS', 'TIMED_OUT')
|
||||
AND _is_deleted = 0
|
||||
GROUP BY
|
||||
organization_id,
|
||||
project_id,
|
||||
environment_id,
|
||||
task_identifier,
|
||||
error_fingerprint;
|
||||
|
||||
ALTER TABLE trigger_dev.error_occurrences_mv_v1 MODIFY QUERY
|
||||
SELECT
|
||||
organization_id,
|
||||
project_id,
|
||||
environment_id,
|
||||
task_identifier,
|
||||
error_fingerprint,
|
||||
task_version,
|
||||
toStartOfMinute (created_at) as minute,
|
||||
any (
|
||||
coalesce(
|
||||
nullIf(toString (error.data.type), ''),
|
||||
nullIf(toString (error.data.name), ''),
|
||||
'Error'
|
||||
)
|
||||
) as error_type,
|
||||
any (
|
||||
coalesce(
|
||||
nullIf(
|
||||
substring(toString (error.data.message), 1, 500),
|
||||
''
|
||||
),
|
||||
'Unknown error'
|
||||
)
|
||||
) as error_message,
|
||||
any (
|
||||
coalesce(
|
||||
substring(toString (error.data.stack), 1, 2000),
|
||||
''
|
||||
)
|
||||
) as stack_trace,
|
||||
count() as count
|
||||
FROM
|
||||
trigger_dev.task_runs_v2
|
||||
WHERE
|
||||
error_fingerprint != ''
|
||||
AND status IN (
|
||||
'SYSTEM_FAILURE',
|
||||
'CRASHED',
|
||||
'INTERRUPTED',
|
||||
'COMPLETED_WITH_ERRORS',
|
||||
'TIMED_OUT'
|
||||
)
|
||||
AND _is_deleted = 0
|
||||
GROUP BY
|
||||
organization_id,
|
||||
project_id,
|
||||
environment_id,
|
||||
task_identifier,
|
||||
error_fingerprint,
|
||||
task_version,
|
||||
minute;
|
||||
Reference in New Issue
Block a user