Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Fixed
- **Docker container logs showed the container ID instead of the name** (#269): the shipped Fluent Bit pipeline had a `Copy container_name service` filter, but nothing ever set `container_name` (the Lua script only extracted the container ID from the log filepath, where the name does not appear), so the copy was a silent no-op and logs reached LogTide with no `service` and only `container_id`/`container_short_id` in metadata. `extract_container_id.lua` now resolves the container name from the container's `config.v2.json` (already available through the existing read-only `/var/lib/docker/containers` mount), caches it per container, and falls back to the 12-char short ID when the file is missing or unreadable, so the `service` field always gets the container name (or at worst the short ID). Verified end-to-end against the real `fluent/fluent-bit` image

## [1.0.3] - 2026-06-26

A security-focused release. It resolves a batch of privately reported issues (coordinated disclosure via KIberblick.de): cross-tenant read on the dashboard API endpoints, stored XSS via OTLP `service.name` in the service map, an open redirect on the auth-free login/register path, a DNS-rebinding gap in the SSRF guard's HTTP path, a first-admin bootstrap promotion race, and a capability-limit check-then-act race; trace span attributes are now PII-masked as well, and `service.name` is sanitized at ingestion as defense in depth. No database migrations; drop-in upgrade. Alongside the security work: two correctness follow-ups from the multi-engine bug-hunt sweep (issue #255): Sigma detection now honors full SigmaHQ field-modifier chains, and the service-map p95 is a true window percentile on every storage engine. The storage-layer change was validated against real ClickHouse, MongoDB and TimescaleDB. This line also fixes two operational bugs: a Redis memory leak where completed/failed BullMQ jobs were never evicted, and a nightly SigmaHQ sync that re-imported the whole catalog as enabled and auto-created alert rules. Plus a few frontend touch-ups: theme-aware trace/session IDs in the log detail, per-occurrence trace links on the error page, metadata copy buttons, a breadcrumbs timeline and nested metadata columns in log search.
Expand Down
35 changes: 34 additions & 1 deletion docker/extract_container_id.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,34 @@
-- Extract container ID from Docker log filepath
-- Extract container ID and name from Docker log filepath
-- Path format: /var/lib/docker/containers/CONTAINER_ID/CONTAINER_ID-json.log
-- The container name is not part of the path, so it is read from the
-- config.v2.json file that Docker keeps next to the log file.

-- Cache of container_id -> container name (or false when not resolvable),
-- so config.v2.json is read once per container, not once per record.
local name_cache = {}

local function lookup_container_name(container_id)
local cached = name_cache[container_id]
if cached ~= nil then
return cached or nil
end

local name = nil
local path = "/var/lib/docker/containers/" .. container_id .. "/config.v2.json"
local file = io.open(path, "r")
if file then
local content = file:read("*a")
file:close()
if content then
-- Container names always start with "/" in config.v2.json
-- (volume mounts also have "Name" keys, but without the slash)
name = content:match('"Name"%s*:%s*"/([^"]+)"')
end
end

name_cache[container_id] = name or false
return name
end

function extract_container_id(tag, timestamp, record)
-- Get the filepath from the record
Expand All @@ -15,6 +44,10 @@ function extract_container_id(tag, timestamp, record)
record["container_id"] = container_id
-- Add short ID (first 12 chars, like docker ps shows)
record["container_short_id"] = container_id:sub(1, 12)
-- Resolve the container name; fall back to the short ID so the
-- downstream "Copy container_name service" filter always works
record["container_name"] = lookup_container_name(container_id)
or record["container_short_id"]
end
end

Expand Down
2 changes: 1 addition & 1 deletion docker/fluent-bit.conf
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
Reserve_Data On
Preserve_Key On

# Extract container ID from filepath using Lua
# Extract container ID from filepath and container name from config.v2.json using Lua
[FILTER]
Name lua
Match docker.*
Expand Down
Loading