Package: plogchain
PlogchainPython Logging based on blockchain 📜 ⛓️.Logs get chainedThe current log line contains the signature of the previous line with your secret.detect lines deleted / lostdetect logs tamperingPhilosophyThe package is intended to be alightweightutil for generatingincorruptiblelogs.For this pupose we rely as much as possible on standard packages: few dependencies, high quality.The formatters are easyextensibleby simply deriving fromBasic.UsageInstallpipinstallplogchainChoose your log typeMany types of logs are supported out-of-the-box:Basicraw text, relying on the standard formatterJsonstructured log lines with static & dynamic fieldsCSVwork in progressYou can write a custom formatter in 20-ish lines.Init once in mainfromplogchainimportLogChainer# Initialize a default chainer.theLogger=LogChainer()# Register the formatter to the logger.theLogger.initLogging()Have a look atthe comprehensive guide of constructor parameters.Use everywhere with python logging moduleimportlogginglogging.debug("My message")logging.info("Some information")Check your logs integrity afterwardsfromplogchainimportLogChaineraLogChain=["2020-03-30 13:38:00.782|0ec90b9839fdd964|TestChaining.py:20 test_logging_happy_case hello gg","2020-03-30 13:38:00.782|2e3f1b4a7b946fb1|TestChaining.py:21 test_logging_happy_case voila1","2020-03-30 13:38:00.782|10d1ab606618492a|TestChaining.py:22 test_logging_happy_case voila2","2020-03-30 13:38:00.782|805757e144f4e385|TestChaining.py:23 test_logging_happy_case voila5","2020-03-30 13:38:00.782|3bda90b5af77d3fe|TestChaining.py:24 test_logging_happy_case voila4"]result=LogChainer.verify(aLogChain)ifnotresult:print("Last good line",result.prevLine)print("First bad line",result.line)else:print("All right")Constructor parametersThey are passed as a dict and/or named arguments.fromplogchainimportLogChainertheLogger=LogChainer(verbosity=3,secret="mySignatureKey")params={"verbosity":3,"secret":"mySignatureKey"}theLogger=LogChainer(params,timestampFmt="iso")ParamDefault valueDescriptionformatterClsformatters.BasicType of logging to perform, raw text, json, customformatsee belowPlaceholder string used by raw-text loggerssecretsecrets.token_urlsafe(128)Signature key to compute the line signatureseedsecrets.token_urlsafe()Random string to sign into the first log linetimestampFmt"iso"iso for 8601 orstrftimecompatible placeholderstimestampPrecision"milliseconds"timespecelement used bythe datetime librarytimestampUtcFalseTransform the timestamp to its value in UTCstreamcoutWhere the logs are sent, file/console/custom streamverbosity0Number [0..5] mapped to a logging.levelThe default format is%(timestamp)s %(levelLetters)s %(fileLine)-15s %(funcName)-15s %(message)-60s |%(signature)s. It relies on some extra fields like the signature at its end.Plogchain extra logging fieldsWe enrich the standard logging record with some handy fields:NameDescriptionfileLineWidespreadfilename:linenolevelLetters4 first letters of logging level names: short and unambiguoussignatureThe digital signature of the previous line. Include it in all your lines to benefit from the chainingtimestampImproved version ofasctime, see belowThetimestampfield offers more flexibility thanasctimein regards to:the precision; can go up to the micro seconds (msecscannot)the decimal separator; you choose, '.' by defaultutc or local timezonecustomize the format only in one place:timestampFmtDynamic logging fields (WIP)The package is suitable for server logging which context changes from one transaction to another.
Here is an example of setting contextual information throughout the lifecycle of a server:defstartServer(containerName)# Static formatting at program startup...theLogger=LogChainer(formatterCls=formatters.Json)theLogger.initLogging()theLogger.setField(containerName=containerName)defhandleTransaction(transactionId,userId):# More contextual data later ontheLogger.setField(uId=userId,trxId=transactionId)ContributingInstallSimply clone and submit pull requests.TestingThe unit tests are located in thetest folderwhich contains the__main__.pyentrypoint.# Run allpythontest# Get additional optionspythontest--helpDeliveryUse to the awesomePoetry toolfor this purpose:poetrybuild
poetrypublish