2026-04-03 15:24:53 +02:00
|
|
|
-- ClickHouse schema initialization (single file, idempotent)
|
2026-04-13 11:49:53 +02:00
|
|
|
-- All statements use IF NOT EXISTS / IF EXISTS for safe re-execution on every startup.
|
|
|
|
|
-- No DROP or INSERT statements -- this file is safe for repeated runs.
|
2026-04-03 15:24:53 +02:00
|
|
|
|
|
|
|
|
-- ── Agent Metrics ───────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS agent_metrics (
|
|
|
|
|
tenant_id LowCardinality(String) DEFAULT 'default',
|
|
|
|
|
collected_at DateTime64(3),
|
2026-04-04 15:00:18 +02:00
|
|
|
environment LowCardinality(String) DEFAULT 'default',
|
2026-04-03 15:24:53 +02:00
|
|
|
instance_id LowCardinality(String),
|
|
|
|
|
metric_name LowCardinality(String),
|
|
|
|
|
metric_value Float64,
|
|
|
|
|
tags Map(String, String) DEFAULT map(),
|
|
|
|
|
server_received_at DateTime64(3) DEFAULT now64(3)
|
|
|
|
|
)
|
|
|
|
|
ENGINE = MergeTree()
|
|
|
|
|
PARTITION BY (tenant_id, toYYYYMM(collected_at))
|
2026-04-04 15:00:18 +02:00
|
|
|
ORDER BY (tenant_id, collected_at, environment, instance_id, metric_name)
|
2026-04-03 15:24:53 +02:00
|
|
|
TTL toDateTime(collected_at) + INTERVAL 365 DAY DELETE
|
|
|
|
|
SETTINGS index_granularity = 8192;
|
|
|
|
|
|
|
|
|
|
-- ── Executions ──────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS executions (
|
|
|
|
|
tenant_id LowCardinality(String) DEFAULT 'default',
|
|
|
|
|
execution_id String,
|
|
|
|
|
start_time DateTime64(3),
|
|
|
|
|
_version UInt64 DEFAULT 1,
|
|
|
|
|
route_id LowCardinality(String),
|
|
|
|
|
instance_id LowCardinality(String),
|
|
|
|
|
application_id LowCardinality(String),
|
2026-04-04 15:00:18 +02:00
|
|
|
environment LowCardinality(String) DEFAULT 'default',
|
2026-04-03 15:24:53 +02:00
|
|
|
status LowCardinality(String),
|
|
|
|
|
correlation_id String DEFAULT '',
|
|
|
|
|
exchange_id String DEFAULT '',
|
|
|
|
|
end_time Nullable(DateTime64(3)),
|
|
|
|
|
duration_ms Nullable(Int64),
|
|
|
|
|
error_message String DEFAULT '',
|
|
|
|
|
error_stacktrace String DEFAULT '',
|
|
|
|
|
error_type LowCardinality(String) DEFAULT '',
|
|
|
|
|
error_category LowCardinality(String) DEFAULT '',
|
|
|
|
|
root_cause_type String DEFAULT '',
|
|
|
|
|
root_cause_message String DEFAULT '',
|
|
|
|
|
diagram_content_hash String DEFAULT '',
|
|
|
|
|
engine_level LowCardinality(String) DEFAULT '',
|
|
|
|
|
input_body String DEFAULT '',
|
|
|
|
|
output_body String DEFAULT '',
|
|
|
|
|
input_headers String DEFAULT '',
|
|
|
|
|
output_headers String DEFAULT '',
|
|
|
|
|
attributes String DEFAULT '',
|
|
|
|
|
trace_id String DEFAULT '',
|
|
|
|
|
span_id String DEFAULT '',
|
|
|
|
|
has_trace_data Bool DEFAULT false,
|
|
|
|
|
is_replay Bool DEFAULT false,
|
|
|
|
|
original_exchange_id String DEFAULT '',
|
|
|
|
|
replay_exchange_id String DEFAULT '',
|
|
|
|
|
|
|
|
|
|
_search_text String MATERIALIZED
|
|
|
|
|
concat(execution_id, ' ', correlation_id, ' ', exchange_id, ' ', route_id,
|
|
|
|
|
' ', error_message, ' ', error_stacktrace, ' ', attributes,
|
|
|
|
|
' ', input_body, ' ', output_body, ' ', input_headers,
|
|
|
|
|
' ', output_headers, ' ', root_cause_message),
|
|
|
|
|
|
|
|
|
|
INDEX idx_search _search_text TYPE ngrambf_v1(3, 256, 2, 0) GRANULARITY 4,
|
|
|
|
|
INDEX idx_error error_message TYPE ngrambf_v1(3, 256, 2, 0) GRANULARITY 4,
|
|
|
|
|
INDEX idx_bodies concat(input_body, ' ', output_body) TYPE ngrambf_v1(3, 256, 2, 0) GRANULARITY 4,
|
|
|
|
|
INDEX idx_headers concat(input_headers, ' ', output_headers) TYPE ngrambf_v1(3, 256, 2, 0) GRANULARITY 4,
|
|
|
|
|
INDEX idx_status status TYPE set(10) GRANULARITY 1,
|
|
|
|
|
INDEX idx_corr correlation_id TYPE bloom_filter(0.01) GRANULARITY 4
|
|
|
|
|
)
|
|
|
|
|
ENGINE = ReplacingMergeTree(_version)
|
|
|
|
|
PARTITION BY (tenant_id, toYYYYMM(start_time))
|
2026-04-04 15:00:18 +02:00
|
|
|
ORDER BY (tenant_id, start_time, environment, application_id, route_id, execution_id)
|
2026-04-03 15:24:53 +02:00
|
|
|
TTL toDateTime(start_time) + INTERVAL 365 DAY DELETE
|
|
|
|
|
SETTINGS index_granularity = 8192;
|
|
|
|
|
|
|
|
|
|
-- ── Processor Executions ────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS processor_executions (
|
|
|
|
|
tenant_id LowCardinality(String) DEFAULT 'default',
|
|
|
|
|
execution_id String,
|
|
|
|
|
seq UInt32,
|
|
|
|
|
parent_seq Nullable(UInt32),
|
|
|
|
|
parent_processor_id String DEFAULT '',
|
|
|
|
|
processor_id String,
|
|
|
|
|
processor_type LowCardinality(String),
|
|
|
|
|
start_time DateTime64(3),
|
|
|
|
|
route_id LowCardinality(String),
|
|
|
|
|
application_id LowCardinality(String),
|
2026-04-04 15:00:18 +02:00
|
|
|
environment LowCardinality(String) DEFAULT 'default',
|
2026-04-03 15:24:53 +02:00
|
|
|
iteration Nullable(Int32),
|
|
|
|
|
iteration_size Nullable(Int32),
|
|
|
|
|
status LowCardinality(String),
|
|
|
|
|
end_time Nullable(DateTime64(3)),
|
|
|
|
|
duration_ms Nullable(Int64),
|
|
|
|
|
error_message String DEFAULT '',
|
|
|
|
|
error_stacktrace String DEFAULT '',
|
|
|
|
|
error_type LowCardinality(String) DEFAULT '',
|
|
|
|
|
error_category LowCardinality(String) DEFAULT '',
|
|
|
|
|
root_cause_type String DEFAULT '',
|
|
|
|
|
root_cause_message String DEFAULT '',
|
|
|
|
|
input_body String DEFAULT '',
|
|
|
|
|
output_body String DEFAULT '',
|
|
|
|
|
input_headers String DEFAULT '',
|
|
|
|
|
output_headers String DEFAULT '',
|
|
|
|
|
attributes String DEFAULT '',
|
|
|
|
|
resolved_endpoint_uri String DEFAULT '',
|
|
|
|
|
circuit_breaker_state LowCardinality(String) DEFAULT '',
|
|
|
|
|
fallback_triggered Bool DEFAULT false,
|
|
|
|
|
filter_matched Bool DEFAULT false,
|
|
|
|
|
duplicate_message Bool DEFAULT false,
|
|
|
|
|
|
|
|
|
|
_search_text String MATERIALIZED
|
|
|
|
|
concat(error_message, ' ', error_stacktrace, ' ', attributes,
|
|
|
|
|
' ', input_body, ' ', output_body, ' ', input_headers, ' ', output_headers),
|
|
|
|
|
|
|
|
|
|
INDEX idx_search _search_text TYPE ngrambf_v1(3, 256, 2, 0) GRANULARITY 4,
|
|
|
|
|
INDEX idx_exec_id execution_id TYPE bloom_filter(0.01) GRANULARITY 4
|
|
|
|
|
)
|
|
|
|
|
ENGINE = MergeTree()
|
|
|
|
|
PARTITION BY (tenant_id, toYYYYMM(start_time))
|
2026-04-04 15:00:18 +02:00
|
|
|
ORDER BY (tenant_id, start_time, environment, application_id, route_id, execution_id, seq)
|
2026-04-03 15:24:53 +02:00
|
|
|
TTL toDateTime(start_time) + INTERVAL 365 DAY DELETE
|
|
|
|
|
SETTINGS index_granularity = 8192;
|
|
|
|
|
|
|
|
|
|
-- ── Stats: Materialized Views + AggregatingMergeTree ────────────────────
|
2026-04-13 11:49:53 +02:00
|
|
|
-- Counts use uniq(execution_id) to deduplicate chunk retries.
|
|
|
|
|
-- Processor counts use uniq(concat(execution_id, seq)) to also preserve loop iterations.
|
2026-04-03 15:24:53 +02:00
|
|
|
|
|
|
|
|
-- stats_1m_all (global)
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS stats_1m_all (
|
|
|
|
|
tenant_id LowCardinality(String),
|
2026-04-21 23:25:22 +02:00
|
|
|
bucket DateTime('UTC'),
|
2026-04-04 15:00:18 +02:00
|
|
|
environment LowCardinality(String) DEFAULT 'default',
|
2026-04-12 23:48:01 +02:00
|
|
|
total_count AggregateFunction(uniq, String),
|
|
|
|
|
failed_count AggregateFunction(uniqIf, String, UInt8),
|
|
|
|
|
running_count AggregateFunction(uniqIf, String, UInt8),
|
2026-04-03 15:24:53 +02:00
|
|
|
duration_sum AggregateFunction(sum, Nullable(Int64)),
|
|
|
|
|
duration_max AggregateFunction(max, Nullable(Int64)),
|
|
|
|
|
p99_duration AggregateFunction(quantile(0.99), Nullable(Int64))
|
|
|
|
|
)
|
|
|
|
|
ENGINE = AggregatingMergeTree()
|
|
|
|
|
PARTITION BY (tenant_id, toYYYYMM(bucket))
|
2026-04-04 15:00:18 +02:00
|
|
|
ORDER BY (tenant_id, bucket, environment)
|
2026-04-03 15:24:53 +02:00
|
|
|
TTL bucket + INTERVAL 365 DAY DELETE;
|
|
|
|
|
|
|
|
|
|
CREATE MATERIALIZED VIEW IF NOT EXISTS stats_1m_all_mv TO stats_1m_all AS
|
|
|
|
|
SELECT
|
|
|
|
|
tenant_id,
|
2026-04-21 23:25:22 +02:00
|
|
|
toDateTime(toStartOfMinute(start_time), 'UTC') AS bucket,
|
2026-04-04 15:00:18 +02:00
|
|
|
environment,
|
2026-04-12 23:48:01 +02:00
|
|
|
uniqState(execution_id) AS total_count,
|
|
|
|
|
uniqIfState(execution_id, status = 'FAILED') AS failed_count,
|
|
|
|
|
uniqIfState(execution_id, status = 'RUNNING') AS running_count,
|
2026-04-03 15:24:53 +02:00
|
|
|
sumState(duration_ms) AS duration_sum,
|
|
|
|
|
maxState(duration_ms) AS duration_max,
|
|
|
|
|
quantileState(0.99)(duration_ms) AS p99_duration
|
|
|
|
|
FROM executions
|
2026-04-04 15:00:18 +02:00
|
|
|
GROUP BY tenant_id, bucket, environment;
|
2026-04-03 15:24:53 +02:00
|
|
|
|
|
|
|
|
-- stats_1m_app (per-application)
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS stats_1m_app (
|
|
|
|
|
tenant_id LowCardinality(String),
|
|
|
|
|
application_id LowCardinality(String),
|
2026-04-21 23:25:22 +02:00
|
|
|
bucket DateTime('UTC'),
|
2026-04-04 15:00:18 +02:00
|
|
|
environment LowCardinality(String) DEFAULT 'default',
|
2026-04-12 23:48:01 +02:00
|
|
|
total_count AggregateFunction(uniq, String),
|
|
|
|
|
failed_count AggregateFunction(uniqIf, String, UInt8),
|
|
|
|
|
running_count AggregateFunction(uniqIf, String, UInt8),
|
2026-04-03 15:24:53 +02:00
|
|
|
duration_sum AggregateFunction(sum, Nullable(Int64)),
|
|
|
|
|
duration_max AggregateFunction(max, Nullable(Int64)),
|
|
|
|
|
p99_duration AggregateFunction(quantile(0.99), Nullable(Int64))
|
|
|
|
|
)
|
|
|
|
|
ENGINE = AggregatingMergeTree()
|
|
|
|
|
PARTITION BY (tenant_id, toYYYYMM(bucket))
|
2026-04-04 15:00:18 +02:00
|
|
|
ORDER BY (tenant_id, bucket, environment, application_id)
|
2026-04-03 15:24:53 +02:00
|
|
|
TTL bucket + INTERVAL 365 DAY DELETE;
|
|
|
|
|
|
|
|
|
|
CREATE MATERIALIZED VIEW IF NOT EXISTS stats_1m_app_mv TO stats_1m_app AS
|
|
|
|
|
SELECT
|
|
|
|
|
tenant_id,
|
|
|
|
|
application_id,
|
2026-04-21 23:25:22 +02:00
|
|
|
toDateTime(toStartOfMinute(start_time), 'UTC') AS bucket,
|
2026-04-04 15:00:18 +02:00
|
|
|
environment,
|
2026-04-12 23:48:01 +02:00
|
|
|
uniqState(execution_id) AS total_count,
|
|
|
|
|
uniqIfState(execution_id, status = 'FAILED') AS failed_count,
|
|
|
|
|
uniqIfState(execution_id, status = 'RUNNING') AS running_count,
|
2026-04-03 15:24:53 +02:00
|
|
|
sumState(duration_ms) AS duration_sum,
|
|
|
|
|
maxState(duration_ms) AS duration_max,
|
|
|
|
|
quantileState(0.99)(duration_ms) AS p99_duration
|
|
|
|
|
FROM executions
|
2026-04-04 15:00:18 +02:00
|
|
|
GROUP BY tenant_id, application_id, bucket, environment;
|
2026-04-03 15:24:53 +02:00
|
|
|
|
|
|
|
|
-- stats_1m_route (per-route)
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS stats_1m_route (
|
|
|
|
|
tenant_id LowCardinality(String),
|
|
|
|
|
application_id LowCardinality(String),
|
|
|
|
|
route_id LowCardinality(String),
|
2026-04-21 23:25:22 +02:00
|
|
|
bucket DateTime('UTC'),
|
2026-04-04 15:00:18 +02:00
|
|
|
environment LowCardinality(String) DEFAULT 'default',
|
2026-04-12 23:48:01 +02:00
|
|
|
total_count AggregateFunction(uniq, String),
|
|
|
|
|
failed_count AggregateFunction(uniqIf, String, UInt8),
|
|
|
|
|
running_count AggregateFunction(uniqIf, String, UInt8),
|
2026-04-03 15:24:53 +02:00
|
|
|
duration_sum AggregateFunction(sum, Nullable(Int64)),
|
|
|
|
|
duration_max AggregateFunction(max, Nullable(Int64)),
|
|
|
|
|
p99_duration AggregateFunction(quantile(0.99), Nullable(Int64))
|
|
|
|
|
)
|
|
|
|
|
ENGINE = AggregatingMergeTree()
|
|
|
|
|
PARTITION BY (tenant_id, toYYYYMM(bucket))
|
2026-04-04 15:00:18 +02:00
|
|
|
ORDER BY (tenant_id, bucket, environment, application_id, route_id)
|
2026-04-03 15:24:53 +02:00
|
|
|
TTL bucket + INTERVAL 365 DAY DELETE;
|
|
|
|
|
|
|
|
|
|
CREATE MATERIALIZED VIEW IF NOT EXISTS stats_1m_route_mv TO stats_1m_route AS
|
|
|
|
|
SELECT
|
|
|
|
|
tenant_id,
|
|
|
|
|
application_id,
|
|
|
|
|
route_id,
|
2026-04-21 23:25:22 +02:00
|
|
|
toDateTime(toStartOfMinute(start_time), 'UTC') AS bucket,
|
2026-04-04 15:00:18 +02:00
|
|
|
environment,
|
2026-04-12 23:48:01 +02:00
|
|
|
uniqState(execution_id) AS total_count,
|
|
|
|
|
uniqIfState(execution_id, status = 'FAILED') AS failed_count,
|
|
|
|
|
uniqIfState(execution_id, status = 'RUNNING') AS running_count,
|
2026-04-03 15:24:53 +02:00
|
|
|
sumState(duration_ms) AS duration_sum,
|
|
|
|
|
maxState(duration_ms) AS duration_max,
|
|
|
|
|
quantileState(0.99)(duration_ms) AS p99_duration
|
|
|
|
|
FROM executions
|
2026-04-04 15:00:18 +02:00
|
|
|
GROUP BY tenant_id, application_id, route_id, bucket, environment;
|
2026-04-03 15:24:53 +02:00
|
|
|
|
|
|
|
|
-- stats_1m_processor (per-processor-type)
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS stats_1m_processor (
|
|
|
|
|
tenant_id LowCardinality(String),
|
|
|
|
|
application_id LowCardinality(String),
|
|
|
|
|
processor_type LowCardinality(String),
|
2026-04-21 23:25:22 +02:00
|
|
|
bucket DateTime('UTC'),
|
2026-04-04 15:00:18 +02:00
|
|
|
environment LowCardinality(String) DEFAULT 'default',
|
2026-04-12 23:12:00 +02:00
|
|
|
total_count AggregateFunction(uniq, String),
|
|
|
|
|
failed_count AggregateFunction(uniqIf, String, UInt8),
|
2026-04-03 15:24:53 +02:00
|
|
|
duration_sum AggregateFunction(sum, Nullable(Int64)),
|
|
|
|
|
duration_max AggregateFunction(max, Nullable(Int64)),
|
|
|
|
|
p99_duration AggregateFunction(quantile(0.99), Nullable(Int64))
|
|
|
|
|
)
|
|
|
|
|
ENGINE = AggregatingMergeTree()
|
|
|
|
|
PARTITION BY (tenant_id, toYYYYMM(bucket))
|
2026-04-04 15:00:18 +02:00
|
|
|
ORDER BY (tenant_id, bucket, environment, application_id, processor_type)
|
2026-04-03 15:24:53 +02:00
|
|
|
TTL bucket + INTERVAL 365 DAY DELETE;
|
|
|
|
|
|
|
|
|
|
CREATE MATERIALIZED VIEW IF NOT EXISTS stats_1m_processor_mv TO stats_1m_processor AS
|
|
|
|
|
SELECT
|
|
|
|
|
tenant_id,
|
|
|
|
|
application_id,
|
|
|
|
|
processor_type,
|
2026-04-21 23:25:22 +02:00
|
|
|
toDateTime(toStartOfMinute(start_time), 'UTC') AS bucket,
|
2026-04-04 15:00:18 +02:00
|
|
|
environment,
|
2026-04-12 23:48:01 +02:00
|
|
|
uniqState(concat(execution_id, toString(seq))) AS total_count,
|
|
|
|
|
uniqIfState(concat(execution_id, toString(seq)), status = 'FAILED') AS failed_count,
|
2026-04-03 15:24:53 +02:00
|
|
|
sumState(duration_ms) AS duration_sum,
|
|
|
|
|
maxState(duration_ms) AS duration_max,
|
|
|
|
|
quantileState(0.99)(duration_ms) AS p99_duration
|
|
|
|
|
FROM processor_executions
|
2026-04-04 15:00:18 +02:00
|
|
|
GROUP BY tenant_id, application_id, processor_type, bucket, environment;
|
2026-04-03 15:24:53 +02:00
|
|
|
|
|
|
|
|
-- stats_1m_processor_detail (per-processor-id)
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS stats_1m_processor_detail (
|
|
|
|
|
tenant_id LowCardinality(String),
|
|
|
|
|
application_id LowCardinality(String),
|
|
|
|
|
route_id LowCardinality(String),
|
|
|
|
|
processor_id String,
|
|
|
|
|
processor_type LowCardinality(String),
|
2026-04-21 23:25:22 +02:00
|
|
|
bucket DateTime('UTC'),
|
2026-04-04 15:00:18 +02:00
|
|
|
environment LowCardinality(String) DEFAULT 'default',
|
2026-04-12 23:12:00 +02:00
|
|
|
total_count AggregateFunction(uniq, String),
|
|
|
|
|
failed_count AggregateFunction(uniqIf, String, UInt8),
|
2026-04-03 15:24:53 +02:00
|
|
|
duration_sum AggregateFunction(sum, Nullable(Int64)),
|
|
|
|
|
duration_max AggregateFunction(max, Nullable(Int64)),
|
|
|
|
|
p99_duration AggregateFunction(quantile(0.99), Nullable(Int64))
|
|
|
|
|
)
|
|
|
|
|
ENGINE = AggregatingMergeTree()
|
|
|
|
|
PARTITION BY (tenant_id, toYYYYMM(bucket))
|
2026-04-04 15:00:18 +02:00
|
|
|
ORDER BY (tenant_id, bucket, environment, application_id, route_id, processor_id, processor_type)
|
2026-04-03 15:24:53 +02:00
|
|
|
TTL bucket + INTERVAL 365 DAY DELETE;
|
|
|
|
|
|
|
|
|
|
CREATE MATERIALIZED VIEW IF NOT EXISTS stats_1m_processor_detail_mv TO stats_1m_processor_detail AS
|
|
|
|
|
SELECT
|
|
|
|
|
tenant_id,
|
|
|
|
|
application_id,
|
|
|
|
|
route_id,
|
|
|
|
|
processor_id,
|
|
|
|
|
processor_type,
|
2026-04-21 23:25:22 +02:00
|
|
|
toDateTime(toStartOfMinute(start_time), 'UTC') AS bucket,
|
2026-04-04 15:00:18 +02:00
|
|
|
environment,
|
2026-04-12 23:48:01 +02:00
|
|
|
uniqState(concat(execution_id, toString(seq))) AS total_count,
|
|
|
|
|
uniqIfState(concat(execution_id, toString(seq)), status = 'FAILED') AS failed_count,
|
2026-04-03 15:24:53 +02:00
|
|
|
sumState(duration_ms) AS duration_sum,
|
|
|
|
|
maxState(duration_ms) AS duration_max,
|
|
|
|
|
quantileState(0.99)(duration_ms) AS p99_duration
|
|
|
|
|
FROM processor_executions
|
2026-04-04 15:00:18 +02:00
|
|
|
GROUP BY tenant_id, application_id, route_id, processor_id, processor_type, bucket, environment;
|
2026-04-03 15:24:53 +02:00
|
|
|
|
|
|
|
|
-- ── Route Diagrams ──────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS route_diagrams (
|
|
|
|
|
tenant_id LowCardinality(String) DEFAULT 'default',
|
|
|
|
|
content_hash String,
|
|
|
|
|
route_id LowCardinality(String),
|
|
|
|
|
instance_id LowCardinality(String),
|
|
|
|
|
application_id LowCardinality(String),
|
2026-04-04 15:00:18 +02:00
|
|
|
environment LowCardinality(String) DEFAULT 'default',
|
2026-04-03 15:24:53 +02:00
|
|
|
definition String,
|
|
|
|
|
created_at DateTime64(3) DEFAULT now64(3)
|
|
|
|
|
)
|
|
|
|
|
ENGINE = ReplacingMergeTree(created_at)
|
2026-04-04 15:00:18 +02:00
|
|
|
ORDER BY (tenant_id, environment, route_id, instance_id, content_hash)
|
2026-04-03 15:24:53 +02:00
|
|
|
SETTINGS index_granularity = 8192;
|
|
|
|
|
|
|
|
|
|
-- ── Agent Events ────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS agent_events (
|
|
|
|
|
tenant_id LowCardinality(String) DEFAULT 'default',
|
|
|
|
|
timestamp DateTime64(3) DEFAULT now64(3),
|
2026-04-04 15:00:18 +02:00
|
|
|
environment LowCardinality(String) DEFAULT 'default',
|
2026-04-03 15:24:53 +02:00
|
|
|
instance_id LowCardinality(String),
|
|
|
|
|
application_id LowCardinality(String),
|
|
|
|
|
event_type LowCardinality(String),
|
2026-04-17 14:25:36 +02:00
|
|
|
detail String DEFAULT '',
|
|
|
|
|
insert_id UUID DEFAULT generateUUIDv4()
|
2026-04-03 15:24:53 +02:00
|
|
|
)
|
|
|
|
|
ENGINE = MergeTree()
|
|
|
|
|
PARTITION BY (tenant_id, toYYYYMM(timestamp))
|
2026-04-04 15:00:18 +02:00
|
|
|
ORDER BY (tenant_id, timestamp, environment, instance_id)
|
2026-04-03 15:24:53 +02:00
|
|
|
TTL toDateTime(timestamp) + INTERVAL 365 DAY DELETE;
|
|
|
|
|
|
|
|
|
|
-- ── Logs ────────────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS logs (
|
|
|
|
|
tenant_id LowCardinality(String) DEFAULT 'default',
|
|
|
|
|
timestamp DateTime64(3),
|
2026-04-04 15:00:18 +02:00
|
|
|
environment LowCardinality(String) DEFAULT 'default',
|
2026-04-03 15:24:53 +02:00
|
|
|
application LowCardinality(String),
|
|
|
|
|
instance_id LowCardinality(String),
|
|
|
|
|
level LowCardinality(String),
|
|
|
|
|
logger_name LowCardinality(String) DEFAULT '',
|
|
|
|
|
message String,
|
|
|
|
|
thread_name LowCardinality(String) DEFAULT '',
|
|
|
|
|
stack_trace String DEFAULT '',
|
|
|
|
|
exchange_id String DEFAULT '',
|
|
|
|
|
mdc Map(String, String) DEFAULT map(),
|
2026-04-17 14:25:36 +02:00
|
|
|
insert_id UUID DEFAULT generateUUIDv4(),
|
2026-04-03 15:24:53 +02:00
|
|
|
|
|
|
|
|
INDEX idx_msg message TYPE ngrambf_v1(3, 256, 2, 0) GRANULARITY 4,
|
|
|
|
|
INDEX idx_stack stack_trace TYPE ngrambf_v1(3, 256, 2, 0) GRANULARITY 4,
|
|
|
|
|
INDEX idx_level level TYPE set(10) GRANULARITY 1
|
|
|
|
|
)
|
|
|
|
|
ENGINE = MergeTree()
|
|
|
|
|
PARTITION BY (tenant_id, toYYYYMM(timestamp))
|
2026-04-04 15:00:18 +02:00
|
|
|
ORDER BY (tenant_id, timestamp, environment, application, instance_id)
|
2026-04-03 15:24:53 +02:00
|
|
|
TTL toDateTime(timestamp) + INTERVAL 365 DAY DELETE
|
|
|
|
|
SETTINGS index_granularity = 8192;
|
|
|
|
|
|
2026-04-12 10:25:46 +02:00
|
|
|
ALTER TABLE logs ADD COLUMN IF NOT EXISTS source LowCardinality(String) DEFAULT 'app';
|
|
|
|
|
|
2026-04-14 14:23:53 +02:00
|
|
|
-- ── Exchange Properties (added for agent protocol v2) ──────────────────
|
|
|
|
|
ALTER TABLE executions ADD COLUMN IF NOT EXISTS input_properties String DEFAULT '';
|
|
|
|
|
ALTER TABLE executions ADD COLUMN IF NOT EXISTS output_properties String DEFAULT '';
|
|
|
|
|
ALTER TABLE processor_executions ADD COLUMN IF NOT EXISTS input_properties String DEFAULT '';
|
|
|
|
|
ALTER TABLE processor_executions ADD COLUMN IF NOT EXISTS output_properties String DEFAULT '';
|
|
|
|
|
|
2026-04-03 15:24:53 +02:00
|
|
|
-- ── Usage Events ────────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS usage_events (
|
2026-04-04 15:00:18 +02:00
|
|
|
tenant_id LowCardinality(String) DEFAULT 'default',
|
2026-04-03 15:24:53 +02:00
|
|
|
timestamp DateTime64(3) DEFAULT now64(3),
|
2026-04-04 15:00:18 +02:00
|
|
|
environment LowCardinality(String) DEFAULT 'default',
|
2026-04-03 15:24:53 +02:00
|
|
|
username LowCardinality(String),
|
|
|
|
|
method LowCardinality(String),
|
|
|
|
|
path String,
|
|
|
|
|
normalized LowCardinality(String),
|
|
|
|
|
status_code UInt16,
|
|
|
|
|
duration_ms UInt32,
|
|
|
|
|
query_params String DEFAULT ''
|
|
|
|
|
)
|
|
|
|
|
ENGINE = MergeTree()
|
2026-04-04 15:00:18 +02:00
|
|
|
ORDER BY (tenant_id, timestamp, environment, username, normalized)
|
2026-04-03 15:24:53 +02:00
|
|
|
TTL toDateTime(timestamp) + INTERVAL 90 DAY;
|
2026-04-16 18:45:38 +02:00
|
|
|
|
|
|
|
|
-- ── Route Catalog ──────────────────────────────────────────────────────
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS route_catalog (
|
|
|
|
|
tenant_id LowCardinality(String) DEFAULT 'default',
|
|
|
|
|
environment LowCardinality(String) DEFAULT 'default',
|
|
|
|
|
application_id LowCardinality(String),
|
|
|
|
|
route_id LowCardinality(String),
|
|
|
|
|
first_seen DateTime64(3),
|
|
|
|
|
last_seen DateTime64(3)
|
|
|
|
|
)
|
|
|
|
|
ENGINE = ReplacingMergeTree(last_seen)
|
|
|
|
|
ORDER BY (tenant_id, environment, application_id, route_id);
|
2026-04-17 14:25:36 +02:00
|
|
|
|
2026-04-23 23:20:45 +02:00
|
|
|
-- ── Server Self-Metrics ────────────────────────────────────────────────
|
|
|
|
|
-- Periodic snapshot of the server's own Micrometer registry (written by
|
|
|
|
|
-- ServerMetricsSnapshotScheduler). No `environment` column — the server
|
|
|
|
|
-- straddles environments. `statistic` distinguishes Timer/DistributionSummary
|
|
|
|
|
-- sub-measurements (count, total_time, max, mean) from plain counter/gauge values.
|
|
|
|
|
|
|
|
|
|
CREATE TABLE IF NOT EXISTS server_metrics (
|
|
|
|
|
tenant_id LowCardinality(String) DEFAULT 'default',
|
|
|
|
|
collected_at DateTime64(3),
|
|
|
|
|
server_instance_id LowCardinality(String),
|
|
|
|
|
metric_name LowCardinality(String),
|
|
|
|
|
metric_type LowCardinality(String),
|
|
|
|
|
statistic LowCardinality(String) DEFAULT 'value',
|
|
|
|
|
metric_value Float64,
|
|
|
|
|
tags Map(String, String) DEFAULT map(),
|
|
|
|
|
server_received_at DateTime64(3) DEFAULT now64(3)
|
|
|
|
|
)
|
|
|
|
|
ENGINE = MergeTree()
|
|
|
|
|
PARTITION BY (tenant_id, toYYYYMM(collected_at))
|
|
|
|
|
ORDER BY (tenant_id, collected_at, server_instance_id, metric_name, statistic)
|
|
|
|
|
TTL toDateTime(collected_at) + INTERVAL 90 DAY DELETE
|
|
|
|
|
SETTINGS index_granularity = 8192;
|
|
|
|
|
|
2026-04-17 14:25:36 +02:00
|
|
|
-- insert_id tiebreak for keyset pagination (fixes same-millisecond cursor collision).
|
|
|
|
|
-- IF NOT EXISTS on ADD COLUMN is idempotent. MATERIALIZE COLUMN is a background mutation,
|
|
|
|
|
-- effectively a no-op once all parts are already materialized.
|
|
|
|
|
ALTER TABLE logs ADD COLUMN IF NOT EXISTS insert_id UUID DEFAULT generateUUIDv4();
|
|
|
|
|
ALTER TABLE logs MATERIALIZE COLUMN insert_id;
|
|
|
|
|
|
|
|
|
|
ALTER TABLE agent_events ADD COLUMN IF NOT EXISTS insert_id UUID DEFAULT generateUUIDv4();
|
|
|
|
|
ALTER TABLE agent_events MATERIALIZE COLUMN insert_id;
|