mirror of https://github.com/status-im/consul.git
feat: add access logging API to proxy defaults (#15780)
This commit is contained in:
parent
04bf24c8c1
commit
233dbcb67f
|
@ -1,6 +1,7 @@
|
|||
package structs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
|
@ -341,6 +342,7 @@ type ProxyConfigEntry struct {
|
|||
TransparentProxy TransparentProxyConfig `json:",omitempty" alias:"transparent_proxy"`
|
||||
MeshGateway MeshGatewayConfig `json:",omitempty" alias:"mesh_gateway"`
|
||||
Expose ExposeConfig `json:",omitempty"`
|
||||
AccessLogs AccessLogsConfig `json:",omitempty" alias:"access_logs"`
|
||||
|
||||
Meta map[string]string `json:",omitempty"`
|
||||
acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"`
|
||||
|
@ -395,6 +397,32 @@ func (e *ProxyConfigEntry) Validate() error {
|
|||
return fmt.Errorf("invalid name (%q), only %q is supported", e.Name, ProxyConfigGlobal)
|
||||
}
|
||||
|
||||
switch e.AccessLogs.Type {
|
||||
case "", StdErrLogSinkType, StdOutLogSinkType:
|
||||
// OK
|
||||
case FileLogSinkType:
|
||||
if e.AccessLogs.Path == "" {
|
||||
return errors.New("path must be specified when using file type access logs")
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("invalid access log type: %s", e.AccessLogs.Type)
|
||||
}
|
||||
|
||||
if e.AccessLogs.JSONFormat != "" && e.AccessLogs.TextFormat != "" {
|
||||
return errors.New("cannot specify both access log JSONFormat and TextFormat")
|
||||
}
|
||||
|
||||
if e.AccessLogs.Type != FileLogSinkType && e.AccessLogs.Path != "" {
|
||||
return errors.New("path is only valid for file type access logs")
|
||||
}
|
||||
|
||||
if e.AccessLogs.JSONFormat != "" {
|
||||
msg := json.RawMessage{}
|
||||
if err := json.Unmarshal([]byte(e.AccessLogs.JSONFormat), &msg); err != nil {
|
||||
return fmt.Errorf("invalid access log json for JSON format: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err := validateConfigEntryMeta(e.Meta); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -3030,6 +3030,57 @@ func TestProxyConfigEntry(t *testing.T) {
|
|||
EnterpriseMeta: *acl.DefaultEnterpriseMeta(),
|
||||
},
|
||||
},
|
||||
"proxy config has invalid access log type": {
|
||||
entry: &ProxyConfigEntry{
|
||||
Name: "global",
|
||||
AccessLogs: AccessLogsConfig{
|
||||
Enabled: true,
|
||||
Type: "stdin",
|
||||
},
|
||||
},
|
||||
validateErr: "invalid access log type: stdin",
|
||||
},
|
||||
"proxy config has invalid access log config - both text and json formats": {
|
||||
entry: &ProxyConfigEntry{
|
||||
Name: "global",
|
||||
AccessLogs: AccessLogsConfig{
|
||||
Enabled: true,
|
||||
JSONFormat: "[%START_TIME%]",
|
||||
TextFormat: "{\"start_time\": \"[%START_TIME%]\"}",
|
||||
},
|
||||
},
|
||||
validateErr: "cannot specify both access log JSONFormat and TextFormat",
|
||||
},
|
||||
"proxy config has invalid access log config - file path with wrong type": {
|
||||
entry: &ProxyConfigEntry{
|
||||
Name: "global",
|
||||
AccessLogs: AccessLogsConfig{
|
||||
Enabled: true,
|
||||
Path: "/tmp/logs.txt",
|
||||
},
|
||||
},
|
||||
validateErr: "path is only valid for file type access logs",
|
||||
},
|
||||
"proxy config has invalid access log config - no file path specified": {
|
||||
entry: &ProxyConfigEntry{
|
||||
Name: "global",
|
||||
AccessLogs: AccessLogsConfig{
|
||||
Enabled: true,
|
||||
Type: FileLogSinkType,
|
||||
},
|
||||
},
|
||||
validateErr: "path must be specified when using file type access logs",
|
||||
},
|
||||
"proxy config has invalid access log JSON format": {
|
||||
entry: &ProxyConfigEntry{
|
||||
Name: "global",
|
||||
AccessLogs: AccessLogsConfig{
|
||||
Enabled: true,
|
||||
JSONFormat: "{\"start_time\": \"[%START_TIME%]\"", // Missing trailing brace
|
||||
},
|
||||
},
|
||||
validateErr: "invalid access log json for JSON format",
|
||||
},
|
||||
}
|
||||
testConfigEntryNormalizeAndValidate(t, cases)
|
||||
}
|
||||
|
|
|
@ -36,6 +36,14 @@ const (
|
|||
MeshGatewayModeRemote MeshGatewayMode = "remote"
|
||||
)
|
||||
|
||||
type LogSinkType string
|
||||
|
||||
const (
|
||||
FileLogSinkType LogSinkType = "file"
|
||||
StdErrLogSinkType LogSinkType = "stderr"
|
||||
StdOutLogSinkType LogSinkType = "stdout"
|
||||
)
|
||||
|
||||
const (
|
||||
// TODO (freddy) Should we have a TopologySourceMixed when there is a mix of proxy reg and tproxy?
|
||||
// Currently we label as proxy-registration if ANY instance has the explicit upstream definition.
|
||||
|
@ -143,6 +151,46 @@ func (c *TransparentProxyConfig) IsZero() bool {
|
|||
return *c == zeroVal
|
||||
}
|
||||
|
||||
// AccessLogsConfig contains the associated default settings for all Envoy instances within the datacenter or partition
|
||||
type AccessLogsConfig struct {
|
||||
// Enabled turns off all access logging
|
||||
Enabled bool `json:",omitempty" alias:"enabled"`
|
||||
|
||||
// DisableListenerLogs turns off just listener logs for connections rejected by Envoy because they don't
|
||||
// have a matching listener filter.
|
||||
DisableListenerLogs bool `json:",omitempty" alias:"disable_listener_logs"`
|
||||
|
||||
// Type selects the output for logs: "file", "stderr". "stdout"
|
||||
Type LogSinkType `json:",omitempty" alias:"type"`
|
||||
|
||||
// Path is the output file to write logs
|
||||
Path string `json:",omitempty" alias:"path"`
|
||||
|
||||
// The presence of one format string or the other implies the access log string encoding.
|
||||
// Defining Both is invalid.
|
||||
JSONFormat string `json:",omitempty" alias:"json_format"`
|
||||
TextFormat string `json:",omitempty" alias:"text_format"`
|
||||
}
|
||||
|
||||
func (c AccessLogsConfig) ToAPI() *api.AccessLogsConfig {
|
||||
if c.IsZero() {
|
||||
return nil
|
||||
}
|
||||
return &api.AccessLogsConfig{
|
||||
Enabled: c.Enabled,
|
||||
DisableListenerLogs: c.DisableListenerLogs,
|
||||
Type: api.LogSinkType(c.Type),
|
||||
Path: c.Path,
|
||||
JSONFormat: c.JSONFormat,
|
||||
TextFormat: c.TextFormat,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *AccessLogsConfig) IsZero() bool {
|
||||
zeroVal := AccessLogsConfig{}
|
||||
return *c == zeroVal
|
||||
}
|
||||
|
||||
// ConnectProxyConfig describes the configuration needed for any proxy managed
|
||||
// or unmanaged. It describes a single logical service's listener and optionally
|
||||
// upstreams and sidecar-related config for a single instance. To describe a
|
||||
|
|
|
@ -122,6 +122,35 @@ type ExposePath struct {
|
|||
ParsedFromCheck bool
|
||||
}
|
||||
|
||||
type LogSinkType string
|
||||
|
||||
const (
|
||||
FileLogSinkType LogSinkType = "file"
|
||||
StdErrLogSinkType LogSinkType = "stderr"
|
||||
StdOutLogSinkType LogSinkType = "stdout"
|
||||
)
|
||||
|
||||
// AccessLogsConfig contains the associated default settings for all Envoy instances within the datacenter or partition
|
||||
type AccessLogsConfig struct {
|
||||
// Enabled turns off all access logging
|
||||
Enabled bool `json:",omitempty" alias:"enabled"`
|
||||
|
||||
// DisableListenerLogs turns off just listener logs for connections rejected by Envoy because they don't
|
||||
// have a matching listener filter.
|
||||
DisableListenerLogs bool `json:",omitempty" alias:"disable_listener_logs"`
|
||||
|
||||
// Type selects the output for logs: "file", "stderr". "stdout"
|
||||
Type LogSinkType `json:",omitempty" alias:"type"`
|
||||
|
||||
// Path is the output file to write logs
|
||||
Path string `json:",omitempty" alias:"path"`
|
||||
|
||||
// The presence of one format string or the other implies the access log string encoding.
|
||||
// Defining Both is invalid.
|
||||
JSONFormat string `json:",omitempty" alias:"json_format"`
|
||||
TextFormat string `json:",omitempty" alias:"text_format"`
|
||||
}
|
||||
|
||||
type UpstreamConfiguration struct {
|
||||
// Overrides is a slice of per-service configuration. The name field is
|
||||
// required.
|
||||
|
@ -266,6 +295,7 @@ type ProxyConfigEntry struct {
|
|||
Config map[string]interface{} `json:",omitempty"`
|
||||
MeshGateway MeshGatewayConfig `json:",omitempty" alias:"mesh_gateway"`
|
||||
Expose ExposeConfig `json:",omitempty"`
|
||||
AccessLogs AccessLogsConfig `json:",omitempty"`
|
||||
|
||||
Meta map[string]string `json:",omitempty"`
|
||||
CreateIndex uint64
|
||||
|
|
|
@ -401,6 +401,13 @@ func TestDecodeConfigEntry(t *testing.T) {
|
|||
"TransparentProxy": {
|
||||
"OutboundListenerPort": 808,
|
||||
"DialedDirectly": true
|
||||
},
|
||||
"AccessLogs": {
|
||||
"Enabled": true,
|
||||
"DisableListenerLogs": true,
|
||||
"Type": "file",
|
||||
"Path": "/tmp/logs.txt",
|
||||
"TextFormat": "[%START_TIME%]"
|
||||
}
|
||||
}
|
||||
`,
|
||||
|
@ -426,6 +433,13 @@ func TestDecodeConfigEntry(t *testing.T) {
|
|||
OutboundListenerPort: 808,
|
||||
DialedDirectly: true,
|
||||
},
|
||||
AccessLogs: AccessLogsConfig{
|
||||
Enabled: true,
|
||||
DisableListenerLogs: true,
|
||||
Type: FileLogSinkType,
|
||||
Path: "/tmp/logs.txt",
|
||||
TextFormat: "[%START_TIME%]",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue