惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Microsoft Azure Blog
Microsoft Azure Blog
The Register - Security
The Register - Security
S
Securelist
Simon Willison's Weblog
Simon Willison's Weblog
T
The Exploit Database - CXSecurity.com
V
Vulnerabilities – Threatpost
NISL@THU
NISL@THU
P
Privacy & Cybersecurity Law Blog
V2EX - 技术
V2EX - 技术
O
OpenAI News
N
News and Events Feed by Topic
AI
AI
P
Proofpoint News Feed
Schneier on Security
Schneier on Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Cloudbric
Cloudbric
Help Net Security
Help Net Security
C
Cyber Attacks, Cyber Crime and Cyber Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Security Latest
Security Latest
Application and Cybersecurity Blog
Application and Cybersecurity Blog
L
LINUX DO - 热门话题
Cyberwarzone
Cyberwarzone
Scott Helme
Scott Helme
The Hacker News
The Hacker News
Hacker News - Newest:
Hacker News - Newest: "LLM"
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Google DeepMind News
Google DeepMind News
H
Hacker News: Front Page
C
Cisco Blogs
Webroot Blog
Webroot Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Hacker News: Ask HN
Hacker News: Ask HN
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
The Last Watchdog
The Last Watchdog
PCI Perspectives
PCI Perspectives
AWS News Blog
AWS News Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Know Your Adversary
Know Your Adversary
Latest news
Latest news
Forbes - Security
Forbes - Security
I
Intezer
Project Zero
Project Zero
C
CERT Recently Published Vulnerability Notes
T
Tenable Blog
TaoSecurity Blog
TaoSecurity Blog
S
Security @ Cisco Blogs
N
News | PayPal Newsroom
H
Heimdal Security Blog
W
WeLiveSecurity

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Почему ваши логи бесполезны и как это починить за полчаса
badcasedaily · 2026-05-19 · via Все публикации подряд на Хабре

Почему ваши логи бесполезны и как это починить за полчаса

Уровень сложностиПростой

Время на прочтение7 мин

Охват и читатели160

Туториал

Три часа ночи, алерт, сервис отдаёт 500. Открываете логи и видите:

2026-05-12 03:14:22 ERROR Something went wrong
2026-05-12 03:14:22 ERROR Failed to process request
2026-05-12 03:14:23 ERROR Unexpected error occurred
2026-05-12 03:14:23 INFO  Request completed

Какой запрос сломался? Какой пользователь? Какой endpoint? Что за ошибка? В логе этого нет.

Вы начинаете прыгать по timestamp, пытаетесь руками сопоставить строки друг с другом, а если сервис обрабатывает 100 запросов в секунду, логи от разных запросов перемешаны в кашу, и отделить один от другого невозможно.

Проблема вообще не в количестве логов и не в уровне детализации. Проблема в формате. Текстовые логи написаны для человека, который сидит перед терминалом и читает их глазами. Но в три часа ночи при 100 RPS глазами ничего не найдёшь. Нужны логи, написанные для машины: фильтруемые, группируемые, с полями, по которым можно строить запросы.

Это и есть structured logging.

Текст vs JSON

Обычный лог:

2026-05-12 03:14:22 ERROR Failed to process payment for user 12345: connection timeout

Вся информация закодирована в строке: user ID, тип ошибки, операция. Чтобы отфильтровать по user_id, нужен regex. Чтобы найти все таймауты, нужен другой regex. Чтобы посчитать количество ошибок по типам — третий. Каждый regex сломается, когда формат сообщения чуть изменится.

Structured лог — тот же самый набор данных, но каждое поле отдельно:

{
  "timestamp": "2026-05-12T03:14:22.456Z",
  "level": "error",
  "message": "Failed to process payment",
  "user_id": 12345,
  "payment_id": "pay_abc123",
  "error": "connection timeout",
  "service": "payment-api",
  "request_id": "req_xyz789",
  "duration_ms": 5023
}

Теперь jq 'select(.user_id == 12345)' даёт все события этого пользователя. В Kibana или Loki запрос service="payment-api" AND level="error" AND duration_ms > 3000 покажет все медленные ошибки за час. Без regex‑ов, без угадывания формата.

Python: structlog

В Python для structured logging есть structlog. Работает поверх стандартного logging или standalone, настраивается за 10 минут.

pip install structlog
import structlog

structlog.configure(
    processors=[
        structlog.contextvars.merge_contextvars,
        structlog.processors.add_log_level,
        structlog.processors.TimeStamper(fmt="iso"),
        structlog.processors.format_exc_info,
        structlog.processors.JSONRenderer(),
    ],
    logger_factory=structlog.PrintLoggerFactory(),
)

log = structlog.get_logger()

Тут стоит объяснить, что такое processors. В structlog каждое лог‑событие проходит через цепочку процессоров: один добавляет timestamp, другой — уровень, третий — контекстные переменные, последний сериализует в JSON. Можно добавлять свои: например, процессор, который маскирует email‑адреса или убирает поля с персональными данными.

Использование:

log.info("payment_started", user_id=123, amount=99.99, currency="USD")
log.error("payment_failed", user_id=123, error="timeout", retry_count=2)

Вывод:

{"event": "payment_started", "user_id": 123, "amount": 99.99, "currency": "USD", "level": "info", "timestamp": "2026-05-12T03:14:22Z"}
{"event": "payment_failed", "user_id": 123, "error": "timeout", "retry_count": 2, "level": "error", "timestamp": "2026-05-12T03:14:27Z"}

Тут еще обратите внимание: вы не конструируете строку руками (f"Payment failed for user {user_id}: {error}"). Вы передаёте поля как именованные аргументы. Structlog сам решает, как их отформатировать. В продакшене — JSON. В разработке можно переключить на красивый текстовый вывод с цветами (заменив JSONRenderer на ConsoleRenderer). Код логирования не меняется.

Request ID: связываем логи одного запроса

Самое ценное в structured logging — возможность привязать все логи одного запроса к одному идентификатору. Без этого при 100 RPS строки от разных запросов перемешиваются, и понять, какой лог к какому запросу относится, невозможно.

В FastAPI это делается через middleware и contextvars:

import uuid
from starlette.middleware.base import BaseHTTPMiddleware

class RequestIDMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request, call_next):
        request_id = request.headers.get("X-Request-ID", str(uuid.uuid4()))
        
        structlog.contextvars.clear_contextvars()
        structlog.contextvars.bind_contextvars(
            request_id=request_id,
            method=request.method,
            path=request.url.path,
        )
        
        response = await call_next(request)
        response.headers["X-Request-ID"] = request_id
        return response

app = FastAPI()
app.add_middleware(RequestIDMiddleware)

bind_contextvars привязывает поля к текущему контексту выполнения (asyncio task). После этого каждый вызов log.info(...), log.error(...) в любом месте обработки запроса автоматически содержит request_id, method и path. Не нужно передавать их через все функции, не нужно протаскивать logger как аргумент.

@app.get("/api/orders/{order_id}")
async def get_order(order_id: int):
    log.info("fetching_order", order_id=order_id)
    order = await db.fetch_order(order_id)
    if not order:
        log.warning("order_not_found", order_id=order_id)
        raise HTTPException(404)
    log.info("order_fetched", order_id=order_id, status=order.status)
    return order

Все три лог‑записи будут содержать один request_id. В Kibana фильтруете по нему и видите полный путь запроса: что искали, нашли ли, сколько заняло.

Если у вас Django вместо FastAPI, принцип тот же: middleware, который привязывает request_id к thread-local или contextvars. Для Flask — before_request hook.

Go: slog из стандартной библиотеки

В Go с версии 1.21 structured logging есть из коробки, без зависимостей. Пакет log/slog стал частью стандартной библиотеки.

import (
    "log/slog"
    "os"
)

func main() {
    logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
        Level: slog.LevelInfo,
    }))
    slog.SetDefault(logger)

    slog.Info("server started", "port", 8080, "env", "production")
    slog.Error("payment failed",
        "user_id", 123,
        "error", "connection timeout",
        "duration_ms", 5023,
    )
}

До slog в Go‑сообществе были zerolog, zap, logrus — каждый со своим API, своими уровнями, своими форматами. slog не заменяет их полностью (у zerolog, например, zero‑allocation logging, что может быть критично при 100K RPS), но для большинства сервисов slog достаточен и не требует зависимости.

Request ID в Go привязывается через context:

func RequestIDMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        requestID := r.Header.Get("X-Request-ID")
        if requestID == "" {
            requestID = uuid.New().String()
        }
        
        logger := slog.Default().With("request_id", requestID,
            "method", r.Method, "path", r.URL.Path)
        ctx := context.WithValue(r.Context(), "logger", logger)
        
        w.Header().Set("X-Request-ID", requestID)
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

Метод With создаёт дочерний логгер с привязанными полями. Все записи через этот логгер будут содержать request_id, method и path.

Что логировать, а что не логировать

Это вопрос, на который нет универсального ответа, но есть здравый смысл.

Логируйте начало и конец обработки запроса (с duration_ms — это бесценно для диагностики latency). Логируйте ошибки с контекстом: не просто «ошибка», а что за операция, какие входные данные, какой ответ от downstream. Логируйте обращения к внешним сервисам: какой сервис, сколько ждали, какой статус ответа. Логируйте бизнес‑события: заказ создан, платёж прошёл, пользователь заблокирован — то, что потом пригодится для расследования инцидентов и аналитики.

Не логируйте пароли, токены, номера карт, персональные данные. Это нарушение GDPR/ФЗ-152, за которое штрафуют. Не логируйте тела запросов и ответов целиком: объём огромный, конфиденциальные данные внутри, и в 99% случаев вам нужны два‑три поля, а не всё тело. Не логируйте на уровне DEBUG в продакшене: потоп данных забьёт диск и Kibana, а полезного в нём мало.

# Плохо
log.info("login", username=username, password=password)
log.info("request", body=request.body)

# Хорошо
log.info("login_attempt", username=username)
log.info("order_received", order_id=data["id"], amount=data["amount"])

Как не утонуть при высокой нагрузке

При 10 000 RPS и 5 строках лога на запрос вы генерируете 50 000 строк в секунду. За сутки это больше 4 миллиардов строк. Даже в JSON это терабайты.

Решение в семплирование. Логируете 10% INFO‑запросов, но 100% ошибок. Объём падает на порядок, а диагностика работает: ошибки видны все, нормальный трафик — выборочно.

import random
import structlog

class SamplingProcessor:
    def __init__(self, sample_rate=0.1):
        self.sample_rate = sample_rate
    
    def __call__(self, logger, method_name, event_dict):
        if event_dict.get("level") in ("error", "warning", "critical"):
            return event_dict
        if random.random() > self.sample_rate:
            raise structlog.DropEvent
        return event_dict

Добавляете SamplingProcessor(0.1) в цепочку процессоров structlog. 10% INFO, 100% WARNING и выше. Для большинства задач этого достаточно: если баг воспроизводится на 10% запросов, вы его увидите. Если на 0.01%, вам нужны не логи, а трейсинг.

Structured logging — возможность в три часа ночи за минуту найти конкретный запрос, понять что с ним произошло и кто виноват. JSON вместо текста, request_id для корреляции, slog или structlog вместо print и fmt.Println. Полчаса на настройку, и следующий алерт вы расследуете в разы быстрее.

Если у вас есть свои подходы к логированию или нашли ошибку, пишите в комментариях. Спасибо, что дочитали.

Если после настройки structured logging хочется пойти дальше — связать логи, метрики и трейсы в одну картину и быстрее разбирать инциденты в продакшене, у OTUS есть два бесплатных открытых урока по теме:

19 мая, 20:00 — «Введение в OpenTelemetry и основы наблюдаемости»
Разберёмся, как строится observability и зачем команде единый контекст для диагностики сервисов.

1 июня, 20:00 — «Мониторинг распределенных систем»
Поговорим о том, как отслеживать состояние сложных систем, находить источник сбоев и не тонуть в техническом шуме.

Открытые уроки проходят в рамках онлайн‑курсов OTUS: можно познакомиться с преподавателями‑практиками, посмотреть на формат обучения и задать вопросы по теме.

А чтобы не пропускать новые материалы про разработку, архитектуру, DevOps и эксплуатацию систем — подписывайтесь на блог.