feat: persist and display exchange properties from agent
Add support for exchange properties sent by the agent alongside headers. Properties flow through the same pipeline as headers: ClickHouse columns (input_properties, output_properties) on both executions and processor_executions tables, MergedExecution record, ChunkAccumulator extraction, DetailService snapshot, and REST API response. UI adds a Properties tab next to Headers in the process diagram detail panel, with the same input/output split table layout. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -41,11 +41,12 @@ public class ClickHouseExecutionStore implements ExecutionStore {
|
||||
environment, status, correlation_id, exchange_id, start_time, end_time, duration_ms,
|
||||
error_message, error_stacktrace, error_type, error_category,
|
||||
root_cause_type, root_cause_message, diagram_content_hash, engine_level,
|
||||
input_body, output_body, input_headers, output_headers, attributes,
|
||||
input_body, output_body, input_headers, output_headers,
|
||||
input_properties, output_properties, attributes,
|
||||
trace_id, span_id, has_trace_data, is_replay,
|
||||
original_exchange_id, replay_exchange_id
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
executions.stream().map(e -> new Object[]{
|
||||
nullToEmpty(e.tenantId()),
|
||||
@@ -73,6 +74,8 @@ public class ClickHouseExecutionStore implements ExecutionStore {
|
||||
nullToEmpty(e.outputBody()),
|
||||
nullToEmpty(e.inputHeaders()),
|
||||
nullToEmpty(e.outputHeaders()),
|
||||
nullToEmpty(e.inputProperties()),
|
||||
nullToEmpty(e.outputProperties()),
|
||||
nullToEmpty(e.attributes()),
|
||||
nullToEmpty(e.traceId()),
|
||||
nullToEmpty(e.spanId()),
|
||||
@@ -95,11 +98,12 @@ public class ClickHouseExecutionStore implements ExecutionStore {
|
||||
iteration, iteration_size, status, end_time, duration_ms,
|
||||
error_message, error_stacktrace, error_type, error_category,
|
||||
root_cause_type, root_cause_message,
|
||||
input_body, output_body, input_headers, output_headers, attributes,
|
||||
input_body, output_body, input_headers, output_headers,
|
||||
input_properties, output_properties, attributes,
|
||||
resolved_endpoint_uri, circuit_breaker_state,
|
||||
fallback_triggered, filter_matched, duplicate_message
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""",
|
||||
processors.stream().map(p -> new Object[]{
|
||||
nullToEmpty(tenantId),
|
||||
@@ -127,6 +131,8 @@ public class ClickHouseExecutionStore implements ExecutionStore {
|
||||
nullToEmpty(p.getOutputBody()),
|
||||
mapToJson(p.getInputHeaders()),
|
||||
mapToJson(p.getOutputHeaders()),
|
||||
mapToJson(p.getInputProperties()),
|
||||
mapToJson(p.getOutputProperties()),
|
||||
mapToJson(p.getAttributes()),
|
||||
nullToEmpty(p.getResolvedEndpointUri()),
|
||||
nullToEmpty(p.getCircuitBreakerState()),
|
||||
@@ -166,6 +172,8 @@ public class ClickHouseExecutionStore implements ExecutionStore {
|
||||
nullToEmpty(p.getOutputBody()),
|
||||
mapToJson(p.getInputHeaders()),
|
||||
mapToJson(p.getOutputHeaders()),
|
||||
mapToJson(p.getInputProperties()),
|
||||
mapToJson(p.getOutputProperties()),
|
||||
mapToJson(p.getAttributes()),
|
||||
nullToEmpty(p.getResolvedEndpointUri()),
|
||||
nullToEmpty(p.getCircuitBreakerState()),
|
||||
@@ -182,11 +190,12 @@ public class ClickHouseExecutionStore implements ExecutionStore {
|
||||
iteration, iteration_size, status, end_time, duration_ms,
|
||||
error_message, error_stacktrace, error_type, error_category,
|
||||
root_cause_type, root_cause_message,
|
||||
input_body, output_body, input_headers, output_headers, attributes,
|
||||
input_body, output_body, input_headers, output_headers,
|
||||
input_properties, output_properties, attributes,
|
||||
resolved_endpoint_uri, circuit_breaker_state,
|
||||
fallback_triggered, filter_matched, duplicate_message
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
""", allRows);
|
||||
}
|
||||
|
||||
@@ -198,7 +207,8 @@ public class ClickHouseExecutionStore implements ExecutionStore {
|
||||
SELECT execution_id, route_id, instance_id, application_id, status,
|
||||
correlation_id, exchange_id, start_time, end_time, duration_ms,
|
||||
error_message, error_stacktrace, diagram_content_hash, engine_level,
|
||||
input_body, output_body, input_headers, output_headers, attributes,
|
||||
input_body, output_body, input_headers, output_headers,
|
||||
input_properties, output_properties, attributes,
|
||||
error_type, error_category, root_cause_type, root_cause_message,
|
||||
trace_id, span_id, has_trace_data, is_replay
|
||||
FROM executions FINAL
|
||||
@@ -218,7 +228,8 @@ public class ClickHouseExecutionStore implements ExecutionStore {
|
||||
iteration, iteration_size, status, end_time, duration_ms,
|
||||
error_message, error_stacktrace, error_type, error_category,
|
||||
root_cause_type, root_cause_message,
|
||||
input_body, output_body, input_headers, output_headers, attributes,
|
||||
input_body, output_body, input_headers, output_headers,
|
||||
input_properties, output_properties, attributes,
|
||||
resolved_endpoint_uri, circuit_breaker_state,
|
||||
fallback_triggered, filter_matched, duplicate_message
|
||||
FROM processor_executions
|
||||
@@ -237,7 +248,8 @@ public class ClickHouseExecutionStore implements ExecutionStore {
|
||||
iteration, iteration_size, status, end_time, duration_ms,
|
||||
error_message, error_stacktrace, error_type, error_category,
|
||||
root_cause_type, root_cause_message,
|
||||
input_body, output_body, input_headers, output_headers, attributes,
|
||||
input_body, output_body, input_headers, output_headers,
|
||||
input_properties, output_properties, attributes,
|
||||
resolved_endpoint_uri, circuit_breaker_state,
|
||||
fallback_triggered, filter_matched, duplicate_message
|
||||
FROM processor_executions
|
||||
@@ -257,7 +269,8 @@ public class ClickHouseExecutionStore implements ExecutionStore {
|
||||
iteration, iteration_size, status, end_time, duration_ms,
|
||||
error_message, error_stacktrace, error_type, error_category,
|
||||
root_cause_type, root_cause_message,
|
||||
input_body, output_body, input_headers, output_headers, attributes,
|
||||
input_body, output_body, input_headers, output_headers,
|
||||
input_properties, output_properties, attributes,
|
||||
resolved_endpoint_uri, circuit_breaker_state,
|
||||
fallback_triggered, filter_matched, duplicate_message
|
||||
FROM processor_executions
|
||||
@@ -305,6 +318,8 @@ public class ClickHouseExecutionStore implements ExecutionStore {
|
||||
emptyToNull(rs.getString("output_body")),
|
||||
emptyToNull(rs.getString("input_headers")),
|
||||
emptyToNull(rs.getString("output_headers")),
|
||||
emptyToNull(rs.getString("input_properties")),
|
||||
emptyToNull(rs.getString("output_properties")),
|
||||
emptyToNull(rs.getString("attributes")),
|
||||
emptyToNull(rs.getString("error_type")),
|
||||
emptyToNull(rs.getString("error_category")),
|
||||
@@ -337,6 +352,8 @@ public class ClickHouseExecutionStore implements ExecutionStore {
|
||||
emptyToNull(rs.getString("output_body")),
|
||||
emptyToNull(rs.getString("input_headers")),
|
||||
emptyToNull(rs.getString("output_headers")),
|
||||
emptyToNull(rs.getString("input_properties")),
|
||||
emptyToNull(rs.getString("output_properties")),
|
||||
emptyToNull(rs.getString("attributes")),
|
||||
null, // loopIndex
|
||||
null, // loopSize
|
||||
|
||||
@@ -362,6 +362,12 @@ SETTINGS index_granularity = 8192;
|
||||
|
||||
ALTER TABLE logs ADD COLUMN IF NOT EXISTS source LowCardinality(String) DEFAULT 'app';
|
||||
|
||||
-- ── 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 '';
|
||||
|
||||
-- ── Usage Events ────────────────────────────────────────────────────────
|
||||
|
||||
CREATE TABLE IF NOT EXISTS usage_events (
|
||||
|
||||
@@ -62,7 +62,7 @@ class ClickHouseSearchIndexIT {
|
||||
500L,
|
||||
"", "", "", "", "", "",
|
||||
"hash-abc", "FULL",
|
||||
"{\"order\":\"12345\"}", "", "", "", "{\"env\":\"prod\"}",
|
||||
"{\"order\":\"12345\"}", "", "", "", "", "", "{\"env\":\"prod\"}",
|
||||
"", "",
|
||||
false, false,
|
||||
null, null
|
||||
@@ -79,7 +79,7 @@ class ClickHouseSearchIndexIT {
|
||||
"java.lang.NPE\n at Foo.bar(Foo.java:42)",
|
||||
"NullPointerException", "RUNTIME", "", "",
|
||||
"", "FULL",
|
||||
"", "", "", "", "",
|
||||
"", "", "", "", "", "", "",
|
||||
"", "",
|
||||
false, false,
|
||||
null, null
|
||||
@@ -94,7 +94,7 @@ class ClickHouseSearchIndexIT {
|
||||
100L,
|
||||
"", "", "", "", "", "",
|
||||
"", "FULL",
|
||||
"", "", "", "", "",
|
||||
"", "", "", "", "", "", "",
|
||||
"", "",
|
||||
false, false,
|
||||
null, null
|
||||
|
||||
@@ -62,7 +62,7 @@ class ClickHouseExecutionReadIT {
|
||||
1000L,
|
||||
"", "", "", "", "", "",
|
||||
"", "REGULAR",
|
||||
"", "", "", "", "{}",
|
||||
"", "", "", "", "", "", "{}",
|
||||
"", "",
|
||||
false, false,
|
||||
null, null
|
||||
|
||||
@@ -59,6 +59,7 @@ class ClickHouseExecutionStoreIT {
|
||||
"hash-abc", "FULL",
|
||||
"{\"key\":\"val\"}", "{\"out\":\"val\"}",
|
||||
"{\"h1\":\"v1\"}", "{\"h2\":\"v2\"}",
|
||||
"", "",
|
||||
"{\"attr\":\"val\"}",
|
||||
"trace-123", "span-456",
|
||||
true, false,
|
||||
@@ -187,7 +188,7 @@ class ClickHouseExecutionStoreIT {
|
||||
null, null,
|
||||
"", "", "", "", "", "",
|
||||
"", "FULL",
|
||||
"", "", "", "", "",
|
||||
"", "", "", "", "", "", "",
|
||||
"", "",
|
||||
false, false,
|
||||
null, null
|
||||
@@ -201,7 +202,7 @@ class ClickHouseExecutionStoreIT {
|
||||
5000L,
|
||||
"", "", "", "", "", "",
|
||||
"", "FULL",
|
||||
"", "", "", "", "",
|
||||
"", "", "", "", "", "", "",
|
||||
"", "",
|
||||
false, false,
|
||||
null, null
|
||||
|
||||
Reference in New Issue
Block a user