Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
6ffbb99
Add log correlation context formatter
rishikeshdevsot Jun 17, 2026
db84dd8
Merge branch 'main' into pr-log-context
rishikeshdevsot Jun 18, 2026
fbb3df0
nit
rishikeshdevsot Jun 18, 2026
bc6cb86
Merge branch 'pr-log-context' of github.com:rishikeshdevsot/clp into …
rishikeshdevsot Jun 18, 2026
962ae48
add struct logging
rishikeshdevsot Jun 21, 2026
c13ecee
linter fixes
rishikeshdevsot Jun 22, 2026
aa7d947
Merge branch 'main' into pr-log-context
rishikeshdevsot Jun 22, 2026
c79962e
Merge branch 'main' into pr-log-context
rishikeshdevsot Jun 22, 2026
b325d9b
feat(logging): Implement structured JSON logging for CLP components
junhaoliao Jun 23, 2026
b2c8a33
docs(logging): Add logging documentation outlining component-specific…
junhaoliao Jun 23, 2026
dd31655
chore(dependencies): Update structlog dependency to version 26.1.0
junhaoliao Jun 23, 2026
63ea1a1
feat(logging): Enhance logging processors with context variable mergi…
junhaoliao Jun 23, 2026
79fd7d3
docs(logging): Update logging documentation to include links for comp…
junhaoliao Jun 23, 2026
0c1b40c
docs(logging): Add timestamp convention guidelines for structured ser…
junhaoliao Jun 23, 2026
715bc7d
Merge branch 'main' into pr-log-context
junhaoliao Jun 23, 2026
966fd23
docs(logging): reorder
junhaoliao Jun 23, 2026
718f6b6
added comments and re-ordered processor chains
rishikeshdevsot Jun 24, 2026
caa20a1
docs(logging): Expand docstrings with parameter and return value desc…
junhaoliao Jun 24, 2026
29d05d5
Merge branch 'main' into pr-log-context
rishikeshdevsot Jun 25, 2026
1d2d21a
clean up doc, future support for logging python services
rishikeshdevsot Jun 26, 2026
021334d
lint fix
rishikeshdevsot Jun 26, 2026
911bda3
linting fixes and comment fixes
rishikeshdevsot Jun 26, 2026
5a19890
fix doc to be consistent
rishikeshdevsot Jun 26, 2026
9134e5d
lint fixes
rishikeshdevsot Jun 26, 2026
4765eca
Merge branch 'main' into pr-log-context
rishikeshdevsot Jun 26, 2026
2956809
Apply suggestions from code review
rishikeshdevsot Jun 29, 2026
6924a1d
Apply suggestions from code review
rishikeshdevsot Jun 29, 2026
8d05764
added fixes from review
rishikeshdevsot Jun 29, 2026
e786072
Merge branch 'pr-log-context' of github.com:rishikeshdevsot/clp into …
rishikeshdevsot Jun 29, 2026
d3eb1d9
ran doc linter
rishikeshdevsot Jun 29, 2026
665a313
nit
rishikeshdevsot Jun 29, 2026
74b367b
cleanup logging.md
rishikeshdevsot Jun 29, 2026
d630c5e
restructured the logging docs
rishikeshdevsot Jun 29, 2026
91b152e
final developer guide
rishikeshdevsot Jun 29, 2026
1f7e0eb
docs(logging): Update logging guides for consistency and clarity
junhaoliao Jun 29, 2026
9345052
docs(logging): Correct typo in logging configuration documentation
junhaoliao Jun 29, 2026
f20f3a4
Revert "docs(logging): Update logging guides for consistency and clar…
junhaoliao Jun 29, 2026
ae977c0
refactor(logging): Update logger implementation to use BoundLogger
junhaoliao Jun 29, 2026
2f63368
polishing doc
rishikeshdevsot Jun 29, 2026
ae07065
Merge branch 'pr-log-context' of github.com:rishikeshdevsot/clp into …
rishikeshdevsot Jun 29, 2026
437c6de
docs(celery): Add module docstring for task execution configuration
junhaoliao Jun 29, 2026
1706cf9
docs(logging): Improve clarity and consistency in logging guides
junhaoliao Jun 29, 2026
58fcfd4
Merge branch 'main' into pr-log-context
rishikeshdevsot Jun 30, 2026
958a3a3
nits
rishikeshdevsot Jun 30, 2026
1166348
Update logging example in developer guide
rishikeshdevsot Jun 30, 2026
b9a7598
Merge branch 'main' into pr-log-context
rishikeshdevsot Jun 30, 2026
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
14 changes: 14 additions & 0 deletions components/clp-mcp-server/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions components/clp-package-utils/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

120 changes: 114 additions & 6 deletions components/clp-py-utils/clp_py_utils/clp_logging.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
"""Shared logging helpers for CLP Python components."""

import logging
import os
import pathlib
from typing import get_args, Literal

import structlog
from structlog.stdlib import BoundLogger
from structlog.typing import Processor

LoggingLevel = Literal[
"INFO",
"DEBUG",
Expand All @@ -12,12 +18,107 @@
"CRITICAL",
]

# Processor chain for events emitted through structlog loggers before they reach
# `ProcessorFormatter`.
_STRUCTLOG_PROCESSORS: tuple[Processor, ...] = (
structlog.stdlib.filter_by_level,
structlog.contextvars.merge_contextvars,
structlog.stdlib.add_logger_name,
structlog.stdlib.add_log_level,
structlog.stdlib.PositionalArgumentsFormatter(),
structlog.processors.TimeStamper(fmt="iso", utc=True, key="timestamp"),
structlog.processors.StackInfoRenderer(),
structlog.processors.format_exc_info,
structlog.processors.UnicodeDecoder(),
structlog.processors.CallsiteParameterAdder(
{
structlog.processors.CallsiteParameter.FILENAME,
structlog.processors.CallsiteParameter.FUNC_NAME,
structlog.processors.CallsiteParameter.LINENO,
}
),
)

# Processor chain for stdlib `LogRecord` objects that did not originate from structlog.
_FOREIGN_PRE_CHAIN: tuple[Processor, ...] = (
structlog.contextvars.merge_contextvars,
structlog.stdlib.add_logger_name,
structlog.stdlib.add_log_level,
structlog.stdlib.ExtraAdder(),
structlog.stdlib.PositionalArgumentsFormatter(),
structlog.processors.TimeStamper(fmt="iso", utc=True, key="timestamp"),
structlog.processors.StackInfoRenderer(),
structlog.processors.format_exc_info,
structlog.processors.UnicodeDecoder(),
structlog.processors.CallsiteParameterAdder(
{
structlog.processors.CallsiteParameter.FILENAME,
structlog.processors.CallsiteParameter.FUNC_NAME,
structlog.processors.CallsiteParameter.LINENO,
}
),
)


def configure_structlog() -> None:
"""Configure structlog with CLP's default processor chain if it is not already configured."""
if not structlog.is_configured():
structlog.configure(
processors=[
*_STRUCTLOG_PROCESSORS,
structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
],
logger_factory=structlog.stdlib.LoggerFactory(),
wrapper_class=BoundLogger,
cache_logger_on_first_use=True,
)


def get_structlog_logger(name: str) -> BoundLogger:
"""
Configure CLP's structured logging defaults and return a structlog logger for a component.

CLP uses structlog's stdlib integration, so this first configures the stdlib logger's
handlers with structlog's `ProcessorFormatter`. Use the returned structlog logger for log calls.

:param name: Name of the logger to create or retrieve.
:return: A structlog logger configured to emit through CLP's JSON formatter.
"""
configure_structlog()
stdlib_logger = get_logger(name)
configure_logging(stdlib_logger, name)
return structlog.stdlib.get_logger(name)


def get_logging_formatter() -> logging.Formatter:
""":return: A JSON log formatter configured with CLP's structlog processors."""
return structlog.stdlib.ProcessorFormatter(
# foreign_pre_chain is run for stdlib LogRecord objects that do not go through
# structlog's processor chain.
foreign_pre_chain=_FOREIGN_PRE_CHAIN,
processors=[
structlog.stdlib.ProcessorFormatter.remove_processors_meta,
structlog.processors.JSONRenderer(),
],
)


def get_logging_formatter():
return logging.Formatter("%(asctime)s %(name)s [%(levelname)s] %(message)s")
def set_json_formatter_on_handlers(logger: logging.Logger) -> None:
"""
Set CLP's JSON log formatter on all handlers currently attached to the logger.

:param logger: Logger whose handlers should use CLP's JSON formatter.
"""
formatter = get_logging_formatter()
for handler in logger.handlers:
handler.setFormatter(formatter)


def get_logger(name: str):
def get_logger(name: str) -> logging.Logger:
"""
:param name: Name of the logger to create or retrieve.
:return: A logger configured with CLP's JSON console formatter.
"""
logger = logging.getLogger(name)
# Setup console logging
logging_console_handler = logging.StreamHandler()
Expand All @@ -28,12 +129,19 @@ def get_logger(name: str):
return logger


def set_logging_level(logger: logging.Logger, level: str | None):
def set_logging_level(logger: logging.Logger, level: str | None) -> None:
"""
Set a logger to the requested logging level, defaulting to INFO when the level is unset or
invalid.

:param logger: Logger whose level should be updated.
:param level: Requested logging level, or `None` to use INFO.
"""
if level is None:
logger.setLevel(logging.INFO)
return
if level not in get_args(LoggingLevel):
logger.warning(f"Invalid logging level: {level}, using INFO as default")
logger.warning("Invalid logging level: %s, using INFO as default", level)
logger.setLevel(logging.INFO)
return

Expand All @@ -43,7 +151,7 @@ def set_logging_level(logger: logging.Logger, level: str | None):
def configure_logging(
logger: logging.Logger,
component_name: str,
):
) -> None:
"""
Configures file logging and the logging level for a logger using environment variables.

Expand Down
1 change: 1 addition & 0 deletions components/clp-py-utils/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ dependencies = [
"result>=0.17.0",
"sqlalchemy>=2.0.46",
"StrEnum>=0.4.15",
"structlog>=26.1.0",
]

[build-system]
Expand Down
14 changes: 14 additions & 0 deletions components/clp-py-utils/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
from celery import Celery
from celery.signals import worker_process_init, worker_process_shutdown
"""Celery app configuration for compression task execution."""

import logging

from celery import Celery, signals
from clp_py_utils.clp_logging import set_json_formatter_on_handlers
from clp_py_utils.telemetry import init_telemetry, shutdown_telemetry

from job_orchestration.executor.compress import celeryconfig
Expand All @@ -8,12 +12,25 @@
app.config_from_object(celeryconfig)


@worker_process_init.connect
@signals.after_setup_logger.connect
@signals.after_setup_task_logger.connect
def setup_json_logging(logger: logging.Logger | None = None, **_: object) -> None:
"""
Use CLP's JSON formatter for loggers configured by Celery.

:param logger: Logger configured by Celery, if one was provided by the signal.
:param _: Additional Celery signal keyword arguments. Unused.
"""
if logger is not None:
set_json_formatter_on_handlers(logger)


@signals.worker_process_init.connect
def setup_telemetry(**kwargs) -> None:
init_telemetry()


@worker_process_shutdown.connect
@signals.worker_process_shutdown.connect
def teardown_telemetry(**kwargs) -> None:
shutdown_telemetry()

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
from celery import Celery
"""Celery app configuration for query task execution."""

import logging

from celery import Celery, signals
from clp_py_utils.clp_logging import set_json_formatter_on_handlers

from job_orchestration.executor.query import celeryconfig

app = Celery("query")
app.config_from_object(celeryconfig)


@signals.after_setup_logger.connect
@signals.after_setup_task_logger.connect
def setup_json_logging(logger: logging.Logger | None = None, **_: object) -> None:
"""
Use CLP's JSON formatter for loggers configured by Celery.

:param logger: Logger configured by Celery, if one was provided by the signal.
:param _: Additional Celery signal keyword arguments. Unused.
"""
if logger is not None:
set_json_formatter_on_handlers(logger)


if "__main__" == __name__:
app.start()
14 changes: 14 additions & 0 deletions components/job-orchestration/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions docs/src/dev-docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ tooling-gh-workflows

design-project-structure
design-deployment-orchestration
logging

design-kv-ir-streams/index
design-metadata-db
Expand Down
Loading
Loading