Skip to content

ccproxy.observability.stats_printer

ccproxy.observability.stats_printer

Stats collector and printer for periodic metrics summary.

This module provides functionality to collect and print periodic statistics from the observability system, including Prometheus metrics and DuckDB storage.

StatsSnapshot dataclass

StatsSnapshot(
    timestamp,
    requests_total,
    requests_last_minute,
    avg_response_time_ms,
    avg_response_time_last_minute_ms,
    tokens_input_total,
    tokens_output_total,
    tokens_input_last_minute,
    tokens_output_last_minute,
    cost_total_usd,
    cost_last_minute_usd,
    errors_total,
    errors_last_minute,
    active_requests,
    top_model,
    top_model_percentage,
)

Snapshot of current statistics.

StatsCollector

StatsCollector(
    settings, metrics_instance=None, storage_instance=None
)

Collects and formats metrics statistics for periodic printing.

Integrates with both Prometheus metrics and DuckDB storage to provide comprehensive statistics about the API performance.

Parameters:

Name Type Description Default
settings ObservabilitySettings

Observability configuration settings

required
metrics_instance Any | None

Prometheus metrics instance

None
storage_instance Any | None

DuckDB storage instance

None
Source code in ccproxy/observability/stats_printer.py
def __init__(
    self,
    settings: ObservabilitySettings,
    metrics_instance: Any | None = None,
    storage_instance: Any | None = None,
):
    """
    Initialize stats collector.

    Args:
        settings: Observability configuration settings
        metrics_instance: Prometheus metrics instance
        storage_instance: DuckDB storage instance
    """
    self.settings = settings
    self._metrics_instance = metrics_instance
    self._storage_instance = storage_instance
    self._last_snapshot: StatsSnapshot | None = None
    self._last_collection_time = time.time()

collect_stats async

collect_stats()

Collect current statistics from all available sources.

Returns:

Type Description
StatsSnapshot

StatsSnapshot with current metrics

Source code in ccproxy/observability/stats_printer.py
async def collect_stats(self) -> StatsSnapshot:
    """
    Collect current statistics from all available sources.

    Returns:
        StatsSnapshot with current metrics
    """
    current_time = time.time()
    timestamp = datetime.now()

    # Initialize default values
    stats_data: dict[str, Any] = {
        "timestamp": timestamp,
        "requests_total": 0,
        "requests_last_minute": 0,
        "avg_response_time_ms": 0.0,
        "avg_response_time_last_minute_ms": 0.0,
        "tokens_input_total": 0,
        "tokens_output_total": 0,
        "tokens_input_last_minute": 0,
        "tokens_output_last_minute": 0,
        "cost_total_usd": 0.0,
        "cost_last_minute_usd": 0.0,
        "errors_total": 0,
        "errors_last_minute": 0,
        "active_requests": 0,
        "top_model": "unknown",
        "top_model_percentage": 0.0,
    }

    # Collect from Prometheus metrics if available
    if self._metrics_instance and self._metrics_instance.is_enabled():
        try:
            await self._collect_from_prometheus(stats_data)
        except Exception as e:
            logger.warning(
                "Failed to collect from Prometheus metrics", error=str(e)
            )

    # Collect from DuckDB storage if available
    if self._storage_instance and self._storage_instance.is_enabled():
        try:
            await self._collect_from_duckdb(stats_data, current_time)
        except Exception as e:
            logger.warning("Failed to collect from DuckDB storage", error=str(e))

    snapshot = StatsSnapshot(
        timestamp=stats_data["timestamp"],
        requests_total=int(stats_data["requests_total"]),
        requests_last_minute=int(stats_data["requests_last_minute"]),
        avg_response_time_ms=float(stats_data["avg_response_time_ms"]),
        avg_response_time_last_minute_ms=float(
            stats_data["avg_response_time_last_minute_ms"]
        ),
        tokens_input_total=int(stats_data["tokens_input_total"]),
        tokens_output_total=int(stats_data["tokens_output_total"]),
        tokens_input_last_minute=int(stats_data["tokens_input_last_minute"]),
        tokens_output_last_minute=int(stats_data["tokens_output_last_minute"]),
        cost_total_usd=float(stats_data["cost_total_usd"]),
        cost_last_minute_usd=float(stats_data["cost_last_minute_usd"]),
        errors_total=int(stats_data["errors_total"]),
        errors_last_minute=int(stats_data["errors_last_minute"]),
        active_requests=int(stats_data["active_requests"]),
        top_model=str(stats_data["top_model"]),
        top_model_percentage=float(stats_data["top_model_percentage"]),
    )
    self._last_snapshot = snapshot
    self._last_collection_time = current_time

    return snapshot

format_stats

format_stats(snapshot)

Format stats snapshot for display.

Parameters:

Name Type Description Default
snapshot StatsSnapshot

Stats snapshot to format

required

Returns:

Type Description
str

Formatted stats string

Source code in ccproxy/observability/stats_printer.py
def format_stats(self, snapshot: StatsSnapshot) -> str:
    """
    Format stats snapshot for display.

    Args:
        snapshot: Stats snapshot to format

    Returns:
        Formatted stats string
    """
    format_type = self.settings.stats_printing_format

    if format_type == "json":
        return self._format_json(snapshot)
    elif format_type == "rich":
        return self._format_rich(snapshot)
    elif format_type == "log":
        return self._format_log(snapshot)
    else:  # console (default)
        return self._format_console(snapshot)

print_stats async

print_stats()

Collect and print current statistics.

Source code in ccproxy/observability/stats_printer.py
async def print_stats(self) -> None:
    """Collect and print current statistics."""
    try:
        snapshot = await self.collect_stats()

        # Only print stats if there is meaningful activity
        if self._has_meaningful_activity(snapshot):
            formatted_stats = self.format_stats(snapshot)

            # Print to stdout for console visibility
            print(formatted_stats)

            # Also log for structured logging
            logger.info(
                "stats_printed",
                requests_last_minute=snapshot.requests_last_minute,
                requests_total=snapshot.requests_total,
                avg_response_time_ms=snapshot.avg_response_time_ms,
                cost_total_usd=snapshot.cost_total_usd,
                active_requests=snapshot.active_requests,
                top_model=snapshot.top_model,
            )
        else:
            logger.debug(
                "stats_skipped_no_activity",
                requests_last_minute=snapshot.requests_last_minute,
                requests_total=snapshot.requests_total,
                active_requests=snapshot.active_requests,
            )

    except Exception as e:
        logger.error("Failed to print stats", error=str(e), exc_info=True)

get_stats_collector

get_stats_collector(
    settings=None,
    metrics_instance=None,
    storage_instance=None,
)

Get or create global stats collector instance.

Parameters:

Name Type Description Default
settings ObservabilitySettings | None

Observability settings

None
metrics_instance Any | None

Metrics instance for dependency injection

None
storage_instance Any | None

Storage instance for dependency injection

None

Returns:

Type Description
StatsCollector

StatsCollector instance

Source code in ccproxy/observability/stats_printer.py
def get_stats_collector(
    settings: ObservabilitySettings | None = None,
    metrics_instance: Any | None = None,
    storage_instance: Any | None = None,
) -> StatsCollector:
    """
    Get or create global stats collector instance.

    Args:
        settings: Observability settings
        metrics_instance: Metrics instance for dependency injection
        storage_instance: Storage instance for dependency injection

    Returns:
        StatsCollector instance
    """
    global _global_stats_collector

    if _global_stats_collector is None:
        if settings is None:
            from ccproxy.config.settings import get_settings

            settings = get_settings().observability

        if metrics_instance is None:
            try:
                from .metrics import get_metrics

                metrics_instance = get_metrics()
            except Exception as e:
                logger.warning("Failed to get metrics instance", error=str(e))

        if storage_instance is None:
            try:
                from .storage.duckdb_simple import SimpleDuckDBStorage

                storage_instance = SimpleDuckDBStorage(settings.duckdb_path)
                # Note: Storage needs to be initialized before use
            except Exception as e:
                logger.warning("Failed to get storage instance", error=str(e))

        _global_stats_collector = StatsCollector(
            settings=settings,
            metrics_instance=metrics_instance,
            storage_instance=storage_instance,
        )

    return _global_stats_collector

reset_stats_collector

reset_stats_collector()

Reset global stats collector instance (mainly for testing).

Source code in ccproxy/observability/stats_printer.py
def reset_stats_collector() -> None:
    """Reset global stats collector instance (mainly for testing)."""
    global _global_stats_collector
    _global_stats_collector = None