Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Log (Structured Logging)

The log function provides structured logging within workflows using the Rust log crate. Log messages and fields support JSONLogic expressions for dynamic content.

Overview

The log function allows you to:

  • Emit structured log messages at any point in a workflow
  • Use JSONLogic expressions for dynamic message content
  • Attach structured fields for machine-readable log data
  • Debug data flow without modifying the message

Configuration

{
    "function": {
        "name": "log",
        "input": {
            "level": "info",
            "message": "JSONLogic expression or static string",
            "fields": {
                "field_name": "JSONLogic expression"
            }
        }
    }
}

Fields

FieldTypeRequiredDescription
levelstringNoLog level: trace, debug, info (default), warn, error
messageJSONLogicYesThe log message (evaluated as JSONLogic against message context)
fieldsobjectNoKey-value pairs where values are JSONLogic expressions

Log Levels

LevelUse Case
traceVery detailed debugging (function entry/exit, variable values)
debugDebugging information (intermediate processing state)
infoGeneral informational messages (processing milestones)
warnWarning conditions (unusual but not erroneous states)
errorError conditions (failures that are handled)

Examples

Simple Static Message

{
    "id": "log_start",
    "function": {
        "name": "log",
        "input": {
            "level": "info",
            "message": "Starting order processing"
        }
    }
}

Dynamic Message with JSONLogic

{
    "id": "log_order",
    "function": {
        "name": "log",
        "input": {
            "level": "info",
            "message": {"cat": ["Processing order ", {"var": "data.order.id"}, " for $", {"var": "data.order.total"}]},
            "fields": {
                "order_id": {"var": "data.order.id"},
                "customer": {"var": "data.customer.name"},
                "total": {"var": "data.order.total"}
            }
        }
    }
}

Debug Logging

{
    "id": "debug_state",
    "function": {
        "name": "log",
        "input": {
            "level": "debug",
            "message": {"cat": ["Current data state: ", {"var": "data"}]},
            "fields": {
                "has_email": {"!!": {"var": "data.email"}},
                "item_count": {"var": "data.items.length"}
            }
        }
    }
}

Warning on Edge Cases

{
    "id": "warn_missing",
    "condition": {"!": {"var": "data.shipping_address"}},
    "function": {
        "name": "log",
        "input": {
            "level": "warn",
            "message": {"cat": ["Order ", {"var": "data.order.id"}, " has no shipping address"]}
        }
    }
}

Log Target

All log messages are emitted with the target dataflow::log, making it easy to filter in your logging configuration:

#![allow(unused)]
fn main() {
// Using env_logger
RUST_LOG=dataflow::log=info cargo run

// Or filter specifically for dataflow logs
env_logger::Builder::new()
    .filter_module("dataflow::log", log::LevelFilter::Debug)
    .init();
}

Notes

  • The log function never modifies the message — it is read-only
  • The log function never fails — it always returns status 200 with no changes
  • All JSONLogic expressions in message and fields are pre-compiled at engine startup
  • If a JSONLogic expression fails to evaluate, the raw expression value is logged instead
  • The fields are formatted as key=value pairs appended to the log message