Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

access_log: add ability to generate JSON access logs preserving data types #9043

Merged
merged 10 commits into from Dec 5, 2019
Merged
14 changes: 9 additions & 5 deletions api/envoy/config/accesslog/v2/file.proto
Expand Up @@ -20,14 +20,18 @@ message FileAccessLog {
// A path to a local file to which to write the access log entries.
string path = 1 [(validate.rules).string = {min_bytes: 1}];

// Access log format. Envoy supports :ref:`custom access log formats
// <config_access_log_format>` as well as a :ref:`default format
// <config_access_log_default_format>`.
oneof access_log_format {
// Access log :ref:`format string<config_access_log_format_strings>`
// Access log :ref:`format string<config_access_log_format_strings>`.
// Envoy supports :ref:`custom access log formats <config_access_log_format>` as well as a
// :ref:`default format <config_access_log_default_format>`.
string format = 2;

// Access log :ref:`format dictionary<config_access_log_format_dictionaries>`
// Access log :ref:`format dictionary<config_access_log_format_dictionaries>`. All values
// are rendered as strings.
google.protobuf.Struct json_format = 3;

// Access log :ref:`format dictionary<config_access_log_format_dictionaries>`. Values are
// rendered as numbers where appropriate.
zuercher marked this conversation as resolved.
Show resolved Hide resolved
google.protobuf.Struct typed_json_format = 4;
}
}
14 changes: 9 additions & 5 deletions api/envoy/config/accesslog/v3alpha/file.proto
Expand Up @@ -20,14 +20,18 @@ message FileAccessLog {
// A path to a local file to which to write the access log entries.
string path = 1 [(validate.rules).string = {min_bytes: 1}];

// Access log format. Envoy supports :ref:`custom access log formats
// <config_access_log_format>` as well as a :ref:`default format
// <config_access_log_default_format>`.
oneof access_log_format {
// Access log :ref:`format string<config_access_log_format_strings>`
// Access log :ref:`format string<config_access_log_format_strings>`.
// Envoy supports :ref:`custom access log formats <config_access_log_format>` as well as a
// :ref:`default format <config_access_log_default_format>`.
string format = 2;

// Access log :ref:`format dictionary<config_access_log_format_dictionaries>`
// Access log :ref:`format dictionary<config_access_log_format_dictionaries>`. All values
// are rendered as strings.
google.protobuf.Struct json_format = 3;

// Access log :ref:`format dictionary<config_access_log_format_dictionaries>`. Values are
// rendered as numbers where appropriate.
google.protobuf.Struct typed_json_format = 4;
}
}
22 changes: 14 additions & 8 deletions docs/root/configuration/observability/access_log.rst
Expand Up @@ -60,10 +60,12 @@ Format Dictionaries
-------------------

Format dictionaries are dictionaries that specify a structured access log output format,
specified using the ``json_format`` key. This allows logs to be output in a structured format
such as JSON.
Similar to format strings, command operators are evaluated and their values inserted into the format
dictionary to construct the log output.
specified using the ``json_format`` or ``typed_json_format`` keys. This allows logs to be output in
a structured format such as JSON. Similar to format strings, command operators are evaluated and
their values inserted into the format dictionary to construct the log output.

The ``typed_json_format`` differs from ``json_format`` in that values are rendered as JSON numbers
where applicable.

For example, with the following format provided in the configuration:

Expand All @@ -89,7 +91,12 @@ This allows you to specify a custom key for each command operator.

Format dictionaries have the following restrictions:

* The dictionary must map strings to strings (specifically, strings to command operators). Nesting is not currently supported.
* The dictionary must map strings to strings (specifically, strings to command operators). Nesting
is not currently supported.
* When using the ``typed_json_format`` command operators will only produce numeric output if the
command operator is the only string that appears in the dictionary value. For example,
``"%DURATION%"`` will log a numeric duration value, but ``"%DURATION%.0"`` will log a string
value.

Command Operators
-----------------
Expand Down Expand Up @@ -281,7 +288,7 @@ The following command operators are supported:

.. note::

This is always the physical remote address of the peer even if the downstream remote address has
This is always the physical remote address of the peer even if the downstream remote address has
been inferred from :ref:`proxy proto <envoy_api_field_listener.FilterChain.use_proxy_proto>`
or :ref:`x-forwarded-for <config_http_conn_man_headers_x-forwarded-for>`.

Expand All @@ -291,7 +298,7 @@ The following command operators are supported:

.. note::

This is always the physical remote address of the peer even if the downstream remote address has
This is always the physical remote address of the peer even if the downstream remote address has
been inferred from :ref:`proxy proto <envoy_api_field_listener.FilterChain.use_proxy_proto>`
or :ref:`x-forwarded-for <config_http_conn_man_headers_x-forwarded-for>`.

Expand Down Expand Up @@ -446,4 +453,3 @@ The following command operators are supported:
The validity end date of the client certificate used to establish the downstream TLS connection.
TCP
The validity end date of the client certificate used to establish the downstream TLS connection.

1 change: 1 addition & 0 deletions include/envoy/access_log/BUILD
Expand Up @@ -14,5 +14,6 @@ envoy_cc_library(
deps = [
"//include/envoy/http:header_map_interface",
"//include/envoy/stream_info:stream_info_interface",
"//source/common/protobuf",
],
)
15 changes: 15 additions & 0 deletions include/envoy/access_log/access_log.h
Expand Up @@ -7,6 +7,8 @@
#include "envoy/http/header_map.h"
#include "envoy/stream_info/stream_info.h"

#include "common/protobuf/protobuf.h"

namespace Envoy {
namespace AccessLog {

Expand Down Expand Up @@ -139,6 +141,19 @@ class FormatterProvider {
const Http::HeaderMap& response_headers,
const Http::HeaderMap& response_trailers,
const StreamInfo::StreamInfo& stream_info) const PURE;
/**
* Extract a value from the provided headers/trailers/stream, preserving the value's type.
* @param request_headers supplies the request headers.
* @param response_headers supplies the response headers.
* @param response_trailers supplies the response trailers.
* @param stream_info supplies the stream info.
* @return ProtobufWkt::Value containing a single value extracted from the given
* headers/trailers/stream.
*/
virtual ProtobufWkt::Value formatValue(const Http::HeaderMap& request_headers,
const Http::HeaderMap& response_headers,
const Http::HeaderMap& response_trailers,
const StreamInfo::StreamInfo& stream_info) const PURE;
};

using FormatterProviderPtr = std::unique_ptr<FormatterProvider>;
Expand Down
2 changes: 2 additions & 0 deletions source/common/access_log/BUILD
Expand Up @@ -39,13 +39,15 @@ envoy_cc_library(
name = "access_log_formatter_lib",
srcs = ["access_log_formatter.cc"],
hdrs = ["access_log_formatter.h"],
external_deps = ["abseil_str_format"],
deps = [
"//include/envoy/access_log:access_log_interface",
"//include/envoy/stream_info:stream_info_interface",
"//source/common/common:assert_lib",
"//source/common/common:utility_lib",
"//source/common/config:metadata_lib",
"//source/common/http:utility_lib",
"//source/common/protobuf:message_validator_lib",
"//source/common/stream_info:utility_lib",
],
)
Expand Down