20
Как хранить логи сервиса в базе данных Алексей Кирпичников Старший разработчик Я.Субботник, Екатеринбург , 6 июля 2013 года

Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

  • Upload
    yandex

  • View
    2.063

  • Download
    2

Embed Size (px)

DESCRIPTION

На примере Python, MongoDB и Яндекс.Такси рассказывается о том, как хранить логи сервиса в базе данных — о том, какие задачи помогает решать такое хранилище логов и чем оно отличается от других, более распространенных вариантов.

Citation preview

Page 1: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

Как хранить логи сервиса в базе данныхАлексей КирпичниковСтарший разработчикЯ.Субботник, Екатеринбург, 6 июля 2013 года

Page 2: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

Яндекс.Такси

Page 3: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

Типичное устройство логов

Balancer (nginx, lighttpd, etc.)access.logerror.log

Backend (django, twisted, etc.)main.logtraceback.log

Page 4: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

• проблемы с сортировкой и поиском• проблемы с хранением сложных данных• недоступность для простых смертных

Чем плохи файлы?

Page 5: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

• capped и TTL-коллекции• гибкая схема• шардирование• удобный поиск по метаданным

MongoDB

Page 6: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

Что записывать в базу?

Page 7: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

Что записывать в базу?

Page 8: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

Что записывать в базу?

Page 9: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

log = {}log['request'] = { 'user_phone': '+79122250228', 'body': request_body}log['inner'] = []...log['inner'].append('something happened')...log['inner'].append('something else happened')...log['response'] = { 'code': 200, 'body': response_body}

db.logs.insert(log)

Ужасная идея

Page 10: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

Одна запись на один запрос — плохая идея

Page 11: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

db.logs.insert({'_id': 'someid', 'request': { 'user_phone': '+79122250228', 'body': request_body }})...db.logs.update({'_id': 'someid'}, {'$push': {'inner': 'something happened'}})...db.logs.update({'_id': 'someid'}, {'$push': {'inner': 'something else happened'}})...db.logs.update({'_id': 'someid'}, {'$set': {'response': {'code': 200}}})

Довольно плохая идея

Page 12: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

Операция update — плохая идея, если у вас MongoDB

Page 13: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

Плохая идея

db.logs.insert({ '_type': 'request', 'user_phone': '+79122250228', 'body': request_body})...db.logs.insert({ '_type': 'inner', 'user_phone': '+79122250228', 'message': 'something happened'})...db.logs.insert({ '_type': 'response', 'user_phone': '+79122250228', 'code': 200})

Page 14: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

Нет смысла хранить метаданные в каждом логе

Page 15: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

Уже лучше

db.logs.insert({ '_type': 'request', '_link': 'somelink', 'user_phone': '+79122250228', 'body': request_body})...db.logs.insert({ '_type': 'inner', '_link': 'somelink', 'message': 'something happened'})...db.logs.insert({ '_type': 'response', '_link': 'somelink', 'code': 200})

Page 16: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

Чем меньше записей в коллекции, тем удобнее с ней

работать

Page 17: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

С этим можно жить

db.logs_request.insert({ '_link': 'somelink', 'body': request_body})...db.logs_inner.insert({ '_link': 'somelink', 'message': 'something happened'})...db.logs_response.insert({ '_link': 'somelink', 'user_phone': '+79122250228', 'code': 200})

Page 18: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

• минимальное вмешательство в основной поток• гибкая адаптация под нагрузку• дублирование в файловые логи

Отказоустойчивость

Page 19: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

• 50 RPS в среднем, 100-150 в пике• хранятся логи за 7 дней• около 20 миллионов записей• остальное - в файлах

Как это работает в Такси?

Page 20: Алексей Кирпичников — Как хранить логи сервиса в базе данных и не погубить продакшен

Старший разработчикЯндекс.Такси

[email protected]_ru

Спасибо

Алексей Кирпичников