#python #azure #logging #azure-functions
Вопрос:
Я пишу много функций Python Azure. Я хочу, чтобы каждая строка в журналах имела префикс invocation-id
от context
, чтобы легко разделять и сопоставлять журналы.
Я знаю, что есть несколько способов сделать это для обычного/автономного приложения на python. Здесь среда выполнения функций Azure предоставляет среду, в которой вызывается мой код. Я не-хочу — /предпочитаю-не-:
- возитесь с существующими обработчиками/форматерами, зарегистрированными средой выполнения функций Azure, или
- напишите мои собственные обработчики/форматеры
(потому что все, что зарегистрировано по умолчанию, отправляет журналы в рабочую область Azure Log Analytics и включает мои панели мониторинга и т. Д.)
Например, следующий код:
import logging
from azure import functions as func
def main(msg: func.QueueMessage, ctx: func.Context) -> None:
logging.info('entry')
logging.info('invocation id of this run: %s', ctx.invocation_id)
logging.debug('doing something...')
logging.info('exit with success')
будет производить журналы, такие как:
entry
invocation id of this run: 111-222-33-4444
doing something...
exit with success
вместо этого я хочу, чтобы:
(111-222-33-4444) entry
(111-222-33-4444) invocation id of this run: 111-222-33-4444
(111-222-33-4444) doing something...
(111-222-33-4444) exit with success
Я видел некоторые документы в Azure, они кажутся бесполезными.
Ответ №1:
Вы можете использовать a LoggerAdapter
для этого, как показано в следующей запускаемой программе:
import logging
class Adapter(logging.LoggerAdapter):
def process(self, msg, kwargs):
return '(%s) %s' % (self.extra['context'], msg), kwargs
def main(msg, ctx):
logger = Adapter(logging.getLogger(), {'context': ctx})
logger.info('entry')
logger.info('invocation id of this run: %s', ctx)
logger.debug('doing something ...')
logger.info('exit with success')
if __name__ == '__main__':
logging.basicConfig(level=logging.DEBUG, format='%(message)s')
main('hello', '111-222-33-4444')
Очевидно, я удалил ссылки на Azure, чтобы запустить его локально, но вы должны понять суть. Предыдущий сценарий печатает
(111-222-33-4444) entry
(111-222-33-4444) invocation id of this run: 111-222-33-4444
(111-222-33-4444) doing something ...
(111-222-33-4444) exit with success
Обновление: Если вы не хотите/не можете использовать LoggerAdapter
, то вы можете создать подкласс Logger
, как описано здесь, или использовать a Filter
, как описано здесь. Но в последнем случае вам все равно придется подключить фильтр ко всем регистраторам (или обработчикам, что было бы проще), представляющим интерес.
Комментарии:
1. Спасибо. Но это похоже на объект-оболочку, который мне придется передавать/создавать в каждой вызываемой функции/модуле. Будет работать только для МОЕГО кода. Например, если я использую какую-либо библиотеку, в которой журналы, использующие
logging.info()
эти журналы, не будут иметь префикса.