-
Notifications
You must be signed in to change notification settings - Fork 257
/
loggingCollector.go
126 lines (112 loc) · 4.8 KB
/
loggingCollector.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/*
Copyright The CloudNativePG Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package logpipe
import (
"fmt"
)
// FieldsPerRecord12 is the number of fields in a CSV log line
// in PostgreSQL 12 or below
const FieldsPerRecord12 int = 23
// FieldsPerRecord13 is the number of fields in a CSV log line
// since PostgreSQL 13
const FieldsPerRecord13 int = 24
// FieldsPerRecord14 is the number of fields in a CSV log line
// since PostgreSQL 14
const FieldsPerRecord14 int = 26
// LoggingCollectorRecordName is the value of the logger field for logging_collector
const LoggingCollectorRecordName = "postgres"
// LogFieldValidator checks if the provided number of fields is valid or not for logging_collector logs
func LogFieldValidator(fields int) *ErrFieldCountExtended {
if fields != FieldsPerRecord12 && fields != FieldsPerRecord13 && fields != FieldsPerRecord14 {
// If the number of fields is not recognised return an error
return &ErrFieldCountExtended{
Err: fmt.Errorf("invalid number of fields opening logging_collector CSV log stream"),
}
}
return nil
}
// LoggingRecord is used to store all the fields of the logging_collector CSV format
type LoggingRecord struct {
LogTime string `json:"log_time,omitempty"`
Username string `json:"user_name,omitempty"`
DatabaseName string `json:"database_name,omitempty"`
ProcessID string `json:"process_id,omitempty"`
ConnectionFrom string `json:"connection_from,omitempty"`
SessionID string `json:"session_id,omitempty"`
SessionLineNum string `json:"session_line_num,omitempty"`
CommandTag string `json:"command_tag,omitempty"`
SessionStartTime string `json:"session_start_time,omitempty"`
VirtualTransactionID string `json:"virtual_transaction_id,omitempty"`
TransactionID string `json:"transaction_id,omitempty"`
ErrorSeverity string `json:"error_severity,omitempty"`
SQLStateCode string `json:"sql_state_code,omitempty"`
Message string `json:"message,omitempty"`
Detail string `json:"detail,omitempty"`
Hint string `json:"hint,omitempty"`
InternalQuery string `json:"internal_query,omitempty"`
InternalQueryPos string `json:"internal_query_pos,omitempty"`
Context string `json:"context,omitempty"`
Query string `json:"query,omitempty"`
QueryPos string `json:"query_pos,omitempty"`
Location string `json:"location,omitempty"`
ApplicationName string `json:"application_name,omitempty"`
BackendType string `json:"backend_type,omitempty"`
LeaderPid string `json:"leader_pid,omitempty"`
QueryID string `json:"query_id,omitempty"`
}
// FromCSV stores inside the record structure the relative fields
// of the CSV log record.
//
// See https://www.postgresql.org/docs/current/runtime-config-logging.html
// section "19.8.4. Using CSV-Format Log Output".
func (r *LoggingRecord) FromCSV(content []string) NamedRecord {
r.LogTime = content[0]
r.Username = content[1]
r.DatabaseName = content[2]
r.ProcessID = content[3] // integer
r.ConnectionFrom = content[4]
r.SessionID = content[5]
r.SessionLineNum = content[6] // bigint
r.CommandTag = content[7]
r.SessionStartTime = content[8]
r.VirtualTransactionID = content[9]
r.TransactionID = content[10] // bigint
r.ErrorSeverity = content[11]
r.SQLStateCode = content[12]
r.Message = content[13]
r.Detail = content[14]
r.Hint = content[15]
r.InternalQuery = content[16]
r.InternalQueryPos = content[17] // integer
r.Context = content[18]
r.Query = content[19]
r.QueryPos = content[20] // integer
r.Location = content[21]
r.ApplicationName = content[22]
// Starting from PostgreSQL 13, there is also the BackendType field.
// See https://www.postgresql.org/docs/13/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-CSVLOG
if len(content) >= FieldsPerRecord13 {
r.BackendType = content[23]
}
// Starting from PostgreSQL 14, there are also the LeaderPid and the QueryID fields.
// See https://www.postgresql.org/docs/14/runtime-config-logging.html#RUNTIME-CONFIG-LOGGING-CSVLOG
if len(content) == FieldsPerRecord14 {
r.LeaderPid = content[24]
r.QueryID = content[25]
}
return r
}
// GetName implements the NamedRecord interface
func (r *LoggingRecord) GetName() string {
return LoggingCollectorRecordName
}