mirror of
https://github.com/hwchase17/langchain.git
synced 2025-05-29 11:09:07 +00:00
Added Python logging
tracer (#14190)
This PR creates a logging handler and adds a simple unit test of it Supercedes https://github.com/langchain-ai/langchain/pull/12862 --------- Co-authored-by: Harrison Chase <hw.chase.17@gmail.com>
This commit is contained in:
parent
1ea48a31da
commit
052e23be3e
@ -7,12 +7,14 @@ from langchain_core.tracers.stdout import (
|
||||
FunctionCallbackHandler,
|
||||
)
|
||||
|
||||
from langchain.callbacks.tracers.logging import LoggingCallbackHandler
|
||||
from langchain.callbacks.tracers.wandb import WandbTracer
|
||||
|
||||
__all__ = [
|
||||
"ConsoleCallbackHandler",
|
||||
"FunctionCallbackHandler",
|
||||
"LoggingCallbackHandler",
|
||||
"LangChainTracer",
|
||||
"LangChainTracerV1",
|
||||
"FunctionCallbackHandler",
|
||||
"ConsoleCallbackHandler",
|
||||
"WandbTracer",
|
||||
]
|
||||
|
46
libs/langchain/langchain/callbacks/tracers/logging.py
Normal file
46
libs/langchain/langchain/callbacks/tracers/logging.py
Normal file
@ -0,0 +1,46 @@
|
||||
__all__ = ["LoggingCallbackHandler"]
|
||||
|
||||
import logging
|
||||
from typing import Any, Optional
|
||||
from uuid import UUID
|
||||
|
||||
from langchain_core.exceptions import TracerException
|
||||
from langchain_core.tracers.stdout import FunctionCallbackHandler
|
||||
from langchain_core.utils.input import get_bolded_text, get_colored_text
|
||||
|
||||
|
||||
class LoggingCallbackHandler(FunctionCallbackHandler):
|
||||
"""Tracer that logs via the input Logger."""
|
||||
|
||||
name: str = "logging_callback_handler"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
logger: logging.Logger,
|
||||
log_level: int = logging.INFO,
|
||||
extra: Optional[dict] = None,
|
||||
**kwargs: Any,
|
||||
) -> None:
|
||||
log_method = getattr(logger, logging.getLevelName(level=log_level).lower())
|
||||
|
||||
def callback(text: str) -> None:
|
||||
log_method(text, extra=extra)
|
||||
|
||||
super().__init__(function=callback, **kwargs)
|
||||
|
||||
def on_text(
|
||||
self,
|
||||
text: str,
|
||||
*,
|
||||
run_id: UUID,
|
||||
parent_run_id: Optional[UUID] = None, # noqa: ARG002
|
||||
**kwargs: Any, # noqa: ARG002
|
||||
) -> None:
|
||||
try:
|
||||
crumbs_str = f"[{self.get_breadcrumbs(run=self._get_run(run_id=run_id))}] "
|
||||
except TracerException:
|
||||
crumbs_str = ""
|
||||
self.function_callback(
|
||||
f'{get_colored_text("[text]", color="blue")}'
|
||||
f' {get_bolded_text(f"{crumbs_str}New text:")}\n{text}'
|
||||
)
|
@ -0,0 +1,37 @@
|
||||
import logging
|
||||
import sys
|
||||
import uuid
|
||||
|
||||
import pytest
|
||||
|
||||
from langchain.callbacks.tracers import LoggingCallbackHandler
|
||||
|
||||
|
||||
def test_logging(
|
||||
caplog: pytest.LogCaptureFixture, capsys: pytest.CaptureFixture[str]
|
||||
) -> None:
|
||||
# Set up a Logger and a handler so we can check the Logger's handlers work too
|
||||
logger = logging.getLogger("test_logging")
|
||||
logger.setLevel(logging.INFO)
|
||||
logger.addHandler(logging.StreamHandler(sys.stdout))
|
||||
|
||||
handler = LoggingCallbackHandler(logger, extra={"test": "test_extra"})
|
||||
handler.on_text("test", run_id=uuid.uuid4())
|
||||
|
||||
# Assert logging actually took place
|
||||
assert len(caplog.record_tuples) == 1
|
||||
record = caplog.records[0]
|
||||
assert record.name == logger.name
|
||||
assert record.levelno == logging.INFO
|
||||
assert (
|
||||
record.msg == "\x1b[36;1m\x1b[1;3m[text]\x1b[0m \x1b[1mNew text:\x1b[0m\ntest"
|
||||
)
|
||||
# Check the extra shows up
|
||||
assert record.test == "test_extra" # type: ignore[attr-defined]
|
||||
|
||||
# Assert log handlers worked
|
||||
cap_result = capsys.readouterr()
|
||||
assert (
|
||||
cap_result.out
|
||||
== "\x1b[36;1m\x1b[1;3m[text]\x1b[0m \x1b[1mNew text:\x1b[0m\ntest\n"
|
||||
)
|
Loading…
Reference in New Issue
Block a user