Skip to content

Latest commit

 

History

History
263 lines (242 loc) · 14.4 KB

File metadata and controls

263 lines (242 loc) · 14.4 KB

Repository Guidelines

Preferred Commands

  • Configure: cmake -S . -B build -DFLB_TESTS_RUNTIME=On -DFLB_TESTS_INTERNAL=On
  • Build: cmake --build build -j8
  • Test: ctest --test-dir build --output-on-failure
  • Prefer targeted tests with ctest --test-dir build -R <name> --output-on-failure when the affected area is known, because the full enabled suite can be slow.
  • Run a focused integration test with ctest --test-dir build -R flb-it-opentelemetry --output-on-failure
  • Run the in-tree Python integration suite with: cd tests/integration && ./setup-venv.sh && ./run_tests.py
  • List available Python integration scenarios with: cd tests/integration && ./run_tests.py --list
  • Run locally with ./build/bin/fluent-bit -c conf/fluent-bit.conf

Project Structure & Module Organization

Fluent Bit is a C/C++ monorepo built with CMake.

  • src/: core engine/runtime (flb_* components, schedulers, routing, I/O).
  • include/fluent-bit/: public/internal headers used by core and plugins.
  • plugins/: input/filter/processor/output plugins (in_*, filter_*, processor_*, out_*).
  • lib/: bundled libraries (e.g., cprofiles, ctraces, cmetrics, chunkio).
  • tests/: integration/runtime tests and fixtures.
  • tests/integration/: in-tree Python integration test suite for end-to-end plugin and protocol validation; introduced from the original github.com/fluent/fluent-bit-test-suite project.
  • conf/: sample configurations for local validation.

Keep changes scoped: plugin logic in its plugin directory, shared behavior in src/ or lib/.

Build, Test, and Development Commands

  • cmake -S . -B build -DFLB_TESTS_RUNTIME=On -DFLB_TESTS_INTERNAL=On: configure with runtime + internal tests.
  • cmake --build build -j8: compile Fluent Bit and tests.
  • ctest --test-dir build --output-on-failure: run enabled tests.
  • ctest --test-dir build -R flb-it-opentelemetry --output-on-failure: run a focused integration test.
  • cd tests/integration && ./setup-venv.sh: create the local virtualenv for the Python integration suite.
  • cd tests/integration && ./run_tests.py --list: list available Python integration scenarios.
  • cd tests/integration && ./run_tests.py: run the full Python integration suite against build/bin/fluent-bit.
  • cd tests/integration && FLUENT_BIT_BINARY=/path/to/fluent-bit ./run_tests.py: run the Python integration suite against a specific binary.
  • ./build/bin/fluent-bit -c conf/fluent-bit.conf: run locally with a config.

Coding Style & Naming Conventions

  • Follow Apache-style C conventions used by Fluent Bit.
  • Use 4-space tabs/indentation and target 100 chars per line; 120 chars max.
  • Always use braces for if/else/while/do blocks.
  • Put function opening braces on the next line: int fn(void)\n{ ... }
  • Keep short boolean conditions on one line when they fit within 100 chars.
  • Wrap conditions only when needed, and break at logical operators (&&, ||); do not force one operand per line when readability does not improve.
  • Keep short function calls on one line when they fit; avoid splitting each argument into separate lines unless line length or clarity requires it.
  • Declare variables at the start of functions, not mid-block.
  • Prefer descriptive snake_case for functions/variables and flb_*/cprof_* prefixes.
  • Use /* ... */ comments (single or multiline), with wrapped long comments.

Testing Guidelines

  • Add or update tests for behavior changes, especially protocol parsing and encoder/decoder paths.
  • Prefer targeted tests close to the changed module (tests/internal, plugin runtime tests).
  • Prefer focused ctest -R ... runs or specific test binaries when the touched area is known.
  • Use tests/integration when validating end-to-end plugin behavior, network protocols, downstream request generation, or local fake-server interactions that are awkward to cover in ctest binaries alone.
  • The Python integration suite is not part of the default CMake ctest targets; run it explicitly from tests/integration.
  • Do not skip focused integration coverage for a touched component when that component has a corresponding tests/integration scenario. Agents must run the focused scenario(s) for the touched component before closing the task.
  • For touched components covered by tests/integration, agents must run the focused scenario(s) twice:
    • once normally to verify behavior;
    • once with valgrind enabled to verify memory-safety behavior.
  • The default expectation for component verification is: ./tests/integration/setup-venv.sh cmake -S . -B build -DFLB_TESTS_RUNTIME=On -DFLB_TESTS_INTERNAL=On cmake --build build -j8 tests/integration/.venv/bin/python -m pytest <focused-scenario> -q VALGRIND=1 VALGRIND_STRICT=1 tests/integration/.venv/bin/python -m pytest <focused-scenario> -q
  • Run broader test coverage when changing shared lifecycle, routing, storage, or accounting code.
  • Validate both success and failure paths (invalid payloads, boundary sizes, null/missing fields).
  • You can also run specific binaries from build/bin (e.g., ./bin/flb-it-opentelemetry).
  • When changing code covered by tests/integration, agents must verify the affected scenarios are valgrind-clean. Run the focused integration tests with tests/integration/run_tests.py --valgrind --valgrind-strict ... and do not stop at functional pass/fail if memory errors or leaks remain.
  • If a focused integration or valgrind run cannot be executed, agents must not silently skip it. They must report the exact blocker in the final response (for example: missing binary, missing Python environment, unsupported scenario, missing dependency, or infrastructure failure).
  • Final task close-outs must include proof of verification:
    • the exact focused integration command(s) run;
    • whether valgrind was used;
    • pass/fail status;
    • any concrete blocker if a required run could not be completed.
  • Keep generated integration artifacts out of git. Do not commit .venv/, .pytest_cache/, results/, or __pycache__/ under tests/integration.

Commit & Pull Request Guidelines

  • Prefix commit subjects with the component/plugin name in lowercase, e.g.:
    • engine: fix flush buffer handling
    • in_opentelemetry: profiles: fix ingestion path
  • Keep subject/body lines <= 80 chars.
  • Keep each commit scoped to one component/prefix; avoid mixed-area commits.
  • Sign commits with DCO: git commit -s.
  • PRs should include: problem statement, scope, test evidence (ctest output), and compatibility notes.
  • If behavior changes user output/config, include a short before/after example.
  • Target master for next major by default; open backport PRs to release branches (1.x) when needed.

Commit Pattern (Branch Practice)

  • Follow observed local history style:
    • component/plugin: component: short imperative description
    • internal tests: tests: internal: short imperative description
    • integration tests under tests/integration/: tests: integration: short imperative description
    • runtime tests/binaries outside tests/integration/: tests: runtime: short imperative description
  • The repository commit-prefix linter in .github/scripts/commit_prefix_check.py is authoritative. When its inferred prefix set is narrower than a hand-written nested subject, follow the linter. Examples from current repo history:
    • include/fluent-bit/config_format/flb_cf.h + src/config_format/flb_cf_yaml.c => config_format:
    • tests/internal/env.c => env: or tests:
    • tests/internal/fuzzers/config_map_fuzzer.c => config_map_fuzzer: or tests:
    • tests/internal/config_map.c => config_map: or tests:
  • Agents must follow this same style when proposing commit subjects or git commit commands; do not invent ad hoc prefixes such as environment: when the touched files map to an existing component or test area prefix.
  • When suggesting commit commands, include DCO signing by default with git commit -s unless the user explicitly asks otherwise.
  • Keep one interface per commit. If an interface touches both .c and .h, commit them together in the same commit.
  • Do not bundle different interfaces into one commit just because they support the same feature. Core config-map changes, input/output/filter/custom/ processor plumbing, plugin changes, tests, and documentation must be split into separate commits unless they are the same interface.
  • Do not mix unrelated interfaces in one commit.
  • Do not include AGENTS.md or other documentation updates in a code commit unless the user explicitly asks for a docs+code combined commit.
  • Prefer concise one-line subjects unless extra context is required.
  • Detect and avoid bad squash commits. Do not place YAML examples, config lines, or multiple subject-like prefix lines in the commit body unless they are fenced code blocks.

Commit Lint Workflow

  • When the user asks for git commit commands, provide commands that also verify commit-prefix lint before push or PR submission.
  • After creating a commit when the user asked for a commit, agents must run the repo linter before closing the task and fix any bad commit subject immediately.
  • Do not treat a local non-PR linter pass as sufficient before push. Outside GitHub PR context, .github/scripts/commit_prefix_check.py validates only HEAD, which can miss earlier commits in the branch.
  • Run the same checker used in CI: python .github/scripts/commit_prefix_check.py
  • The checker requires gitpython. If python -c 'import git' fails, install it before running the linter: python3 -m pip install gitpython
  • Do not assume a generic docs: prefix is acceptable. Check the touched file prefixes from repo history and from .github/scripts/commit_prefix_check.py path inference before choosing a commit subject. For example, changes only to AGENTS.md must use agents:, not docs:.
  • For pull-request-style validation, use full history and fetch the base branch first, matching CI behavior: git fetch --all --prune git fetch origin <base-branch>:origin/<base-branch>
  • Before pushing a branch or opening/updating a PR, agents must lint the full PR commit range against the base branch, not just the latest commit. Use the CI-style environment when possible, for example: GITHUB_EVENT_NAME=pull_request GITHUB_BASE_REF=<base-branch> python .github/scripts/commit_prefix_check.py
  • If a commit mixes component code and integration tests, do not assume a local HEAD-only lint pass proves the earlier code commit is acceptable. Validate the whole branch range before push/PR submission.
  • When giving commit-command sequences to the user, include a final lint step that checks the PR range and mention the gitpython install step if it may be missing locally.

Agent Action Limits

  • Do not open issues, pull requests, or remote branches unless the user explicitly asks.
  • Do not rewrite git history, amend commits, or force-push unless the user explicitly asks.
  • Do not revert user changes outside the requested scope.
  • Prefer minimal patches that avoid unrelated formatting or refactoring churn.

Agent Playbook (Pipeline Architecture Primer)

Runtime model (mental map)

  • Fluent Bit moves data through: input -> chunk -> router -> task -> filter/processor -> output -> engine result handling.
  • Routing is per output instance; one chunk can fan out to many routes.
  • Route state is independent (success/retry/drop can differ per output).

Data units and boundaries

  • A signal is the high-level type: logs, metrics, traces, profiles, blobs.
  • A record/event is the logical payload unit inside a signal.
  • A chunk is the persisted/queued container (often MessagePack-backed).
  • A task is the engine execution unit for a chunk across routes.
  • Never assume "one chunk = one route" or "one serialized event = one log record" in shared code.

Component responsibilities

  • Inputs (plugins/in_*) create/append data and trigger ingestion.
  • Input chunk layer (src/flb_input_chunk.c) manages lifecycle, routing masks, storage pressure, and drop/release behavior.
  • Router (src/flb_router*.c) resolves tag/signal matches to outputs.
  • Task layer (src/flb_task.c) tracks per-route state and retries.
  • Filters (plugins/filter_*) run on matching streams before output flush.
  • Processors (plugins/processor_*) can run in input/output contexts depending on configuration and may mutate/drop payloads.
  • Outputs (plugins/out_*) serialize/protocol-encode and return flush result.
  • Engine (src/flb_engine.c) applies final retry/drop accounting and task teardown.

Signal-aware behavior rules

  • Shared paths must branch correctly by event_type (logs vs non-logs).
  • Some logic is meaningful only for logs (record-level semantics), while metrics/traces/profiles/blobs may follow different serialization/counting.
  • Group/metadata markers can exist as serialized events; treat them as transport/data-shape artifacts unless the interface explicitly requires them.

Counting and metrics guidance

  • Separate these concepts when reviewing code:
    • serialized events in a buffer
    • logical records after processing
    • per-route processed/retry/drop counters
    • byte accounting (chunk bytes vs route-effective bytes)
  • Prefer route-aware values when updating route metrics.
  • Preserve explicit zero values; use clear sentinel values for "unknown".

Retry/drop semantics

  • FLB_OK: route succeeded.
  • FLB_RETRY: route keeps task/chunk for retry scheduling.
  • FLB_ERROR: route failure/drop path.
  • Final chunk release happens only when all active routes are resolved.

Storage/backlog interaction

  • In-memory and filesystem backlog paths may use different code paths; validate both when touching chunk/task lifecycle.
  • Backlog-loaded chunks must preserve route state and accounting parity with live-ingested chunks.

Review checklist before patching

  • Trace one full path for affected signals: input -> chunk -> task -> output -> engine completion.
  • Verify fan-out behavior (single chunk, multiple outputs).
  • Verify processing behavior (drop/modify/no-op) in both input and output processor contexts.
  • Verify empty payload behavior (outputs should not crash on zero records).
  • Verify metrics/counters for success, retry, and drop paths.

Testing strategy

  • Use tests/internal for core lifecycle/accounting logic.
  • Use tests/runtime for plugin-level behavior and end-to-end semantics.
  • Add regression tests for:
    • mixed signals
    • processor drop/modify paths
    • multi-route fan-out
    • backlog + live ingestion parity