diff --git a/pkg/apis/cpo.opensource.cybertec.at/v1/crds.go b/pkg/apis/cpo.opensource.cybertec.at/v1/crds.go index bf7a3934..1980ada1 100644 --- a/pkg/apis/cpo.opensource.cybertec.at/v1/crds.go +++ b/pkg/apis/cpo.opensource.cybertec.at/v1/crds.go @@ -707,6 +707,49 @@ var PostgresCRDResourceValidation = apiextv1.CustomResourceValidation{ "ttl": { Type: "integer", }, + "log": { + Type: "object", + Properties: map[string]apiextv1.JSONSchemaProps{ + "type": { + Type: "string", + Enum: []apiextv1.JSON{ + {Raw: []byte(`"plain"`)}, + {Raw: []byte(`"json"`)}, + }, + }, + "level": { + Type: "string", + Enum: []apiextv1.JSON{ + {Raw: []byte(`"DEBUG"`)}, + {Raw: []byte(`"INFO"`)}, + {Raw: []byte(`"WARNING"`)}, + {Raw: []byte(`"ERROR"`)}, + {Raw: []byte(`"CRITICAL"`)}, + }, + }, + "traceback_level": { + Type: "string", + Enum: []apiextv1.JSON{ + {Raw: []byte(`"DEBUG"`)}, + {Raw: []byte(`"INFO"`)}, + {Raw: []byte(`"WARNING"`)}, + {Raw: []byte(`"ERROR"`)}, + {Raw: []byte(`"CRITICAL"`)}, + }, + }, + "static_fields": { + Type: "object", + AdditionalProperties: &apiextv1.JSONSchemaPropsOrBool{ + Schema: &apiextv1.JSONSchemaProps{ + Type: "string", + }, + }, + }, + "deduplicate_heartbeat_logs": { + Type: "boolean", + }, + }, + }, }, }, "podAnnotations": { diff --git a/pkg/apis/cpo.opensource.cybertec.at/v1/postgresql_type.go b/pkg/apis/cpo.opensource.cybertec.at/v1/postgresql_type.go index 51387778..f5a4a987 100644 --- a/pkg/apis/cpo.opensource.cybertec.at/v1/postgresql_type.go +++ b/pkg/apis/cpo.opensource.cybertec.at/v1/postgresql_type.go @@ -182,6 +182,7 @@ type Patroni struct { SynchronousNodeCount uint32 `json:"synchronous_node_count,omitempty" defaults:"1"` Multisite *Multisite `json:"multisite,omitempty"` FailsafeMode *bool `json:"failsafe_mode,omitempty"` + Log *PatroniLog `json:"log,omitempty"` } // StandbyDescription contains remote primary config or s3/gs wal path @@ -342,3 +343,11 @@ type EtcdConfig struct { Protocol *string `json:"protocol,omitempty"` CertSecretName *string `json:"certSecretName,omitempty"` } + +type PatroniLog struct { + Type string `json:"type,omitempty"` + Level string `json:"level,omitempty"` + TracebackLevel string `json:"traceback_level,omitempty"` + StaticFields map[string]string `json:"static_fields,omitempty"` + DeduplicateHeartbeatLogs *bool `json:"deduplicate_heartbeat_logs,omitempty"` +} diff --git a/pkg/cluster/k8sres.go b/pkg/cluster/k8sres.go index cccc7ee3..d9543fd8 100644 --- a/pkg/cluster/k8sres.go +++ b/pkg/cluster/k8sres.go @@ -81,6 +81,7 @@ type pgBootstrap struct { type spiloConfiguration struct { PgLocalConfiguration map[string]interface{} `json:"postgresql"` Bootstrap pgBootstrap `json:"bootstrap"` + Log *spiloLogConfiguration `json:"log,omitempty"` } type TDEConfig struct { @@ -88,6 +89,14 @@ type TDEConfig struct { KeyBits string } +type spiloLogConfiguration struct { + Type string `json:"type,omitempty"` + Level string `json:"level,omitempty"` + TracebackLevel string `json:"traceback_level,omitempty"` + StaticFields map[string]string `json:"static_fields,omitempty"` + DeduplicateHeartbeatLogs *bool `json:"deduplicate_heartbeat_logs,omitempty"` +} + func (c *Cluster) statefulSetName() string { return c.Name } @@ -468,6 +477,26 @@ PatroniInitDBParams: config.PgLocalConfiguration[patroniPGHBAConfParameterName] = patroni.PgHba } + if patroni.Log != nil { + logConfig := &spiloLogConfiguration{} + if patroni.Log.Type != "" { + logConfig.Type = patroni.Log.Type + } + if patroni.Log.Level != "" { + logConfig.Level = patroni.Log.Level + } + if patroni.Log.TracebackLevel != "" { + logConfig.TracebackLevel = patroni.Log.TracebackLevel + } + if patroni.Log.StaticFields != nil { + logConfig.StaticFields = patroni.Log.StaticFields + } + if patroni.Log.DeduplicateHeartbeatLogs != nil { + logConfig.DeduplicateHeartbeatLogs = patroni.Log.DeduplicateHeartbeatLogs + } + config.Log = logConfig + } + res, err := json.Marshal(config) return string(res), err }