Establish enforced logging port (#286) - #292
Conversation
Wrap femtologging behind an opaque LoggerHandle and route all Episodic emission paths through level-specific port helpers. This makes correlation context attachable at one seam and rejects raw logger method calls. Enforce the backend import boundary with Hecate, add type and scanner regressions, and document the logging-port contract.
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueWarning Your free Security trial is over. An organization admin can activate billing to continue. Comment |
Reviewer's GuideThis PR establishes episodic.logging as the sole production logging seam by wrapping femtologging behind an opaque LoggerHandle, migrating operational and structured logging paths to wrapper-based emission, and enforcing both import and direct-call boundaries through Hecate, ty, and a production-tree regression scanner. File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Gates Failed
Enforce advisory code health rules
(3 files with Code Duplication, Large Method)
Our agent can fix these. Install it.
Gates Passed
5 Quality Gates Passed
Reason for failure
| Enforce advisory code health rules | Violations | Code Health Impact | |
|---|---|---|---|
| test_chrono_langgraph.py | 1 advisory rule | 10.00 → 9.39 | Suppress |
| architecture_hecate_config.py | 1 advisory rule | 10.00 → 9.60 | Suppress |
| logging.py | 1 advisory rule | 9.39 → 9.10 | Suppress |
Quality Gate Profile: Pay Down Tech Debt
Install CodeScene MCP: safeguard and uplift AI-generated code. Catch issues early with our IDE extension and CLI tool.
|
|
||
|
|
||
| def log_error( | ||
| logger: _CompatibleLogger, |
There was a problem hiding this comment.
❌ Getting worse: Code Duplication
introduced similar code in: log_debug,log_exception
| def _external_logging_fixture_config(package: str) -> str: | ||
| """Return a fixture policy that enforces the femtologging boundary.""" | ||
| return textwrap.dedent( | ||
| f"""\ | ||
| [tool.hecate] | ||
| root_packages = ["{package}"] | ||
| default_rule_id = "ARCH001" | ||
| include_external_packages = true | ||
|
|
||
| [[tool.hecate.groups]] | ||
| name = "logging_port" | ||
| prefixes = ["{package}.logging"] | ||
| allowed = ["logging_port", "logging_backend"] | ||
|
|
||
| [[tool.hecate.groups]] | ||
| name = "logging_backend" | ||
| prefixes = ["femtologging"] | ||
| allowed = ["logging_backend"] | ||
|
|
||
| [[tool.hecate.groups]] | ||
| name = "external_libraries" | ||
| prefixes = [ | ||
| "alembic", | ||
| "celery", | ||
| "falcon", | ||
| "httpx", | ||
| "langgraph", | ||
| "openai", | ||
| "pydantic", | ||
| "sqlalchemy", | ||
| ] | ||
| allowed = ["external_libraries"] | ||
|
|
||
| [[tool.hecate.groups]] | ||
| name = "composition_root" | ||
| prefixes = ["{package}.runtime"] | ||
| allowed = [ | ||
| "application", | ||
| "composition_root", | ||
| "domain", | ||
| "external_libraries", | ||
| "inbound_adapter", | ||
| "logging_port", | ||
| "outbound_adapter", | ||
| ] | ||
|
|
||
| [[tool.hecate.groups]] | ||
| name = "domain" | ||
| prefixes = ["{package}.domain"] | ||
| allowed = ["domain", "external_libraries", "logging_port"] | ||
|
|
||
| [[tool.hecate.groups]] | ||
| name = "application" | ||
| prefixes = ["{package}.service"] | ||
| allowed = ["application", "domain", "external_libraries", "logging_port"] | ||
|
|
||
| [[tool.hecate.groups]] | ||
| name = "inbound_adapter" | ||
| prefixes = ["{package}.api"] | ||
| allowed = [ | ||
| "application", | ||
| "domain", | ||
| "external_libraries", | ||
| "inbound_adapter", | ||
| "logging_port", | ||
| ] | ||
|
|
||
| [[tool.hecate.groups]] | ||
| name = "outbound_adapter" | ||
| prefixes = ["{package}.storage"] | ||
| allowed = [ | ||
| "application", | ||
| "domain", | ||
| "external_libraries", | ||
| "logging_port", | ||
| "outbound_adapter", | ||
| ] | ||
| """ | ||
| ) |
There was a problem hiding this comment.
❌ New issue: Large Method
_external_logging_fixture_config has 71 lines, threshold = 70
| errors: list[tuple[str, tuple[object, ...], dict[str, object]]] = [] | ||
|
|
||
| def capture_error( | ||
| logger: object, |
There was a problem hiding this comment.
❌ New issue: Code Duplication
The module contains 2 functions with similar structure: test_chrono_node_logs_evaluation_failure,test_chrono_node_logs_missing_request
Summary
Closes #286.
episodic.loggingas the explicit logging port, with an opaqueLoggerHandleand wrappers for debug, info, warning, error, and exceptionemission.
orchestration, observability, and provider-error paths.
regressions through
tyand a production-tree scanner.rules for future cross-cutting logging changes.
Validation
make check-fmtmake lintmake typecheckmake check-architecturemake markdownlintmake nixietimeout-retry tests.
make testcompleted with 1,230 passing and 3 skipped; its twotimeout-only environment-wiring tests then passed in isolated sequential
retries.
References
Summary by Sourcery
Enforce
episodic.loggingas the sole application logging port and prevent production code from bypassing it.New Features:
LoggerHandleand explicit wrapper functions as the publicepisodic.loggingport for debug, info, warning, error, and exception emission.Bug Fixes:
Enhancements:
Documentation:
Tests: