Содержание

Добавление ошибок в проект

Аутентификация к API запросу происходит через токен проекта. Его можно найти в интерфейсе редактирования проекта в поле Токен. API_URL = https://err-scout.ru/api

Рекомендуемый способ передачи ошибок

В этом разделе представлен рекомендуемый способ автоматической отправки ошибок в API `https://err-scout.ru/api` для внешних Python-приложений.

Используется декоратор `@detailed_exception_logger`, который автоматически:

При возникновении исключения, декоратор автоматически формирует объект `error_data`, содержащий:

Пример использования

@detailed_exception_logger
def divide(a, b):
    return a / b
 
divide(10, 0)

Код декоратора

import json
import traceback
import sys
import os
import inspect
from datetime import datetime
from functools import wraps
import requests
 
from config import API_URL, AUTH_TOKEN, ENVIRONMENT, RELEASE
 
def send_error_to_api(error_data: dict):
    headers = {
        'Content-Type': 'application/json',
        'Authorization': AUTH_TOKEN
    }
    payload = {
        "jsonrpc": "2.0",
        "method": "Error.create",
        "params": error_data,
        "id": 1
    }
    response = requests.post(API_URL, json=payload, headers=headers)
    response.raise_for_status()
    return response.json()
 
def detailed_exception_logger(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except Exception as e:
            exc_type, exc_value, exc_tb = sys.exc_info()
            timestamp = datetime.utcnow().isoformat()
 
            stack_trace = []
            tb = exc_tb
            index = 0
            while tb:
                frame = tb.tb_frame
                lineno = tb.tb_lineno
                filename = frame.f_code.co_filename
                func_name = frame.f_code.co_name
 
                try:
                    with open(filename, 'r', encoding='utf-8') as f:
                        lines = f.readlines()
                        code_line = lines[lineno - 1].strip() if lineno <= len(lines) else ""
                except Exception:
                    code_line = ""
 
                stack_trace.append({
                    "file": filename,
                    "line": lineno,
                    "function": func_name,
                    "code": code_line,
                    "index": index
                })
 
                tb = tb.tb_next
                index += 1
 
            error_data = {
                "error_type": exc_type.__name__,
                "error_message": str(exc_value),
                "timestamp": timestamp,
                "environment": ENVIRONMENT,
                "release": RELEASE,
                "platform": sys.platform,
                "language_version": sys.version.split()[0],
                "user_id": "auto-reporter",
                "user_email": "",
                "request_data": {
                    "function": func.__name__,
                    "args": [repr(a) for a in args],
                    "kwargs": {k: repr(v) for k, v in kwargs.items()}
                },
                "stack_trace": stack_trace,
                "tags": [
                    {"key": "module", "value": func.__module__},
                    {"key": "pid", "value": str(os.getpid())},
                    {"key": "cwd", "value": os.getcwd()}
                ]
            }
 
            try:
                send_error_to_api(error_data)
            except Exception as api_error:
                print(f"[error-scout] Failed to send error: {api_error}")
                print(json.dumps(error_data, indent=2))
 
            raise
 
    return wrapper

Дополнительно