fluent-bit icon indicating copy to clipboard operation
fluent-bit copied to clipboard

`modify` filter does not respect nested keys

Open astorath opened this issue 4 years ago • 23 comments

Bug Report

Describe the bug

modify filter does not respect nested keys

To Reproduce

  • Config:
    [SERVICE]
        Flush        1
        Daemon       Off
        Log_Level    debug
        Parsers_File parsers.conf
    
    [INPUT]
        Name             tail
        Path        /log.json
    
    [FILTER]
        Name parser
        Match *
        Key_Name log
        Parser test
    
    [FILTER]
        Name  modify
        Match *
    
        Condition Key_exists           json
    
        Copy        json.Message      log
    
    [OUTPUT]
        Name  stdout
    
  • Example log message if applicable:
{ "json": { "Message": "HttpClientTracingProvider:: Class is receiving HTTP Response from  using .: StatusCode=200 Elapsed=00:00:00.0078867 ResponseHeaders={$Headers} ResponseBody={$Body}" } }
  • Steps to reproduce the problem: Just run fluent-bit with config attached.

Expected behavior

json.Message contents should be copied to log key.

Screenshots

image

Your Environment

  • Version used: 1.3.7, 1.4.3
  • Configuration: provided above
  • Environment name and version (e.g. Kubernetes? What version?): docker 19.03.8
  • Server type and version: -
  • Operating System and version: MacOS 10.15
  • Filters and plugins: -

Additional context

Non-nested keys are working fine

astorath avatar May 03 '20 19:05 astorath

Can confirm this still does not work on v1.5.2. What I'm doing to work around, for now, is using the nest filter to lift records up and then process with rename. This isn't optimal, though, as I'd ideally only like to lift 1 or 2 keys rather than the whole nested structure.

mshade avatar Aug 04 '20 01:08 mshade

Does not work in v1.5.2 too. I had to use the same workaround.

vinodkmrm avatar Aug 09 '20 15:08 vinodkmrm

Anyone found a way out? Any relation with https://docs.fluentbit.io/manual/administration/configuring-fluent-bit/record-accessor?

trnl avatar Nov 09 '20 11:11 trnl

The issue still exist in 1.7 :-(

vladimir259 avatar Feb 26 '21 12:02 vladimir259

I've found out a more effective workaround for this issue than using nest filter, you can use instead the Lua filter https://docs.fluentbit.io/manual/pipeline/filters/lua with a script like this:

function label_key_rename(tag, timestamp, record)
    local old_key, new_key = "oldKey", "newKey"

    local labels = record["kubernetes"]["labels"]
    local new_record = record
    local code = 0

    if labels[old_key] ~= nil then
        code = 1
        local new_labels = {}
        for key, value in pairs(labels) do
            if key == old_key then key = new_key end
            new_labels[key] = value
        end
        new_record["kubernetes"]["labels"] = new_labels
    end

    return code, timestamp, new_record
end

maximchukm avatar Mar 23 '21 19:03 maximchukm

I've found out a more effective workaround for this issue than using nest filter, you can use instead the Lua filter https://docs.fluentbit.io/manual/pipeline/filters/lua with a script like this:

I'm a bit concerned about using lua - the main point of using fluent-bit in place of fluentd is performance. Falling back to scripting somewhat defeats this advantage. Am I wrong?

astorath avatar Apr 06 '21 16:04 astorath

I've found out a more effective workaround for this issue than using nest filter, you can use instead the Lua filter https://docs.fluentbit.io/manual/pipeline/filters/lua with a script like this:

I'm a bit concerned about using lua - the main point of using fluent-bit in place of fluentd is performance. Falling back to scripting somewhat defeats this advantage. Am I wrong?

Sure, native C implementation still will be faster. But using lua script with straight logic is much better both from readability and performance points than juggling with "nest" plugin (one operation per field instead of 3+)

maximchukm avatar Apr 06 '21 17:04 maximchukm

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.

github-actions[bot] avatar May 19 '21 01:05 github-actions[bot]

Still a valid issue, commenting so this doesn't get closed.

isaccavalcante avatar May 21 '21 20:05 isaccavalcante

Not sure how you would support this perfectly without a new parameter with a json path. I've used nest like this, hopefully this helps people.

    [FILTER]
        Name                nest
        Match               kube.*
        Operation           lift
        Nested_under        kubernetes
        Add_prefix          temp_l1_

    [FILTER]
        Name                nest
        Match               kube.*
        Operation           lift
        Nested_under        temp_l1_labels
        Add_prefix          temp_l2_

    [FILTER]
        Name                modify
        Match               kube.*
        Rename              temp_l2_label1 label1
        Rename              temp_l2_label2 label2

    [FILTER]
        Name                nest
        Match               kube.*
        Operation           nest
        Wildcard            temp_l2_*
        Nest_under          temp_l1_labels
        Remove_prefix       temp_l2_

    [FILTER]
        Name                nest
        Match               kube.*
        Operation           nest
        Wildcard            temp_l1_*
        Nest_under          kubernetes
        Remove_prefix       temp_l1_

mattwhittingham avatar Jun 18 '21 17:06 mattwhittingham

function label_key_rename(tag, timestamp, record) local old_key, new_key = "oldKey", "newKey"

local labels = record["kubernetes"]["labels"]
local new_record = record
local code = 0

if labels[old_key] ~= nil then
    code = 1
    local new_labels = {}
    for key, value in pairs(labels) do
        if key == old_key then key = new_key end
        new_labels[key] = value
    end
    new_record["kubernetes"]["labels"] = new_labels
end

return code, timestamp, new_record

end

I'm attempting this approach, however I'm completely unable to find any documentation on how to add my lua file to fluent bit. We are using the docker image, do we have to create a custom image on top of the base fluentbit image and upload the lua file there?

VIPHercules avatar Sep 01 '21 21:09 VIPHercules

I have the same issue ! i running fluent-bit from container image 1.8.6 latest

Input

{
  "method":"POST",
  "remoteAddr":"1.2.3.4",
  "user":{"group": ["a", "b", "c"]}
}
    [FILTER]
        Name    record_modifier
        Match   app.log
        Remove_key  remoteAddr
        Remove_key  user.group

Remove the nested key user.group not work

scila1996 avatar Sep 02 '21 19:09 scila1996

This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 5 days. Maintainers can add the exempt-stale label.

github-actions[bot] avatar Jan 04 '22 01:01 github-actions[bot]

This issue is still valid, why isn't this issue not labeled as a bug?

amitjoseph avatar Jan 07 '22 04:01 amitjoseph

Still a problem. I'd like to remove some kubernetes.examplekey but the filter doesn't respect nested keys. record_modifier has the same problem

data-dude avatar Feb 04 '22 15:02 data-dude

Still a problem. I'd like to remove some kubernetes.examplekey but the filter doesn't respect nested keys. record_modifier has the same problem

I encountered a similar issue and i managed to resolve it using a super simple lua script, hope it helps:

function remove_k8s_labels_annotations(tag, timestamp, record)
      record['kubernetes']['labels'] = nil
      record['kubernetes']['annotations'] = nil

      return 2, timestamp, record
    end

and you use it like this:

[FILTER]
        Name    lua
        Match   kube.*
        script  functions.lua
        call    remove_k8s_labels_annotations

dFurman avatar Feb 24 '22 08:02 dFurman

This problem is still actual not only for the modify plugin but GELF output plugin also. I cannot set a nested key for Gelf_Host_Key parameter.

sane4ek-2 avatar Mar 04 '22 12:03 sane4ek-2

But you can simply turn it off

[FILTER]
    Name                kubernetes
    Labels              Off
    Annotations         Off

Still a problem. I'd like to remove some kubernetes.examplekey but the filter doesn't respect nested keys. record_modifier has the same problem

function remove_k8s_labels_annotations(tag, timestamp, record)
      record['kubernetes']['labels'] = nil
      record['kubernetes']['annotations'] = nil

alt-dima avatar Mar 20 '22 12:03 alt-dima

This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 5 days. Maintainers can add the exempt-stale label.

github-actions[bot] avatar Jun 19 '22 02:06 github-actions[bot]

But you can simply turn it off

[FILTER]
    Name                kubernetes
    Labels              Off
    Annotations         Off

Still a problem. I'd like to remove some kubernetes.examplekey but the filter doesn't respect nested keys. record_modifier has the same problem

function remove_k8s_labels_annotations(tag, timestamp, record)
      record['kubernetes']['labels'] = nil
      record['kubernetes']['annotations'] = nil

Turning it Off does not work. The K8S labels and annotations still remain present.

It would be nice if we could turn it Off so it does not show anymore, Or to be able to target nested keys in case we want to remove specific keys only. Commenting as this issue is still present.

TheZhyer avatar Jun 24 '22 10:06 TheZhyer

Having the same problem as explained in this issue.

My use case: we have a field (that comes from kubernetes audit logs, so we can't modify the source) where record["foo"]["bar"] sometimes is a specific string and other times is a json object. Because of this, Opensearch complains and rejects the log.

Our idea is to modify the record. Something like

if record["foo"]["bar"]=string then 
  modify record to record["foo"]["custom"]["bar"]
end

I know this can be done with a Lua script, but it would be much more readable (and less error prone) to do it via the modify filter.

Any plans on adding this feature to modify?

antoniocascais avatar Aug 31 '22 13:08 antoniocascais

Please note that fixing this could have side effects.

For example, with ElasticSearch there will be an error if for some entries foo has nested values and for some it is a string; i.e. object mapping for [foo] tried to parse field [foo] as object, but found a concrete value.

Currently, this can be avoided by renaming keys with a string value like so

      [FILTER]
          Name modify
          Rename foo bar
          Condition Key_exists foo

mjiderhamn avatar Sep 12 '22 08:09 mjiderhamn

Still a problem. I'd like to remove some kubernetes.examplekey but the filter doesn't respect nested keys. record_modifier has the same problem

I encountered a similar issue and i managed to resolve it using a super simple lua script, hope it helps:

function remove_k8s_labels_annotations(tag, timestamp, record)
      record['kubernetes']['labels'] = nil
      record['kubernetes']['annotations'] = nil

      return 2, timestamp, record
    end

and you use it like this:

[FILTER]
        Name    lua
        Match   kube.*
        script  functions.lua
        call    remove_k8s_labels_annotations

Yea that might work for some people. I found the easiest was to set the kubernetes plugin filter to annotations off and lables off See docs for more details: https://docs.fluentbit.io/manual/pipeline/filters/kubernetes

data-dude avatar Sep 12 '22 12:09 data-dude