Add Kafka topic template routing for Kubernetes pod log streams#539
Open
jeremyudis wants to merge 1 commit into
Open
Add Kafka topic template routing for Kubernetes pod log streams#539jeremyudis wants to merge 1 commit into
jeremyudis wants to merge 1 commit into
Conversation
Adds writer.kafka.topicTemplate so a single log config running in
Kubernetes mode can route each pod log stream to a topic derived from
its source. Supported variables: %{namespace}, %{container} (the
container directory in the kubelet /var/log/pods layout), and
%{metadata:<key>} (pod labels/annotations via podMetadataFields).
Pod-level identifiers (pod name / uid) are rejected at config load time
to avoid unbounded topic cardinality. Resolution is all-or-nothing: if
any variable is unresolvable or the result is not a legal Kafka topic
name, the writer falls back to the static topic (legacy \N capture
group expansion preserved) and emits a fallback metric.
Also fixes RecursiveFSEventProcessor to collect configs from all
matching logConfigMap entries instead of stopping at the first, so a
wildcard logDir config (e.g. "/*" for per-container directories) no
longer shadows an exact-directory config at the same depth.
Includes a Kubernetes sample config and README documenting container
stdout tailing and routing precedence.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
writer.kafka.topicTemplate, letting a single log config running in Kubernetes mode (DaemonSet tailing/var/log/pods) route each pod log stream to a Kafka topic derived from its source.Supported variables:
%{namespace}— the pod's Kubernetes namespace (parsed from thenamespace_podname_uidpod directory name)%{container}— the container directory in the standard kubelet layout/var/log/pods/<ns>_<pod>_<uid>/<container>/0.log(uselogDir=/*so each container directory becomes its own stream)%{metadata:<key>}— a pod label/annotation fetched via the existingpodMetadataFieldsmechanism, enabling self-serve routing (teams annotate their pods with a topic name)Topic resolution precedence (per stream, at writer creation)
topicTemplate— used only when every variable resolves and the result is a legal Kafka topic nametopic— the required static fallback; legacy\Ncapture-group expansion againstlogStreamRegexis unchanged. Fallbacks emitsinger.writer.topic_template_fallbackDesign notes
%{podName},%{podUid}) are deliberately rejected at config load time: pods churn on every restart/reschedule, so they would create unbounded topic cardinality.%{...}syntax, and illegal topic characters are allConfigurationExceptions at startup.KafkaProducerManager), so many resolved topics add no producer overhead.RecursiveFSEventProcessorto collect configs from all matchinglogConfigMapentries instead of stopping at the first, so a wildcardlogDirconfig (e.g./*) no longer permanently shadows an exact-directory config at the same depth.Docs
docs/configuration_samples/sample_kubernetes/README.md— Kubernetes mode, container stdout tailing, routing precedence, DaemonSet deployment notesdocs/configuration_samples/sample_kubernetes/conf.d/container.stdout_logs.properties— working per-container routing exampleTest plan
TestTopicTemplateResolver(17 tests): template validation (rejects pod-level/unknown variables, malformed syntax, illegal characters), namespace/container/metadata resolution, all unresolvable-variable and illegal-topic fallback pathsTestTopicTemplateRouting(5 tests): writer-factory precedence — template wins when resolvable, falls back to static topic otherwise, legacy capture-group expansion preservedTestContainerLogStreams(3 tests): end-to-end with the kubelet fixture —logDir=/*produces one stream per container directory with concrete paths resolving tologs_default_web/logs_default_sidecar; wildcard and exact configs no longer shadow each otherTestLogConfigUtils(+4 tests): config parsing accepts valid templates and rejects invalid ones at load timeTestPodLogCycle,TestPodAllowlist,TestKubeService,TestRecursiveEventProcessor— 71/71 passing🤖 Generated with Claude Code