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

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

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

setup_kwargs = {
    'name': 'logchain',
    'version': '0.5.0',
    'description': 'Python logging secured by blockchain',
    'long_description': '# Logchain\n\n[![Pipeline status](https://gitlab.com/ggpack/logchain-py/badges/master/pipeline.svg)](https://gitlab.com/ggpack/logchain-py/pipelines)\n[![Coverage report](https://gitlab.com/ggpack/logchain-py/badges/master/coverage.svg?job=unittest)](https://gitlab.com/ggpack/logchain-py/-/jobs)\n\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-py/-/blob/master/LICENSE)\n[![Package](https://img.shields.io/badge/PIP-logchain-blue.svg)](https://pypi.org/project/logchain)\n\nPython logging secured by 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 easily **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\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.\nchainer = LogChainer()\n\n# Register the formatter to the logger.\nchainer.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-04-25 00:21:36.266 TestChaining.py:33 test_logging_happy_case hello gg |862101dead44e3fb",\n\t"2020-04-25 00:21:36.266 TestChaining.py:34 test_logging_happy_case voila1 |87f4b398040df0b0",\n\t"2020-04-25 00:21:36.266 TestChaining.py:35 test_logging_happy_case voila2 |98e33f86376f5858",\n\t"2020-04-25 00:21:36.267 TestChaining.py:36 test_logging_happy_case voila3 |0757cf00b412a767",\n\t"2020-04-25 00:21:36.267 TestChaining.py:37 test_logging_happy_case voila4 |95ea9b92cc3e1bc7"\n]\n\nchainer = LogChainer(secret = "Et2FwQefvb7HfCb7tATguSicVj_7TVlM")\nresult = chainer.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 named arguments.\n``` python\nfrom logchain import LogChainer\n\nchainer = LogChainer(verbosity = 3, secret = "mySignatureKey")\n\nparams = {"verbosity": 3, "secret": "mySignatureKey", "timestamp": {"fmt": "%s"}}\nchainer = LogChainer(**params)\n```\n\n| **Param** *Type* | Default value | Description |\n| ----- | ------------- | ----------- |\n| **name** *string* | None | Name of the logger instanciated, defaults to the root logger |\n| **formatterCls** *class* | formatters.Basic | Type of logging to perform, raw text, json, custom |\n| **format** *string* | see below | Placeholder string used by raw-text loggers |\n| **secret** *string* | secrets.token_urlsafe(128) | Signature key to compute the line signature |\n| **seed** *string* | secrets.token_urlsafe() | Random string to sign into the first log line |\n| **timestamp** *dict* | see below | Group of properties for the timestamp |\n| **stream** *stream* | stderr | Where the logs are sent, file/console/custom stream |\n| **verbosity** *int* | 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## Settings of `timestamp`\n| **Param** *Type* | Default value | Description |\n| ----- | ------------- | ----------- |\n| **fmt** *string* | "iso" | iso for 8601 or `strftime` compatible placeholders (ex: "%F %T.%f" |\n| **precision** *string* | "milliseconds" | `timespec` element used by [the datetime library](https://docs.python.org/3/library/datetime.html#datetime.datetime.isoformat) |\n| **utc** *bool* | False | Transform the timestamp to its value in UTC |\n\n\n## Logchain extra logging fields\nWe enrich the standard logging record with some handy string 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: `timestamp.fmt`\n\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.setFields(appName = appName)\n\t\tlogging.info("Creating the app")\n\n\tdef handleTransaction(self, userId, callback):\n\t\twith self.logger.managedFields(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# The log chain in transparent for the callbacks\ndef callback1():\n\tlogging.warning("Something happened")\n\ndef callback2():\n\tlogging.info("Serving a resource")\n```\n\n**main.py**\n``` python\ndef main():\n\tchainer = logchain.LogChainer(formatterCls = logchain.formatters.Json)\n\tchainer.initLogging()\n\n\tapp = App("MyApp", chainer)\n\tapp.handleTransaction("user1", callback1)\n\tapp.handleTransaction("user1", callback2)\n\tapp.close()\n```\n\nYou can either use:\n* `setFields`: set some permanant fields, remove one by setting it to `None`.\n* `managedFields`: set some temporary fields for the scope of the `context manager`.\n\n## Using named loggers\n``` python\nfrom logchain import LogChainer\n\nchainer = LogChainer()\nlogger = chainer.initLogging(name = __name__)\nlogger.info("I am special!")\n```\n\n## Verbosity to logging.levels\nThe default mapping is described by the variable `VerbosityToLevel` as follows:\n\n| Verbosity |  Level  |\n| :---------: | ------- |\n| **0** | ERROR |\n| **1** | WARNING |\n| **2** | INFO |\n| ***other*** | DEBUG |\n\n----\n\n# Contributing\n\n## Install\n[**The code is hosted on Gitlab 🦊**](https://gitlab.com/ggpack/logchain-py)\n\nSimply clone and submit pull requests.\n\n## Testing\nThe unit tests are located in the [test folder](https://gitlab.com/ggpack/logchain-py/-/blob/master/test) and discovered by the module `unittest`.\n\n``` bash\n# Run all\npython -m unittest discover -s test\n\n# Get additional options\npython -m unittest --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\n[A CI/CD job](https://gitlab.com/ggpack/logchain-py/-/blob/master/.gitlab-ci.yml) handles the new tag event and publishes the package to PYPI using the awesome [Poetry tool](https://python-poetry.org).\n\n\n# Thanks\nIcons made by [Freepik](https://www.flaticon.com/authors/freepik) from [www.flaticon.com](https://www.flaticon.com)\n',
    'author': 'Gg Math',
    'author_email': 'code@gmath.io',
    'maintainer': None,
    'maintainer_email': None,
    'url': 'https://gitlab.com/ggpack/logchain-py',
    'packages': packages,
    'package_data': package_data,
    'python_requires': '>=3.2,<4.0',
}


setup(**setup_kwargs)
