Envoy Remote Access Log Collector

Gokhan Karadas
2 min readApr 17, 2021

--

Envoy proxy logs contain some information about our request that’s is useful for debugging and troubleshooting. Envoy proxies print access info to stdout.

- Enable Envoy’s access logging with istio

You can also choose between JSON and text by setting accessLogEncoding to JSON or TEXT.

You may also want to customize the format of the access log by editing accessLogFormat.

spec:
meshConfig:
accessLogFile: /dev/stdout
accessLogEncoding: JSON

- Enable per workload access log

Use EnvoyFilter to modify values for certain fields, add specific filters, or even add entirely new listeners, clusters, etc.

apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: searchapi-access-log
spec:
workloadSelector:
labels:
app: search-api
configPatches:
- applyTo: NETWORK_FILTER
match:
context: ANY
listener:
filterChain:
filter:
name: "envoy.http_connection_manager"
patch:
operation: MERGE
value:
typed_config:
"@type": "type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager"
access_log:
- name: envoy.file_access_log
config:
path: /dev/stdout
jsonFormat:
authority: "%REQ(:AUTHORITY)%"
path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
protocol: "%PROTOCOL%"
response_code: "%RESPONSE_CODE%"
response_flags: "%RESPONSE_FLAGS%"
route_name: "%ROUTE_NAME%"
upstream_host: "%UPSTREAM_HOST%"
user_agent: "%REQ(USER-AGENT)%"
x_agent_name: "%REQ(X-AGENTNAME)%"
x_forwarded_for: "%REQ(X-FORWARDED-FOR)%"

How do we send to access log remote service?

We need to build a grpc server. with an endpoint that responds to AccessLogService_StreamAccessLogsServer. Envoy then will connect to it to send the logs. At his point envoyproxy go-control-plane help us to build our remote access log service.

Register our grpc server to Envoy. Envoy will connect and send StreamAccessLogsMessage messages forever. And transform HTTP or TCP logs to our current model.

grpcServer := grpc.NewServer()
//Acl log
v2.RegisterAccessLogServiceServer(grpcServer, converter.New())

We listen to grpc access log stream forever.

func (s *server) StreamAccessLogs(stream v2.AccessLogService_StreamAccessLogsServer) error {
for {
in, err := stream.Recv()
if err == io.EOF {
return nil
}
if err != nil {
return err
}
logEntries := transform(in.GetHttpLogs())
for _, logEntry := range logEntries {
var data []byte
data, err = json.Marshal(logEntry)
fmt.Println(string(data))
}
}
}

We need to configure istio control plane for sending access log to our collector.

data:
mesh: |-
accessLogEncoding: JSON
accessLogFile: ""
accessLogFormat: ""
connectTimeout: 15s
enableEnvoyAccessLogService: true
defaultConfig:
envoyAccessLogService:
address: envoy-accesslog-collector.platform:9001

enableEnvoyAccessLogService: This flag enables Envoy’s gRPC Access Log Service.

envoyAccessLogService.address: Address of the service to which access logs from Envoys should be sent.

2021-04-17T09:29:51.252863378Z {"timestamp":"","traceId":"6e3ead4b-3de3-4633-99ad-c961a00c74fa","method":"GET","protocol":"HTTP11","scheme":"","statusCode":503,"domain":"search","path":"/available-indexes","userAgent":"Apache-HttpClient/4.5.10 (Java/1.8.0_222)","referer":"","forwardedFor":"x","upsteamFailure":"","upstreamCluster":"","downstreamDirectRemoteAddress":{"address":"x","port":21288},"downstreamRemoteAddress":{"address":"x","port":21288},"downstreamLocalAddress":{"address":"x","port":8080},"upstreamRemoteAddress":{"address":"","port":0},"upstreamLocalAddress":{"address":"","port":0},"time_ms":0,"request":{"headersBytes":1498,"bodyBytes":0,"remoteIP":"x"},"response":{"details":"no_healthy_upstream","headersBytes":113,"bodyBytes":19}}

See full code in here.

References:

--

--

Responses (1)