diff --git a/expected/json.out b/expected/json.out index 2e8cac0..9c180fc 100644 --- a/expected/json.out +++ b/expected/json.out @@ -50,13 +50,13 @@ set statement_timeout=200; ERROR: canceling statement due to statement timeout -- Check json generated spans with sql error code set statement_timeout TO DEFAULT; -SELECT trace_id, name, sql_error_code, lvl FROM peek_ordered_json_spans; - trace_id | name | sql_error_code | lvl -----------------------------------+-----------------------------+----------------+----- - 00000000000000000000000000000001 | select * from pg_sleep($1); | 57014 | 1 - 00000000000000000000000000000001 | Planner | | 2 - 00000000000000000000000000000001 | ExecutorRun | 57014 | 2 - 00000000000000000000000000000001 | FunctionScan on pg_sleep | 57014 | 3 +SELECT trace_id, name, sql_error_code, status_code, status_message, lvl FROM peek_ordered_json_spans; + trace_id | name | sql_error_code | status_code | status_message | lvl +----------------------------------+-----------------------------+----------------+-------------+-------------------+----- + 00000000000000000000000000000001 | select * from pg_sleep($1); | 57014 | 2 | "SQLError: 57014" | 1 + 00000000000000000000000000000001 | Planner | | 1 | | 2 + 00000000000000000000000000000001 | ExecutorRun | 57014 | 2 | "SQLError: 57014" | 2 + 00000000000000000000000000000001 | FunctionScan on pg_sleep | 57014 | 2 | "SQLError: 57014" | 3 (4 rows) CALL clean_spans(); diff --git a/expected/utility.out b/expected/utility.out index 333c1da..fff8113 100644 --- a/expected/utility.out +++ b/expected/utility.out @@ -71,7 +71,7 @@ CREATE VIEW peek_spans_with_level AS CREATE VIEW peek_ordered_spans AS SELECT * FROM peek_spans_with_level order by span_start, lvl, span_end, deparse_info; -- Column type to convert json to record -create type span_json as ("traceId" text, "parentSpanId" text, "spanId" text, name text, "startTimeUnixNano" text, "endTimeUnixNano" text, attributes jsonb, kind int); +create type span_json as ("traceId" text, "parentSpanId" text, "spanId" text, name text, "startTimeUnixNano" text, "endTimeUnixNano" text, attributes jsonb, kind int, status jsonb); CREATE VIEW peek_json_spans AS SELECT * FROM jsonb_populate_recordset(null::span_json, (SELECT jsonb_path_query_array(pg_tracing_json_spans()::jsonb, '$.resourceSpans[0].scopeSpans[*].spans[*]'))); CREATE FUNCTION get_int_attribute(attributes jsonb, keyvalue text) returns bigint @@ -94,6 +94,7 @@ CREATE FUNCTION get_string_attribute(attributes jsonb, keyvalue text) returns te CREATE VIEW peek_json_spans_with_level AS WITH RECURSIVE list_trace_spans(trace_id, parent_id, span_id, name, span_start, span_end, kind, query_id, pid, userid, dbid, sql_error_code, subxact_count, + status_code, status_message, plan_startup_cost, plan_total_cost, plan_rows, plan_width, rows, nloops, shared_blks_hit, shared_blks_read, shared_blks_dirtied, shared_blks_written, @@ -111,6 +112,8 @@ WITH RECURSIVE list_trace_spans(trace_id, parent_id, span_id, name, span_start, get_int_attribute(p.attributes, 'backend.database_id'), get_string_attribute(p.attributes, 'query.sql_error_code'), get_int_attribute(p.attributes, 'query.subxact_count'), + p.status -> 'code', + p.status -> 'message', get_double_attribute(p.attributes, 'plan.cost.startup'), get_double_attribute(p.attributes, 'plan.cost.total'), get_double_attribute(p.attributes, 'plan.rows'), @@ -151,6 +154,8 @@ WITH RECURSIVE list_trace_spans(trace_id, parent_id, span_id, name, span_start, get_int_attribute(s.attributes, 'backend.database_id'), get_string_attribute(s.attributes, 'query.sql_error_code'), get_int_attribute(s.attributes, 'query.subxact_count'), + s.status -> 'code', + s.status -> 'message', get_double_attribute(s.attributes, 'plan.cost.startup'), get_double_attribute(s.attributes, 'plan.cost.total'), get_double_attribute(s.attributes, 'plan.rows'), diff --git a/sql/json.sql b/sql/json.sql index 52b712e..b1cb31e 100644 --- a/sql/json.sql +++ b/sql/json.sql @@ -14,7 +14,7 @@ set statement_timeout=200; /*dddbs='postgres.db',traceparent='00-00000000000000000000000000000001-0000000000000001-01'*/ select * from pg_sleep(1); -- Check json generated spans with sql error code set statement_timeout TO DEFAULT; -SELECT trace_id, name, sql_error_code, lvl FROM peek_ordered_json_spans; +SELECT trace_id, name, sql_error_code, status_code, status_message, lvl FROM peek_ordered_json_spans; CALL clean_spans(); -- Test subxact_count and node counters with json export diff --git a/sql/utility.sql b/sql/utility.sql index 6404a62..4298cda 100644 --- a/sql/utility.sql +++ b/sql/utility.sql @@ -81,7 +81,7 @@ CREATE VIEW peek_ordered_spans AS SELECT * FROM peek_spans_with_level order by span_start, lvl, span_end, deparse_info; -- Column type to convert json to record -create type span_json as ("traceId" text, "parentSpanId" text, "spanId" text, name text, "startTimeUnixNano" text, "endTimeUnixNano" text, attributes jsonb, kind int); +create type span_json as ("traceId" text, "parentSpanId" text, "spanId" text, name text, "startTimeUnixNano" text, "endTimeUnixNano" text, attributes jsonb, kind int, status jsonb); CREATE VIEW peek_json_spans AS SELECT * FROM jsonb_populate_recordset(null::span_json, (SELECT jsonb_path_query_array(pg_tracing_json_spans()::jsonb, '$.resourceSpans[0].scopeSpans[*].spans[*]'))); @@ -108,6 +108,7 @@ CREATE FUNCTION get_string_attribute(attributes jsonb, keyvalue text) returns te CREATE VIEW peek_json_spans_with_level AS WITH RECURSIVE list_trace_spans(trace_id, parent_id, span_id, name, span_start, span_end, kind, query_id, pid, userid, dbid, sql_error_code, subxact_count, + status_code, status_message, plan_startup_cost, plan_total_cost, plan_rows, plan_width, rows, nloops, shared_blks_hit, shared_blks_read, shared_blks_dirtied, shared_blks_written, @@ -125,6 +126,8 @@ WITH RECURSIVE list_trace_spans(trace_id, parent_id, span_id, name, span_start, get_int_attribute(p.attributes, 'backend.database_id'), get_string_attribute(p.attributes, 'query.sql_error_code'), get_int_attribute(p.attributes, 'query.subxact_count'), + p.status -> 'code', + p.status -> 'message', get_double_attribute(p.attributes, 'plan.cost.startup'), get_double_attribute(p.attributes, 'plan.cost.total'), get_double_attribute(p.attributes, 'plan.rows'), @@ -165,6 +168,8 @@ WITH RECURSIVE list_trace_spans(trace_id, parent_id, span_id, name, span_start, get_int_attribute(s.attributes, 'backend.database_id'), get_string_attribute(s.attributes, 'query.sql_error_code'), get_int_attribute(s.attributes, 'query.subxact_count'), + s.status -> 'code', + s.status -> 'message', get_double_attribute(s.attributes, 'plan.cost.startup'), get_double_attribute(s.attributes, 'plan.cost.total'), get_double_attribute(s.attributes, 'plan.rows'), diff --git a/src/pg_tracing_json.c b/src/pg_tracing_json.c index 48734e5..b242457 100644 --- a/src/pg_tracing_json.c +++ b/src/pg_tracing_json.c @@ -44,6 +44,8 @@ * From https://github.com/open-telemetry/opentelemetry-proto/blob/v1.3.1/opentelemetry/proto/trace/v1/trace.proto#L159-L161 */ #define SPAN_KIND_SERVER 2 +#define STATUS_CODE_OK 1 +#define STATUS_CODE_ERROR 2 static void append_text_field(StringInfo str, const char *label, const char *value, bool add_comma) @@ -210,6 +212,21 @@ append_node_counters(StringInfo str, const NodeCounters * node_counters) append_attribute_double(str, "jit.emission_counter", emission_counter, true, true); } +static void +append_span_status_code(StringInfo str, const Span * span) +{ + int code = STATUS_CODE_OK; + + appendStringInfo(str, "\"status\":{"); + if (span->sql_error_code > 0) + { + code = STATUS_CODE_ERROR; + append_text_field(str, "message", psprintf("SQLError: %s", unpack_sql_state(span->sql_error_code)), true); + } + append_int_field(str, "code", code, false); + appendStringInfo(str, "},"); +} + static void append_span_attributes(const JsonContext * json_ctx, const Span * span) { @@ -268,6 +285,7 @@ append_span(const JsonContext * json_ctx, const Span * span) append_int_field(str, "kind", SPAN_KIND_SERVER, true); append_nano_timestamp(str, "startTimeUnixNano", span->start, true); append_nano_timestamp(str, "endTimeUnixNano", span->end, true); + append_span_status_code(str, span); append_span_attributes(json_ctx, span); appendStringInfoChar(str, '}'); }