From 71905a77584836b2024828a2a2013419a5ec5721 Mon Sep 17 00:00:00 2001 From: Sven Rebhan <36194019+srebhan@users.noreply.github.com> Date: Fri, 25 Aug 2023 15:18:08 +0200 Subject: [PATCH] feat(outputs.postgresql): Add option to create time column with timezone (#13763) --- plugins/outputs/postgresql/README.md | 5 ++++ plugins/outputs/postgresql/postgresql.go | 12 ++++++++- plugins/outputs/postgresql/sample.conf | 5 ++++ .../outputs/postgresql/table_manager_test.go | 25 +++++++++++++++++++ 4 files changed, 46 insertions(+), 1 deletion(-) diff --git a/plugins/outputs/postgresql/README.md b/plugins/outputs/postgresql/README.md index bde0089d7..0cf7ff17f 100644 --- a/plugins/outputs/postgresql/README.md +++ b/plugins/outputs/postgresql/README.md @@ -58,6 +58,11 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details. ## NOTE: Some tools (e.g. Grafana) require the default name so be careful! # timestamp_column_name = "time" + ## Type of the timestamp column + ## Currently, "timestamp without time zone" and "timestamp with time zone" + ## are supported + # timestamp_column_type = "timestamp without time zone" + ## Templated statements to execute when creating a new table. # create_templates = [ # '''CREATE TABLE {{ .table }} ({{ .columns }})''', diff --git a/plugins/outputs/postgresql/postgresql.go b/plugins/outputs/postgresql/postgresql.go index cda801a63..498513ba4 100644 --- a/plugins/outputs/postgresql/postgresql.go +++ b/plugins/outputs/postgresql/postgresql.go @@ -42,6 +42,7 @@ type Postgresql struct { TagsAsJsonb bool `toml:"tags_as_jsonb"` FieldsAsJsonb bool `toml:"fields_as_jsonb"` TimestampColumnName string `toml:"timestamp_column_name"` + TimestampColumnType string `toml:"timestamp_column_type"` CreateTemplates []*sqltemplate.Template `toml:"create_templates"` AddColumnTemplates []*sqltemplate.Template `toml:"add_column_templates"` TagTableCreateTemplates []*sqltemplate.Template `toml:"tag_table_create_templates"` @@ -110,10 +111,19 @@ func (p *Postgresql) Init() error { p.TimestampColumnName = "time" } + switch p.TimestampColumnType { + case "": + p.TimestampColumnType = PgTimestampWithoutTimeZone + case PgTimestampWithoutTimeZone, PgTimestampWithTimeZone: + // do nothing for the valid choices + default: + return fmt.Errorf("unknown timestamp column type %q", p.TimestampColumnType) + } + // Initialize the column prototypes p.timeColumn = utils.Column{ Name: p.TimestampColumnName, - Type: PgTimestampWithoutTimeZone, + Type: p.TimestampColumnType, Role: utils.TimeColType, } p.tagIDColumn = utils.Column{Name: "tag_id", Type: PgBigInt, Role: utils.TagsIDColType} diff --git a/plugins/outputs/postgresql/sample.conf b/plugins/outputs/postgresql/sample.conf index d2493f17c..816cb44b2 100644 --- a/plugins/outputs/postgresql/sample.conf +++ b/plugins/outputs/postgresql/sample.conf @@ -41,6 +41,11 @@ ## NOTE: Some tools (e.g. Grafana) require the default name so be careful! # timestamp_column_name = "time" + ## Type of the timestamp column + ## Currently, "timestamp without time zone" and "timestamp with time zone" + ## are supported + # timestamp_column_type = "timestamp without time zone" + ## Templated statements to execute when creating a new table. # create_templates = [ # '''CREATE TABLE {{ .table }} ({{ .columns }})''', diff --git a/plugins/outputs/postgresql/table_manager_test.go b/plugins/outputs/postgresql/table_manager_test.go index ec4381b03..ef110ce1e 100644 --- a/plugins/outputs/postgresql/table_manager_test.go +++ b/plugins/outputs/postgresql/table_manager_test.go @@ -470,3 +470,28 @@ func TestTableManager_addColumnTemplates(t *testing.T) { assert.Equal(t, 1, stmtCount) } + +func TestTableManager_TimeWithTimezone(t *testing.T) { + p := newPostgresqlTest(t) + p.TagsAsForeignKeys = true + p.TimestampColumnType = "timestamp with time zone" + require.NoError(t, p.Init()) + require.NoError(t, p.Connect()) + + metrics := []telegraf.Metric{ + newMetric(t, "", MSS{"pop": "tart"}, MSI{"a": 1, "b": 2}), + } + tsrc := NewTableSources(p.Postgresql, metrics)[t.Name()] + require.NoError(t, p.tableManager.MatchSource(ctx, p.db, tsrc)) + p.Logger.Info("ok") + + expected := `CREATE TABLE "public"."TestTableManager_TimeWithTimezone" ("time" timestamp with time zone, "tag_id" bigint, "a" bigint, "b" bigint)` + stmtCount := 0 + for _, log := range p.Logger.Logs() { + if strings.Contains(log.String(), expected) { + stmtCount++ + } + } + + require.Equal(t, 1, stmtCount) +}