Log Parsing Configuration
Kloudfuse extracts structure from every log line automatically — a fingerprint, a set of facets, and a timestamp — using the parsing pipeline described in How a log line reaches the Logs Store. This page is the configuration reference for that pipeline: how to customize what it extracts when the automatic heuristics aren’t precise enough. All of it is configured under kf_parsing_config in the logs-parser Helm values.
Remap (deprecated)
|
The remap stage, set up using YAML, is being discontinued in favor of Logs Remap — a newer engine that performs the same job (normalizing each agent’s raw payload into message, timestamp, source, and labels) but is configured through an editable UI page instead of Helm values, with a live preview against real traffic. See Logs Remap and Remap Architecture. New deployments should configure normalization in Logs Remap. This stage is retained only for deployments still running with |
Remap is the pipeline’s first stage — it maps fields from the incoming payload (JSON, msgpack, or proto, depending on your agent) onto Kloudfuse’s internal fields: message, timestamp, source, and initial labels/facets.
logs-parser:
kf_parsing_config:
config: |-
- remap:
args:
kf_source:
- "$.logSource"
kf_msg:
- "$.logMessage"
conditions:
- matcher: "__kf_agent"
value: "fluent-bit"
op: "=="
__kf_agent is a reserved matcher for the sending agent, and supports datadog, fluent-bit, fluentd, kinesis, gcp, otlp, and filebeat. All Remap fields must be given in JSONPath notation.
Relabel
Relabel works on the labels Remap (or Logs Remap) produced — it can add, drop, rewrite, or derive a label. It’s loosely inspired by Prometheus relabeling (a regex against one or more source labels, an action, a target), but the action set below is this pipeline’s own, not an exact match to Prometheus’s.
The relabel function is specific to the logs-parser pipeline and only affects logs. Metrics, Events, and Traces each have their own relabeling mechanism at the ingester level, and those rules do adhere to the Prometheus relabel_config format — see How Relabel Rules Work.
|
Actions
action selects what the function does with sourceLabels (a comma-separated list — facets prefixed @, labels prefixed # or bare):
- replace
-
Regex-matches
sourceLabels(joined byseparator) againstregex, and if it matches, writesreplacementtotargetLabel. WhentargetLabelis prefixed@, it creates a facet instead of a label. - drop
-
Discards the log line entirely if
sourceLabelsmatchesregex. - keep
-
Discards the log line if
sourceLabelsdoes not matchregex. - lowercase
-
Writes the lowercase value of
sourceLabelstotargetLabel. - uppercase
-
Writes the uppercase value of
sourceLabelstotargetLabel. - label_map
-
Changes the name of every label matching
regexby replacing the matched part withreplacement. Unlike the other actions, this operates on label names, not values, and ignoressourceLabels. - label_keep
-
Removes every label whose name does not match
regex;sourceLabelsis ignored. - label_drop
-
Removes every label whose name matches
regex;sourceLabelsis ignored. - facet_to_label_map
-
Copies the value of a facet in
sourceLabelsand assigns it totargetLabelas a label. Withregex/replacement, it transforms the value along the way; without a regex, it copies it as-is. This is the action to use for Transform's "promote a facet to a label" use case.
- relabel:
args:
- action: "replace"
- regex: ".*"
- replacement: "production"
- targetLabel: "env"
- relabel:
args:
- action: "drop"
- sourceLabels: "@path"
- regex: "/healthz"
Functions and conditions
Every pipeline function — relabel, transform, parser (dissect/grok), and the others listed under Other pipeline functions — is a list item under config, with its arguments under args and, optionally, a list of conditions that determine whether it runs for a given log line. remap always runs first, ahead of everything else. Beyond that, each function executes in a fixed stage, and your config list’s order doesn’t change which stage a function runs in — it only orders functions relative to each other within the same stage. relabel always runs before Grammar (parser, JSON auto-parsing) and transform always runs after it, so a relabel rule can never see a facet parser extracts no matter which one you write first — see Relabel, Transform priority order. A function with no conditions always runs. Each condition is a matcher / value / op triplet:
- matcher
-
A label (
#name), a facet (@name), the message field (%kf_msg— the only supported field), a JSONPath from the incoming payload (remap only), or the reserved__kf_agent(remap only). - value
-
A literal string, or a regex, depending on
op. - op
-
One of
==,!=,=~(regex match),!~(regex not match),contains,startsWith,endsWith, orin(value is one of a comma-separated list) — each also has a negated form:not contains,not startsWith,not endsWith, andnot in.opis case-insensitive.
logs-parser:
kf_parsing_config:
configPath: "/conf"
config: |-
- <FUNC_NAME>:
args:
- <FUNC_ARGS>
conditions:
- matcher: <LABEL|FACET|FIELD|JSON_PATH|__kf_agent>
value: "<EXPECTED_VALUE>"
op: "<OP_VALUE>"
Grammar: dissect and grok patterns
Kloudfuse auto-detects facets and a timestamp from the message using a heuristic, which won’t always be precise. Define a custom pattern to extract fields exactly instead.
Dissect patterns
A dissect pattern functions as a text tokenizer: sections like %{fieldname} separated by literal delimiter text. Prefixes applied to the field name alter its behavior — %{?a} matches without capturing, %{+b} appends to a previous capture, and %{&c} refers to an earlier capture. To create a nested field name, use bracket notation (%{[field][subfield]}) rather than one containing a literal dot. Test the pattern with a dissect debugger before deploying it.
- parser:
dissect:
args:
- tokenizer: '%{timestamp} %{level} [LLRealtimeSegmentDataManager_%{segment_name}]'
conditions:
- matcher: "%kf_msg"
value: "LLRealtimeSegmentDataManager_"
op: "contains"
Grok patterns
A grok pattern is a set of named regular expressions — flexible, but not as easy to read at a glance. See the Grok filter plugin documentation for the pattern syntax, and test patterns with a grok debugger before deploying.
Apply one or more patterns to a field with args: patterns (a list — combined together) and optionally field (defaults to the message):
- parser:
grok:
args:
- patterns:
- '%{TIMESTAMP_ISO8601:ts} %{LOGLEVEL:level} %{GREEDYDATA:msg}'
conditions:
- matcher: "#source"
value: "nginx"
op: "=="
Reusable pattern definitions go under parser_patterns, and can be referenced by name elsewhere in the config:
parser_patterns:
- dissect:
timestamp_pat: "<REGEX>"
- grok:
NGINX_HOST: (?:%{IP:destination_ip}|%{NGINX_NOTSEPARATOR:destination_domain})(:%{NUMBER:destination_port})?
Worked example: deriving a facet with a tokenizer
Given this log line:
10.12.0.35 - - [26/May/2021:18:59:10 +0000] "GET /unavailable HTTP/1.1" 503 21 "-" "hey/0.0.1"
this dissect tokenizer:
'%{sourceIp} - - [%{timestamp}] "%{requestMethod} %{uri} %{_}" %{responseCode} %{contentLength}'
produces the facets sourceIp: 10.12.0.35, requestMethod: GET, responseCode: 503, and contentLength: 21. Limit the tokenizer to a single source by using a conditions matcher on #source, so it applies only to the logs it’s meant for:
logs-parser:
kf_parsing_config:
config: |-
- parser:
dissect:
args:
- tokenizer: '%{sourceIp} - - [%{timestamp}] "%{requestMethod} %{uri} %{_}" %{responseCode} %{contentLength}'
conditions:
- matcher: "#source"
value: "nginx"
op: "=="
Add another - parser: dissect: … item, with its own conditions, for a second source — each function in the config list is independently scoped by its own conditions block; nothing groups them by source implicitly.
JSON logs
Kloudfuse automatically detects JSON messages and turns each field into a facet, flattening nested objects with _ — {"location": {"city": "SF"}} becomes the facet location_city. A field that is an array — such as "aliases": ["johndoe", "johnny"] — is extracted as a single string facet.
By default, a single log line can generate up to 50 facets. This is a strict ceiling, not a truncation to the first 50: a JSON object with 51 fields results in zero facets. Raise the ceiling with skipAutoFacet:
logs-parser:
kf_parsing_config:
config: |-
...
- skipAutoFacet:
args:
maxFacetsCount: 100
Once ingested, query the extracted facets from the Logs Explorer the same way as any other facet — see Logs Search Syntax.
Transform and fingerprinting
relabel always runs before Grammar and JSON auto-parsing, and transform always runs after — regardless of where either appears in your config list. For this reason, transform, not relabel, is used when something depends on a facet that Grammar or JSON auto-parsing extracts. The most common application is facet_to_label_map, which promotes a facet extracted by Grammar into a label — for example, promoting the facet eventSource into the label source:
- transform:
args:
- action: "facet_to_label_map"
- sourceLabels: "@eventSource"
- targetLabel: "source"
conditions:
- matcher: "#source"
op: "=="
value: "awsLogSource"
Any other action in Relabel’s action table — drop, keep, label_map, and so on — functions the same way here. The difference between transform and relabel determines when the rule applies relative to extraction, not the action’s capabilities. If a drop or keep condition depends on a facet extracted by Grammar, it must be written using transform, since relabel runs too early to see that facet, regardless of its position in the config list.
At some point in the pipeline, the internal Kf-Parse stage produces the log’s fingerprint by dividing the message into its static template and dynamic values — so that ts=2023-02-01T22:51:33Z caller=logging.go:29 method=Authorise result=false took=9.775µs becomes the fingerprint ts=<v_0> caller=<v_1> method=<v_2> result=<v_3> took=<v_4> plus the facets ts, caller, method, result, and took. Storing the template once and the variable values separately is what keeps Kloudfuse’s highly repetitive log traffic both fully indexed and storage-efficient — see Log Fingerprints for where this shows up in the Explorer. Kf-Parse itself isn’t configurable.
For more information on how Kloudfuse selects and validates a log’s timestamp, see Log Timestamp Handling.
Other pipeline functions
Beyond remap, relabel/transform, and dissect/grok, the pipeline supports these additional functions — each a list item under config, exactly like the examples above:
| Function | What it does |
|---|---|
|
Adds a facet with a fixed value. Args: |
|
Removes one or more named facets. Args: |
|
Renames a facet. Args: |
|
Moves a label’s value into a facet of the same or a different name. Args: |
|
Forces the log’s level to a fixed value, overriding whatever was detected. Args: |
|
Parses a facet as the log’s timestamp using one or more explicit formats, instead of relying on automatic timestamp detection. Args: |
|
Tunes how far into the message the automatic timestamp-detection heuristic looks. Args: |
|
Restricts extraction to only the named facets, discarding everything else auto-detection would otherwise extract. Args: |
|
Raises the default 50-facet ceiling on JSON auto-parsing. Args: |
|
Parses the message as logfmt (space-separated |
|
Unconditionally drops the log line — pair it with |
|
Controls this log’s archival behavior — which archive it’s written to, and whether it’s indexed for live search as well. See Archiving Logs and Hydration. |
A further set of low-level tokenization primitives — resetPos, truncate, tokenize, rebuild, tokenizedKvExtract, tokenizedTsExtract, dissectKVOptimize, and tokenizedNewr — exist for advanced custom parsing scenarios beyond what dissect and grok cover. They’re implementation details rather than something most configurations need; contact your Kloudfuse representative if dissect or grok don’t cover a format you’re trying to parse.
References
-
Dissect filter syntax — the closest external reference for the
%{field}tokenizer syntax Kloudfuse’sdissectfollows; confirm edge-case behavior against a debugger or a running cluster rather than assuming an exact match. -
Dissect debugger — test a tokenizer against a sample line before deploying it.
-
Grok filter plugin documentation — the full pattern syntax and predefined patterns (
%{IP:client_ip},%{TIMESTAMP_ISO8601:ts}, and so on). -
Grok debugger — test a pattern against a sample line before deploying it.
-
Log Parsing Examples — worked dissect and grok examples, including common mistakes and their fixes.