diff --git a/sql/pre_install/tables.sql b/sql/pre_install/tables.sql index e226ffe8a06..06f6e7fb46d 100644 --- a/sql/pre_install/tables.sql +++ b/sql/pre_install/tables.sql @@ -278,8 +278,7 @@ CREATE TABLE _timescaledb_internal.bgw_job_stat_history ( execution_start TIMESTAMPTZ NOT NULL DEFAULT NOW(), execution_finish TIMESTAMPTZ, succeeded boolean NOT NULL DEFAULT FALSE, - config jsonb, - error_data jsonb, + data jsonb, -- table constraints CONSTRAINT bgw_job_stat_history_pkey PRIMARY KEY (id) ); diff --git a/sql/updates/latest-dev.sql b/sql/updates/latest-dev.sql index 3b8ac88e728..2af2957646d 100644 --- a/sql/updates/latest-dev.sql +++ b/sql/updates/latest-dev.sql @@ -344,8 +344,7 @@ CREATE TABLE _timescaledb_internal.bgw_job_stat_history ( execution_start TIMESTAMPTZ NOT NULL DEFAULT NOW(), execution_finish TIMESTAMPTZ, succeeded boolean NOT NULL DEFAULT FALSE, - config jsonb, - error_data jsonb, + data jsonb, -- table constraints CONSTRAINT bgw_job_stat_history_pkey PRIMARY KEY (id) ); @@ -356,13 +355,13 @@ CREATE INDEX bgw_job_stat_history_job_id_idx ON _timescaledb_internal.bgw_job_st REVOKE ALL ON _timescaledb_internal.bgw_job_stat_history FROM PUBLIC; -INSERT INTO _timescaledb_internal.bgw_job_stat_history (job_id, pid, execution_start, execution_finish, error_data) +INSERT INTO _timescaledb_internal.bgw_job_stat_history (job_id, pid, execution_start, execution_finish, data) SELECT job_id, pid, start_time, finish_time, - error_data + jsonb_build_object('error_data', error_data) FROM _timescaledb_internal.job_errors ORDER BY diff --git a/sql/updates/reverse-dev.sql b/sql/updates/reverse-dev.sql index 0c201759d2f..19c0c236790 100644 --- a/sql/updates/reverse-dev.sql +++ b/sql/updates/reverse-dev.sql @@ -230,7 +230,7 @@ SELECT pid, execution_start, execution_finish, - error_data + data->'error_data' FROM _timescaledb_internal.bgw_job_stat_history WHERE diff --git a/sql/views.sql b/sql/views.sql index f37126f9a0f..d771e624ead 100644 --- a/sql/views.sql +++ b/sql/views.sql @@ -281,20 +281,20 @@ CREATE OR REPLACE VIEW timescaledb_information.job_errors WITH (security_barrier = true) AS SELECT job_id, - error_data->>'proc_schema' as proc_schema, - error_data->>'proc_name' as proc_name, + data->'job'->>'proc_schema' as proc_schema, + data->'job'->>'proc_name' as proc_name, pid, execution_start AS start_time, execution_finish AS finish_time, - error_data->>'sqlerrcode' AS sqlerrcode, - CASE WHEN error_data->>'message' IS NOT NULL THEN - CASE WHEN error_data->>'detail' IS NOT NULL THEN - CASE WHEN error_data->>'hint' IS NOT NULL THEN concat(error_data->>'message', '. ', error_data->>'detail', '. ', error_data->>'hint') - ELSE concat(error_data->>'message', ' ', error_data->>'detail') + data->'error_data'->>'sqlerrcode' AS sqlerrcode, + CASE WHEN data->'error_data'->>'message' IS NOT NULL THEN + CASE WHEN data->'error_data'->>'detail' IS NOT NULL THEN + CASE WHEN data->'error_data'->>'hint' IS NOT NULL THEN concat(data->'error_data'->>'message', '. ', data->'error_data'->>'detail', '. ', data->'error_data'->>'hint') + ELSE concat(data->'error_data'->>'message', ' ', data->'error_data'->>'detail') END ELSE - CASE WHEN error_data->>'hint' IS NOT NULL THEN concat(error_data->>'message', '. ', error_data->>'hint') - ELSE error_data->>'message' + CASE WHEN data->'error_data'->>'hint' IS NOT NULL THEN concat(data->'error_data'->>'message', '. ', data->'error_data'->>'hint') + ELSE data->'error_data'->>'message' END END ELSE @@ -320,22 +320,22 @@ SELECT h.id, h.job_id, h.succeeded, - coalesce(h.error_data->>'proc_schema', j.proc_schema) as proc_schema, - coalesce(h.error_data->>'proc_name', j.proc_name) as proc_name, + coalesce(h.data->'job'->>'proc_schema', j.proc_schema) as proc_schema, + coalesce(h.data->'job'->>'proc_name', j.proc_name) as proc_name, h.pid, h.execution_start AS start_time, h.execution_finish AS finish_time, - h.config, - h.error_data->>'sqlerrcode' AS sqlerrcode, + h.data->'job'->'config' AS config, + h.data->'error_data'->>'sqlerrcode' AS sqlerrcode, CASE - WHEN h.succeeded IS FALSE AND h.error_data->>'message' IS NOT NULL THEN - CASE WHEN h.error_data->>'detail' IS NOT NULL THEN - CASE WHEN h.error_data->>'hint' IS NOT NULL THEN concat(h.error_data->>'message', '. ', h.error_data->>'detail', '. ', h.error_data->>'hint') - ELSE concat(h.error_data->>'message', ' ', h.error_data->>'detail') + WHEN h.succeeded IS FALSE AND h.data->'error_data'->>'message' IS NOT NULL THEN + CASE WHEN h.data->'error_data'->>'detail' IS NOT NULL THEN + CASE WHEN h.data->'error_data'->>'hint' IS NOT NULL THEN concat(h.data->'error_data'->>'message', '. ', h.data->'error_data'->>'detail', '. ', h.data->'error_data'->>'hint') + ELSE concat(h.data->'error_data'->>'message', ' ', h.data->'error_data'->>'detail') END ELSE - CASE WHEN h.error_data->>'hint' IS NOT NULL THEN concat(h.error_data->>'message', '. ', h.error_data->>'hint') - ELSE h.error_data->>'message' + CASE WHEN h.data->'error_data'->>'hint' IS NOT NULL THEN concat(h.data->'error_data'->>'message', '. ', h.data->'error_data'->>'hint') + ELSE h.data->'error_data'->>'message' END END WHEN h.succeeded IS FALSE AND h.execution_finish IS NOT NULL THEN diff --git a/src/bgw/job_stat.c b/src/bgw/job_stat.c index 530d0273a9a..32e08d1c738 100644 --- a/src/bgw/job_stat.c +++ b/src/bgw/job_stat.c @@ -680,7 +680,7 @@ ts_bgw_job_stat_mark_end(BgwJob *job, JobResult result, Jsonb *edata) } void -ts_bgw_job_stat_mark_crash_reported(BgwJob *job, JobResult result, Jsonb *edata) +ts_bgw_job_stat_mark_crash_reported(BgwJob *job, JobResult result) { if (!bgw_job_stat_scan_job_id(job->fd.id, bgw_job_stat_tuple_mark_crash_reported, @@ -693,7 +693,7 @@ ts_bgw_job_stat_mark_crash_reported(BgwJob *job, JobResult result, Jsonb *edata) errmsg("unable to find job statistics for job %d", job->fd.id))); } - ts_bgw_job_stat_history_mark_end(job, result, edata); + ts_bgw_job_stat_history_mark_end(job, result, NULL); pgstat_report_activity(STATE_IDLE, NULL); } @@ -800,21 +800,7 @@ ts_bgw_job_stat_next_start(BgwJobStat *jobstat, BgwJob *job, int32 consecutive_f /* Update the errors table regarding the crash */ if (!ts_flags_are_set_32(jobstat->fd.flags, LAST_CRASH_REPORTED)) { - NameData proc_schema = { .data = { 0 } }, proc_name = { .data = { 0 } }; - JsonbParseState *parse_state = NULL; - JsonbValue *result = NULL; - - /* add the proc_schema, proc_name to the jsonb */ - namestrcpy(&proc_schema, NameStr(job->fd.proc_schema)); - namestrcpy(&proc_name, NameStr(job->fd.proc_name)); - - /* build jsonb error data field */ - pushJsonbValue(&parse_state, WJB_BEGIN_OBJECT, NULL); - ts_jsonb_add_str(parse_state, "proc_schema", NameStr(proc_schema)); - ts_jsonb_add_str(parse_state, "proc_name", NameStr(proc_name)); - result = pushJsonbValue(&parse_state, WJB_END_OBJECT, NULL); - - ts_bgw_job_stat_mark_crash_reported(job, JOB_FAILURE, JsonbValueToJsonb(result)); + ts_bgw_job_stat_mark_crash_reported(job, JOB_FAILURE); } return calculate_next_start_on_crash(jobstat->fd.consecutive_crashes, job); diff --git a/src/bgw/job_stat.h b/src/bgw/job_stat.h index 033b544dfc6..ce58745636f 100644 --- a/src/bgw/job_stat.h +++ b/src/bgw/job_stat.h @@ -40,8 +40,7 @@ extern bool ts_bgw_job_stat_should_execute(BgwJobStat *jobstat, BgwJob *job); extern TimestampTz ts_bgw_job_stat_next_start(BgwJobStat *jobstat, BgwJob *job, int32 consecutive_failed_launches); -extern TSDLLEXPORT void ts_bgw_job_stat_mark_crash_reported(BgwJob *job, JobResult result, - Jsonb *edata); +extern TSDLLEXPORT void ts_bgw_job_stat_mark_crash_reported(BgwJob *job, JobResult result); extern TSDLLEXPORT TimestampTz ts_get_next_scheduled_execution_slot(BgwJob *job, TimestampTz finish_time); diff --git a/src/bgw/job_stat_history.c b/src/bgw/job_stat_history.c index 203c42bcf2a..41eb42fa297 100644 --- a/src/bgw/job_stat_history.c +++ b/src/bgw/job_stat_history.c @@ -8,7 +8,9 @@ #include #include +#include "compat/compat.h" #include "guc.h" +#include "hypertable.h" #include "job_stat_history.h" #include "jsonb_utils.h" #include "timer.h" @@ -21,51 +23,107 @@ typedef struct BgwJobStatHistoryContext Jsonb *edata; } BgwJobStatHistoryContext; +static Jsonb * +build_job_info(BgwJob *job) +{ + JsonbParseState *parse_state = NULL; + pushJsonbValue(&parse_state, WJB_BEGIN_OBJECT, NULL); + + /* all fields that is possible to change with `alter_job` API */ + ts_jsonb_add_interval(parse_state, "schedule_interval", &job->fd.schedule_interval); + ts_jsonb_add_interval(parse_state, "max_runtime", &job->fd.max_runtime); + ts_jsonb_add_int32(parse_state, "max_retries", job->fd.max_retries); + ts_jsonb_add_interval(parse_state, "retry_period", &job->fd.retry_period); + ts_jsonb_add_str(parse_state, "proc_schema", NameStr(job->fd.proc_schema)); + ts_jsonb_add_str(parse_state, "proc_name", NameStr(job->fd.proc_name)); + ts_jsonb_add_str(parse_state, "owner", GetUserNameFromId(job->fd.owner, false)); + ts_jsonb_add_bool(parse_state, "scheduled", job->fd.scheduled); + ts_jsonb_add_bool(parse_state, "fixed_schedule", job->fd.fixed_schedule); + + if (job->fd.initial_start) + ts_jsonb_add_interval(parse_state, "initial_start", &job->fd.retry_period); + + if (job->fd.hypertable_id != INVALID_HYPERTABLE_ID) + ts_jsonb_add_int32(parse_state, "hypertable_id", job->fd.hypertable_id); + + if (job->fd.config != NULL) + { + /* config information jsonb*/ + JsonbValue value = { 0 }; + JsonbToJsonbValue(job->fd.config, &value); + ts_jsonb_add_value(parse_state, "config", &value); + } + + if (strlen(NameStr(job->fd.check_schema)) > 0) + ts_jsonb_add_str(parse_state, "check_schema", NameStr(job->fd.check_schema)); + + if (strlen(NameStr(job->fd.check_name)) > 0) + ts_jsonb_add_str(parse_state, "check_name", NameStr(job->fd.check_name)); + + if (job->fd.timezone != NULL) + ts_jsonb_add_str(parse_state, "timezone", text_to_cstring(job->fd.timezone)); + + return JsonbValueToJsonb(pushJsonbValue(&parse_state, WJB_END_OBJECT, NULL)); +} + +static Jsonb * +ts_bgw_job_stat_history_build_data_info(BgwJobStatHistoryContext *context) +{ + JsonbParseState *parse_state = NULL; + JsonbValue value = { 0 }; + pushJsonbValue(&parse_state, WJB_BEGIN_OBJECT, NULL); + + Assert(context != NULL && context->job != NULL); + + /* job information jsonb */ + JsonbToJsonbValue(build_job_info(context->job), &value); + ts_jsonb_add_value(parse_state, "job", &value); + + if (context->edata != NULL) + { + /* error information jsonb */ + JsonbToJsonbValue(context->edata, &value); + ts_jsonb_add_value(parse_state, "error_data", &value); + } + + return JsonbValueToJsonb(pushJsonbValue(&parse_state, WJB_END_OBJECT, NULL)); +} + static void -ts_bgw_job_stat_history_insert(BgwJob *job, BgwJobStatHistoryContext *context) +ts_bgw_job_stat_history_insert(BgwJobStatHistoryContext *context) { + Assert(context != NULL); + Relation rel = table_open(catalog_get_table_id(ts_catalog_get(), BGW_JOB_STAT_HISTORY), ShareRowExclusiveLock); TupleDesc desc = RelationGetDescr(rel); NullableDatum values[Natts_bgw_job_stat_history] = { { 0 } }; CatalogSecurityContext sec_ctx; - ts_datum_set_int32(Anum_bgw_job_stat_history_job_id, values, job->fd.id, false); + ts_datum_set_int32(Anum_bgw_job_stat_history_job_id, values, context->job->fd.id, false); ts_datum_set_int32(Anum_bgw_job_stat_history_pid, values, 0, true); ts_datum_set_timestamptz(Anum_bgw_job_stat_history_execution_start, values, - job->job_history.execution_start, + context->job->job_history.execution_start, false); ts_datum_set_timestamptz(Anum_bgw_job_stat_history_execution_finish, values, 0, true); - ts_datum_set_bool(Anum_bgw_job_stat_history_succeeded, values, false); - ts_datum_set_jsonb(Anum_bgw_job_stat_history_config, values, job->fd.config); - - if (job->fd.config != NULL) - { - ts_datum_set_jsonb(Anum_bgw_job_stat_history_config, values, job->fd.config); - } - - /* In case of the GUC be disabled all errors are logged then the `context` will contain - * `error_data` information */ - if (context != NULL) - { - ts_datum_set_timestamptz(Anum_bgw_job_stat_history_execution_finish, - values, - ts_timer_get_current_timestamp(), - false); - ts_datum_set_jsonb(Anum_bgw_job_stat_history_error_data, values, context->edata); - } - else - ts_datum_set_jsonb(Anum_bgw_job_stat_history_error_data, values, NULL); + ts_datum_set_timestamptz(Anum_bgw_job_stat_history_execution_finish, + values, + ts_timer_get_current_timestamp(), + false); + ts_datum_set_jsonb(Anum_bgw_job_stat_history_data, + values, + ts_bgw_job_stat_history_build_data_info(context)); ts_catalog_database_info_become_owner(ts_catalog_database_info_get(), &sec_ctx); - if (job->job_history.id == INVALID_BGW_JOB_STAT_HISTORY_ID) + if (context->job->job_history.id == INVALID_BGW_JOB_STAT_HISTORY_ID) { /* We need to get a new job id to mark the end later */ - job->job_history.id = ts_catalog_table_next_seq_id(ts_catalog_get(), BGW_JOB_STAT_HISTORY); + context->job->job_history.id = + ts_catalog_table_next_seq_id(ts_catalog_get(), BGW_JOB_STAT_HISTORY); } - ts_datum_set_int64(Anum_bgw_job_stat_history_id, values, job->job_history.id, false); + ts_datum_set_int64(Anum_bgw_job_stat_history_id, values, context->job->job_history.id, false); ts_catalog_insert_datums(rel, desc, values); ts_catalog_restore_user(&sec_ctx); @@ -80,7 +138,11 @@ ts_bgw_job_stat_history_mark_start(BgwJob *job) if (!ts_guc_enable_job_execution_logging) return; - ts_bgw_job_stat_history_insert(job, NULL); + BgwJobStatHistoryContext context = { + .job = job, + }; + + ts_bgw_job_stat_history_insert(&context); } static bool @@ -151,18 +213,13 @@ bgw_job_stat_history_tuple_mark_end(TupleInfo *ti, void *const data) BoolGetDatum((context->result == JOB_SUCCESS)); doReplace[AttrNumberGetAttrOffset(Anum_bgw_job_stat_history_succeeded)] = true; - if (context->job->fd.config != NULL) - { - values[AttrNumberGetAttrOffset(Anum_bgw_job_stat_history_config)] = - JsonbPGetDatum(context->job->fd.config); - doReplace[AttrNumberGetAttrOffset(Anum_bgw_job_stat_history_config)] = true; - } + Jsonb *job_history_data = ts_bgw_job_stat_history_build_data_info(context); - if (context->edata != NULL) + if (job_history_data != NULL) { - values[AttrNumberGetAttrOffset(Anum_bgw_job_stat_history_error_data)] = - JsonbPGetDatum(context->edata); - doReplace[AttrNumberGetAttrOffset(Anum_bgw_job_stat_history_error_data)] = true; + values[AttrNumberGetAttrOffset(Anum_bgw_job_stat_history_data)] = + JsonbPGetDatum(job_history_data); + doReplace[AttrNumberGetAttrOffset(Anum_bgw_job_stat_history_data)] = true; } HeapTuple new_tuple = @@ -204,7 +261,7 @@ ts_bgw_job_stat_history_mark_end(BgwJob *job, JobResult result, Jsonb *edata) * to insert all the information in the job error history table */ if (!ts_guc_enable_job_execution_logging && result != JOB_SUCCESS) { - ts_bgw_job_stat_history_insert(new_job, &context); + ts_bgw_job_stat_history_insert(&context); } else { diff --git a/src/compat/compat.h b/src/compat/compat.h index 2760a15bb74..7c3c0a61d89 100644 --- a/src/compat/compat.h +++ b/src/compat/compat.h @@ -6,6 +6,7 @@ #pragma once #include + #include #include #include @@ -16,6 +17,7 @@ #include #include #include +#include #include #include @@ -1038,3 +1040,14 @@ error_severity(int elevel) return prefix; } #endif + +#if PG14_LT +/* Copied from jsonb_util.c */ +static inline void +JsonbToJsonbValue(Jsonb *jsonb, JsonbValue *val) +{ + val->type = jbvBinary; + val->val.binary.data = &jsonb->root; + val->val.binary.len = VARSIZE(jsonb) - VARHDRSZ; +} +#endif diff --git a/src/telemetry/telemetry_metadata.c b/src/telemetry/telemetry_metadata.c index 1991a4f0bb9..df4529cf241 100644 --- a/src/telemetry/telemetry_metadata.c +++ b/src/telemetry/telemetry_metadata.c @@ -17,17 +17,6 @@ #include "scan_iterator.h" #include "jsonb_utils.h" -#if PG14_LT -/* Copied from jsonb_util.c */ -static void -JsonbToJsonbValue(Jsonb *jsonb, JsonbValue *val) -{ - val->type = jbvBinary; - val->val.binary.data = &jsonb->root; - val->val.binary.len = VARSIZE(jsonb) - VARHDRSZ; -} -#endif - void ts_telemetry_event_truncate(void) { diff --git a/src/ts_catalog/catalog.h b/src/ts_catalog/catalog.h index b51d371ef8f..102a16e51c1 100644 --- a/src/ts_catalog/catalog.h +++ b/src/ts_catalog/catalog.h @@ -688,8 +688,7 @@ enum Anum_bgw_job_stat_history Anum_bgw_job_stat_history_execution_start, Anum_bgw_job_stat_history_execution_finish, Anum_bgw_job_stat_history_succeeded, - Anum_bgw_job_stat_history_config, - Anum_bgw_job_stat_history_error_data, + Anum_bgw_job_stat_history_data, _Anum_bgw_job_stat_history_max, }; @@ -703,8 +702,7 @@ typedef struct FormData_bgw_job_stat_history TimestampTz execution_start; TimestampTz execution_finish; bool succeeded; - Jsonb *config; - Jsonb *error_data; + Jsonb *data; } FormData_bgw_job_stat_history; typedef FormData_bgw_job_stat_history *Form_bgw_job_stat_history; diff --git a/test/expected/telemetry.out b/test/expected/telemetry.out index d287e22d68b..72f9eedfe32 100644 --- a/test/expected/telemetry.out +++ b/test/expected/telemetry.out @@ -544,16 +544,16 @@ EXECUTE record_from_prepared; DEALLOCATE record_from_prepared; SELECT get_telemetry_report()->'functions_used'; - ?column? --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - {"pg_catalog.count()": 1, "pg_catalog.sum(bigint)": 4, "pg_catalog.abs(integer)": 1, "pg_catalog.max(integer)": 2, "pg_catalog.min(integer)": 1, "pg_catalog.sum(integer)": 1, "pg_catalog.int8(numeric)": 4, "pg_catalog.sum(interval)": 2, "pg_catalog.current_database()": 1, "public.get_telemetry_report()": 1, "pg_catalog.text(pg_catalog.name)": 1, "pg_catalog.int4eq(integer,integer)": 3, "pg_catalog.int4mi(integer,integer)": 11, "pg_catalog.int4pl(integer,integer)": 3, "pg_catalog.concat(pg_catalog.\"any\")": 3, "pg_catalog.pg_get_userbyid(pg_catalog.oid)": 1, "pg_catalog.nameeq(pg_catalog.name,pg_catalog.name)": 2, "pg_catalog.texteq(pg_catalog.text,pg_catalog.text)": 1, "pg_catalog.nameregexeq(pg_catalog.name,pg_catalog.text)": 1, "pg_catalog.textregexeq(pg_catalog.text,pg_catalog.text)": 1, "pg_catalog.jsonb_object_agg(pg_catalog.\"any\",pg_catalog.\"any\")": 1, "pg_catalog.jsonb_object_field(pg_catalog.jsonb,pg_catalog.text)": 1, "pg_catalog.jsonb_object_field_text(pg_catalog.jsonb,pg_catalog.text)": 15, "pg_catalog.pg_has_role(pg_catalog.name,pg_catalog.oid,pg_catalog.text)": 1, "pg_catalog.pg_has_role(pg_catalog.name,pg_catalog.name,pg_catalog.text)": 1} + ?column? +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + {"pg_catalog.count()": 1, "pg_catalog.sum(bigint)": 4, "pg_catalog.abs(integer)": 1, "pg_catalog.max(integer)": 2, "pg_catalog.min(integer)": 1, "pg_catalog.sum(integer)": 1, "pg_catalog.int8(numeric)": 4, "pg_catalog.sum(interval)": 2, "pg_catalog.current_database()": 1, "public.get_telemetry_report()": 1, "pg_catalog.text(pg_catalog.name)": 1, "pg_catalog.int4eq(integer,integer)": 3, "pg_catalog.int4mi(integer,integer)": 11, "pg_catalog.int4pl(integer,integer)": 3, "pg_catalog.concat(pg_catalog.\"any\")": 3, "pg_catalog.pg_get_userbyid(pg_catalog.oid)": 1, "pg_catalog.nameeq(pg_catalog.name,pg_catalog.name)": 2, "pg_catalog.texteq(pg_catalog.text,pg_catalog.text)": 1, "pg_catalog.nameregexeq(pg_catalog.name,pg_catalog.text)": 1, "pg_catalog.textregexeq(pg_catalog.text,pg_catalog.text)": 1, "pg_catalog.jsonb_object_agg(pg_catalog.\"any\",pg_catalog.\"any\")": 1, "pg_catalog.jsonb_object_field(pg_catalog.jsonb,pg_catalog.text)": 16, "pg_catalog.jsonb_object_field_text(pg_catalog.jsonb,pg_catalog.text)": 15, "pg_catalog.pg_has_role(pg_catalog.name,pg_catalog.oid,pg_catalog.text)": 1, "pg_catalog.pg_has_role(pg_catalog.name,pg_catalog.name,pg_catalog.text)": 1} (1 row) -- check the report again to see if resetting works SELECT get_telemetry_report()->'functions_used'; - ?column? ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - {"pg_catalog.count()": 1, "pg_catalog.sum(bigint)": 4, "pg_catalog.max(integer)": 2, "pg_catalog.int8(numeric)": 4, "pg_catalog.sum(interval)": 2, "pg_catalog.current_database()": 1, "public.get_telemetry_report()": 1, "pg_catalog.text(pg_catalog.name)": 1, "pg_catalog.int4eq(integer,integer)": 2, "pg_catalog.concat(pg_catalog.\"any\")": 3, "pg_catalog.pg_get_userbyid(pg_catalog.oid)": 1, "pg_catalog.nameeq(pg_catalog.name,pg_catalog.name)": 2, "pg_catalog.texteq(pg_catalog.text,pg_catalog.text)": 1, "pg_catalog.nameregexeq(pg_catalog.name,pg_catalog.text)": 1, "pg_catalog.textregexeq(pg_catalog.text,pg_catalog.text)": 1, "pg_catalog.jsonb_object_agg(pg_catalog.\"any\",pg_catalog.\"any\")": 1, "pg_catalog.jsonb_object_field(pg_catalog.jsonb,pg_catalog.text)": 1, "pg_catalog.jsonb_object_field_text(pg_catalog.jsonb,pg_catalog.text)": 15, "pg_catalog.pg_has_role(pg_catalog.name,pg_catalog.oid,pg_catalog.text)": 1, "pg_catalog.pg_has_role(pg_catalog.name,pg_catalog.name,pg_catalog.text)": 1} + ?column? +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + {"pg_catalog.count()": 1, "pg_catalog.sum(bigint)": 4, "pg_catalog.max(integer)": 2, "pg_catalog.int8(numeric)": 4, "pg_catalog.sum(interval)": 2, "pg_catalog.current_database()": 1, "public.get_telemetry_report()": 1, "pg_catalog.text(pg_catalog.name)": 1, "pg_catalog.int4eq(integer,integer)": 2, "pg_catalog.concat(pg_catalog.\"any\")": 3, "pg_catalog.pg_get_userbyid(pg_catalog.oid)": 1, "pg_catalog.nameeq(pg_catalog.name,pg_catalog.name)": 2, "pg_catalog.texteq(pg_catalog.text,pg_catalog.text)": 1, "pg_catalog.nameregexeq(pg_catalog.name,pg_catalog.text)": 1, "pg_catalog.textregexeq(pg_catalog.text,pg_catalog.text)": 1, "pg_catalog.jsonb_object_agg(pg_catalog.\"any\",pg_catalog.\"any\")": 1, "pg_catalog.jsonb_object_field(pg_catalog.jsonb,pg_catalog.text)": 16, "pg_catalog.jsonb_object_field_text(pg_catalog.jsonb,pg_catalog.text)": 15, "pg_catalog.pg_has_role(pg_catalog.name,pg_catalog.oid,pg_catalog.text)": 1, "pg_catalog.pg_has_role(pg_catalog.name,pg_catalog.name,pg_catalog.text)": 1} (1 row) \c :TEST_DBNAME :ROLE_SUPERUSER diff --git a/tsl/test/expected/bgw_job_stat_history.out b/tsl/test/expected/bgw_job_stat_history.out index bd1891a07e5..128cdb5d94c 100644 --- a/tsl/test/expected/bgw_job_stat_history.out +++ b/tsl/test/expected/bgw_job_stat_history.out @@ -34,8 +34,8 @@ SELECT pg_sleep(6); (1 row) -SELECT add_job('custom_job_ok', '1h', initial_start := now()) AS job_id_1 \gset -SELECT add_job('custom_job_error', '1h', initial_start := now()) AS job_id_2 \gset +SELECT add_job('custom_job_ok', schedule_interval => interval '1 hour', initial_start := now()) AS job_id_1 \gset +SELECT add_job('custom_job_error', schedule_interval => interval '1 hour', initial_start := now()) AS job_id_2 \gset SELECT test.wait_for_job_to_run(:job_id_1, 1); wait_for_job_to_run --------------------- @@ -299,6 +299,44 @@ ORDER BY id; public | custom_job_ok | t | {"only_last_change_is_logged": 1} | | (5 rows) +-- Alter other information about the job +CREATE PROCEDURE custom_job_alter(job_id int, config jsonb) LANGUAGE PLPGSQL AS +$$ +BEGIN + RAISE LOG 'custom_job_alter'; +END +$$; +SELECT add_job('custom_job_alter', schedule_interval => interval '1 hour', initial_start := now()) AS job_id_3 \gset +SELECT test.wait_for_job_to_run(:job_id_3, 1); + wait_for_job_to_run +--------------------- + t +(1 row) + +SELECT timezone, fixed_schedule, config, schedule_interval +FROM alter_job(:job_id_3, timezone => 'America/Sao_Paulo', fixed_schedule => false, config => '{"key": "value"}'::jsonb, schedule_interval => interval '10 min', next_start => now()); + timezone | fixed_schedule | config | schedule_interval +-------------------+----------------+------------------+------------------- + America/Sao_Paulo | f | {"key": "value"} | @ 10 mins +(1 row) + +SELECT test.wait_for_job_to_run(:job_id_3, 2); + wait_for_job_to_run +--------------------- + t +(1 row) + +-- Should return two executions, the second will show the changed values +SELECT job_id, succeeded, data->'job'->>'timezone' AS timezone, data->'job'->>'fixed_schedule' AS fixed_schedule, data->'job'->>'schedule_interval' AS schedule_interval, data->'job'->'config' AS config +FROM _timescaledb_internal.bgw_job_stat_history +WHERE job_id = :job_id_3 +ORDER BY id; + job_id | succeeded | timezone | fixed_schedule | schedule_interval | config +--------+-----------+-------------------+----------------+-------------------+------------------ + 1002 | t | | true | 01:00:00 | + 1002 | t | America/Sao_Paulo | false | 00:10:00 | {"key": "value"} +(2 rows) + SELECT delete_job(:job_id_1); delete_job ------------ @@ -311,6 +349,12 @@ SELECT delete_job(:job_id_2); (1 row) +SELECT delete_job(:job_id_3); + delete_job +------------ + +(1 row) + ALTER SYSTEM RESET timescaledb.enable_job_execution_logging; SELECT pg_reload_conf(); pg_reload_conf diff --git a/tsl/test/expected/bgw_job_stat_history_errors.out b/tsl/test/expected/bgw_job_stat_history_errors.out index ae67b6b28b5..722c9e1a4f8 100644 --- a/tsl/test/expected/bgw_job_stat_history_errors.out +++ b/tsl/test/expected/bgw_job_stat_history_errors.out @@ -68,11 +68,11 @@ select pg_sleep(10); (1 row) -select job_id, error_data->'proc_name' as proc_name, error_data->>'message' as err_message, error_data->>'sqlerrcode' as sqlerrcode +select job_id, data->'job'->>'proc_name' as proc_name, data->'error_data'->>'message' as err_message, data->'error_data'->>'sqlerrcode' as sqlerrcode from _timescaledb_internal.bgw_job_stat_history where job_id = :jobf_id and succeeded is false; - job_id | proc_name | err_message | sqlerrcode ---------+------------+----------------------+------------ - 1000 | "job_fail" | raising an exception | P0001 + job_id | proc_name | err_message | sqlerrcode +--------+-----------+----------------------+------------ + 1000 | job_fail | raising an exception | P0001 (1 row) select delete_job(:jobf_id); @@ -88,12 +88,12 @@ select pg_sleep(20); (1 row) -- exclude the retention policy -select job_id, error_data->>'message' as err_message, error_data->>'sqlerrcode' as sqlerrcode +select job_id, data->'job'->>'proc_name' as proc_name, data->'error_data'->>'message' as err_message, data->'error_data'->>'sqlerrcode' as sqlerrcode from _timescaledb_internal.bgw_job_stat_history WHERE job_id != 2 and succeeded is false; - job_id | err_message | sqlerrcode ---------+-----------------------------------------------------+------------ - 1000 | raising an exception | P0001 - 1002 | could not serialize access due to concurrent update | 40001 + job_id | proc_name | err_message | sqlerrcode +--------+--------------+-----------------------------------------------------+------------ + 1000 | job_fail | raising an exception | P0001 + 1002 | custom_proc2 | could not serialize access due to concurrent update | 40001 (2 rows) ALTER SYSTEM RESET DEFAULT_TRANSACTION_ISOLATION; @@ -111,17 +111,17 @@ SELECT next_start FROM alter_job(2, next_start => '2060-01-01 00:00:00+00'::time (1 row) TRUNCATE TABLE _timescaledb_internal.bgw_job_stat_history; -INSERT INTO _timescaledb_internal.bgw_job_stat_history(job_id, pid, succeeded, execution_start, execution_finish, error_data) +INSERT INTO _timescaledb_internal.bgw_job_stat_history(job_id, pid, succeeded, execution_start, execution_finish, data) VALUES (123, 12345, false, '2000-01-01 00:00:00+00'::timestamptz, '2000-01-01 00:00:10+00'::timestamptz, '{}'), (456, 45678, false, '2000-01-01 00:00:20+00'::timestamptz, '2000-01-01 00:00:40+00'::timestamptz, '{}'), -- not older than a month (123, 23456, false, '2050-01-01 00:00:00+00'::timestamptz, '2050-01-01 00:00:10+00'::timestamptz, '{}'); -- 3 rows in the table before policy runs -SELECT job_id, pid, succeeded, execution_start, execution_finish, error_data +SELECT job_id, pid, succeeded, execution_start, execution_finish, data FROM _timescaledb_internal.bgw_job_stat_history WHERE succeeded IS FALSE; - job_id | pid | succeeded | execution_start | execution_finish | error_data ---------+-------+-----------+------------------------------+------------------------------+------------ + job_id | pid | succeeded | execution_start | execution_finish | data +--------+-------+-----------+------------------------------+------------------------------+------ 123 | 12345 | f | Fri Dec 31 16:00:00 1999 PST | Fri Dec 31 16:00:10 1999 PST | {} 456 | 45678 | f | Fri Dec 31 16:00:20 1999 PST | Fri Dec 31 16:00:40 1999 PST | {} 123 | 23456 | f | Fri Dec 31 16:00:00 2049 PST | Fri Dec 31 16:00:10 2049 PST | {} @@ -137,11 +137,11 @@ SELECT test.wait_for_job_to_run(2, 1); (1 row) -- only the last row remains -SELECT job_id, pid, succeeded, execution_start, execution_finish, error_data +SELECT job_id, pid, succeeded, execution_start, execution_finish, data FROM _timescaledb_internal.bgw_job_stat_history WHERE succeeded IS FALSE; - job_id | pid | succeeded | execution_start | execution_finish | error_data ---------+-------+-----------+------------------------------+------------------------------+------------ + job_id | pid | succeeded | execution_start | execution_finish | data +--------+-------+-----------+------------------------------+------------------------------+------ 123 | 23456 | f | Fri Dec 31 16:00:00 2049 PST | Fri Dec 31 16:00:10 2049 PST | {} (1 row) diff --git a/tsl/test/expected/bgw_job_stat_history_errors_permissions.out b/tsl/test/expected/bgw_job_stat_history_errors_permissions.out index 3eb7aad5dcb..60348d43987 100644 --- a/tsl/test/expected/bgw_job_stat_history_errors_permissions.out +++ b/tsl/test/expected/bgw_job_stat_history_errors_permissions.out @@ -73,8 +73,8 @@ SELECT pg_sleep(6); -- job crashed. \set start '2000-01-01 00:00:00+00' \set finish '2000-01-01 00:00:10+00' -INSERT INTO _timescaledb_internal.bgw_job_stat_history(job_id, pid, succeeded, execution_start, execution_finish, error_data) VALUES - (11111, 12345, false, :'start'::timestamptz, :'finish'::timestamptz, '{"message": "not an error"}'), +INSERT INTO _timescaledb_internal.bgw_job_stat_history(job_id, pid, succeeded, execution_start, execution_finish, data) VALUES + (11111, 12345, false, :'start'::timestamptz, :'finish'::timestamptz, '{"error_data": {"message": "not an error"}}'), (22222, 45678, false, :'start'::timestamptz, :'finish'::timestamptz, '{}'); -- We check the log as different users and should only see what we -- have permissions to see. We only bother about jobs at 1000 or diff --git a/tsl/test/expected/telemetry_stats-13.out b/tsl/test/expected/telemetry_stats-13.out index 02ad4b35409..1d412cd19bc 100644 --- a/tsl/test/expected/telemetry_stats-13.out +++ b/tsl/test/expected/telemetry_stats-13.out @@ -457,14 +457,14 @@ VALUES (2000, 'User-Defined Action [2000]', interval '3 days', interval '1 hour' (2005, 'User-Defined Action [2005]', interval '3 days', interval '1 hour', 5, interval '5 min', '_timescaledb_functions', 'policy_refresh_continuous_aggregate'); -- create some errors for them INSERT INTO -_timescaledb_internal.bgw_job_stat_history(job_id, pid, succeeded, execution_start, execution_finish, error_data) -values (2000, 12345, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"public", "proc_name": "custom_action_1"}'), -(2000, 23456, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"ABCDE", "proc_schema": "public", "proc_name": "custom_action_1"}'), -(2001, 54321, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"public", "proc_name": "custom_action_2"}'), -(2002, 23443, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"JF009", "proc_schema":"_timescaledb_functions", "proc_name": "policy_compression"}'), -(2003, 14567, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"_timescaledb_functions", "proc_name": "policy_retention"}'), -(2004, 78907, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}'), -(2005, 45757, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}'); +_timescaledb_internal.bgw_job_stat_history(job_id, pid, succeeded, execution_start, execution_finish, data) +values (2000, 12345, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema":"public", "proc_name": "custom_action_1"}}'), +(2000, 23456, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"ABCDE"}, "job": {"proc_schema": "public", "proc_name": "custom_action_1"}}'), +(2001, 54321, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "public", "proc_name": "custom_action_2"}}'), +(2002, 23443, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"JF009"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_compression"}}'), +(2003, 14567, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_retention"}}'), +(2004, 78907, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}}'), +(2005, 45757, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}}'); -- we have 3 error records for user-defined actions, and three for policies, so we expect 4 types of jobs SELECT jsonb_pretty(get_telemetry_report() -> 'errors_by_sqlerrcode'); jsonb_pretty diff --git a/tsl/test/expected/telemetry_stats-14.out b/tsl/test/expected/telemetry_stats-14.out index 8f98f058924..d5160052fb7 100644 --- a/tsl/test/expected/telemetry_stats-14.out +++ b/tsl/test/expected/telemetry_stats-14.out @@ -457,14 +457,14 @@ VALUES (2000, 'User-Defined Action [2000]', interval '3 days', interval '1 hour' (2005, 'User-Defined Action [2005]', interval '3 days', interval '1 hour', 5, interval '5 min', '_timescaledb_functions', 'policy_refresh_continuous_aggregate'); -- create some errors for them INSERT INTO -_timescaledb_internal.bgw_job_stat_history(job_id, pid, succeeded, execution_start, execution_finish, error_data) -values (2000, 12345, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"public", "proc_name": "custom_action_1"}'), -(2000, 23456, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"ABCDE", "proc_schema": "public", "proc_name": "custom_action_1"}'), -(2001, 54321, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"public", "proc_name": "custom_action_2"}'), -(2002, 23443, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"JF009", "proc_schema":"_timescaledb_functions", "proc_name": "policy_compression"}'), -(2003, 14567, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"_timescaledb_functions", "proc_name": "policy_retention"}'), -(2004, 78907, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}'), -(2005, 45757, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}'); +_timescaledb_internal.bgw_job_stat_history(job_id, pid, succeeded, execution_start, execution_finish, data) +values (2000, 12345, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema":"public", "proc_name": "custom_action_1"}}'), +(2000, 23456, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"ABCDE"}, "job": {"proc_schema": "public", "proc_name": "custom_action_1"}}'), +(2001, 54321, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "public", "proc_name": "custom_action_2"}}'), +(2002, 23443, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"JF009"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_compression"}}'), +(2003, 14567, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_retention"}}'), +(2004, 78907, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}}'), +(2005, 45757, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}}'); -- we have 3 error records for user-defined actions, and three for policies, so we expect 4 types of jobs SELECT jsonb_pretty(get_telemetry_report() -> 'errors_by_sqlerrcode'); jsonb_pretty diff --git a/tsl/test/expected/telemetry_stats-15.out b/tsl/test/expected/telemetry_stats-15.out index 8f98f058924..d5160052fb7 100644 --- a/tsl/test/expected/telemetry_stats-15.out +++ b/tsl/test/expected/telemetry_stats-15.out @@ -457,14 +457,14 @@ VALUES (2000, 'User-Defined Action [2000]', interval '3 days', interval '1 hour' (2005, 'User-Defined Action [2005]', interval '3 days', interval '1 hour', 5, interval '5 min', '_timescaledb_functions', 'policy_refresh_continuous_aggregate'); -- create some errors for them INSERT INTO -_timescaledb_internal.bgw_job_stat_history(job_id, pid, succeeded, execution_start, execution_finish, error_data) -values (2000, 12345, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"public", "proc_name": "custom_action_1"}'), -(2000, 23456, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"ABCDE", "proc_schema": "public", "proc_name": "custom_action_1"}'), -(2001, 54321, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"public", "proc_name": "custom_action_2"}'), -(2002, 23443, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"JF009", "proc_schema":"_timescaledb_functions", "proc_name": "policy_compression"}'), -(2003, 14567, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"_timescaledb_functions", "proc_name": "policy_retention"}'), -(2004, 78907, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}'), -(2005, 45757, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}'); +_timescaledb_internal.bgw_job_stat_history(job_id, pid, succeeded, execution_start, execution_finish, data) +values (2000, 12345, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema":"public", "proc_name": "custom_action_1"}}'), +(2000, 23456, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"ABCDE"}, "job": {"proc_schema": "public", "proc_name": "custom_action_1"}}'), +(2001, 54321, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "public", "proc_name": "custom_action_2"}}'), +(2002, 23443, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"JF009"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_compression"}}'), +(2003, 14567, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_retention"}}'), +(2004, 78907, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}}'), +(2005, 45757, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}}'); -- we have 3 error records for user-defined actions, and three for policies, so we expect 4 types of jobs SELECT jsonb_pretty(get_telemetry_report() -> 'errors_by_sqlerrcode'); jsonb_pretty diff --git a/tsl/test/expected/telemetry_stats-16.out b/tsl/test/expected/telemetry_stats-16.out index 8f98f058924..d5160052fb7 100644 --- a/tsl/test/expected/telemetry_stats-16.out +++ b/tsl/test/expected/telemetry_stats-16.out @@ -457,14 +457,14 @@ VALUES (2000, 'User-Defined Action [2000]', interval '3 days', interval '1 hour' (2005, 'User-Defined Action [2005]', interval '3 days', interval '1 hour', 5, interval '5 min', '_timescaledb_functions', 'policy_refresh_continuous_aggregate'); -- create some errors for them INSERT INTO -_timescaledb_internal.bgw_job_stat_history(job_id, pid, succeeded, execution_start, execution_finish, error_data) -values (2000, 12345, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"public", "proc_name": "custom_action_1"}'), -(2000, 23456, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"ABCDE", "proc_schema": "public", "proc_name": "custom_action_1"}'), -(2001, 54321, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"public", "proc_name": "custom_action_2"}'), -(2002, 23443, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"JF009", "proc_schema":"_timescaledb_functions", "proc_name": "policy_compression"}'), -(2003, 14567, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"_timescaledb_functions", "proc_name": "policy_retention"}'), -(2004, 78907, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}'), -(2005, 45757, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}'); +_timescaledb_internal.bgw_job_stat_history(job_id, pid, succeeded, execution_start, execution_finish, data) +values (2000, 12345, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema":"public", "proc_name": "custom_action_1"}}'), +(2000, 23456, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"ABCDE"}, "job": {"proc_schema": "public", "proc_name": "custom_action_1"}}'), +(2001, 54321, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "public", "proc_name": "custom_action_2"}}'), +(2002, 23443, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"JF009"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_compression"}}'), +(2003, 14567, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_retention"}}'), +(2004, 78907, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}}'), +(2005, 45757, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}}'); -- we have 3 error records for user-defined actions, and three for policies, so we expect 4 types of jobs SELECT jsonb_pretty(get_telemetry_report() -> 'errors_by_sqlerrcode'); jsonb_pretty diff --git a/tsl/test/sql/bgw_job_stat_history.sql b/tsl/test/sql/bgw_job_stat_history.sql index 979dcdb2093..f8a5469deec 100644 --- a/tsl/test/sql/bgw_job_stat_history.sql +++ b/tsl/test/sql/bgw_job_stat_history.sql @@ -25,8 +25,8 @@ SHOW timescaledb.enable_job_execution_logging; SELECT _timescaledb_functions.start_background_workers(); SELECT pg_sleep(6); -SELECT add_job('custom_job_ok', '1h', initial_start := now()) AS job_id_1 \gset -SELECT add_job('custom_job_error', '1h', initial_start := now()) AS job_id_2 \gset +SELECT add_job('custom_job_ok', schedule_interval => interval '1 hour', initial_start := now()) AS job_id_1 \gset +SELECT add_job('custom_job_error', schedule_interval => interval '1 hour', initial_start := now()) AS job_id_2 \gset SELECT test.wait_for_job_to_run(:job_id_1, 1); SELECT test.wait_for_job_to_run(:job_id_2, 1); @@ -134,8 +134,30 @@ FROM timescaledb_information.job_history WHERE job_id = :job_id_1 ORDER BY id; +-- Alter other information about the job +CREATE PROCEDURE custom_job_alter(job_id int, config jsonb) LANGUAGE PLPGSQL AS +$$ +BEGIN + RAISE LOG 'custom_job_alter'; +END +$$; + +SELECT add_job('custom_job_alter', schedule_interval => interval '1 hour', initial_start := now()) AS job_id_3 \gset +SELECT test.wait_for_job_to_run(:job_id_3, 1); + +SELECT timezone, fixed_schedule, config, schedule_interval +FROM alter_job(:job_id_3, timezone => 'America/Sao_Paulo', fixed_schedule => false, config => '{"key": "value"}'::jsonb, schedule_interval => interval '10 min', next_start => now()); +SELECT test.wait_for_job_to_run(:job_id_3, 2); + +-- Should return two executions, the second will show the changed values +SELECT job_id, succeeded, data->'job'->>'timezone' AS timezone, data->'job'->>'fixed_schedule' AS fixed_schedule, data->'job'->>'schedule_interval' AS schedule_interval, data->'job'->'config' AS config +FROM _timescaledb_internal.bgw_job_stat_history +WHERE job_id = :job_id_3 +ORDER BY id; + SELECT delete_job(:job_id_1); SELECT delete_job(:job_id_2); +SELECT delete_job(:job_id_3); ALTER SYSTEM RESET timescaledb.enable_job_execution_logging; SELECT pg_reload_conf(); diff --git a/tsl/test/sql/bgw_job_stat_history_errors.sql b/tsl/test/sql/bgw_job_stat_history_errors.sql index ec22b7c240f..8f88008a564 100644 --- a/tsl/test/sql/bgw_job_stat_history_errors.sql +++ b/tsl/test/sql/bgw_job_stat_history_errors.sql @@ -53,14 +53,14 @@ select add_job('custom_proc2', '2 min', initial_start => now() + interval '5 sec SELECT _timescaledb_functions.start_background_workers(); -- enough time to for job_fail to fail select pg_sleep(10); -select job_id, error_data->'proc_name' as proc_name, error_data->>'message' as err_message, error_data->>'sqlerrcode' as sqlerrcode +select job_id, data->'job'->>'proc_name' as proc_name, data->'error_data'->>'message' as err_message, data->'error_data'->>'sqlerrcode' as sqlerrcode from _timescaledb_internal.bgw_job_stat_history where job_id = :jobf_id and succeeded is false; select delete_job(:jobf_id); select pg_sleep(20); -- exclude the retention policy -select job_id, error_data->>'message' as err_message, error_data->>'sqlerrcode' as sqlerrcode +select job_id, data->'job'->>'proc_name' as proc_name, data->'error_data'->>'message' as err_message, data->'error_data'->>'sqlerrcode' as sqlerrcode from _timescaledb_internal.bgw_job_stat_history WHERE job_id != 2 and succeeded is false; ALTER SYSTEM RESET DEFAULT_TRANSACTION_ISOLATION; @@ -69,13 +69,13 @@ SELECT pg_reload_conf(); -- test the retention job SELECT next_start FROM alter_job(2, next_start => '2060-01-01 00:00:00+00'::timestamptz); TRUNCATE TABLE _timescaledb_internal.bgw_job_stat_history; -INSERT INTO _timescaledb_internal.bgw_job_stat_history(job_id, pid, succeeded, execution_start, execution_finish, error_data) +INSERT INTO _timescaledb_internal.bgw_job_stat_history(job_id, pid, succeeded, execution_start, execution_finish, data) VALUES (123, 12345, false, '2000-01-01 00:00:00+00'::timestamptz, '2000-01-01 00:00:10+00'::timestamptz, '{}'), (456, 45678, false, '2000-01-01 00:00:20+00'::timestamptz, '2000-01-01 00:00:40+00'::timestamptz, '{}'), -- not older than a month (123, 23456, false, '2050-01-01 00:00:00+00'::timestamptz, '2050-01-01 00:00:10+00'::timestamptz, '{}'); -- 3 rows in the table before policy runs -SELECT job_id, pid, succeeded, execution_start, execution_finish, error_data +SELECT job_id, pid, succeeded, execution_start, execution_finish, data FROM _timescaledb_internal.bgw_job_stat_history WHERE succeeded IS FALSE; -- drop all job_stats for the retention job @@ -83,7 +83,7 @@ DELETE FROM _timescaledb_internal.bgw_job_stat WHERE job_id = 2; SELECT next_start FROM alter_job(2, next_start => now() + interval '2 seconds') \gset SELECT test.wait_for_job_to_run(2, 1); -- only the last row remains -SELECT job_id, pid, succeeded, execution_start, execution_finish, error_data +SELECT job_id, pid, succeeded, execution_start, execution_finish, data FROM _timescaledb_internal.bgw_job_stat_history WHERE succeeded IS FALSE; diff --git a/tsl/test/sql/bgw_job_stat_history_errors_permissions.sql b/tsl/test/sql/bgw_job_stat_history_errors_permissions.sql index ebe5ba5f298..d3a9319981f 100644 --- a/tsl/test/sql/bgw_job_stat_history_errors_permissions.sql +++ b/tsl/test/sql/bgw_job_stat_history_errors_permissions.sql @@ -59,8 +59,8 @@ SELECT pg_sleep(6); -- job crashed. \set start '2000-01-01 00:00:00+00' \set finish '2000-01-01 00:00:10+00' -INSERT INTO _timescaledb_internal.bgw_job_stat_history(job_id, pid, succeeded, execution_start, execution_finish, error_data) VALUES - (11111, 12345, false, :'start'::timestamptz, :'finish'::timestamptz, '{"message": "not an error"}'), +INSERT INTO _timescaledb_internal.bgw_job_stat_history(job_id, pid, succeeded, execution_start, execution_finish, data) VALUES + (11111, 12345, false, :'start'::timestamptz, :'finish'::timestamptz, '{"error_data": {"message": "not an error"}}'), (22222, 45678, false, :'start'::timestamptz, :'finish'::timestamptz, '{}'); -- We check the log as different users and should only see what we diff --git a/tsl/test/sql/telemetry_stats.sql.in b/tsl/test/sql/telemetry_stats.sql.in index bd2f0abf63f..b0cc7583397 100644 --- a/tsl/test/sql/telemetry_stats.sql.in +++ b/tsl/test/sql/telemetry_stats.sql.in @@ -151,14 +151,14 @@ VALUES (2000, 'User-Defined Action [2000]', interval '3 days', interval '1 hour' (2005, 'User-Defined Action [2005]', interval '3 days', interval '1 hour', 5, interval '5 min', '_timescaledb_functions', 'policy_refresh_continuous_aggregate'); -- create some errors for them INSERT INTO -_timescaledb_internal.bgw_job_stat_history(job_id, pid, succeeded, execution_start, execution_finish, error_data) -values (2000, 12345, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"public", "proc_name": "custom_action_1"}'), -(2000, 23456, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"ABCDE", "proc_schema": "public", "proc_name": "custom_action_1"}'), -(2001, 54321, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"public", "proc_name": "custom_action_2"}'), -(2002, 23443, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"JF009", "proc_schema":"_timescaledb_functions", "proc_name": "policy_compression"}'), -(2003, 14567, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"_timescaledb_functions", "proc_name": "policy_retention"}'), -(2004, 78907, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}'), -(2005, 45757, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"sqlerrcode":"P0001", "proc_schema":"_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}'); +_timescaledb_internal.bgw_job_stat_history(job_id, pid, succeeded, execution_start, execution_finish, data) +values (2000, 12345, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema":"public", "proc_name": "custom_action_1"}}'), +(2000, 23456, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"ABCDE"}, "job": {"proc_schema": "public", "proc_name": "custom_action_1"}}'), +(2001, 54321, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "public", "proc_name": "custom_action_2"}}'), +(2002, 23443, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"JF009"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_compression"}}'), +(2003, 14567, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_retention"}}'), +(2004, 78907, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}}'), +(2005, 45757, false, '2040-01-01 00:00:00+00'::timestamptz, '2040-01-01 00:00:01+00'::timestamptz, '{"error_data": {"sqlerrcode":"P0001"}, "job": {"proc_schema": "_timescaledb_functions", "proc_name": "policy_refresh_continuous_aggregate"}}'); -- we have 3 error records for user-defined actions, and three for policies, so we expect 4 types of jobs SELECT jsonb_pretty(get_telemetry_report() -> 'errors_by_sqlerrcode');