diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | python-gelf-formatter.spec | 480 | ||||
-rw-r--r-- | sources | 1 |
3 files changed, 482 insertions, 0 deletions
@@ -0,0 +1 @@ +/gelf-formatter-0.2.1.tar.gz diff --git a/python-gelf-formatter.spec b/python-gelf-formatter.spec new file mode 100644 index 0000000..8484399 --- /dev/null +++ b/python-gelf-formatter.spec @@ -0,0 +1,480 @@ +%global _empty_manifest_terminate_build 0 +Name: python-gelf-formatter +Version: 0.2.1 +Release: 1 +Summary: GELF formatter for the Python standard library logging module. +License: MIT +URL: https://github.com/joaodrp/gelf-formatter +Source0: https://mirrors.aliyun.com/pypi/web/packages/69/7c/4c4ed3d41e2fba4aa525583fa6bb86698e25c6567916d9553f942b5cd241/gelf-formatter-0.2.1.tar.gz +BuildArch: noarch + + +%description +## Motivation +There are several packages available providing *handlers* for the standard library logging module that can send application logs to [Graylog](https://www.graylog.org/) by TCP/UDP/HTTP ([py-gelf](https://pypi.org/project/pygelf/) is a good example). Although these can be useful, it's not ideal to make an application performance dependent on network requests just for the purpose of delivering logs. +Alternatively, one can simply log to a file or `stdout` and have a collector (like [Fluentd](https://www.fluentd.org/)) processing and sending those logs *asynchronously* to a remote server (and not just to Graylog, as GELF can be used as a generic log format), which is a common pattern for containerized applications. In a scenario like this all we need is a GELF logging *formatter*. +## Features +- Support for arbitrary additional fields; +- Support for including reserved [`logging.LogRecord`](https://docs.python.org/3/library/logging.html#logrecord-attributes) attributes as additional fields; +- Exceptions detection with traceback formatting; +- Zero dependencies and tiny footprint. +## Installation +### With pip +```text +$ pip install gelf-formatter +``` +### From source +```text +$ python setup.py install +``` +## Usage +Simply create a `gelfformatter.GelfFormatter` instance and pass it as argument to [`logging.Handler.setFormatter`](https://docs.python.org/3/library/logging.html#logging.Handler.setFormatter): +```python +import sys +import logging +from gelfformatter import GelfFormatter +formatter = GelfFormatter() +handler = logging.StreamHandler(sys.stdout) +handler.setFormatter(formatter) +``` +Apply it globally with [`logging.basicConfig`](https://docs.python.org/3/library/logging.html#logging.basicConfig) to automatically format log records from third-party packages as well: +```python +logging.basicConfig(level=logging.DEBUG, handlers=[handler]) +``` +Alternatively, you can configure a local [`logging.Logger`](https://docs.python.org/3/library/logging.html#logging.Logger) instance through [`logging.Logger.addHandler`](https://docs.python.org/3/library/logging.html#logging.Logger.addHandler): +```python +logger = logging.getLogger('my-app') +logger.addHandler(handler) +``` +That's it. You can now use the logging module as usual, all records will be formatted as GELF messages. +### Standard Fields +The formatter will output all (non-deprecated) fields described in the [GELF Payload Specification (version 1.1)](http://docs.graylog.org/en/latest/pages/gelf.html#gelf-payload-specification): +- `version`: String, always set to `1.1`; +- `host`: String, the output of [`socket.gethostname`](https://docs.python.org/3/library/socket.html#socket.gethostname) at initialization; +- `short_message`: String, log record message; +- `full_message` (*optional*): String, formatted exception traceback (if any); +- `timestamp`: Number, time in seconds since the epoch as a floating point; +- `level`: Integer, *syslog* severity level. +None of these fields can be ignored, renamed or overridden. +#### Example +```python +logging.info("Some message") +``` +```text +{"version":"1.1","host":"my-server","short_message":"Some message","timestamp":1557342545.1067393,"level":6} +``` +#### Exceptions +The `full_message` field is used to store the traceback of exceptions. You just need to log them with [`logging.exception`](https://docs.python.org/3/library/logging.html#logging.exception). +##### Example +```python +import urllib.request +req = urllib.request.Request('http://www.pythonnn.org') +try: + urllib.request.urlopen(req) +except urllib.error.URLError as e: + logging.exception(e.reason) +``` +```text +{"version": "1.1", "short_message": "[Errno -2] Name or service not known", "timestamp": 1557342714.0695107, "level": 3, "host": "my-server", "full_message": "Traceback (most recent call last):\n ...(truncated)... raise URLError(err)\nurllib.error.URLError: <urlopen error [Errno -2] Name or service not known>"} +``` +### Additional Fields +The GELF specification allows arbitrary additional fields, with keys prefixed with an underscore. +To include additional fields use the standard logging `extra` keyword. Keys will be automatically prefixed with an underscore (if not already). +#### Example +```python +logging.info("request received", extra={"path": "/orders/1", "method": "GET"}) +``` +```text +{"version": "1.1", "short_message": "request received", "timestamp": 1557343604.5892842, "level": 6, "host": "my-server", "_path": "/orders/1", "_method": "GET"} +``` +#### Reserved Fields +By default the formatter ignores all [`logging.LogRecord` attributes](https://docs.python.org/3/library/logging.html#logrecord-attributes). You can however opt to include them as additional fields. This can be used to display useful information like the current module, filename, line number, etc. +To do so, simply pass a list of `LogRecord` attribute names as value of the `allowed_reserved_attrs` keyword when initializing a `GelfFormatter`. You can also modify the `allowed_reserved_attrs` instance variable of an already initialized formatter. +##### Example +```python +attrs = ["lineno", "module", "filename"] +formatter = GelfFormatter(allowed_reserved_attrs=attrs) +# or +formatter.allowed_reserved_attrs = attrs +logging.debug("starting application...") +``` +```text +{"version": "1.1", "short_message": "starting application...", "timestamp": 1557346554.989846, "level": 6, "host": "my-server", "_lineno": 175, "_module": "myapp", "_filename": "app.py"} +``` +You can optionally customize the name of these additional fields using a [`logging.Filter`](https://docs.python.org/3/library/logging.html#filter-objects) (see below). +Similarily, you can choose to ignore additional attributes passed via the `extra` keyword argument. This can be usefull to e.g. not log keywords named `secret` or `password`. +To do so, pass a list of names to the `ignored_attrs` keyword when initializing a `GelfFormatter`. You can also modify the `ignored_attrs` instance variable of an already initialized formatter. +##### Example +But be aware: nested fields will be printed! Only the root level of keywords is filtered by the `ignored_attrs`. +```python +attrs = ["secret", "password"] +formatter = GelfFormatter(ignored_attrs=attrs) +# or +formatter.ignored_attrs = attrs +logging.debug("app config", extra={"connection": "local", "secret": "verySecret!", "mysql": {"user": "test", "password": "will_be_logged"}}) +``` +```text +{"version": "1.1", "short_message": "app config", "timestamp": 1557346554.989846, "level": 6, "host": "my-server", "_connection": "local", "_mysql": {"user": "test", "password": "will_be_logged"}} +``` +#### Context Fields +Having the ability to define a set of additional fields once and have them included in all log messages can be useful to avoid repetitive `extra` key/value pairs and enable contextual logging. +Python's logging module provides several options to add context to a logger, among which we highlight the [`logging.LoggerAdapter`](https://docs.python.org/3/library/logging.html#loggeradapter-objects) and [`logging.Filter`](https://docs.python.org/3/library/logging.html#filter-objects). +Between these we recommend a `logging.Filter`, which is simpler and can be attached directly to a [`logging.Handler`](https://docs.python.org/3/library/logging.html#handler-objects). A `logging.Filter` can therefore be used locally (on a [`logging.Logger`](https://docs.python.org/3/library/logging.html#logger-objects)) or globally (through `logging.basicConfig`). If you opt for a `LoggerAdapter` you'll need a `logging.Logger` to wrap. +You can also use a `logging.Filter` to reuse/rename any of the reserved `logging.LogRecord` attributes. +##### Example +```python +class ContextFilter(logging.Filter): + def filter(self, record): + # Add any number of arbitrary additional fields + record.app = "my-app" + record.app_version = "1.2.3" + record.environment = os.environ.get("APP_ENV") + # Reuse any reserved `logging.LogRecord` attributes + record.file = record.filename + record.line = record.lineno + return True +formatter = GelfFormatter() +handler = logging.StreamHandler(sys.stdout) +handler.setFormatter(formatter) +handler.addFilter(ContextFilter()) +logging.basicConfig(level=logging.DEBUG, handlers=[handler]) +logging.info("hi", extra=dict(foo="bar")) +``` +```text +{"version": "1.1", "short_message": "hi", "timestamp": 1557431642.189755, "level": 6, "host": "my-server", "_foo": "bar", "_app": "my-app", "_app_version": "1.2.3", "_environment": "development", "_file": "app.py", "_line": 159} +``` +## Pretty-Print +Looking for a GELF log pretty-printer? If so, have a look at [gelf-pretty](https://github.com/joaodrp/gelf-pretty) :fire: +## Contributions +This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please refer to our [contributing guide](CONTRIBUTING.md) for further information. + +%package -n python3-gelf-formatter +Summary: GELF formatter for the Python standard library logging module. +Provides: python-gelf-formatter +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-pip +%description -n python3-gelf-formatter +## Motivation +There are several packages available providing *handlers* for the standard library logging module that can send application logs to [Graylog](https://www.graylog.org/) by TCP/UDP/HTTP ([py-gelf](https://pypi.org/project/pygelf/) is a good example). Although these can be useful, it's not ideal to make an application performance dependent on network requests just for the purpose of delivering logs. +Alternatively, one can simply log to a file or `stdout` and have a collector (like [Fluentd](https://www.fluentd.org/)) processing and sending those logs *asynchronously* to a remote server (and not just to Graylog, as GELF can be used as a generic log format), which is a common pattern for containerized applications. In a scenario like this all we need is a GELF logging *formatter*. +## Features +- Support for arbitrary additional fields; +- Support for including reserved [`logging.LogRecord`](https://docs.python.org/3/library/logging.html#logrecord-attributes) attributes as additional fields; +- Exceptions detection with traceback formatting; +- Zero dependencies and tiny footprint. +## Installation +### With pip +```text +$ pip install gelf-formatter +``` +### From source +```text +$ python setup.py install +``` +## Usage +Simply create a `gelfformatter.GelfFormatter` instance and pass it as argument to [`logging.Handler.setFormatter`](https://docs.python.org/3/library/logging.html#logging.Handler.setFormatter): +```python +import sys +import logging +from gelfformatter import GelfFormatter +formatter = GelfFormatter() +handler = logging.StreamHandler(sys.stdout) +handler.setFormatter(formatter) +``` +Apply it globally with [`logging.basicConfig`](https://docs.python.org/3/library/logging.html#logging.basicConfig) to automatically format log records from third-party packages as well: +```python +logging.basicConfig(level=logging.DEBUG, handlers=[handler]) +``` +Alternatively, you can configure a local [`logging.Logger`](https://docs.python.org/3/library/logging.html#logging.Logger) instance through [`logging.Logger.addHandler`](https://docs.python.org/3/library/logging.html#logging.Logger.addHandler): +```python +logger = logging.getLogger('my-app') +logger.addHandler(handler) +``` +That's it. You can now use the logging module as usual, all records will be formatted as GELF messages. +### Standard Fields +The formatter will output all (non-deprecated) fields described in the [GELF Payload Specification (version 1.1)](http://docs.graylog.org/en/latest/pages/gelf.html#gelf-payload-specification): +- `version`: String, always set to `1.1`; +- `host`: String, the output of [`socket.gethostname`](https://docs.python.org/3/library/socket.html#socket.gethostname) at initialization; +- `short_message`: String, log record message; +- `full_message` (*optional*): String, formatted exception traceback (if any); +- `timestamp`: Number, time in seconds since the epoch as a floating point; +- `level`: Integer, *syslog* severity level. +None of these fields can be ignored, renamed or overridden. +#### Example +```python +logging.info("Some message") +``` +```text +{"version":"1.1","host":"my-server","short_message":"Some message","timestamp":1557342545.1067393,"level":6} +``` +#### Exceptions +The `full_message` field is used to store the traceback of exceptions. You just need to log them with [`logging.exception`](https://docs.python.org/3/library/logging.html#logging.exception). +##### Example +```python +import urllib.request +req = urllib.request.Request('http://www.pythonnn.org') +try: + urllib.request.urlopen(req) +except urllib.error.URLError as e: + logging.exception(e.reason) +``` +```text +{"version": "1.1", "short_message": "[Errno -2] Name or service not known", "timestamp": 1557342714.0695107, "level": 3, "host": "my-server", "full_message": "Traceback (most recent call last):\n ...(truncated)... raise URLError(err)\nurllib.error.URLError: <urlopen error [Errno -2] Name or service not known>"} +``` +### Additional Fields +The GELF specification allows arbitrary additional fields, with keys prefixed with an underscore. +To include additional fields use the standard logging `extra` keyword. Keys will be automatically prefixed with an underscore (if not already). +#### Example +```python +logging.info("request received", extra={"path": "/orders/1", "method": "GET"}) +``` +```text +{"version": "1.1", "short_message": "request received", "timestamp": 1557343604.5892842, "level": 6, "host": "my-server", "_path": "/orders/1", "_method": "GET"} +``` +#### Reserved Fields +By default the formatter ignores all [`logging.LogRecord` attributes](https://docs.python.org/3/library/logging.html#logrecord-attributes). You can however opt to include them as additional fields. This can be used to display useful information like the current module, filename, line number, etc. +To do so, simply pass a list of `LogRecord` attribute names as value of the `allowed_reserved_attrs` keyword when initializing a `GelfFormatter`. You can also modify the `allowed_reserved_attrs` instance variable of an already initialized formatter. +##### Example +```python +attrs = ["lineno", "module", "filename"] +formatter = GelfFormatter(allowed_reserved_attrs=attrs) +# or +formatter.allowed_reserved_attrs = attrs +logging.debug("starting application...") +``` +```text +{"version": "1.1", "short_message": "starting application...", "timestamp": 1557346554.989846, "level": 6, "host": "my-server", "_lineno": 175, "_module": "myapp", "_filename": "app.py"} +``` +You can optionally customize the name of these additional fields using a [`logging.Filter`](https://docs.python.org/3/library/logging.html#filter-objects) (see below). +Similarily, you can choose to ignore additional attributes passed via the `extra` keyword argument. This can be usefull to e.g. not log keywords named `secret` or `password`. +To do so, pass a list of names to the `ignored_attrs` keyword when initializing a `GelfFormatter`. You can also modify the `ignored_attrs` instance variable of an already initialized formatter. +##### Example +But be aware: nested fields will be printed! Only the root level of keywords is filtered by the `ignored_attrs`. +```python +attrs = ["secret", "password"] +formatter = GelfFormatter(ignored_attrs=attrs) +# or +formatter.ignored_attrs = attrs +logging.debug("app config", extra={"connection": "local", "secret": "verySecret!", "mysql": {"user": "test", "password": "will_be_logged"}}) +``` +```text +{"version": "1.1", "short_message": "app config", "timestamp": 1557346554.989846, "level": 6, "host": "my-server", "_connection": "local", "_mysql": {"user": "test", "password": "will_be_logged"}} +``` +#### Context Fields +Having the ability to define a set of additional fields once and have them included in all log messages can be useful to avoid repetitive `extra` key/value pairs and enable contextual logging. +Python's logging module provides several options to add context to a logger, among which we highlight the [`logging.LoggerAdapter`](https://docs.python.org/3/library/logging.html#loggeradapter-objects) and [`logging.Filter`](https://docs.python.org/3/library/logging.html#filter-objects). +Between these we recommend a `logging.Filter`, which is simpler and can be attached directly to a [`logging.Handler`](https://docs.python.org/3/library/logging.html#handler-objects). A `logging.Filter` can therefore be used locally (on a [`logging.Logger`](https://docs.python.org/3/library/logging.html#logger-objects)) or globally (through `logging.basicConfig`). If you opt for a `LoggerAdapter` you'll need a `logging.Logger` to wrap. +You can also use a `logging.Filter` to reuse/rename any of the reserved `logging.LogRecord` attributes. +##### Example +```python +class ContextFilter(logging.Filter): + def filter(self, record): + # Add any number of arbitrary additional fields + record.app = "my-app" + record.app_version = "1.2.3" + record.environment = os.environ.get("APP_ENV") + # Reuse any reserved `logging.LogRecord` attributes + record.file = record.filename + record.line = record.lineno + return True +formatter = GelfFormatter() +handler = logging.StreamHandler(sys.stdout) +handler.setFormatter(formatter) +handler.addFilter(ContextFilter()) +logging.basicConfig(level=logging.DEBUG, handlers=[handler]) +logging.info("hi", extra=dict(foo="bar")) +``` +```text +{"version": "1.1", "short_message": "hi", "timestamp": 1557431642.189755, "level": 6, "host": "my-server", "_foo": "bar", "_app": "my-app", "_app_version": "1.2.3", "_environment": "development", "_file": "app.py", "_line": 159} +``` +## Pretty-Print +Looking for a GELF log pretty-printer? If so, have a look at [gelf-pretty](https://github.com/joaodrp/gelf-pretty) :fire: +## Contributions +This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please refer to our [contributing guide](CONTRIBUTING.md) for further information. + +%package help +Summary: Development documents and examples for gelf-formatter +Provides: python3-gelf-formatter-doc +%description help +## Motivation +There are several packages available providing *handlers* for the standard library logging module that can send application logs to [Graylog](https://www.graylog.org/) by TCP/UDP/HTTP ([py-gelf](https://pypi.org/project/pygelf/) is a good example). Although these can be useful, it's not ideal to make an application performance dependent on network requests just for the purpose of delivering logs. +Alternatively, one can simply log to a file or `stdout` and have a collector (like [Fluentd](https://www.fluentd.org/)) processing and sending those logs *asynchronously* to a remote server (and not just to Graylog, as GELF can be used as a generic log format), which is a common pattern for containerized applications. In a scenario like this all we need is a GELF logging *formatter*. +## Features +- Support for arbitrary additional fields; +- Support for including reserved [`logging.LogRecord`](https://docs.python.org/3/library/logging.html#logrecord-attributes) attributes as additional fields; +- Exceptions detection with traceback formatting; +- Zero dependencies and tiny footprint. +## Installation +### With pip +```text +$ pip install gelf-formatter +``` +### From source +```text +$ python setup.py install +``` +## Usage +Simply create a `gelfformatter.GelfFormatter` instance and pass it as argument to [`logging.Handler.setFormatter`](https://docs.python.org/3/library/logging.html#logging.Handler.setFormatter): +```python +import sys +import logging +from gelfformatter import GelfFormatter +formatter = GelfFormatter() +handler = logging.StreamHandler(sys.stdout) +handler.setFormatter(formatter) +``` +Apply it globally with [`logging.basicConfig`](https://docs.python.org/3/library/logging.html#logging.basicConfig) to automatically format log records from third-party packages as well: +```python +logging.basicConfig(level=logging.DEBUG, handlers=[handler]) +``` +Alternatively, you can configure a local [`logging.Logger`](https://docs.python.org/3/library/logging.html#logging.Logger) instance through [`logging.Logger.addHandler`](https://docs.python.org/3/library/logging.html#logging.Logger.addHandler): +```python +logger = logging.getLogger('my-app') +logger.addHandler(handler) +``` +That's it. You can now use the logging module as usual, all records will be formatted as GELF messages. +### Standard Fields +The formatter will output all (non-deprecated) fields described in the [GELF Payload Specification (version 1.1)](http://docs.graylog.org/en/latest/pages/gelf.html#gelf-payload-specification): +- `version`: String, always set to `1.1`; +- `host`: String, the output of [`socket.gethostname`](https://docs.python.org/3/library/socket.html#socket.gethostname) at initialization; +- `short_message`: String, log record message; +- `full_message` (*optional*): String, formatted exception traceback (if any); +- `timestamp`: Number, time in seconds since the epoch as a floating point; +- `level`: Integer, *syslog* severity level. +None of these fields can be ignored, renamed or overridden. +#### Example +```python +logging.info("Some message") +``` +```text +{"version":"1.1","host":"my-server","short_message":"Some message","timestamp":1557342545.1067393,"level":6} +``` +#### Exceptions +The `full_message` field is used to store the traceback of exceptions. You just need to log them with [`logging.exception`](https://docs.python.org/3/library/logging.html#logging.exception). +##### Example +```python +import urllib.request +req = urllib.request.Request('http://www.pythonnn.org') +try: + urllib.request.urlopen(req) +except urllib.error.URLError as e: + logging.exception(e.reason) +``` +```text +{"version": "1.1", "short_message": "[Errno -2] Name or service not known", "timestamp": 1557342714.0695107, "level": 3, "host": "my-server", "full_message": "Traceback (most recent call last):\n ...(truncated)... raise URLError(err)\nurllib.error.URLError: <urlopen error [Errno -2] Name or service not known>"} +``` +### Additional Fields +The GELF specification allows arbitrary additional fields, with keys prefixed with an underscore. +To include additional fields use the standard logging `extra` keyword. Keys will be automatically prefixed with an underscore (if not already). +#### Example +```python +logging.info("request received", extra={"path": "/orders/1", "method": "GET"}) +``` +```text +{"version": "1.1", "short_message": "request received", "timestamp": 1557343604.5892842, "level": 6, "host": "my-server", "_path": "/orders/1", "_method": "GET"} +``` +#### Reserved Fields +By default the formatter ignores all [`logging.LogRecord` attributes](https://docs.python.org/3/library/logging.html#logrecord-attributes). You can however opt to include them as additional fields. This can be used to display useful information like the current module, filename, line number, etc. +To do so, simply pass a list of `LogRecord` attribute names as value of the `allowed_reserved_attrs` keyword when initializing a `GelfFormatter`. You can also modify the `allowed_reserved_attrs` instance variable of an already initialized formatter. +##### Example +```python +attrs = ["lineno", "module", "filename"] +formatter = GelfFormatter(allowed_reserved_attrs=attrs) +# or +formatter.allowed_reserved_attrs = attrs +logging.debug("starting application...") +``` +```text +{"version": "1.1", "short_message": "starting application...", "timestamp": 1557346554.989846, "level": 6, "host": "my-server", "_lineno": 175, "_module": "myapp", "_filename": "app.py"} +``` +You can optionally customize the name of these additional fields using a [`logging.Filter`](https://docs.python.org/3/library/logging.html#filter-objects) (see below). +Similarily, you can choose to ignore additional attributes passed via the `extra` keyword argument. This can be usefull to e.g. not log keywords named `secret` or `password`. +To do so, pass a list of names to the `ignored_attrs` keyword when initializing a `GelfFormatter`. You can also modify the `ignored_attrs` instance variable of an already initialized formatter. +##### Example +But be aware: nested fields will be printed! Only the root level of keywords is filtered by the `ignored_attrs`. +```python +attrs = ["secret", "password"] +formatter = GelfFormatter(ignored_attrs=attrs) +# or +formatter.ignored_attrs = attrs +logging.debug("app config", extra={"connection": "local", "secret": "verySecret!", "mysql": {"user": "test", "password": "will_be_logged"}}) +``` +```text +{"version": "1.1", "short_message": "app config", "timestamp": 1557346554.989846, "level": 6, "host": "my-server", "_connection": "local", "_mysql": {"user": "test", "password": "will_be_logged"}} +``` +#### Context Fields +Having the ability to define a set of additional fields once and have them included in all log messages can be useful to avoid repetitive `extra` key/value pairs and enable contextual logging. +Python's logging module provides several options to add context to a logger, among which we highlight the [`logging.LoggerAdapter`](https://docs.python.org/3/library/logging.html#loggeradapter-objects) and [`logging.Filter`](https://docs.python.org/3/library/logging.html#filter-objects). +Between these we recommend a `logging.Filter`, which is simpler and can be attached directly to a [`logging.Handler`](https://docs.python.org/3/library/logging.html#handler-objects). A `logging.Filter` can therefore be used locally (on a [`logging.Logger`](https://docs.python.org/3/library/logging.html#logger-objects)) or globally (through `logging.basicConfig`). If you opt for a `LoggerAdapter` you'll need a `logging.Logger` to wrap. +You can also use a `logging.Filter` to reuse/rename any of the reserved `logging.LogRecord` attributes. +##### Example +```python +class ContextFilter(logging.Filter): + def filter(self, record): + # Add any number of arbitrary additional fields + record.app = "my-app" + record.app_version = "1.2.3" + record.environment = os.environ.get("APP_ENV") + # Reuse any reserved `logging.LogRecord` attributes + record.file = record.filename + record.line = record.lineno + return True +formatter = GelfFormatter() +handler = logging.StreamHandler(sys.stdout) +handler.setFormatter(formatter) +handler.addFilter(ContextFilter()) +logging.basicConfig(level=logging.DEBUG, handlers=[handler]) +logging.info("hi", extra=dict(foo="bar")) +``` +```text +{"version": "1.1", "short_message": "hi", "timestamp": 1557431642.189755, "level": 6, "host": "my-server", "_foo": "bar", "_app": "my-app", "_app_version": "1.2.3", "_environment": "development", "_file": "app.py", "_line": 159} +``` +## Pretty-Print +Looking for a GELF log pretty-printer? If so, have a look at [gelf-pretty](https://github.com/joaodrp/gelf-pretty) :fire: +## Contributions +This project adheres to the Contributor Covenant [code of conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please refer to our [contributing guide](CONTRIBUTING.md) for further information. + +%prep +%autosetup -n gelf-formatter-0.2.1 + +%build +%py3_build + +%install +%py3_install +install -d -m755 %{buildroot}/%{_pkgdocdir} +if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi +if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi +if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi +if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi +pushd %{buildroot} +if [ -d usr/lib ]; then + find usr/lib -type f -printf "\"/%h/%f\"\n" >> filelist.lst +fi +if [ -d usr/lib64 ]; then + find usr/lib64 -type f -printf "\"/%h/%f\"\n" >> filelist.lst +fi +if [ -d usr/bin ]; then + find usr/bin -type f -printf "\"/%h/%f\"\n" >> filelist.lst +fi +if [ -d usr/sbin ]; then + find usr/sbin -type f -printf "\"/%h/%f\"\n" >> filelist.lst +fi +touch doclist.lst +if [ -d usr/share/man ]; then + find usr/share/man -type f -printf "\"/%h/%f.gz\"\n" >> doclist.lst +fi +popd +mv %{buildroot}/filelist.lst . +mv %{buildroot}/doclist.lst . + +%files -n python3-gelf-formatter -f filelist.lst +%dir %{python3_sitelib}/* + +%files help -f doclist.lst +%{_docdir}/* + +%changelog +* Tue Jun 20 2023 Python_Bot <Python_Bot@openeuler.org> - 0.2.1-1 +- Package Spec generated @@ -0,0 +1 @@ +86b45d445e9c0926f8ac6ef2984facf3 gelf-formatter-0.2.1.tar.gz |