Skip to content

in_winevtlog: Add text format for event rendering#11448

Merged
edsiper merged 3 commits intomasterfrom
cosmo0920-add-text-rendering-format-on-in_winevtlog
Feb 13, 2026
Merged

in_winevtlog: Add text format for event rendering#11448
edsiper merged 3 commits intomasterfrom
cosmo0920-add-text-rendering-format-on-in_winevtlog

Conversation

@cosmo0920
Copy link
Contributor

@cosmo0920 cosmo0920 commented Feb 10, 2026

For alignment of EventViewer format, we need to provide another format for rendering as text which means key=value rendered key-value pairs that are concatenate with newlines.
This could be improved for the affinity of extracting the similar rendering of EventViewer.


Enter [N/A] in the box, if an item is not applicable to your change.

Testing
Before we can approve your change; please submit the following in a comment:

  • Example configuration file for the change
PS> bin/fluent-bit -i winevtlog -p Channels=System -p render_event_as_text=On -o stdout -v
  • Debug log output from testing the change
Fluent Bit v5.0.0
* Copyright (C) 2015-2025 The Fluent Bit Authors
* Fluent Bit is a CNCF graduated project under the Fluent organization
* https://fluentbit.io

______ _                  _    ______ _ _           _____  _____           _
|  ___| |                | |   | ___ (_) |         |  ___||  _  |         | |
| |_  | |_   _  ___ _ __ | |_  | |_/ /_| |_  __   _|___ \ | |/' |______ __| | _____   __
|  _| | | | | |/ _ \ '_ \| __| | ___ \ | __| \ \ / /   \ \|  /| |______/ _` |/ _ \ \ / /
| |   | | |_| |  __/ | | | |_  | |_/ / | |_   \ V //\__/ /\ |_/ /     | (_| |  __/\ V /
\_|   |_|\__,_|\___|_| |_|\__| \____/|_|\__|   \_/ \____(_)\___/       \__,_|\___| \_/


[2026/02/10 16:55:27.402106400] [ info] Configuration:
[2026/02/10 16:55:27.402384100] [ info]  flush time     | 1.000000 seconds
[2026/02/10 16:55:27.402422700] [ info]  grace          | 5 seconds
[2026/02/10 16:55:27.402440800] [ info]  daemon         | 0
[2026/02/10 16:55:27.402457300] [ info] ___________
[2026/02/10 16:55:27.402473900] [ info]  inputs:
[2026/02/10 16:55:27.402490100] [ info]      winevtlog
[2026/02/10 16:55:27.402506000] [ info] ___________
[2026/02/10 16:55:27.402522000] [ info]  filters:
[2026/02/10 16:55:27.402541400] [ info] ___________
[2026/02/10 16:55:27.402561100] [ info]  outputs:
[2026/02/10 16:55:27.402579700] [ info]      stdout.0
[2026/02/10 16:55:27.402599400] [ info] ___________
[2026/02/10 16:55:27.402627300] [ info]  collectors:
[2026/02/10 16:55:27.403789400] [ info] [fluent bit] version=5.0.0, commit=d7dd1fd3ba, pid=54184
[2026/02/10 16:55:27.403835700] [debug] [engine] maxstdio set: 512
[2026/02/10 16:55:27.403854600] [debug] [engine] coroutine stack size: 98302 bytes (96.0K)
[2026/02/10 16:55:27.404240400] [ info] [storage] ver=1.5.4, type=memory, sync=normal, checksum=off, max_chunks_up=128
[2026/02/10 16:55:27.404261100] [ info] [simd    ] SSE2
[2026/02/10 16:55:27.404270400] [ info] [cmetrics] version=1.0.7
[2026/02/10 16:55:27.404282400] [ info] [ctraces ] version=0.7.0
[2026/02/10 16:55:27.404604600] [ info] [input:winevtlog:winevtlog.0] initializing
[2026/02/10 16:55:27.404621300] [ info] [input:winevtlog:winevtlog.0] storage_strategy='memory' (memory only)
[2026/02/10 16:55:27.404789200] [debug] [winevtlog:winevtlog.0] created event channels: read=776 write=780
[2026/02/10 16:55:27.404811800] [debug] [input:winevtlog:winevtlog.0] connect to local machine
[2026/02/10 16:55:27.404823600] [debug] [input:winevtlog:winevtlog.0] read limit per cycle is set up as 512.0K
[2026/02/10 16:55:27.405447100] [debug] [stdout:stdout.0] created event channels: read=816 write=820
[2026/02/10 16:55:27.406538500] [ info] [sp] stream processor started
[2026/02/10 16:55:27.406770600] [ info] [output:stdout:stdout.0] worker #0 started
[2026/02/10 16:55:27.406954300] [ info] [engine] Shutdown Grace Period=5, Shutdown Input Grace Period=2
[2026/02/10 16:55:33.418844900] [debug] [input:winevtlog:winevtlog.0] read 480 bytes from 'System'
[2026/02/10 16:55:34.413761700] [debug] [task] created task=0000021BC77B79E0 id=0 OK
[0] winevtlog.0: [[[2026/02/10 16:55:34.413818600] [debug] [output:stdout:stdout.0] task_id=0 assigned to thread #0
1770710133.418792300, {}], {"log"=>"ProviderName=Microsoft-Windows-Kernel-Power
ProviderGuid={331C3B3A-2005-44C2-AC5E-77220C37D6B4}
Qualifiers=
EventID=105
Version=1
Level=4
Task=100
Opcode=0
Keywords=0x8000000000000404
TimeCreated=2026-02-10 16:55:31 +0900
EventRecordID=61071
ActivityID=
RelatedActivityID=
ProcessID=4
ThreadID=59612
Channel=System
Computer=DESKTOP-JLLFF9D
UserID=NT AUTHORITY\SYSTEM
Message=Power source change.", "StringInserts"=>[false, 94676, 94676]}]
[2026/02/10 16:55:34.423879300] [debug] [out flush] cb_destroy coro_id=0
[2026/02/10 16:55:34.424140400] [debug] [task] destroy task=0000021BC77B79E0 (task_id=0)
[2026/02/10 16:55:36.417064400] [debug] [input:winevtlog:winevtlog.0] read 480 bytes from 'System'
[2026/02/10 16:55:37.425191500] [debug] [task] created task=0000021BC77B71C0 id=0 OK
[0] winevtlog.0: [[1770710136.416911800, {[2026/02/10 16:55:37.425218300] [debug] [output:stdout:stdout.0] task_id=0 assigned to thread #0
}], {"log"=>"ProviderName=Microsoft-Windows-Kernel-Power
ProviderGuid={331C3B3A-2005-44C2-AC5E-77220C37D6B4}
Qualifiers=
EventID=105
Version=1
Level=4
Task=100
Opcode=0
Keywords=0x8000000000000404
TimeCreated=2026-02-10 16:55:35 +0900
EventRecordID=61072
ActivityID=
RelatedActivityID=
ProcessID=4
ThreadID=50308
Channel=System
Computer=DESKTOP-JLLFF9D
UserID=NT AUTHORITY\SYSTEM
Message=Power source change.", "StringInserts"=>[true, 90184, 94676]}]
[2026/02/10 16:55:37.426037100] [debug] [out flush] cb_destroy coro_id=1
[2026/02/10 16:55:37.426084000] [debug] [task] destroy task=0000021BC77B71C0 (task_id=0)
[2026/02/10 16:55:42] [engine] caught signal (SIGINT)
[2026/02/10 16:55:42.542074800] [ warn] [engine] service will shutdown in max 5 seconds
[2026/02/10 16:55:42.542142700] [ info] [engine] pausing all inputs..
[2026/02/10 16:55:42.542169600] [ info] [input] pausing winevtlog.0
[2026/02/10 16:55:43.538159800] [ info] [engine] service has stopped (0 pending tasks)
[2026/02/10 16:55:43.538192900] [ info] [input] pausing winevtlog.0
[2026/02/10 16:55:43.538234500] [ info] [output:stdout:stdout.0] thread worker #0 stopping...
[2026/02/10 16:55:43.538599300] [ info] [output:stdout:stdout.0] thread worker #0 stopped

StringInserts is still handled as a separated key-arrayed-values. So, users can easily remove the latter pipeline or just removing with StringInsert=Off.

  • Attached Valgrind output that shows no leaks or memory corruption was found

If this is a change to packaging of containers or native binaries then please confirm it works for all targets.

  • Run local packaging test showing all targets (including any new ones) build.
  • Set ok-package-test label to test for all targets (requires maintainer to do).

Documentation

  • Documentation required for this feature

Backporting

  • Backport to latest stable release.

Fluent Bit is licensed under Apache 2.0, by submitting this pull request I understand that this code will be released under the terms of that license.

Summary by CodeRabbit

  • New Features

    • Add text-formatted event rendering: events can be emitted as key=value text payloads with optional structured string-inserts as an alternative to XML.
    • New configuration options to enable text rendering and customize the output key for rendered text.
  • Improvements

    • Validation prevents enabling both XML and text rendering and requires a non-empty text key when text rendering is enabled.
    • Improved error handling to ensure resources are cleaned up on invalid configuration.

Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
@coderabbitai
Copy link

coderabbitai bot commented Feb 10, 2026

📝 Walkthrough

Walkthrough

Adds a text-based rendering path and associated helpers to the Windows Event Log input plugin, introduces config options and validation for text vs XML rendering, adds UTF-8/guid/sid/time helpers and a text event packer, and unifies memory cleanup across rendering branches.

Changes

Cohort / File(s) Summary
Config & init
plugins/in_winevtlog/in_winevtlog.c, plugins/in_winevtlog/winevtlog.h
Adds config fields render_event_as_xml, render_event_as_text, render_event_text_key; validation for mutual exclusion and non-empty text key; ensures encoder/context are freed on init errors.
Text utilities & packing
plugins/in_winevtlog/pack.c
Adds wide-string→UTF‑8, GUID/SID→UTF‑8, FILETIME→string, uint→string helpers and winevtlog_pack_text_event() to build key=value text bodies and optionally include StringInserts as structured payload.
Runtime integration
plugins/in_winevtlog/winevtlog.c, plugins/in_winevtlog/pack.c, plugins/in_winevtlog/winevtlog.h
Integrates text rendering branch in read flow, calls the new packer, and unifies memory free ordering across XML, text, and default branches to avoid leaks.

Sequence Diagram(s)

sequenceDiagram
    participant EventProvider as "Event Provider"
    participant Reader as "winevtlog_read"
    participant Renderer as "render_system / get_description"
    participant Packer as "winevtlog_pack_text_event"
    participant Encoder as "log_encoder"

    EventProvider->>Reader: deliver event (system + message + inserts)
    Reader->>Renderer: render system metadata & message
    Renderer-->>Reader: rendered_system, message, string_inserts
    Reader->>Packer: pack text event (system, message, inserts, channel, ctx)
    Packer->>Encoder: append key=value payload (and optional StringInserts)
    Encoder-->>Reader: ack
    Reader->>Reader: free rendered buffers / cleanup
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • edsiper
  • fujimotos
  • koleini

Poem

🐰 I nibble bytes and shape them neat,
Keys and values hop in a line so sweet.
UTF‑8 fur and timestamps bright,
Events now sing in text by night.
Hooray — I thump, the logs delight!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and directly summarizes the main change: adding text format support for event rendering in the in_winevtlog plugin.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cosmo0920-add-text-rendering-format-on-in_winevtlog

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cosmo0920 cosmo0920 added this to the Fluent Bit v5.0 milestone Feb 10, 2026
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: adada3d79c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@plugins/in_winevtlog/pack.c`:
- Around line 1070-1081: The code unconditionally overwrites ret when calling
flb_log_event_encoder_append_body_string for ctx->render_event_text_key,
ignoring earlier failures from flb_log_event_encoder_begin_record and
flb_log_event_encoder_set_current_timestamp; update the flow so you check ret
after flb_log_event_encoder_begin_record and again after
flb_log_event_encoder_set_current_timestamp and only call
flb_log_event_encoder_append_body_string (for ctx->render_event_text_key and
later for text/out_len) when ret == FLB_EVENT_ENCODER_SUCCESS, preserving and
propagating the first failure instead of clobbering it; reference the ret
variable and the functions flb_log_event_encoder_begin_record,
flb_log_event_encoder_set_current_timestamp, and
flb_log_event_encoder_append_body_string on ctx->log_encoder (and the keys
ctx->render_event_text_key and text/out_len) when making these guard checks.
- Around line 122-143: In append_kv_line, failing flb_sds_cat calls can set
*text to NULL and subsequent flb_sds_cat calls will dereference it; update the
function (append_kv_line) to check the return of each flb_sds_cat invocation
immediately and return -1 on NULL instead of only after the final call, i.e.,
after each assignment like "*text = flb_sds_cat(...)" verify "*text != NULL" and
bail out if it is, so you never call flb_sds_cat with a NULL *text; keep the
existing input NULL checks for text/key and preserve the final newline append
and return codes.

In `@plugins/in_winevtlog/winevtlog.c`:
- Around line 930-946: The code calls render_system_event, get_description, and
get_string_inserts but only frees message and string_inserts inside the if
(rendered_system) block; add cleanup when render_system_event fails by ensuring
message and string_inserts are freed even if rendered_system is NULL (either add
an else branch after if (rendered_system) that flb_free(string_inserts) and
flb_free(message) as needed, or move the frees for string_inserts and message
out of the conditional), referencing render_system_event, get_description,
get_string_inserts, rendered_system, string_inserts, message and
winevtlog_pack_text_event so the allocation/free pairs are balanced.
🧹 Nitpick comments (2)
plugins/in_winevtlog/pack.c (2)

404-490: filetime_to_string largely duplicates pack_filetime.

The two functions share identical timezone / formatting logic. Consider extracting the shared core into a helper that returns the formatted string, then have both callers use it — pack_filetime would pass the result to the encoder, and filetime_to_string would return it to the caller.


585-615: Remove unused static function uint_to_string_u64.

This function has no callers anywhere in the codebase. The text event packer formats numeric fields inline via _snprintf_s instead, making this function dead code.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@plugins/in_winevtlog/pack.c`:
- Around line 873-891: The code in winevtlog_pack_text_event uses
flb_sds_create_size to allocate `text` but assumes it remains non-NULL after
calls to append_kv_line; if append_kv_line hit OOM and flb_sds_cat returned
NULL, `text` can become NULL and later flb_sds_len(text) will dereference NULL.
Fix by checking `text` for NULL after each append_kv_line call (or immediately
before any use like flb_sds_len/text concatenation near where flb_sds_len(text)
is called) and handle the OOM case by freeing/returning early (or propagating
the error). Ensure append_kv_line's contract is respected (it should return NULL
on failure) and add a guard in winevtlog_pack_text_event before using `text`
(and similarly around the block at lines 1074-1078) to avoid dereferencing a
NULL sds.
🧹 Nitpick comments (3)
plugins/in_winevtlog/pack.c (3)

413-499: filetime_to_string largely duplicates pack_filetime (~60 lines of identical timezone/formatting logic).

The only difference is the output sink: pack_filetime appends to the encoder, filetime_to_string returns a heap-allocated string. Consider extracting the shared FILETIME→local-time→formatted-string conversion into a single helper that both can call. This would eliminate the maintenance burden of keeping two copies in sync.

Also a minor nit: len is declared size_t (line 420) but receives int from _snprintf_s. The cast on line 482 works in practice (the buffer is large enough that truncation won't occur), but declaring len as int would be cleaner and match the return type.

Also applies to: 341-411


528-592: LookupAccountSidA shares a single len variable for both account and domain buffer sizes.

Line 558 passes &len for both cchName and cchReferencedDomainName. The API modifies both on output, so after the call len holds whichever was written last. This mirrors the same pattern in pack_sid (line 651–652), so it's a pre-existing quirk rather than a new bug. With MAX_NAME=256 it's unlikely to cause issues in practice, but using separate size variables would be more correct.

Suggested improvement
-    DWORD len = MAX_NAME, err = ERROR_SUCCESS;
+    DWORD name_len = MAX_NAME;
+    DWORD domain_len = MAX_NAME;
+    DWORD err = ERROR_SUCCESS;
     ...
-        if (LookupAccountSidA(NULL, sid, account, &len, domain, &len, &sid_type)) {
+        if (LookupAccountSidA(NULL, sid, account, &name_len, domain, &domain_len, &sid_type)) {

594-624: Remove the unused uint_to_string_u64 function.

This function (lines 594–624) is never called anywhere in the codebase. All numeric conversions in winevtlog_pack_text_event use inline _snprintf_s with a local numbuf buffer, making this function dead code.

Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@plugins/in_winevtlog/pack.c`:
- Around line 528-592: The LookupAccountSidA call in sid_to_utf8 uses a single
DWORD variable (len) for both the account and domain buffer sizes which is
incorrect; create two separate DWORD variables (e.g., name_len and domain_len)
initialized to MAX_NAME, pass &name_len for the account cchName and &domain_len
for cchReferencedDomainName, and adjust any logic that reads/uses those lengths
accordingly; also apply the same fix to the similar pattern in pack_sid to
ensure both calls use distinct size variables instead of the shared len.
🧹 Nitpick comments (2)
plugins/in_winevtlog/pack.c (2)

413-499: filetime_to_string duplicates most of pack_filetime (lines 341–411).

The two functions share nearly identical time-zone and formatting logic. Consider extracting the shared conversion into a common helper that both can call, reducing maintenance burden if the format or TZ logic changes.


594-624: Remove unused uint_to_string_u64 function.

This function is defined but never called anywhere in the codebase. Consider removing it to eliminate dead code.

Signed-off-by: Hiroshi Hatake <hiroshi@chronosphere.io>
@edsiper edsiper merged commit ac13de9 into master Feb 13, 2026
64 of 65 checks passed
@edsiper edsiper deleted the cosmo0920-add-text-rendering-format-on-in_winevtlog branch February 13, 2026 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants