Skip to content

Commit

Permalink
Merge pull request stanfordnlp#684 from KCaverly/logging_v0
Browse files Browse the repository at this point in the history
Add initial Logger
  • Loading branch information
okhat authored Mar 25, 2024
2 parents 2dacce4 + b3a1b14 commit c8375fc
Show file tree
Hide file tree
Showing 9 changed files with 519 additions and 417 deletions.
10 changes: 1 addition & 9 deletions dsp/modules/azure_openai.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import logging

# Configure logging
logging.basicConfig(
level=logging.INFO,
format="%(message)s",
handlers=[logging.FileHandler("azure_openai_usage.log")],
)

import functools
import json
import logging
from typing import Any, Literal, Optional, cast

import backoff
Expand Down
11 changes: 0 additions & 11 deletions dsp/modules/databricks.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,3 @@
import logging

# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(message)s',
handlers=[
logging.FileHandler('openai_usage.log'),
],
)

import functools
import json
from typing import Literal, Optional
Expand Down
10 changes: 1 addition & 9 deletions dsp/modules/gpt3.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import logging

# Configure logging
logging.basicConfig(
level=logging.INFO,
format="%(message)s",
handlers=[logging.FileHandler("openai_usage.log")],
)

import functools
import json
import logging
from typing import Any, Literal, Optional, cast

import backoff
Expand Down
1 change: 1 addition & 0 deletions dspy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

# Functional must be imported after primitives, predict and signatures
from .functional import * # isort: skip
from .utils.logging import logger, set_log_level, set_log_output

settings = dsp.settings

Expand Down
1 change: 1 addition & 0 deletions dspy/utils/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from .dummies import *
from .logging import *
103 changes: 103 additions & 0 deletions dspy/utils/logging.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@

import logging
import os
import sys
import typing as t

import structlog

logger = structlog.get_logger()

class LogSettings:
def __init__(self, level: str, output_type: str, method: str, file_name: t.Optional[str]) -> None:
self.level = level
self.output_type = output_type
self.method = method
self.file_name = file_name
self._configure_structlog()

def _configure_structlog(self):

if self.output_type == "str":
renderer = structlog.dev.ConsoleRenderer()
else:
renderer = structlog.processors.JSONRenderer()

structlog.configure(
processors=[
structlog.stdlib.add_logger_name,
structlog.stdlib.add_log_level,
structlog.processors.CallsiteParameterAdder(
{
structlog.processors.CallsiteParameter.FILENAME,
structlog.processors.CallsiteParameter.LINENO,
},
),
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.StackInfoRenderer(),
structlog.processors.format_exc_info,
structlog.processors.UnicodeDecoder(),
renderer,
],
logger_factory=structlog.stdlib.LoggerFactory(),
wrapper_class=structlog.stdlib.BoundLogger,
)

def set_log_level(self, level: str) -> None:
"""Set the logging level."""

level = level.upper()
if level not in ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]:
raise ValueError("log level provider ({level}) is not one of DEBUG, INFO, WARNING, ERROR, CRITICAL")

self.level = level

log_level = getattr(logging, level)
logger.setLevel(log_level)

def set_log_output(self, method: t.Optional[str] = None, file_name: t.Optional[str] = None, output_type: t.Optional[str] = None):

if method is not None and method not in ["console", "file"]:
raise ValueError("method provided can only be 'console', 'file'")

if method == "file" and file_name is None:
raise ValueError("file_name must be provided when method = 'file'")

if method is not None:
self.method = method
self.file_name = file_name

if output_type is not None and output_type not in ["str", "json"]:
raise ValueError("output_type provided can only be 'str', 'json'")

if output_type is not None:
self.output_type = output_type

# Update Renderer
self._configure_structlog()

# Grab the root logger
log = logging.getLogger()
for handler in log.handlers[:]:
log.removeHandler(handler)

# Add new Handler
if self.method == "file":
assert self.file_name is not None
log.addHandler(logging.FileHandler(self.file_name))
else:
log.addHandler(logging.StreamHandler(sys.stdout))


level = os.environ.get("log_level", "info").upper()

# Set Defaults
logging.basicConfig(
format="%(message)s",
stream=sys.stdout,
level=level,
)

settings = LogSettings(level=level, output_type="str", method="console", file_name=None)
set_log_level = settings.set_log_level
set_log_output = settings.set_log_output
Loading

0 comments on commit c8375fc

Please sign in to comment.