Skip to content

fix: set up log formatting to human readable text and set that as the default#43

Closed
ktstrader wants to merge 1 commit into
mainfrom
fix/BED-8744-add-text-log-format
Closed

fix: set up log formatting to human readable text and set that as the default#43
ktstrader wants to merge 1 commit into
mainfrom
fix/BED-8744-add-text-log-format

Conversation

@ktstrader

@ktstrader ktstrader commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Description

OpenHound previously wrote all file/stdout logs as JSON, which is hard to read when tailing logs or debugging locally. So this introduces human-readable plain-text log format and makes it the default, while keeping structured JSON available as an opt-in.

Changes:

  • New OpenHoundTextFormatter — renders each record as a single readable line:
    2026-06-25 12:00:00 [INFO] logger:function:line - message | key=value
  • Extra/structured fields (e.g. resource, phase, extension) are appended as key=value pairs so context is preserved without full JSON. Null extras (like taskName) are dropped, and exceptions are appended on a following line.
  • Format selection — added log_format (default "text"), a _validate_format() helper, and a _file_formatter() method that returns the JSON or text formatter based on config. All three handler modes (container, CLI, service) now use _file_formatter() instead of hardcoding JSON.
  • Config toggle via dlt's reserved key — the format is read from runtime.log_format. dlt treats only the exact string "JSON" specially (and skips format-string validation for it), so we piggyback on that: "JSON" selects JSON logs; anything else (including dlt's default format string when unset) falls back to text. This avoids introducing a separate namespace and avoids the ValueError: invalid format crash that other values trigger.
  • Example configs — removed the hardcoded log_format = "JSON" from both BloodHound Community and Enterprise example configs; documented text as the default with a commented, uppercase # log_format = "JSON" opt-in.

Tests:

  • test_validate_format_defaults_to_text — validates "JSON"/"text" and the text fallback for invalid values.
  • test_file_formatter_selection — confirms log_format selects the matching formatter.
  • test_text_formatter_produces_plain_text — asserts the text output renders the message/args, level, location, and extras, and is not valid JSON.
  • test_log_routing_content — pins RUNTIME__LOG_FORMAT=JSON so its JSON-parsing assertions stay self-contained regardless of the new default.

Motivation and Context

Resolves: BED-8744

Screenshots

Default:

2026-06-25 11:48:13 [INFO] openhound.core.manager:validate_metadata:119 - Extension 'faker' has valid metadata | extension=faker phase=metadata_validation
2026-06-25 11:48:13 [INFO] openhound.core.manager:from_entrypoint:156 - Loaded extension 'faker' from entry point 'openhound.sources' | extension=faker phase=extension_loading
2026-06-25 11:48:13 [INFO] openhound.core.manager:validate_metadata:119 - Extension 'github' has valid metadata | extension=github phase=metadata_validation
2026-06-25 11:48:13 [INFO] openhound.core.manager:from_entrypoint:156 - Loaded extension 'github' from entry point 'openhound.sources' | extension=github phase=extension_loading
2026-06-25 11:48:13 [INFO] openhound.core.manager:validate_metadata:119 - Extension 'jamf' has valid metadata | extension=jamf phase=metadata_validation
2026-06-25 11:48:13 [INFO] openhound.core.manager:from_entrypoint:156 - Loaded extension 'jamf' from entry point 'openhound.sources' | extension=jamf phase=extension_loading
2026-06-25 11:48:13 [INFO] openhound.core.collect:run:61 - Starting collector 'jamf'
2026-06-25 11:48:14 [ERROR] openhound.core.resources:sync_wrapper:68 - Error in resource 'users' during iteration: Expecting value: line 1 column 1 (char 0) | resource=users phase=resource_iteration

With log_format = "JSON" set in config.toml:

{"timestamp": "2026-06-25 11:46:12", "level": "INFO", "logger": "openhound.core.manager", "module": "manager", "function": "validate_metadata", "line": 119, "message": "Extension 'faker' has valid metadata", "openhound_version": "0.2.9.dev1", "taskName": null, "extension": "faker", "phase": "metadata_validation"}
{"timestamp": "2026-06-25 11:46:12", "level": "INFO", "logger": "openhound.core.manager", "module": "manager", "function": "from_entrypoint", "line": 156, "message": "Loaded extension 'faker' from entry point 'openhound.sources'", "openhound_version": "0.2.9.dev1", "taskName": null, "extension": "faker", "phase": "extension_loading"}
{"timestamp": "2026-06-25 11:46:12", "level": "INFO", "logger": "openhound.core.manager", "module": "manager", "function": "validate_metadata", "line": 119, "message": "Extension 'github' has valid metadata", "openhound_version": "0.2.9.dev1", "taskName": null, "extension": "github", "phase": "metadata_validation"}

@ktstrader ktstrader self-assigned this Jun 25, 2026
@ktstrader ktstrader closed this Jun 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant