Format string saya saat ini adalah:
formatter = logging.Formatter('%(asctime)s : %(message)s')
dan saya ingin menambahkan bidang baru bernama app_name
yang akan memiliki nilai berbeda di setiap skrip yang berisi pemformat ini.
import logging
formatter = logging.Formatter('%(asctime)s %(app_name)s : %(message)s')
syslog.setFormatter(formatter)
logger.addHandler(syslog)
Tapi saya tidak yakin bagaimana meneruskan app_name
nilai itu ke logger untuk diinterpolasi ke dalam format string. Saya jelas bisa membuatnya muncul di pesan log dengan meneruskannya setiap kali tetapi ini berantakan.
Saya sudah mencoba:
logging.info('Log message', app_name='myapp')
logging.info('Log message', {'app_name', 'myapp'})
logging.info('Log message', 'myapp')
tapi tidak ada yang berhasil.
log
panggilan? Jika demikian, lihat dokumen yang menyatakan "Fungsionalitas ini dapat digunakan untuk memasukkan nilai Anda sendiri ke dalam LogRecord…" Tapi ini sepertinya kasus utama untuk menggunakanlogger = logging.getLogger('myapp')
dan memasukkannya ke dalamlogger.info
panggilan.logger
objek di setiap aplikasi, Anda dapat membuat masing-masing menggunakan nama yang berbeda oleh instantiating Andalogger
s seperti:logger = logging.getLogger(myAppName)
. perhatikan itu__name__
adalah nama modul python, jadi jika setiap aplikasi adalah modul pythonnya sendiri, itu juga akan berfungsi.Jawaban:
Anda bisa menggunakan LoggerAdapter sehingga Anda tidak perlu meneruskan info tambahan dengan setiap panggilan logging:
import logging extra = {'app_name':'Super App'} logger = logging.getLogger(__name__) syslog = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s %(app_name)s : %(message)s') syslog.setFormatter(formatter) logger.setLevel(logging.INFO) logger.addHandler(syslog) logger = logging.LoggerAdapter(logger, extra) logger.info('The sky is so blue')
log (sesuatu seperti)
2013-07-09 17:39:33,596 Super App : The sky is so blue
Filter juga dapat digunakan untuk menambahkan informasi kontekstual.
import logging class AppFilter(logging.Filter): def filter(self, record): record.app_name = 'Super App' return True logger = logging.getLogger(__name__) logger.addFilter(AppFilter()) syslog = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s %(app_name)s : %(message)s') syslog.setFormatter(formatter) logger.setLevel(logging.INFO) logger.addHandler(syslog) logger.info('The sky is so blue')
menghasilkan catatan log serupa.
sumber
config.ini
file? Saya ingin menambahkan nama host saat inisocket.gethostname()
.import uuid uniqueId = str(uuid.uuid4()) extra = {"u_id" : uniqueId} RotatingHandler = RotatingFileHandler(LOG_FILENAME,encoding='utf-8',maxBytes=maxSize, backupCount=batchSize) logger.basicConfig(handlers=[RotatingHandler],level=logLevel.upper(),format='%(levelname)s %(u_id)s %(funcName)s %(asctime)s %(message)s ',datefmt='%m/%d/%Y %I:%M:%S %p') logger = logger.LoggerAdapter(logger=logger, extra=extra)
Anda perlu meneruskan dict sebagai parameter ke ekstra untuk melakukannya dengan cara itu.
logging.info('Log message', extra={'app_name': 'myapp'})
Bukti:
>>> import logging >>> logging.basicConfig(format="%(foo)s - %(message)s") >>> logging.warning('test', extra={'foo': 'bar'}) bar - test
Selain itu, sebagai catatan, jika Anda mencoba memasukkan pesan tanpa meneruskan dict, maka pesan itu akan gagal.
>>> logging.warning('test') Traceback (most recent call last): File "/usr/lib/python2.7/logging/__init__.py", line 846, in emit msg = self.format(record) File "/usr/lib/python2.7/logging/__init__.py", line 723, in format return fmt.format(record) File "/usr/lib/python2.7/logging/__init__.py", line 467, in format s = self._fmt % record.__dict__ KeyError: 'foo' Logged from file <stdin>, line 1
sumber
logging.info()
? Itu gagal ketika saya mencoba terakhir. : /logging.Formatter
kelas: class CustomFormatter (logging.Formatter): format def (self, record): if not hasattr (record, 'foo'): record.foo = 'default_foo' return super (CustomFormatter, self.format (record) h = loggin.StreamHandler () h.setFormatter (CustomFormatter ('% (foo) s% (message) s') logger = logging.getLogger ('bar') logger.addHandler ( h) logger.error ('hey!', extra = {'foo': 'FOO'}) logger.error ('hey!')Python3
Mulai Python3.2, Anda sekarang dapat menggunakan LogRecordFactory
>>> import logging >>> logging.basicConfig(format="%(custom_attribute)s - %(message)s") >>> old_factory = logging.getLogRecordFactory() >>> def record_factory(*args, **kwargs): record = old_factory(*args, **kwargs) record.custom_attribute = "my-attr" return record >>> logging.setLogRecordFactory(record_factory) >>> logging.info("hello") my-attr - hello
Tentu saja
record_factory
dapat disesuaikan agar dapat dipanggil dan nilaicustom_attribute
dapat diperbarui jika Anda menyimpan referensi ke dapat dipanggil pabrik.Mengapa itu lebih baik daripada menggunakan Adaptor / Filter?
logger = logging.getLogger(..)
) sekarang akan memiliki format log yang sama. (ini tidak terjadi pada Filter / Adaptor di mana Anda harus menggunakan objek pencatat yang sama)sumber
Cara lainnya adalah dengan membuat LoggerAdapter khusus. Ini sangat berguna ketika Anda tidak dapat mengubah format ATAU jika format Anda dibagikan dengan kode yang tidak mengirimkan kunci unik (dalam kasus Anda app_name ):
class LoggerAdapter(logging.LoggerAdapter): def __init__(self, logger, prefix): super(LoggerAdapter, self).__init__(logger, {}) self.prefix = prefix def process(self, msg, kwargs): return '[%s] %s' % (self.prefix, msg), kwargs
Dan dalam kode Anda, Anda akan membuat dan menginisialisasi logger Anda seperti biasa:
logger = logging.getLogger(__name__) # Add any custom handlers, formatters for this logger myHandler = logging.StreamHandler() myFormatter = logging.Formatter('%(asctime)s %(message)s') myHandler.setFormatter(myFormatter) logger.addHandler(myHandler) logger.setLevel(logging.INFO)
Terakhir, Anda akan membuat adaptor pembungkus untuk menambahkan awalan sesuai kebutuhan:
logger = LoggerAdapter(logger, 'myapp') logger.info('The world bores you when you are cool.')
Outputnya akan terlihat seperti ini:
2013-07-09 17:39:33,596 [myapp] The world bores you when you are cool.
sumber
Saya menemukan pertanyaan SO ini setelah menerapkannya sendiri. Semoga bisa membantu seseorang. Dalam kode di bawah ini, saya memasukkan kunci tambahan yang disebut
claim_id
dalam format logger. Ini akan mencatat klaim_id setiap kali adaclaim_id
kunci yang ada di lingkungan. Dalam kasus penggunaan saya, saya perlu mencatat informasi ini untuk fungsi AWS Lambda.import logging import os LOG_FORMAT = '%(asctime)s %(name)s %(levelname)s %(funcName)s %(lineno)s ClaimID: %(claim_id)s: %(message)s' class AppLogger(logging.Logger): # Override all levels similarly - only info overriden here def info(self, msg, *args, **kwargs): return super(AppLogger, self).info(msg, extra={"claim_id": os.getenv("claim_id", "")}) def get_logger(name): """ This function sets log level and log format and then returns the instance of logger""" logging.setLoggerClass(AppLogger) logging.basicConfig(level=logging.INFO, format=LOG_FORMAT) logger = logging.getLogger(name) logger.setLevel(logging.INFO) return logger LOGGER = get_logger(__name__) LOGGER.info("Hey") os.environ["claim_id"] = "12334" LOGGER.info("Hey")
Inti: https://gist.github.com/ramanujam/306f2e4e1506f302504fb67abef50652
sumber
Menggunakan jawaban mr2ert, saya menemukan solusi yang nyaman ini (Meskipun saya kira itu tidak disarankan) - Ganti metode logging bawaan untuk menerima argumen khusus dan membuat
extra
kamus di dalam metode:import logging class CustomLogger(logging.Logger): def debug(self, msg, foo, *args, **kwargs): extra = {'foo': foo} if self.isEnabledFor(logging.DEBUG): self._log(logging.DEBUG, msg, args, extra=extra, **kwargs) *repeat for info, warning, etc* logger = CustomLogger('CustomLogger', logging.DEBUG) formatter = logging.Formatter('%(asctime)s [%(foo)s] %(message)s') handler = logging.StreamHandler() handler.setFormatter(formatter) logger.addHandler(handler) logger.debug('test', 'bar')
Keluaran:
2019-03-02 20:06:51,998 [bar] test
Ini adalah fungsi bawaan untuk referensi:
def debug(self, msg, *args, **kwargs): """ Log 'msg % args' with severity 'DEBUG'. To pass exception information, use the keyword argument exc_info with a true value, e.g. logger.debug("Houston, we have a %s", "thorny problem", exc_info=1) """ if self.isEnabledFor(DEBUG): self._log(DEBUG, msg, args, **kwargs)
sumber
mengimpor penebangan;
kelas LogFilter (logging.Filter):
def __init__(self, code): self.code = code def filter(self, record): record.app_code = self.code return True
logging.basicConfig (format = '[% (asctime) s:% (levelname) s] :: [% (module) s ->% (name) s] - APP_CODE:% (app_code) s - MSG:% (pesan ) s ');
kelas Logger:
def __init__(self, className): self.logger = logging.getLogger(className) self.logger.setLevel(logging.ERROR) @staticmethod def getLogger(className): return Logger(className) def logMessage(self, level, code, msg): self.logger.addFilter(LogFilter(code)) if level == 'WARN': self.logger.warning(msg) elif level == 'ERROR': self.logger.error(msg) else: self.logger.info(msg)
Tes kelas: logger = Logger.getLogger ('Test')
if __name__=='__main__': logger.logMessage('ERROR','123','This is an error')
sumber