syntax = "proto3"; package envoy.config.tap.v3; import "envoy/config/common/matcher/v3/matcher.proto"; import "envoy/config/core/v3/base.proto"; import "envoy/config/core/v3/grpc_service.proto"; import "envoy/config/route/v3/route_components.proto"; import "google/protobuf/duration.proto"; import "google/protobuf/wrappers.proto"; import "envoy/annotations/deprecation.proto"; import "udpa/annotations/status.proto"; import "udpa/annotations/versioning.proto"; import "validate/validate.proto"; option java_package = "io.envoyproxy.envoy.config.tap.v3"; option java_outer_classname = "CommonProto"; option java_multiple_files = true; option go_package = "github.com/envoyproxy/go-control-plane/envoy/config/tap/v3;tapv3"; option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#protodoc-title: Tap common configuration] // Tap configuration. message TapConfig { // [#comment:TODO(mattklein123): Rate limiting] option (udpa.annotations.versioning).previous_message_type = "envoy.service.tap.v2alpha.TapConfig"; // The match configuration. If the configuration matches the data source being tapped, a tap will // occur, with the result written to the configured output. // Exactly one of :ref:`match ` and // :ref:`match_config ` must be set. If both // are set, the :ref:`match ` will be used. MatchPredicate match_config = 1 [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; // The match configuration. If the configuration matches the data source being tapped, a tap will // occur, with the result written to the configured output. // Exactly one of :ref:`match ` and // :ref:`match_config ` must be set. If both // are set, the :ref:`match ` will be used. common.matcher.v3.MatchPredicate match = 4; // The tap output configuration. If a match configuration matches a data source being tapped, // a tap will occur and the data will be written to the configured output. OutputConfig output_config = 2 [(validate.rules).message = {required: true}]; // [#not-implemented-hide:] Specify if Tap matching is enabled. The % of requests\connections for // which the tap matching is enabled. When not enabled, the request\connection will not be // recorded. // // .. note:: // // This field defaults to 100/:ref:`HUNDRED // `. core.v3.RuntimeFractionalPercent tap_enabled = 3; } // Tap match configuration. This is a recursive structure which allows complex nested match // configurations to be built using various logical operators. // [#next-free-field: 11] message MatchPredicate { option (udpa.annotations.versioning).previous_message_type = "envoy.service.tap.v2alpha.MatchPredicate"; // A set of match configurations used for logical operations. message MatchSet { option (udpa.annotations.versioning).previous_message_type = "envoy.service.tap.v2alpha.MatchPredicate.MatchSet"; // The list of rules that make up the set. repeated MatchPredicate rules = 1 [(validate.rules).repeated = {min_items: 2}]; } oneof rule { option (validate.required) = true; // A set that describes a logical OR. If any member of the set matches, the match configuration // matches. MatchSet or_match = 1; // A set that describes a logical AND. If all members of the set match, the match configuration // matches. MatchSet and_match = 2; // A negation match. The match configuration will match if the negated match condition matches. MatchPredicate not_match = 3; // The match configuration will always match. bool any_match = 4 [(validate.rules).bool = {const: true}]; // HTTP request headers match configuration. HttpHeadersMatch http_request_headers_match = 5; // HTTP request trailers match configuration. HttpHeadersMatch http_request_trailers_match = 6; // HTTP response headers match configuration. HttpHeadersMatch http_response_headers_match = 7; // HTTP response trailers match configuration. HttpHeadersMatch http_response_trailers_match = 8; // HTTP request generic body match configuration. HttpGenericBodyMatch http_request_generic_body_match = 9; // HTTP response generic body match configuration. HttpGenericBodyMatch http_response_generic_body_match = 10; } } // HTTP headers match configuration. message HttpHeadersMatch { option (udpa.annotations.versioning).previous_message_type = "envoy.service.tap.v2alpha.HttpHeadersMatch"; // HTTP headers to match. repeated route.v3.HeaderMatcher headers = 1; } // HTTP generic body match configuration. // List of text strings and hex strings to be located in HTTP body. // All specified strings must be found in the HTTP body for positive match. // The search may be limited to specified number of bytes from the body start. // // .. attention:: // // Searching for patterns in HTTP body is potentially cpu intensive. For each specified pattern, http body is scanned byte by byte to find a match. // If multiple patterns are specified, the process is repeated for each pattern. If location of a pattern is known, ``bytes_limit`` should be specified // to scan only part of the http body. message HttpGenericBodyMatch { message GenericTextMatch { oneof rule { option (validate.required) = true; // Text string to be located in HTTP body. string string_match = 1 [(validate.rules).string = {min_len: 1}]; // Sequence of bytes to be located in HTTP body. bytes binary_match = 2 [(validate.rules).bytes = {min_len: 1}]; } } // Limits search to specified number of bytes - default zero (no limit - match entire captured buffer). uint32 bytes_limit = 1; // List of patterns to match. repeated GenericTextMatch patterns = 2 [(validate.rules).repeated = {min_items: 1}]; } // Tap output configuration. message OutputConfig { option (udpa.annotations.versioning).previous_message_type = "envoy.service.tap.v2alpha.OutputConfig"; // Output sinks for tap data. Currently a single sink is allowed in the list. Once multiple // sink types are supported this constraint will be relaxed. repeated OutputSink sinks = 1 [(validate.rules).repeated = {min_items: 1 max_items: 1}]; // For buffered tapping, the maximum amount of received body that will be buffered prior to // truncation. If truncation occurs, the :ref:`truncated // ` field will be set. If not specified, the // default is 1KiB. google.protobuf.UInt32Value max_buffered_rx_bytes = 2; // For buffered tapping, the maximum amount of transmitted body that will be buffered prior to // truncation. If truncation occurs, the :ref:`truncated // ` field will be set. If not specified, the // default is 1KiB. google.protobuf.UInt32Value max_buffered_tx_bytes = 3; // Indicates whether taps produce a single buffered message per tap, or multiple streamed // messages per tap in the emitted :ref:`TraceWrapper // ` messages. Note that streamed tapping does not // mean that no buffering takes place. Buffering may be required if data is processed before a // match can be determined. See the HTTP tap filter :ref:`streaming // ` documentation for more information. bool streaming = 4; } // Tap output sink configuration. // [#next-free-field: 6] message OutputSink { option (udpa.annotations.versioning).previous_message_type = "envoy.service.tap.v2alpha.OutputSink"; // Output format. All output is in the form of one or more :ref:`TraceWrapper // ` messages. This enumeration indicates // how those messages are written. Note that not all sinks support all output formats. See // individual sink documentation for more information. enum Format { // Each message will be written as JSON. Any :ref:`body ` // data will be present in the :ref:`as_bytes // ` field. This means that body data will be // base64 encoded as per the `proto3 JSON mappings // `_. JSON_BODY_AS_BYTES = 0; // Each message will be written as JSON. Any :ref:`body ` // data will be present in the :ref:`as_string // ` field. This means that body data will be // string encoded as per the `proto3 JSON mappings // `_. This format type is // useful when it is known that that body is human readable (e.g., JSON over HTTP) and the // user wishes to view it directly without being forced to base64 decode the body. JSON_BODY_AS_STRING = 1; // Binary proto format. Note that binary proto is not self-delimiting. If a sink writes // multiple binary messages without any length information the data stream will not be // useful. However, for certain sinks that are self-delimiting (e.g., one message per file) // this output format makes consumption simpler. PROTO_BINARY = 2; // Messages are written as a sequence tuples, where each tuple is the message length encoded // as a `protobuf 32-bit varint // `_ // followed by the binary message. The messages can be read back using the language specific // protobuf coded stream implementation to obtain the message length and the message. PROTO_BINARY_LENGTH_DELIMITED = 3; // Text proto format. PROTO_TEXT = 4; } // Sink output format. Format format = 1 [(validate.rules).enum = {defined_only: true}]; oneof output_sink_type { option (validate.required) = true; // Tap output will be streamed out the :http:post:`/tap` admin endpoint. // // .. attention:: // // It is only allowed to specify the streaming admin output sink if the tap is being // configured from the :http:post:`/tap` admin endpoint. Thus, if an extension has // been configured to receive tap configuration from some other source (e.g., static // file, XDS, etc.) configuring the streaming admin output type will fail. StreamingAdminSink streaming_admin = 2; // Tap output will be written to a file per tap sink. FilePerTapSink file_per_tap = 3; // [#not-implemented-hide:] // GrpcService to stream data to. The format argument must be PROTO_BINARY. // [#comment: TODO(samflattery): remove cleanup in uber_per_filter.cc once implemented] StreamingGrpcSink streaming_grpc = 4; // Tap output will be buffered in a single block before flushing to the :http:post:`/tap` admin endpoint // // .. attention:: // // It is only allowed to specify the buffered admin output sink if the tap is being // configured from the :http:post:`/tap` admin endpoint. Thus, if an extension has // been configured to receive tap configuration from some other source (e.g., static // file, XDS, etc.) configuring the buffered admin output type will fail. BufferedAdminSink buffered_admin = 5; } } // Streaming admin sink configuration. message StreamingAdminSink { option (udpa.annotations.versioning).previous_message_type = "envoy.service.tap.v2alpha.StreamingAdminSink"; } // BufferedAdminSink configures a tap output to collect traces without returning them until // one of multiple criteria are satisfied. // Similar to StreamingAdminSink, it is only allowed to specify the buffered admin output // sink if the tap is being configured from the ``/tap`` admin endpoint. message BufferedAdminSink { // Stop collecting traces when the specified number are collected. // If other criteria for ending collection are reached first, this value will not be used. uint64 max_traces = 1 [(validate.rules).uint64 = {gt: 0}]; // Acts as a fallback to prevent the client from waiting for long periods of time. // After timeout has occurred, a buffer flush will be triggered, returning the traces buffered so far. // This may result in returning fewer traces than were requested, and in the case that no traces are // buffered during this time, no traces will be returned. // Specifying 0 for the timeout value (or not specifying a value at all) indicates an infinite timeout. google.protobuf.Duration timeout = 2; } // The file per tap sink outputs a discrete file for every tapped stream. message FilePerTapSink { option (udpa.annotations.versioning).previous_message_type = "envoy.service.tap.v2alpha.FilePerTapSink"; // Path prefix. The output file will be of the form _.pb, where is an // identifier distinguishing the recorded trace for stream instances (the Envoy // connection ID, HTTP stream ID, etc.). string path_prefix = 1 [(validate.rules).string = {min_len: 1}]; } // [#not-implemented-hide:] Streaming gRPC sink configuration sends the taps to an external gRPC // server. message StreamingGrpcSink { option (udpa.annotations.versioning).previous_message_type = "envoy.service.tap.v2alpha.StreamingGrpcSink"; // Opaque identifier, that will be sent back to the streaming grpc server. string tap_id = 1; // The gRPC server that hosts the Tap Sink Service. core.v3.GrpcService grpc_service = 2 [(validate.rules).message = {required: true}]; }