Стас Рудаков, компания СООО "Гейм Стрим"/Wargaming.net
Значение логов очень часто недооценивается, а зря. Доклад с оживленным диспутом со всеми участниками митапа, чтобы разобраться: как, куда и зачем писать логи. Помимо этого затронут вопрос, как из логов выжать больше информации.
3. Про что будем говорить?
Про логгирование, Стас Рудаков
4. Про что будем говорить?
Про логгирование, там же было написано :)
Про логгирование, Стас Рудаков
5. Про что будем говорить?
Про логгирование, там же было написано :)
А именно:
зачем;
как;
проблемы;
очевидные пути решения;
неочевидные пути решения;
open source инструменты.
Про логгирование, Стас Рудаков
7. Что вообще значит “записать в лог”?
сформировать сообщение
Про логгирование, Стас Рудаков
8. Что вообще значит “записать в лог”?
сформировать сообщение
по некому событию
Про логгирование, Стас Рудаков
9. Что вообще значит “записать в лог”?
сформировать сообщение
по некому событию
и, если это сообщение нас вообще интересует,
Про логгирование, Стас Рудаков
10. Что вообще значит “записать в лог”?
сформировать сообщение
по некому событию
и, если это сообщение нас вообще интересует,
записать или отправить его куда-то,
Про логгирование, Стас Рудаков
11. Что вообще значит “записать в лог”?
сформировать сообщение
по некому событию
и, если это сообщение нас вообще интересует,
записать или отправить его куда-то,
куда имеют доступ заинтересованные лица.
Про логгирование, Стас Рудаков
15. Писать логи очень просто
1
import logging
2
3
4
5
6
7
logging . basicConfig (
format = ’ [%( asctime ) s ][%( levelname ) s ][%( name ) s ] %( message ) s ’ ,
stream = sys . stdout ,
level = logging . INFO
)
8
9
10
logger = logging . getLogger ( " meetup . python . minsk " )
logger . info ( " Stas has just started the talk on logging " )
Про логгирование, Стас Рудаков
16. Писать логи очень просто
1
import logging
2
3
4
5
6
7
logging . basicConfig (
format = ’ [%( asctime ) s ][%( levelname ) s ][%( name ) s ] %( message ) s ’ ,
stream = sys . stdout ,
level = logging . INFO
)
8
9
10
1
logger = logging . getLogger ( " meetup . python . minsk " )
logger . info ( " Stas has just started the talk on logging " )
[2014 -01 -31 06:23:27 ,904][ INFO ][ meetup . python . minsk ] Stas has
just started the talk on logging
Про логгирование, Стас Рудаков
17. logging: архитектура на пальцах
сформировать сообщение
по некому событию
и, если это сообщение нас вообще
интересует,
записать или отправить его куда-то,
куда имеют доступ
заинтересованные лица.
Про логгирование, Стас Рудаков
24. tips n tricks: уровни логгирования
Про логгирование, Стас Рудаков
25. tips n tricks: уровни логгирования
CRITICAL = 50
logger.critical(u’проблема, после которой приложение не может
восстановиться без постороннего вмешательства’)
Про логгирование, Стас Рудаков
26. tips n tricks: уровни логгирования
CRITICAL = 50
logger.critical(u’проблема, после которой приложение не может
восстановиться без постороннего вмешательства’)
ERROR = 40
logger.error(u’проблема, из-за которой приложение работает не в
штатном режиме’)
Про логгирование, Стас Рудаков
27. tips n tricks: уровни логгирования
CRITICAL = 50
logger.critical(u’проблема, после которой приложение не может
восстановиться без постороннего вмешательства’)
ERROR = 40
logger.error(u’проблема, из-за которой приложение работает не в
штатном режиме’)
WARNING = 30 # уровень по умолчанию
logger.warning(u’проблема, которая не мешает работе приложения, но
на которую стоит обратить внимание’)
Про логгирование, Стас Рудаков
28. tips n tricks: уровни логгирования
CRITICAL = 50
logger.critical(u’проблема, после которой приложение не может
восстановиться без постороннего вмешательства’)
ERROR = 40
logger.error(u’проблема, из-за которой приложение работает не в
штатном режиме’)
WARNING = 30 # уровень по умолчанию
logger.warning(u’проблема, которая не мешает работе приложения, но
на которую стоит обратить внимание’)
INFO = 20
logger.info(u’обычная запись в лог’)
Про логгирование, Стас Рудаков
29. tips n tricks: уровни логгирования
CRITICAL = 50
logger.critical(u’проблема, после которой приложение не может
восстановиться без постороннего вмешательства’)
ERROR = 40
logger.error(u’проблема, из-за которой приложение работает не в
штатном режиме’)
WARNING = 30 # уровень по умолчанию
logger.warning(u’проблема, которая не мешает работе приложения, но
на которую стоит обратить внимание’)
INFO = 20
logger.info(u’обычная запись в лог’)
DEBUG = 10
logger.debug(u’логи, которые помогли нам при отладке приложения и
которые вряд ли пригодятся в будущем’)
Про логгирование, Стас Рудаков
30. tips n tricks: traceback
1
try :
2
do_ s o me t hi n g_ u n sa f e ()
except Exception as e :
logger . exception ( ’ Unexpected exception ’)
raise
3
4
5
Про логгирование, Стас Рудаков
31. tips n tricks: traceback
1
try :
2
do_ s o me t hi n g_ u n sa f e ()
except Exception as e :
logger . exception ( ’ Unexpected exception ’)
raise
3
4
5
В лог отправится:
1
2
3
4
5
6
7
8
9
[2014 -01 -29 23:35:04 ,393][ examples ][ ERROR ] Unexpected exception
Traceback ( most recent call last ) :
File " stacktrace1 . py " , line 22 , in < module >
d o_ s o me t hi n g_ u n sa f e ()
File " stacktrace1 . py " , line 18 , in do _ so m e th i ng _ u ns a fe
down_rabbit_hole ()
File " stacktrace1 . py " , line 17 , in down_rabbit_hole
sender = message . sender
AttributeError : ’ NoneType ’ object has no attribute ’ sender ’
Про логгирование, Стас Рудаков
32. tips n tricks: traceback
1
try :
2
validate_data ( data )
except ValidationError as e :
logger . exception ( ’ Validation failed ’)
3
4
А в лог запишется
1
2
3
4
5
6
7
8
9
[2014 -01 -29 08:33:53 ,439][ examples ][ ERROR ] Validation failed
Traceback ( most recent call last ) :
File " stacktrace2 . py " , line 27 , in < module >
validate_data ( data )
File " stacktrace2 . py " , line 22 , in validate_data
check_values ( data )
File " stacktrace2 . py " , line 21 , in check_values
raise ValidationError ( ’ security key is missing ’)
ValidationError : security key is missing
Про логгирование, Стас Рудаков
33. tips n tricks: traceback
1
try :
2
validate_data ( data )
except ValidationError as e :
logger . exception ( ’ Validation failed ’)
3
4
А в лог запишется
1
2
3
4
5
6
7
8
9
[2014 -01 -29 08:33:53 ,439][ examples ][ ERROR ] Validation failed
Traceback ( most recent call last ) :
File " stacktrace2 . py " , line 27 , in < module >
validate_data ( data )
File " stacktrace2 . py " , line 22 , in validate_data
check_values ( data )
File " stacktrace2 . py " , line 21 , in check_values
raise ValidationError ( ’ security key is missing ’)
ValidationError : security key is missing
Но разве уровень ERROR нам подходит?
Про логгирование, Стас Рудаков
34. tips n tricks: traceback
1
try :
2
validate_data ( data )
except ValidationError as e :
logger . warning ( ’ Validation failed ’ , exc_info = True )
3
4
Получаем
1
2
3
4
5
6
7
8
9
[2014 -01 -29 08:33:53 ,439][ examples ][ WARNING ] Validation failed
Traceback ( most recent call last ) :
File " stacktrace2 . py " , line 27 , in < module >
validate_data ( data )
File " stacktrace2 . py " , line 22 , in validate_data
check_values ( data )
File " stacktrace2 . py " , line 21 , in check_values
raise ValidationError ( ’ security key is missing ’)
ValidationError : security key is missing
Про логгирование, Стас Рудаков
35. tips n tricks: “ленивое” форматирование
1
2
3
logger . info (
’ Request id =% s message =% r ’ % (100500 , { ’ event ’: ’ meetup ’ })
)
Про логгирование, Стас Рудаков
36. tips n tricks: “ленивое” форматирование
1
2
3
logger . info (
’ Request id =% s message =% r ’ % (100500 , { ’ event ’: ’ meetup ’ })
)
Зачем форматировать строку, если мы не знаем, попадет ли она в лог?
Про логгирование, Стас Рудаков
37. tips n tricks: “ленивое” форматирование
1
2
3
logger . info (
’ Request id =% s message =% r ’ % (100500 , { ’ event ’: ’ meetup ’ })
)
Зачем форматировать строку, если мы не знаем, попадет ли она в лог?
1
2
3
logger . info (
’ Request id =% s message =% r ’ , 100500 , { ’ event ’: ’ meetup ’}
)
Про логгирование, Стас Рудаков
38. tips n tricks: “ленивое” форматирование
1
2
3
logger . info (
’ Request id =% s message =% r ’ % (100500 , { ’ event ’: ’ meetup ’ })
)
Зачем форматировать строку, если мы не знаем, попадет ли она в лог?
1
2
3
logger . info (
’ Request id =% s message =% r ’ , 100500 , { ’ event ’: ’ meetup ’}
)
*args работают, **kwargs не работают
Про логгирование, Стас Рудаков
39. tips n tricks: ротация
в один прекрасный день. . .
Про логгирование, Стас Рудаков
40. tips n tricks: ротация
в один прекрасный день. . . no space left on device
Про логгирование, Стас Рудаков
41. tips n tricks: ротация
в один прекрасный день. . . no space left on device
from logging.handlers import *
1
2
3
4
5
1
2
3
4
5
Rotating Fi l eH a n dl e r (
filename , mode = ’a ’ ,
maxBytes =0 , backupCount =0 ,
encoding = None , delay = False
)
$ ls logs
meetup . log
meetup . log .1
meetup . log .2
meetup . log .3
Про логгирование, Стас Рудаков
42. tips n tricks: ротация
в один прекрасный день. . . no space left on device
from logging.handlers import *
1
2
3
4
5
1
2
3
4
5
Rotating Fi l eH a n dl e r (
filename , mode = ’a ’ ,
maxBytes =0 , backupCount =0 ,
encoding = None , delay = False
)
1
$ ls logs
meetup . log
meetup . log .1
meetup . log .2
meetup . log .3
1
Про логгирование, Стас Рудаков
2
3
4
5
2
3
4
5
T i m e d Ro t a t i n g F i l e H a n d l e r (
filename ,
when = ’h ’ , interval =1 ,
backupCount =0 , encoding = None ,
delay = False , utc = False )
$ ls logs
meetup . log
meetup . log .2014 -01 -31 _17
meetup . log .2014 -01 -31 _18
meetup . log .2014 -01 -31 _19
43. tips n tricks: ротация
в один прекрасный день. . . no space left on device
from logging.handlers import *
1
2
3
4
5
1
2
3
4
5
Rotating Fi l eH a n dl e r (
filename , mode = ’a ’ ,
maxBytes =0 , backupCount =0 ,
encoding = None , delay = False
)
1
$ ls logs
meetup . log
meetup . log .1
meetup . log .2
meetup . log .3
1
2
3
4
5
2
3
4
5
T i m e d Ro t a t i n g F i l e H a n d l e r (
filename ,
when = ’h ’ , interval =1 ,
backupCount =0 , encoding = None ,
delay = False , utc = False )
$ ls logs
meetup . log
meetup . log .2014 -01 -31 _17
meetup . log .2014 -01 -31 _18
meetup . log .2014 -01 -31 _19
Если варианты выше не подходят, можно использовать утилиту logrotate и
1
Wa tc he dFi le Ha ndl er ( fname , mode = ’a ’ , encoding = None , delay = False )
Про логгирование, Стас Рудаков
45. Sentry - это. . .
open source
аггрегатор
сообщений об
ошибках,
написанный на
Python +
Django +
Celery,
с клиентами
для многих
языков и
платформ.
Про логгирование, Стас Рудаков
49. Sentry: как подключить
1
2
3
4
5
6
7
from raven . handlers . logging import SentryHandler
handler = SentryHandler ( ’ http :// public : secret@example . com /1 ’ ,
level = logging . WARNING )
logger = logging . getLogger ( ’ coffeemaker ’)
logger . addHandler ( handler )
logger . warning ( ’ We are running out of milk ’)
logger . error ( ’ Not enough milk for a cappuccino ’)
Про логгирование, Стас Рудаков
50. Sentry: как подключить
1
2
3
4
5
6
7
from raven . handlers . logging import SentryHandler
handler = SentryHandler ( ’ http :// public : secret@example . com /1 ’ ,
level = logging . WARNING )
logger = logging . getLogger ( ’ coffeemaker ’)
logger . addHandler ( handler )
logger . warning ( ’ We are running out of milk ’)
logger . error ( ’ Not enough milk for a cappuccino ’)
HTTP? Cерьезно?
Про логгирование, Стас Рудаков
51. А теперь давайте вспомним, что мы с этими логами собирались делать
Debug
Разбор инцидентов
Про логгирование, Стас Рудаков
52. А теперь давайте вспомним, что мы с этими логами собирались делать
Debug
Разбор инцидентов
Сбор статистики
Средне- и долгосрочный мониторинг
Инструмент для службы поддержки пользователей
Аналитика
Про логгирование, Стас Рудаков
53. Назад в будущее
Современные вызовы:
хотим убедиться, что логи не были модифицированы злоумышленником
после взлома;
переходим от программ к сложным распределенным системам — хочется
иметь логгирование уровня всей системы, а не отдельных приложений;
быстрый поиск;
метрики.
Про логгирование, Стас Рудаков
56. elasticsearch - это. . .
распределенный
полнотекстовый
поисковый движок
c RESTful web-интерфейсом,
с документами без схемы
и возможностями аггрегации документов.
Про логгирование, Стас Рудаков
57. elasticsearch - это. . .
распределенный
полнотекстовый
поисковый движок
c RESTful web-интерфейсом,
с документами без схемы
и возможностями аггрегации документов.
Написан на Java
с использованием библиотеки Apache Lucene.
Используется в Mozilla, GitHub и многих других компаниях
(если вам нужно убедить своего менеджера).
Про логгирование, Стас Рудаков
58. elasticsearch - это. . .
распределенный
полнотекстовый
поисковый движок
c RESTful web-интерфейсом,
с документами без схемы
и возможностями аггрегации документов.
Написан на Java
с использованием библиотеки Apache Lucene.
Используется в Mozilla, GitHub и многих других компаниях
(если вам нужно убедить своего менеджера).
Но как связать логгирование и elasticsearch?
Про логгирование, Стас Рудаков
62. structlog — последний ингридиент
1
2
3
4
5
6
>>> from structlog import get_logger
>>> log = get_logger ()
>>> log = log . bind ( user = ’ anonymous ’ , some_key =23)
>>> log = log . bind ( user = ’ hynek ’ , another_key =42)
>>> log . info ( ’ user . logged_in ’ , happy = True )
some_key =23 user = ’ hynek ’ another_key =42 happy = True event = ’ user .
logged_in ’
http://www.structlog.org/
Про логгирование, Стас Рудаков
63. Что мы не объяли?
Syslog Protocol
Логи в реляционной базе данных
journald
logplex, fluentd
Агенты для сбора логов
Что, собственно, писать в логи.
Про логгирование, Стас Рудаков
64. Выводы
Батарейка logging вполне подходит для 95% случаев1 .
1
По статистике, не стоит доверять 75% статистики
Про логгирование, Стас Рудаков
65. Выводы
Батарейка logging вполне подходит для 95% случаев1 .
Архитектуры систем логгирования похожи как на микро, так и на макро
уровне.
1
По статистике, не стоит доверять 75% статистики
Про логгирование, Стас Рудаков
66. Выводы
Батарейка logging вполне подходит для 95% случаев1 .
Архитектуры систем логгирования похожи как на микро, так и на макро
уровне.
Open source инструменты помогают выжать из логов очень много полезных
свойств.
1
По статистике, не стоит доверять 75% статистики
Про логгирование, Стас Рудаков
67. Выводы
Батарейка logging вполне подходит для 95% случаев1 .
Архитектуры систем логгирования похожи как на микро, так и на макро
уровне.
Open source инструменты помогают выжать из логов очень много полезных
свойств.
Я вас всех порядочно утомил.
1
По статистике, не стоит доверять 75% статистики
Про логгирование, Стас Рудаков