Spaces:
Sleeping
Sleeping
| import json | |
| import logging | |
| import os | |
| import sys | |
| import threading | |
| import time | |
| from dataclasses import dataclass | |
| from typing import Any | |
| SENSITIVE_KEYS = { | |
| "api_key", | |
| "authorization", | |
| "cookie", | |
| "hf_token", | |
| "password", | |
| "secret", | |
| "token", | |
| } | |
| class GenerationStats: | |
| prompt_tokens: int = 0 | |
| completion_tokens: int = 0 | |
| queue_ms: float = 0 | |
| inference_ms: float = 0 | |
| first_token_ms: float | None = None | |
| chunks: int = 0 | |
| output_chars: int = 0 | |
| class RuntimeMetrics: | |
| def __init__(self, started_at: float | None = None) -> None: | |
| self._lock = threading.Lock() | |
| self._started_at = time.time() if started_at is None else started_at | |
| self.http_requests = 0 | |
| self.http_errors = 0 | |
| self.completions = 0 | |
| self.completion_errors = 0 | |
| self.active_generations = 0 | |
| self.prompt_tokens = 0 | |
| self.completion_tokens = 0 | |
| def record_http(self, status_code: int) -> None: | |
| with self._lock: | |
| self.http_requests += 1 | |
| if status_code >= 500: | |
| self.http_errors += 1 | |
| def generation_started(self) -> None: | |
| with self._lock: | |
| self.active_generations += 1 | |
| def generation_finished( | |
| self, | |
| stats: GenerationStats, | |
| *, | |
| failed: bool, | |
| ) -> None: | |
| with self._lock: | |
| self.active_generations = max(0, self.active_generations - 1) | |
| self.completions += 1 | |
| self.prompt_tokens += stats.prompt_tokens | |
| self.completion_tokens += stats.completion_tokens | |
| if failed: | |
| self.completion_errors += 1 | |
| def snapshot(self) -> dict[str, Any]: | |
| with self._lock: | |
| return { | |
| "uptime_seconds": round(time.time() - self._started_at, 1), | |
| "http_requests": self.http_requests, | |
| "http_errors": self.http_errors, | |
| "completions": self.completions, | |
| "completion_errors": self.completion_errors, | |
| "active_generations": self.active_generations, | |
| "prompt_tokens": self.prompt_tokens, | |
| "completion_tokens": self.completion_tokens, | |
| } | |
| def env_flag(name: str, default: bool = False) -> bool: | |
| value = os.getenv(name) | |
| if value is None: | |
| return default | |
| return value.strip().lower() in {"1", "true", "yes", "on"} | |
| def is_sensitive_key(key: Any) -> bool: | |
| normalized = str(key).strip().lower().replace("-", "_") | |
| return ( | |
| normalized in SENSITIVE_KEYS | |
| or normalized.endswith("_token") | |
| or "api_key" in normalized | |
| or "authorization" in normalized | |
| or "cookie" in normalized | |
| or "password" in normalized | |
| or "secret" in normalized | |
| ) | |
| def sanitize(value: Any, max_text_chars: int = 2_000) -> Any: | |
| if isinstance(value, dict): | |
| return { | |
| str(key): ( | |
| "[REDACTED]" | |
| if is_sensitive_key(key) | |
| else sanitize(item, max_text_chars) | |
| ) | |
| for key, item in value.items() | |
| } | |
| if isinstance(value, (list, tuple)): | |
| return [sanitize(item, max_text_chars) for item in value] | |
| if isinstance(value, str) and len(value) > max_text_chars: | |
| omitted = len(value) - max_text_chars | |
| return f"{value[:max_text_chars]}...[truncated {omitted} chars]" | |
| return value | |
| class JsonFormatter(logging.Formatter): | |
| def format(self, record: logging.LogRecord) -> str: | |
| payload = { | |
| "timestamp": self.formatTime(record, "%Y-%m-%dT%H:%M:%S%z"), | |
| "level": record.levelname, | |
| "logger": record.name, | |
| "message": record.getMessage(), | |
| } | |
| event_fields = getattr(record, "event_fields", None) | |
| if isinstance(event_fields, dict): | |
| payload.update(event_fields) | |
| if record.exc_info: | |
| payload["exception"] = self.formatException(record.exc_info) | |
| return json.dumps(payload, ensure_ascii=True, default=str) | |
| def configure_logger(name: str = "browso.server") -> logging.Logger: | |
| logger = logging.getLogger(name) | |
| level_name = os.getenv("LOG_LEVEL", "INFO").upper() | |
| logger.setLevel(getattr(logging, level_name, logging.INFO)) | |
| logger.propagate = False | |
| if not logger.handlers: | |
| handler = logging.StreamHandler(sys.stdout) | |
| handler.setFormatter(JsonFormatter()) | |
| logger.addHandler(handler) | |
| return logger | |
| def log_event( | |
| logger: logging.Logger, | |
| event: str, | |
| *, | |
| level: int = logging.INFO, | |
| exc_info: bool = False, | |
| max_text_chars: int = 2_000, | |
| **fields: Any, | |
| ) -> None: | |
| logger.log( | |
| level, | |
| event, | |
| exc_info=exc_info, | |
| extra={ | |
| "event_fields": { | |
| "event": event, | |
| **sanitize(fields, max_text_chars=max_text_chars), | |
| } | |
| }, | |
| ) | |
| def summarize_messages(messages: list[dict[str, Any]]) -> dict[str, Any]: | |
| roles: dict[str, int] = {} | |
| text_chars = 0 | |
| tool_calls = 0 | |
| for message in messages: | |
| role = str(message.get("role", "unknown")) | |
| roles[role] = roles.get(role, 0) + 1 | |
| content = message.get("content") | |
| if isinstance(content, str): | |
| text_chars += len(content) | |
| elif isinstance(content, list): | |
| for part in content: | |
| if isinstance(part, dict) and isinstance(part.get("text"), str): | |
| text_chars += len(part["text"]) | |
| if isinstance(message.get("tool_calls"), list): | |
| tool_calls += len(message["tool_calls"]) | |
| return { | |
| "message_count": len(messages), | |
| "roles": roles, | |
| "text_chars": text_chars, | |
| "tool_call_count": tool_calls, | |
| } | |