@ -1,6 +1,6 @@
syntax = "proto3" ;
syntax = "proto3" ;
package envoy . extensions . filters.http.proto_message_logging .v3 ;
package envoy . extensions . filters.http.proto_message_extraction .v3 ;
import "envoy/config/core/v3/base.proto" ;
import "envoy/config/core/v3/base.proto" ;
@ -8,33 +8,39 @@ import "xds/annotations/v3/status.proto";
import "udpa/annotations/status.proto" ;
import "udpa/annotations/status.proto" ;
option java_package = "io.envoyproxy.envoy.extensions.filters.http.proto_message_logging .v3" ;
option java_package = "io.envoyproxy.envoy.extensions.filters.http.proto_message_extraction .v3" ;
option java_outer_classname = "ConfigProto" ;
option java_outer_classname = "ConfigProto" ;
option java_multiple_files = true ;
option java_multiple_files = true ;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/proto_message_logging/v3;proto_message_logging v3" ;
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/filters/http/proto_message_extraction/v3;proto_message_extraction v3" ;
option ( udpa.annotations.file_status ) . package_version_status = ACTIVE ;
option ( udpa.annotations.file_status ) . package_version_status = ACTIVE ;
option ( xds.annotations.v3.file_status ) . work_in_progress = true ;
option ( xds.annotations.v3.file_status ) . work_in_progress = true ;
/ / [ # not - implemented - hide : ]
/ / [ # protodoc - title : Proto Message Extraction ]
/ / [ # protodoc - title : Proto Message Logging ]
/ / Proto Message Logging : ref : ` configuration overview
/ / < config_http_filters_proto_message_logging > ` .
/ / [ # extension : envoy.filters.http.proto_message_logging ]
/ /
/ /
/ / ProtoMessageLogging filter supports logging scrubbed gRPC requests / responses ( proto messages )
/ / [ # extension : envoy.filters.http.proto_message_extraction ]
/ / as google.protobuf.Struct and storing results
/ /
/ / in the dynamic metadata ` envoy.filters.http.proto_message_logging ` for later access.
/ / Overview
/ / - - - - - - - -
/ /
/ / ProtoMessageExtraction filter supports extracting gRPC
/ / requests / responses ( proto messages ) into google.protobuf.Struct and storing
/ / results in the dynamic metadata ` envoy.filters.http.proto_message_extraction `
/ / for later access.
/ /
/ / Assumptions
/ / - - - - - - - - - - -
/ /
/ /
/ / # Assumptions
/ / This filter assumes it is only applicable for gRPC with Protobuf as payload.
/ / This filter assumes it is only applicable for gRPC with Protobuf as payload.
/ /
/ /
/ / # Process Flow
/ / Process Flow
/ / - - - - - - - - - - - -
/ /
/ / On the request path , it will check
/ / On the request path , it will check
/ /
/ /
/ / 1. if the incoming gRPC request is configured , the filter tries to :
/ / 1. if the incoming gRPC request is configured , the filter tries to :
/ /
/ /
/ / a. buffer the incoming data to complete protobuf messages
/ / a. buffer the incoming data to complete protobuf messages
/ / b. log individual protobuf messages according to directives
/ / b. extract individual protobuf messages according to directives
/ / c. write the result into the dynamic metadata.
/ / c. write the result into the dynamic metadata.
/ / d. pass through the request data
/ / d. pass through the request data
/ /
/ /
@ -45,50 +51,57 @@ option (xds.annotations.v3.file_status).work_in_progress = true;
/ / 1. if the incoming gRPC request is configured , the filter tries to :
/ / 1. if the incoming gRPC request is configured , the filter tries to :
/ /
/ /
/ / a. buffer the incoming data to complete protobuf messages
/ / a. buffer the incoming data to complete protobuf messages
/ / b. log individual protobuf messages according to directives
/ / b. extract individual protobuf messages according to directives
/ / c. write the result into the dynamic metadata.
/ / c. write the result into the dynamic metadata.
/ / d. pass through the response data
/ / d. pass through the response data
/ /
/ /
/ / 2. otherwise , pass through the response.
/ / 2. otherwise , pass through the response.
/ /
/ /
/ / # Config Requirements
/ / Config Requirements
/ / - - - - - - - - - - - - - - - - - - -
/ / Here are config requirements
/ / Here are config requirements
/ /
/ / 1. the log target field should be among the following primitive types : ` string ` , ` uint32 ` , ` uint64 ` , ` int32 ` , ` int64 ` , ` sint32 ` , ` sint64 ` , ` fixed32 ` , ` fixed64 ` , ` sfixed32 ` , ` sfixed64 ` , ` float ` , ` double ` .
/ / 1. the extracted target field should be among the following primitive types :
/ /
/ / ` string ` , ` uint32 ` , ` uint64 ` , ` int32 ` , ` int64 ` , ` sint32 ` , ` sint64 ` ,
/ / ` fixed32 ` , ` fixed64 ` , ` sfixed32 ` , ` sfixed64 ` , ` float ` , ` double ` .
/ / 2. the target field could be repeated .
/ / 2. the target field could be repeated .
/ /
/ / 3. the intermediate type could also be repeated .
/ / 3. the intermediate type could also be repeated .
/ /
/ / # Output Format
/ / Output Format
/ / The logged requests and responses will be will be added in the dynamic ` ` metadata < google.protobuf.Struct > ` ` with the same layout of the message.
/ / - - - - - - - - - - - - -
/ /
/ / The extracted requests and responses will be will be added in the dynamic
/ / ` ` metadata < google.protobuf.Struct > ` ` with the same layout of the message.
/ / For the default ` FIRST_AND_LAST ` mode , it will be like :
/ / For the default ` FIRST_AND_LAST ` mode , it will be like :
/ / . . code - block : : json
/ / {
/ / {
/ / "requests" : {
/ / "requests" : {
/ / "first" : {
/ / "first" : {
/ / "foo" : "val_foo1" ,
/ / "foo" : "val_foo1" ,
/ / . . .
/ / }
/ / }
/ / "last" : {
/ / "last" : {
/ / "foo" : "val_foo3" ,
/ / "foo" : "val_foo3" ,
/ / . . .
/ / }
/ / }
/ / } ,
/ / } ,
/ / "responses" : {
/ / "responses" : {
/ / "first" : {
/ / "first" : {
/ / "baz" : "val_baz1" ,
/ / "baz" : "val_baz1" ,
/ / . . .
/ / }
/ / }
/ / "last" : {
/ / "last" : {
/ / "baz" : "val_foo3" ,
/ / "baz" : "val_foo3" ,
/ / . . .
/ / }
/ / }
/ / }
/ / }
/ / }
/ / }
/ / Example for ` FIRST_AND_LAST ` mode
/ / - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/ /
/ /
/ /
/ / # Example for ` FIRST_AND_LAST ` mode
/ / Let ' s say we have the following definition for the bi - streaming request
/ / Let ' s say we have the following definition for the bi - streaming request
/ / ` pkg.svc.Method ` .
/ / ` pkg.svc.Method ` .
/ /
/ /
@ -111,7 +124,7 @@ option (xds.annotations.v3.file_status).work_in_progress = true;
/ /
/ /
/ / message Msg {
/ / message Msg {
/ / string bar = 1 ;
/ / string bar = 1 ;
/ / string not_logg ed = 2 ;
/ / string not_extract ed = 2 ;
/ / }
/ / }
/ /
/ /
/ / This is the filter config in JSON.
/ / This is the filter config in JSON.
@ -121,15 +134,15 @@ option (xds.annotations.v3.file_status).work_in_progress = true;
/ / {
/ / {
/ / "descriptor_set" : { } ,
/ / "descriptor_set" : { } ,
/ / "mode" : "FIRST_AND_LAST" ,
/ / "mode" : "FIRST_AND_LAST" ,
/ / "logging _by_method" : {
/ / "extraction _by_method" : {
/ / "pkg.svc.Method" : {
/ / "pkg.svc.Method" : {
/ / "request_logging _by_field" : {
/ / "request_extraction _by_field" : {
/ / "foo" : "LOG " ,
/ / "foo" : "EXTRACT " ,
/ / "nested.doubled_nested.bar" : "LOG " ,
/ / "nested.doubled_nested.bar" : "EXTRACT " ,
/ / "redacted" : "LOG _REDACT"
/ / "redacted" : "EXTRACT _REDACT"
/ / } ,
/ / } ,
/ / "response_logging _by_field" : {
/ / "response_extraction _by_field" : {
/ / "bar" : "LOG " ,
/ / "bar" : "EXTRACT " ,
/ / }
/ / }
/ / }
/ / }
/ / }
/ / }
@ -142,18 +155,18 @@ option (xds.annotations.v3.file_status).work_in_progress = true;
/ /
/ /
/ / {
/ / {
/ / "foo" : "val_foo1" ,
/ / "foo" : "val_foo1" ,
/ / "nested" : { "double_nested" : { "bar" : "val_bar1" , "not_logged" : "val_not_logged1" } ,
/ / "nested" : { "double_nested" : { "bar" : "val_bar1" , "not_extracted" :
/ / "redacted" : { "bar" : "val_redacted_bar1" }
/ / "val_not_extracted1" } , " redacted" : { "bar" : "val_redacted_bar1" }
/ / }
/ / }
/ / {
/ / {
/ / "foo" : "val_foo2" ,
/ / "foo" : "val_foo2" ,
/ / "nested" : { "double_nested" : { "bar" : "val_bar2" , "not_logged" : "val_not_logged2" } ,
/ / "nested" : { "double_nested" : { "bar" : "val_bar2" , "not_extracted" :
/ / "redacted" : { "bar" : "val_redacted_bar2" }
/ / "val_not_extracted2" } , " redacted" : { "bar" : "val_redacted_bar2" }
/ / }
/ / }
/ / {
/ / {
/ / "foo" : "val_foo3" ,
/ / "foo" : "val_foo3" ,
/ / "nested" : { "double_nested" : { "bar" : "val_bar3" , "not_logged" : "val_not_logged3" } ,
/ / "nested" : { "double_nested" : { "bar" : "val_bar3" , "not_extracted" :
/ / "redacted" : { "bar" : "val_redacted_bar3" }
/ / "val_not_extracted3" } , " redacted" : { "bar" : "val_redacted_bar3" }
/ / }
/ / }
/ /
/ /
/ / the filter receives the following ` MethodResponse ` message in
/ / the filter receives the following ` MethodResponse ` message in
@ -172,7 +185,7 @@ option (xds.annotations.v3.file_status).work_in_progress = true;
/ / }
/ / }
/ /
/ /
/ / The filter will write the following dynamic
/ / The filter will write the following dynamic
/ / metadata ( ` envoy.filters.http.proto_message_logging ` ) in JSON.
/ / metadata ( ` envoy.filters.http.proto_message_extraction ` ) in JSON.
/ /
/ /
/ / . . code - block : : json
/ / . . code - block : : json
/ /
/ /
@ -199,11 +212,11 @@ option (xds.annotations.v3.file_status).work_in_progress = true;
/ / }
/ / }
/ / }
/ / }
message ProtoMessageLogging Config {
message ProtoMessageExtraction Config {
enum Log Mode {
enum Extract Mode {
Log Mode_UNSPECIFIED = 0 ;
Extract Mode_UNSPECIFIED = 0 ;
/ / The filter will log the first and the last message for
/ / The filter will extract the first and the last message for
/ / for streaming cases , containing
/ / for streaming cases , containing
/ / client - side streaming , server - side streaming or bi - directional streaming.
/ / client - side streaming , server - side streaming or bi - directional streaming.
FIRST_AND_LAST = 1 ;
FIRST_AND_LAST = 1 ;
@ -216,40 +229,41 @@ message ProtoMessageLoggingConfig {
config.core.v3.DataSource data_source = 1 ;
config.core.v3.DataSource data_source = 1 ;
/ / Unimplemented , the key of proto descriptor TypedMetadata.
/ / Unimplemented , the key of proto descriptor TypedMetadata.
/ / Among filters depending on the proto descriptor , we can have a TypedMetadata
/ / Among filters depending on the proto descriptor , we can have a
/ / for proto descriptors , so that these filters can share one copy of proto
/ / TypedMetadata for proto descriptors , so that these filters can share one
/ / descriptor in memory.
/ / copy of proto descriptor in memory.
string proto_descriptor_typed_metadata = 2 ;
string proto_descriptor_typed_metadata = 2 ;
}
}
Log Mode mode = 3 ;
Extract Mode mode = 3 ;
/ / Specify the message logging info.
/ / Specify the message extraction info.
/ / The key is the fully qualified gRPC method name.
/ / The key is the fully qualified gRPC method name.
/ / ` ` $ { package } . $ { Service } . $ { Method } ` ` , like
/ / ` ` $ { package } . $ { Service } . $ { Method } ` ` , like
/ / ` ` endpoints.examples.bookstore.BookStore.GetShelf ` `
/ / ` ` endpoints.examples.bookstore.BookStore.GetShelf ` `
/ /
/ /
/ / The value is the message logging information for individual gRPC methods.
/ / The value is the message extraction information for individual gRPC
map < string , MethodLogging > logging_by_method = 4 ;
/ / methods.
map < string , MethodExtraction > extraction_by_method = 4 ;
}
}
/ / This message can be used to support per route config approach later even
/ / This message can be used to support per route config approach later even
/ / though the Istio doesn ' t support that so far.
/ / though the Istio doesn ' t support that so far.
message MethodLogging {
message MethodExtraction {
enum Log Directive {
enum Extract Directive {
Log Directive_UNSPECIFIED = 0 ;
Extract Directive_UNSPECIFIED = 0 ;
/ / The value of this field will be logg ed.
/ / The value of this field will be extract ed.
LOG = 1 ;
EXTRACT = 1 ;
/ / It should be only annotated on Message type fields so if the field isn ' t
/ / It should be only annotated on Message type fields so if the field isn ' t
/ / empty , an empty Struct will be logg ed.
/ / empty , an empty Struct will be extract ed.
LOG _REDACT = 2 ;
EXTRACT _REDACT = 2 ;
}
}
/ / The mapping of field path to its Log Directive for request messages
/ / The mapping of field path to its Extract Directive for request messages
map < string , LogDirective > request_logging _by_field = 2 ;
map < string , ExtractDirective > request_extraction _by_field = 2 ;
/ / The mapping of field path to its Log Directive for response messages
/ / The mapping of field path to its Extract Directive for response messages
map < string , LogDirective > response_logging _by_field = 3 ;
map < string , ExtractDirective > response_extraction _by_field = 3 ;
}
}