# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['logchain', 'logchain.formatters']

package_data = \
{'': ['*']}

setup_kwargs = {
    'name': 'logchain',
    'version': '0.2.1',
    'description': 'Python Logging secured by blockchain',
    'long_description': '# Logchain\n\n[![pipeline status](https://gitlab.com/ggpack/logchain/badges/master/pipeline.svg)](https://gitlab.com/ggpack/logchain/-/commits/master)\n![Dependencies](https://img.shields.io/badge/dependencies-0-blue.svg)\n[![license](https://img.shields.io/badge/license-ISC-blue.svg)](https://gitlab.com/ggpack/logchain/-/blob/master/LICENSE)\n\n[![Web page](https://img.shields.io/badge/website-github.io/logchain-blue.svg)](https://gg-math.github.io/logchain)\n[![Package](https://img.shields.io/badge/PIP-logchain-blue.svg)](https://pypi.org/project/logchain)\n\nPython Logging based on blockchain 📜 ⛓️.\n\n## Logs get chained\nThe current log line contains the signature of the previous line with your secret.\n* detect lines deleted / lost\n* detect logs tampering\n\n## Philosophy\nThe package is intended to be a **lightweight** util for generating **incorruptible** logs.\n\nFor this pupose we rely as much as possible on standard packages: few dependencies, high quality.\n\nThe formatters are easy **extensible** by simply deriving from `Basic`.\n\n\n# Usage\n\n## Install\n``` bash\npip install logchain\n```\n\n## Choose your log type\n\nMany types of logs are supported out-of-the-box:\n- `Basic` raw text, relying on the standard formatter\n- `Json` structured log lines with static & dynamic fields\n- `CSV` work in progress\n\nYou can write a custom formatter in 20-ish lines.\n\n## Init once in main\n``` python\nfrom logchain import LogChainer\n\n# Initialize a default chainer.\ntheLogger = LogChainer()\n\n# Register the formatter to the logger.\ntheLogger.initLogging()\n```\n\nHave a look at [the comprehensive guide of constructor parameters](#constructor-parameters).\n\n## Use everywhere with python logging module\n``` python\nimport logging\n\nlogging.debug("My message")\nlogging.info("Some information")\n```\n\n## Check your logs integrity afterwards\n``` python\nfrom logchain import LogChainer\n\naLogChain = [\n\t"2020-03-30 13:38:00.782|0ec90b9839fdd964|TestChaining.py:20 test_logging_happy_case hello gg",\n\t"2020-03-30 13:38:00.782|2e3f1b4a7b946fb1|TestChaining.py:21 test_logging_happy_case voila1",\n\t"2020-03-30 13:38:00.782|10d1ab606618492a|TestChaining.py:22 test_logging_happy_case voila2",\n\t"2020-03-30 13:38:00.782|805757e144f4e385|TestChaining.py:23 test_logging_happy_case voila5",\n\t"2020-03-30 13:38:00.782|3bda90b5af77d3fe|TestChaining.py:24 test_logging_happy_case voila4"\n]\nresult = LogChainer.verify(aLogChain)\n\nif not result:\n\tprint("Last good line", result.prevLine)\n\tprint("First bad line", result.line)\nelse:\n\tprint("All right")\n```\n\n## Constructor parameters\n\nThey are passed as a dict and/or named arguments.\n``` python\nfrom logchain import LogChainer\n\ntheLogger = LogChainer(verbosity = 3, secret = "mySignatureKey")\n\nparams = {"verbosity": 3, "secret": "mySignatureKey"}\ntheLogger = LogChainer(params, timestampFmt = "iso")\n```\n\n| Param | Default value | Description |\n| ----- | ------------- | ----------- |\n| formatterCls | formatters.Basic | Type of logging to perform, raw text, json, custom |\n| format | see below | Placeholder string used by raw-text loggers |\n| secret | secrets.token_urlsafe(128) | Signature key to compute the line signature |\n| seed | secrets.token_urlsafe() | Random string to sign into the first log line |\n| timestampFmt | "iso" | iso for 8601 or `strftime` compatible placeholders |\n| timestampPrecision | "milliseconds" | `timespec` element used by [the datetime library](https://docs.python.org/3/library/datetime.html#datetime.datetime.isoformat) |\n| timestampUtc | False | Transform the timestamp to its value in UTC |\n| stream | cout | Where the logs are sent, file/console/custom stream |\n| verbosity | 0 | Number [0..5] mapped to a logging.level |\n\nThe 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.\n\n\n## Logchain extra logging fields\nWe enrich the standard logging record with some handy fields:\n\n| Name | Description |\n| ---- | ----------- |\n| fileLine | Widespread `filename:lineno` |\n| levelLetters | 4 first letters of logging level names: short and unambiguous |\n| signature | The digital signature of the previous line. Include it in all your lines to benefit from the chaining |\n| timestamp | Improved version of `asctime`, see below |\n\n\nThe `timestamp` field offers more flexibility than `asctime` in regards to:\n- the precision; can go up to the micro seconds (`msecs` cannot)\n- the decimal separator; you choose, \'.\' by default\n- utc or local timezone\n- customize the format only in one place: `timestampFmt`\n\n## Dynamic logging fields\nThe package is suitable for server/app logging which context changes from one transaction to another.\nHere is an example of setting contextual information throughout the lifecycle of an app:\n\n**App.py**\n``` python\nclass App:\n\tdef __init__(self, appName, logger):\n\t\tself.logger = logger\n\t\tself.logger.setField(appName = appName)\n\t\tlogging.info("Creating the app")\n\n\tdef handleTransaction(self, userId, callback):\n\t\twith self.logger.managedField(uId = userId, trxId = secrets.token_urlsafe(8)):\n\t\t\tcallback()\n\n\tdef close(self):\n\t\tlogging.info("Closing the app")\n```\n\n**Callbacks.py**\n``` python\n\t# The log chain in transparent for the callbacks\n\tdef callback1():\n\t\tlogging.warn("Something happened")\n\n\tdef callback2():\n\t\tlogging.info("Serving a resource")\n```\n\n**main.py**\n``` python\ndef main():\n\ttheLogger = logchain.LogChainer(formatterCls = logchain.formatters.Json)\n\ttheLogger.initLogging()\n\n\tapp = App("MyApp", theLogger)\n\tapp.handleTransaction("user1", callback1)\n\tapp.handleTransaction("user1", callback2)\n\tapp.close()\n```\n\nYou can either use:\n* `setField`: set a permanant field, remove it by setting it to `None`.\n* `managedField`: set a temporary field for the scope of the `context manager`.\n\n----\n\n# Contributing\n\n## Install\n[**The code is hosted on Gitlab 🦊**](https://gitlab.com/ggpack/logchain)\n\nSimply clone and submit pull requests.\n\n## Testing\nThe unit tests are located in the [test folder](https://gitlab.com/ggpack/logchain/-/blob/master/test)\nwhich contains the `__main__.py` entrypoint.\n\n``` bash\n# Run all\npython test\n\n# Get additional options\npython test --help\n```\n\n## Releasing\nThe process is triggered by a tag added to a commit. The tag must match the pattern `release_<VERSION>`\nand `VERSION` has to comply to **[semver](https://semver.org)**.\n\nA CI/CD job handles the new tag event and publishes the package to PYPI using\nusing to the awesome [Poetry tool](https://python-poetry.org):\n\n``` bash\npoetry version $VERSION\npoetry build\npoetry publish\n```\n',
    'author': 'Gg Math',
    'author_email': 'code@gmath.io',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://gg-math.github.io/logchain',
    'packages': packages,
    'package_data': package_data,
    'python_requires': '>=3.2,<4.0',
}


setup(**setup_kwargs)
