envoyproxy/envoy

Request Body logging

Closed this issue ยท 14 comments

Title: Request Body logging

Description:

how can i log the content of a request / the request-body with Envoy ?
I want to send the body content (decoded) lets say to elastic-search or write in to a file.

One could use lua-script to get the request object and send the request to an upstream cluster !

Or are there better ways for doing this ?

thanks

I am facing a similar issue. For now I have configured a route with a generic "/*" prefix plus shadow annotation so that all incoming HTTP requests are forwarded from Envoy to a Logstash instance that in turn ingests data to an Elasticsearch cluster:

{
    "clusters": [],
    "prefix": "/*",
    "prefix_rewrite": "/",
    "shadow": {
        "name": "cluster_shadow_logstash_default_svc_cluster_local_8080"
    }

This works fine for HTTP requests, but responses are not forwarded. I would like to avoid custom script execution on Envoy and just forward all incoming request/response messages, ideally delegating any kind of processing (e.g. pair aggregation by header-id) to Logstash.

Thanks in advance.

Anyone wants to share a lua script that forwards the requests?

Hi ,

this works for me. I forwarding the request to fluentd service.

           ` inline_code :  

            function envoy_on_request(request_handle)
            
            local body = request_handle:body()
            result = tostring(body)
            request_handle:logDebug(result)
            
            -- Make an HTTP call.
            local headers, body = request_handle:httpCall(
            "fluentd",
            {
             [":method"] = "POST",
             [":path"] = "/",
             [":authority"] = "lua_cluster"
            },
            result,
            24224)
              
            end
            function envoy_on_response(response_handle)
              -- Make an HTTP call here too
            end  `

How have you defined fluentd? Is it a separate service with a ClusterId (kubernates)? I'm wondering how the envoy.yaml is picking it up.

Hi marimarkov,

fluentd is defined inside cluster section of static_resources:

clusters:
- name: fluentd
    connect_timeout: 0.25s
    type: strict_dns # static
    lb_policy: round_robin
    hosts:
    - socket_address:
        address: fluentd
        port_value: 24224

closing this issue because it seems that right now request/response body logging is not supported .

@githubYasser do we have any updates on it? Can we capture request/response from envoy now?

kenju commented

@githubYasser

Thanks for the nice suggestion ๐Ÿ‘

My question is, below line returns Lua's userdata, which means that has few useful information for debugging since it shows just a single pointer.

            local body = request_handle:body()
            result = tostring(body)
            request_handle:logDebug(result)

This line will show something like this:

[2019-09-20 08:58:47.242][13][debug][lua] [source/extensions/filters/http/lua/lua_filter.cc:589] script log: userdata: 0x418dcf88

And, even if you send the data to fluentd, I though it will be "userdata: 0x418dcf88" string, correct?


I think, what you might want is something like this:

                  local index = 0
                  for chunk in handle:bodyChunks() do
                    local len = chunk:length()
                    local result = chunk:getBytes(index, len)
                    index = index + len

                    handle:logDebug(result)

                    -- Make an HTTP call.
                    local headers, body = handle:httpCall(
                     "fluentd",
                        {
                          [":method"] = "POST",
                          [":path"] = "/",
                          [":authority"] = "lua_cluster"
                        },
                      result,
                      24224)
                  end

You can use getBytes to read the real value from the pointers.

kenju commented

FYI

I created a reproducible repository to show how to log HTTP POST body using Lua's HTTP Filter.

https://github.com/kenju/envoy-lua-filters-sample
moved ๐Ÿ‘‰ https://github.com/kenju/service-mesh-patterns/tree/c22ae3850c2b34515c88a91459542af872d55e24/envoy-lua-filters

Hope it helps anyone who has same problems with us.

@kenju
your repo is private, we could not have access

xring commented

@kenju

                  local index = 0
                  for chunk in handle:bodyChunks() do
                    local len = chunk:length()
                    local result = chunk:getBytes(index, len)
                    index = index + len

                    handle:logDebug(result)

                    -- Make an HTTP call.
                    local headers, body = handle:httpCall(
                     "fluentd",
                        {
                          [":method"] = "POST",
                          [":path"] = "/",
                          [":authority"] = "lua_cluster"
                        },
                      result,
                      24224)
                  end

for each chunk from handle:bodyChunks(), read from index to len, why should index update to index + len ? per my understanding index should always be 0, any ref about this?

local index = 0
                  for chunk in handle:bodyChunks() do
                    local len = chunk:length()
                    local result = chunk:getBytes(index, len)
                    index = index + len

                    handle:logDebug(result)

                    -- Make an HTTP call.
                    local headers, body = handle:httpCall(
                     "fluentd",
                        {
                          [":method"] = "POST",
                          [":path"] = "/",
                          [":authority"] = "lua_cluster"
                        },
                      result,
                      24224)
                  end

I agree with @xring

@johnzheng1975 i tried the same way to print the requests on the console. it prints nothing and no error also on the console. am I missing anything here ?

               local index = 0
              for chunk in handle:bodyChunks() do
                local len = chunk:length()
                local result = chunk:getBytes(index, len)
                index = index + len

                handle:logInfo(result)
              end