Fluent Bit’s modify filter can dynamically alter record data, but its real power emerges when you combine it with conditional logic, allowing you to route, drop, or transform data based on its content.

Here’s Fluent Bit processing logs in real-time, applying a conditional modification:

# Start Fluent Bit with a config that uses the modify filter for conditional logic
fluent-bit -c fluent-bit.conf

Let’s imagine we’re receiving logs from multiple applications, and we want to tag Kubernetes pods with a specific label if they are running in the production namespace and have error in their log message.

Our fluent-bit.conf might look like this:

[SERVICE]
    Flush        1
    Daemon       off
    Log_Level    info

[INPUT]
    Name         tail
    Path         /var/log/app/*.log
    Tag          app.logs

[FILTER]
    Name         modify
    Match        app.logs
    Add_Label    environment production
    Add_Label    critical_error false
    # Conditional logic starts here
    Set          critical_error true
    If           $kubernetes['namespace'] == 'production' && $log * "error"

[OUTPUT]
    Name         stdout
    Match        *

In this configuration:

  • We define a tail input to read logs from /var/log/app/*.log and tag them as app.logs.
  • The modify filter is applied to app.logs.
  • We initially add two labels: environment set to production and critical_error set to false. These are baseline values.
  • The crucial part is the If condition: Set critical_error true If $kubernetes['namespace'] == 'production' && $log * "error".
    • Set critical_error true: This tells Fluent Bit to set the critical_error field to true.
    • If $kubernetes['namespace'] == 'production' && $log * "error": This is the condition. The Set action only happens if Fluent Bit can access a field named kubernetes (which it will have if the Kubernetes filter is also enabled and processing these logs), and within that, a field namespace that equals 'production'. Additionally, the log message itself ($log) must contain the substring "error".

If a log record matches these criteria (i.e., it’s from the production namespace and its message contains "error"), the critical_error label will be updated from its initial false to true. Otherwise, it remains false.

This allows for powerful data enrichment and routing. Imagine a scenario where you want to send errors from production to a separate, high-priority alert system. You could use this conditional logic to set a flag, and then a subsequent output plugin (like elasticsearch or kafka) could use a Match clause like Match environment=production,critical_error=true to route only those specific logs.

The modify filter supports a wide range of actions beyond Set and Add_Label, including Remove, Rename, Drop, and Replace. These can all be combined with If conditions. For instance, you could Drop logs that don’t meet certain criteria or Replace a sensitive field’s value if it’s detected in a specific context.

The If statement uses a C-style syntax with logical operators (&& for AND, || for OR, ! for NOT) and supports comparisons (==, !=, >, <, >=, <=). You can also use string matching with * (wildcard) and ~ (regex). For example, If $http.request.method * "POST" would match any POST requests.

What most people don’t realize is the granular control you have over which fields are checked within the If condition. If you’re using the Kubernetes filter, you can directly access fields like $kubernetes['pod_name'], $kubernetes['namespace'], or $kubernetes['labels']['app']. If you’ve parsed JSON logs, you can access nested fields like $json_payload['user']['id']. This deep inspection is key to building sophisticated routing and filtering rules.

The next logical step is to explore how to use these conditionally modified records for dynamic output routing.

Want structured learning?

Take the full Fluentbit course →