Giter Club home page Giter Club logo

graypy's Introduction

graypy

PyPI Status Build Status Documentation Status Coverage Status

Description

Python logging handlers that send log messages in the Graylog Extended Log Format (GELF).

graypy supports sending GELF logs to both Graylog2 and Graylog3 servers.

Installing

Using pip

Install the basic graypy python logging handlers:

pip install graypy

Install with requirements for GELFRabbitHandler:

pip install graypy[amqp]

Using easy_install

Install the basic graypy python logging handlers:

easy_install graypy

Install with requirements for GELFRabbitHandler:

easy_install graypy[amqp]

Usage

graypy sends GELF logs to a Graylog server via subclasses of the python logging.Handler class.

Below is the list of ready to run GELF logging handlers defined by graypy:

  • GELFUDPHandler - UDP log forwarding
  • GELFTCPHandler - TCP log forwarding
  • GELFTLSHandler - TCP log forwarding with TLS support
  • GELFHTTPHandler - HTTP log forwarding
  • GELFRabbitHandler - RabbitMQ log forwarding

UDP Logging

UDP Log forwarding to a locally hosted Graylog server can be easily done with the GELFUDPHandler:

import logging
import graypy

my_logger = logging.getLogger('test_logger')
my_logger.setLevel(logging.DEBUG)

handler = graypy.GELFUDPHandler('localhost', 12201)
my_logger.addHandler(handler)

my_logger.debug('Hello Graylog.')

UDP GELF Chunkers

GELF UDP Chunking is supported by the GELFUDPHandler and is defined by the gelf_chunker argument within its constructor. By default the GELFWarningChunker is used, thus, GELF messages that chunk overflow (i.e. consisting of more than 128 chunks) will issue a GELFChunkOverflowWarning and will be dropped.

Other gelf_chunker options are also available:

  • BaseGELFChunker silently drops GELF messages that chunk overflow
  • GELFTruncatingChunker issues a GELFChunkOverflowWarning and simplifies and truncates GELF messages that chunk overflow in a attempt to send some content to Graylog. If this process fails to prevent another chunk overflow a GELFTruncationFailureWarning is issued.

RabbitMQ Logging

Alternately, use GELFRabbitHandler to send messages to RabbitMQ and configure your Graylog server to consume messages via AMQP. This prevents log messages from being lost due to dropped UDP packets (GELFUDPHandler sends messages to Graylog using UDP). You will need to configure RabbitMQ with a gelf_log queue and bind it to the logging.gelf exchange so messages are properly routed to a queue that can be consumed by Graylog (the queue and exchange names may be customized to your liking).

import logging
import graypy

my_logger = logging.getLogger('test_logger')
my_logger.setLevel(logging.DEBUG)

handler = graypy.GELFRabbitHandler('amqp://guest:guest@localhost/', exchange='logging.gelf')
my_logger.addHandler(handler)

my_logger.debug('Hello Graylog.')

Django Logging

It's easy to integrate graypy with Django's logging settings. Just add a new handler in your settings.py:

LOGGING = {
    'version': 1,
    # other dictConfig keys here...
    'handlers': {
        'graypy': {
            'level': 'WARNING',
            'class': 'graypy.GELFUDPHandler',
            'host': 'localhost',
            'port': 12201,
        },
    },
    'loggers': {
        'django.request': {
            'handlers': ['graypy'],
            'level': 'ERROR',
            'propagate': True,
        },
    },
}

Traceback Logging

By default log captured exception tracebacks are added to the GELF log as full_message fields:

import logging
import graypy

my_logger = logging.getLogger('test_logger')
my_logger.setLevel(logging.DEBUG)

handler = graypy.GELFUDPHandler('localhost', 12201)
my_logger.addHandler(handler)

try:
    puff_the_magic_dragon()
except NameError:
    my_logger.debug('No dragons here.', exc_info=1)

Default Logging Fields

By default a number of debugging logging fields are automatically added to the GELF log if available:

  • function
  • pid
  • process_name
  • thread_name

You can disable automatically adding these debugging logging fields by specifying debugging_fields=False in the handler's constructor:

handler = graypy.GELFUDPHandler('localhost', 12201, debugging_fields=False)

Adding Custom Logging Fields

graypy also supports including custom fields in the GELF logs sent to Graylog. This can be done by using Python's LoggerAdapter and Filter classes.

Using LoggerAdapter

LoggerAdapter makes it easy to add static information to your GELF log messages:

import logging
import graypy

my_logger = logging.getLogger('test_logger')
my_logger.setLevel(logging.DEBUG)

handler = graypy.GELFUDPHandler('localhost', 12201)
my_logger.addHandler(handler)

my_adapter = logging.LoggerAdapter(logging.getLogger('test_logger'),
                                   {'username': 'John'})

my_adapter.debug('Hello Graylog from John.')

Using Filter

Filter gives more flexibility and allows for dynamic information to be added to your GELF logs:

import logging
import graypy

class UsernameFilter(logging.Filter):
    def __init__(self):
        # In an actual use case would dynamically get this
        # (e.g. from memcache)
        self.username = 'John'

    def filter(self, record):
        record.username = self.username
        return True

my_logger = logging.getLogger('test_logger')
my_logger.setLevel(logging.DEBUG)

handler = graypy.GELFUDPHandler('localhost', 12201)
my_logger.addHandler(handler)

my_logger.addFilter(UsernameFilter())

my_logger.debug('Hello Graylog from John.')

Contributors

  • Sever Banesiu
  • Daniel Miller
  • Tushar Makkar
  • Nathan Klapstein

graypy's People

Contributors

alexbrasetvik avatar anthchirp avatar atugushev avatar bitdeli-chef avatar claytondaley avatar colinhowe avatar crohling avatar dmuntean avatar domino14 avatar garethr avatar hoffmann avatar iggy avatar imankulov avatar janoberst avatar jhildreth avatar jjhooper avatar joeshaw avatar millerdev avatar nklapste avatar paulius-maruska avatar praseodym avatar ress avatar severb avatar sjonhortensius avatar stratosgear avatar tobiasmcnulty avatar tusharmakkar08 avatar vmarkovtsev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

graypy's Issues

Interaction with graypy breaks

Hello,

Commit d96aabe#graypy/handler.py introduced the logging of loads of additional fields in the record. Some fields were added to a skip list.

This change broke interop with logbook. Logbook adds a member called frame to the record before emitting it. This is a frame and cannot be JSON serialized.

Could 'frame' be added to the skiplist?

Cheers,
Colin

last release not working?

Hi I'm not sure why it doesn't work, maybe some non-printable character inside? But the latest version doesn't work

  File "/usr/local/lib/python2.6/dist-packages/graypy/__init__.py", line 1, in <module>
    from graypy.handler import GELFHandler, WAN_CHUNK, LAN_CHUNK
  File "/usr/local/lib/python2.6/dist-packages/graypy/handler.py", line 167
    return {sanitize(k): sanitize(v) for k, v in obj.items()}
                                       ^
SyntaxError: invalid syntax

Call to basicConfig() is needed

Should fix README.rst to include logging.basicConfig() before sending log messages. Patch follows.

diff --git a/README.rst b/README.rst
index 14cc99f..7a4fe98 100644
--- a/README.rst
+++ b/README.rst
@@ -17,6 +17,7 @@ Messages are sent to Graylog2 using a custom handler for the builtin logging lib
import logging
import graypy

  • logging.basicConfig()
    my_logger = logging.getLogger('test_logger')
    my_logger.setLevel(logging.DEBUG)

@@ -30,6 +31,7 @@ Alternately, use GELFRabbitHandler to send messages to RabbitMQ and configur
import logging
import graypy

  • logging.basicConfig()
    my_logger = logging.getLogger('test_logger')
    my_logger.setLevel(logging.DEBUG)

@@ -43,6 +45,7 @@ Tracebacks are added as full messages::
import logging
import graypy

  • logging.basicConfig()
    my_logger = logging.getLogger('test_logger')
    my_logger.setLevel(logging.DEBUG)

Problem adding filters for django logging

I have the following settings for django in settings.py:

LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'formatters': {
            'simple': {
                'format': '%(levelname)s %(message)s'
            }
        },
        'filters': {
            'fields': {
                'env': 'test'
            }
        },
        'handlers': {
            'graypy': {
                'level': 'DEBUG',
                'class': 'graypy.GELFHandler',
                'host': 'graylog2.example.org',
                'port': 12201,
                'filters': ['fields']
            }
        },
        'loggers': {
            'testlogger': {
                'handlers': ['graypy'],
                'level': 'DEBUG',
                'propagate': True
            }
        }
    }

But I didn't see any filters setup for graylog in GUI, so I checked it locally with logging.getLogger('testlogger').handlers[0].filters[0].__dict__ and it returns {'name': '', 'nlen': 0}. Then I made a little change that I throw the filters out handlers and put that in loggers like:

'loggers': {
            'testlogger': {
                'handlers': ['graypy'],
                'filters': ['fields'],
                'level': 'DEBUG',
                'propagate': True
            }
        }

And it didn't work as well. The only way seems working for me is manually add a filter class just like the sample in README. So I don't know if dict config hasn't been supported by graylog or I did something in my config.

Undefined variable chunk_size in GraylogTcpHandler

BaseGELFHandler.__init__(self, host, port, chunk_size,

GraylogTcpHandler tries to pass chunk_size to the base class and fails with exception:

Traceback (most recent call last):
File "/srv/cms/cms/afl/wsgi.py", line 22, in
application = get_wsgi_application()
File "/srv/cms/cms-lib/django/core/wsgi.py", line 14, in get_wsgi_application
django.setup()
File "/srv/cms/cms-lib/django/init.py", line 20, in setup
configure_logging(settings.LOGGING_CONFIG, settings.LOGGING)
File "/srv/cms/cms-lib/django/utils/log.py", line 87, in configure_logging
logging_config_func(logging_settings)
File "/usr/lib/python2.7/logging/config.py", line 794, in dictConfig
dictConfigClass(config).configure()
File "/usr/lib/python2.7/logging/config.py", line 576, in configure
'%r: %s' % (name, e))
ValueError: Unable to configure handler 'graylog-gelf': global name 'chunk_size' is not defined

extra_fields with numerical values

I'm super new to both Graylog2 and graypy, so please let me know if I'm doing something wrong!

I'm working on a simple request timing middleware for Django and I would like to be able to send this data to Graylog2 (so I can chart it). This isn't working for me right now, as It looks like non-string extra_fields values are being converted to strings repr() inside of add_extra_fields():

if isinstance(value, basestring):
    message_dict['_%s' % key] = value
else:
    message_dict['_%s' % key] = repr(value)

I can send you a pull request that changes this section to allow numbers or strings to be written if needed.

Can this help to encrypt log while sending to graylog servers

Hi

I am new this technology in first place. I am exploring few option to achieve following sceneario

From source system, I need to pull syslog , encrypt it and then send to gray log servers... so is that mandatory to send syslog via AMQP ? this program automatically encrypts message which is being sent to graylog. sorry if these silly doubts...but I am trying to analyze if this program can help me

GELFRabbitHandler error when following example docs

Does anyone know what this is caused by? It seems to happen in Python 2.6 but not 2.7.

>>> handler = graypy.GELFRabbitHandler('amqp://guest:guest@localhost/', 'logging.gelf')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/cesar/virtualenvs/venomenv/lib/python2.6/site-packages/graypy/rabbitmq.py", line 46, in __init__
    super(GELFRabbitHandler, self).__init__(host, port)
TypeError: super() argument 1 must be type, not classobj

GELF TCP with TLS Enabled

I was wondering if there were any plans to add support for sending to Graylog GELF TCP inputs that have TLS enabled?

I'd be happy to look into this more if that would be helpful.

graypy crashing when passed a django WSGIRequest

stelios reported that

When django throws an error 500 graypy throws TypeError when doing
json.dumps.
Here's (part of) the stacktrace:

Traceback (most recent call last):
 File "/usr/lib/python2.6/logging/handlers.py", line 541, in emit
   s = self.makePickle(record)
 File "/usr/local/lib/python2.6/dist-packages/graypy/handler.py",
line 28, in makePickle
   return zlib.compress(json.dumps(message_dict))
 File "/usr/lib/python2.6/json/__init__.py", line 230, in dumps
   return _default_encoder.encode(obj)
 File "/usr/lib/python2.6/json/encoder.py", line 367, in encode
   chunks = list(self.iterencode(o))
 File "/usr/lib/python2.6/json/encoder.py", line 309, in _iterencode
   for chunk in self._iterencode_dict(o, markers):
 File "/usr/lib/python2.6/json/encoder.py", line 275, in
_iterencode_dict
   for chunk in self._iterencode(value, markers):
 File "/usr/lib/python2.6/json/encoder.py", line 317, in _iterencode
   for chunk in self._iterencode_default(o, markers):
 File "/usr/lib/python2.6/json/encoder.py", line 323, in
_iterencode_default
   newobj = self.default(o)
 File "/usr/lib/python2.6/json/encoder.py", line 344, in default
   raise TypeError(repr(o) + " is not JSON serializable")
TypeError: <WSGIRequest

This is "normal" since WSGIRequest is not JSON serializable but how
can you then send error 500 errors from
Django to graylog2. Hope I'm not missing something obvious...

simply not working

import logging
import graypy

my_logger = logging.getLogger('test_logger')
my_logger.setLevel(logging.DEBUG)

handler = graypy.GELFHandler('my_graylog_server', 12201)
my_logger.addHandler(handler)

my_adapter = logging.LoggerAdapter(logging.getLogger('test_logger'),
                                   { 'username': 'John' })

my_adapter.debug('Hello Graylog2 from John.')

is not working

I think the issue is the url that should send to /gelf
because when I curl from the terminal to my graylog server , it works

 curl -XPOST http://my_graylog_server:12201/gelf -p0 -d '{"short_message":"Hello there", "host":"example1111.org", "facility":"test", "_foo":"bar"}'

ImportError: No module named 'handler' (+fix)

I have too little Python knowledge to explain this; but I had to edit graypy/init and change

from handler import ..

to

from graypy.handler import ..

or else the import graypy statement would throw an error

allow to customize full_message

I like the stack trace in full_message when it is an exception.

but the fallback to record.message() that is also used for the short_message is just unnecessary data collection into graylog.

What would be nice if we could write a filter that can provide a custom implementation on a record.
e.g. record.get_full_message()

test_resolve_host fails due to hostname != FQDN

The Debian package of graypy 1.1.2-1 fails in test_resolve_host:

I: pybuild base:217: cd /<<PKGBUILDDIR>>/.pybuild/cpython2_2.7_graypy/build; python2.7 -m pytest tests
============================= test session starts ==============================
platform linux2 -- Python 2.7.16, pytest-3.10.1, py-1.7.0, pluggy-0.8.0
rootdir: /<<PKGBUILDDIR>>, inifile:
collected 262 items

tests/integration/test_chunked_logging.py s                              [  0%]
tests/integration/test_common_logging.py sssssssssssssss                 [  6%]
tests/integration/test_debugging_fields.py sssssss                       [  8%]
tests/integration/test_extra_fields.py sssssss                           [ 11%]
tests/integration/test_status_issue.py sssssssssssssssssssssssssssssssss [ 24%]
ssssssssssss                                                             [ 28%]
tests/unit/test_ExcludeFilter.py .......                                 [ 31%]
tests/unit/test_GELFRabbitHandler.py ..x.                                [ 32%]
tests/unit/test_handler.py ............................................. [ 50%]
...................sssssssssssssss...................................... [ 77%]
......................................F........ss..........              [100%]

=================================== FAILURES ===================================
______________________________ test_resolve_host _______________________________

    def test_resolve_host():
        """Test all posible resolutions of :meth:`BaseGELFHandler._resolve_host`"""
        assert socket.gethostname() == BaseGELFHandler._resolve_host(False, None)
        assert socket.getfqdn() == BaseGELFHandler._resolve_host(True, None)
>       assert socket.gethostname() == BaseGELFHandler._resolve_host(True, "localhost")
E       AssertionError: assert 'x86-grnet-02' == 'x86-grnet-02.debian.org'
E         - x86-grnet-02
E         + x86-grnet-02.debian.org

tests/unit/test_handler.py:176: AssertionError
========= 1 failed, 168 passed, 92 skipped, 1 xfailed in 0.86 seconds ==========

BaseGELFHandler._resolve_host returns the FQDN, but socket.gethostname returns only the hostname (first part of the FQDN).

Full build log: https://buildd.debian.org/status/fetch.php?pkg=graypy&arch=all&ver=1.1.2-1&stamp=1562588890&raw=0

Convert Bool to String

The GELF protocol only allows string and numeric values.

Type Bool is excluded from the log.

AWS S3 and Lambda

Hello,

We have logs being stored in s3 buckets on AWS. I was wondering what you all thought about using your code as a Lambda function to move those logs into Graylog?

Thanks for any feedback!

Chris Edwards

Fails to log silently with specific extra field

If I add extra field named 'status' to the extra fields dict when logging, graypy will drop the message without any error (nothing gets logged).
Example:

import logging
import graypy

mylog=logging.getLogger('order.processing')
handler=graypy.GELFHandler('mylogserver',debugging_fields=True)
mylog.addHandler(handler)
#the following line works
mylog.info("Test123",extra={'fld1':1,'fld2':2})
# the following line doesn't output anything to GrayLog:
mylog.info("Test with status", extra={'fld1':1,'fld2':2, 'status':'OK'})

Gelf TCP Sender

It would be nice to have TCP sender also, to work with graylog2 tcp inputs

Celery

Any ideas on how you would hook this up to Django-less Celery? The logging documentation doesn't seem all that helpful.

Thanks!

Support RFC 5424 timestamp

Would you be open to supporting a timestamp format as specified by RFC 5424 (section 6.2.3) for readability? I know that this is not specified by GELF 1.1 so I would suggest to make it configurable using a timestamp_format='rfc-3339' parameter.

Related standards: ISO 8601, RFC 3339.

Versioning of Graypy

Hey @severb

In Pypi server the live version of Graypy is 0.2.14 while in the setup.py the version mentioned is 0.2.13. What's the reason behind such discrepancy? Can we please get it updated? Also, it would be great if we can maintain tags for the same.

Thanks.

Adding Travis Support

Hey @severb

Since graypy is an evolving project, I think it would be great to add automated tests/CI support using Travis. I can help in setting up that. Let me know if you are interested.

Thanks.

Release 1.1.1 appears to have broken graypy

Release 1.1.1 an hour ago.

from graypy import GELFHandler
Traceback (most recent call last):
File "", line 1, in
ImportError: cannot import name 'GELFHandler'

Is the 1.x release not intended to be backwards compatible with 0.3.x releases?

GELF TCP input does not support compression

The Graylog documentation says:

GELF TCP does not support compression due to the use of the null byte (\0) as frame delimiter.

But the GELFTcpHandler class allows to set the compress parameter to True, thereby breaking the reception of logs by Graylog.

Please, remove the compress parameter from GELFTcpHandler class.

Appending extra fields directly during initialization of GELFHandler

Hi guys,

Thanks for the package! Really awesome stuff.

I'd like to ask if there's a way to append extra fields to each log request from the initialization of GELFHandler itself?

I'm running a tornado app and I'm able to log everything correctly with:

handler = graypy.GELFHandler('ip, 12201, localname="service")
logging.getLogger("tornado.access").addHandler(handler)
logging.getLogger("tornado.application").addHandler(handler)
logging.getLogger("tornado.general").addHandler(handler)

I'd like to be able to append some extra fields onto every log that uses the GELFHandler. Looking at the docs, it seems like the way to do it is via LoggerAdapter but that wouldn't work in tornado's case as it uses the logger("tornado.access") by default etc.

GELFRabbitHandler and missing Queue/Binding

I was having trouble with the GELFRabbitHandler example because the queue and exchange weren't bound. I eventually realized this because rabbitmqadmin provides the feedback "Message published but NOT routed". GELFRabbitHandler provides no feedback about this situation. I checked and a comparable situation exists if the exchange is missing.

Are there any acceptable options to remedy this situation? I work in a regulated industry (healthcare). I'm using the GELFRabbitHandler because I have to maintain the integrity of the logs (can't drop UDP packets). If GELFRabbitHandler isn't working, I really need to know so I can stop serving content.

I realize errors while logging are a bit of a catch-22 since the log is the standard place to send them. Is there an appropriate (alternative) way of escalating an issue like this? For example, would you be open to a PR that adds a "strict" mode that:

  • Attempts to send a message
  • If it gets one of the two severe errors ("Not found" or "NOT routed"), attempts to create the infrastructure
  • If it cannot create the infrastructure (for example, due to permissions), raises an exception (with the intent that the server produces a 500 error)

If you prefer, I could make the 3rd bullet a callback to make it easy to produce custom behaviors (e.g. email the admins).

Warrings include whole image in binary.

I am using logger with three handlers:

  • console
  • graypy
  • reportportal

Reportportal handler is able to log images. So I would like to log them and I am expecting that console log and graypy log in this situation remain silent or print some warring.

Graypy, however, post waring which contains the whole big image in binary and make impossible to read other console logs.

/env/lib64/python3.7/site-packages/graypy/handler.py:469: GELFChunkOverflowWarning: chunk overflowing GELF message: b'x\x9c\xec\xbd\xfb[\xd3N\xd07\xfc\xafp\xa8\n\x88\x90C\x93\xb4\x88\nrFD\x0e\x82\x80\x15mJ#\x08\x14\x84""\xea\xdf\xfet\xb3\x9fIf\xb2\x9b\xe2\xf7~\xdf\x1f\x9e\xeb\xb9n/\xaf-m\x92\xcd\xee\xec\x9cgv\xf6~\xe8G\xfb\xea\xfa\xe4\xa2345\xe4N8C\xe3C\xc7\x17\xd7\xdd\xde\x97\xb3\x8b\xcb\x9b\xd6q\xef\xfb\xf5\xf1\xc5U\xf7\xf3y\xfb\xfa\xba\xf9\xb5\xdd\xbb\xf0\xe3\xe4\xa8}1p\xdd\xbaj\xb7;\xbdk\xdd\x81\xee\xf9\xe5d\xfe\xd5\x9d\xb8\xec|\xed=\xd6=\xe9=\xd2m\x9e_\x0eM\xb9A-\xaaF5/\x0c\'|\xc7\xa9\xd6\xfd`|\xe8\xac\xfd\xa3}64\x15\x8e\x0f%\xcd\xd6\xc9\xd9I\xf7\xae\xd7\xf5\xe5Y\xf3\xae}\xf5\xac\xdb{\xf0\xba\xd7Err\xa6^8y|q\xde\x9e\xfcv\xd2=mN~=\xe9N&W\x17\x9d\xee\xb3v\xe7(\xbd\xf1\xa4\xf3u\xf2\xfc\xee\xa6{rv=\xd9\xba8\xbfl^\xb5W\xce{#\x9d\xb8\xbc\xebuqv\xd2\xe9u\xe1\xf9\xe3C\x9f\x93\x9bN\xab\xab\'zv\xf1\xf5\xf3\x89\xba\xa9w\xc7\xe7\xcb\x93\xa3\xde\x1d\xb5zM\xdd\xd4=\xbej7\x8f>w\x9a\xe7\xea\xcdo\x9b\'\x9d\xf7\xe9/\xe9\x8dW\x17\xad\x1e\x14\xf8\xc5\r\xfd\x93\xba\xda\x9bk\xeb\xf4\xf3I\'\xb9\x18\x9a\xea\xdc\x9c\x9d\xf5~jv{\xbf\x1d\x9f\xb7;=x\xde\x0f\x1d5\xbb\xcd\xdec\x8d\x9b$I\x8e6\xd6\x97\x1aW\x8dN\xe3\xc6q\xdc\xa6\xfet\x1c\xd1^\xad,\xcfo\x19\xbfW-w\xaa\xd6\xd3\xdd6\xe2\xf4[h\xdeU\xbb=M_\xe6\xf2\x1f\x07\xf4\xc7\xca\xfc\xec\xfb\x9f\xe8 m\xf7\xf5GE\x7f\xfc\xd1\x1f\x1f\xf5\xc7\x87\x0f\xe9C\x89\xfe6\xb7\xae?\xbb;\xfa3\xf4\xf5\xe7%\xef\xae\xbcu\xc2z\xa4\xffN\xf8\x05\xaf\xa5?\xaf\xad\xcf8n\x1d/\xdfL\xbfU\xcd\xeb\x9ff\xf8 u;8\xa3?\xf1\xf5\x03\xbf6\x9f\xde\xee\xf3\x9f\x9e\xaa\xd1\xb5\x1c\xfd\xe5\x0b\xeb\xbcf\xfc\xd4[\x15\xf1\xa6C\xfd1\xa5?\x86\xd3\xa7\x12Z\xbe\xec\xa1\xe4Ic\xc8\xc3\x7f\xf6\xf0\xaf\xb1\xfd\x9b\x97e\x10\x9b\xca\xd7\xd0\xad\xbfY,N<J\xec\x7f\x13\xc0\x14z\xfc\xcb\xb2\xe4\xed;

I would like to see warring which contains only informartion about binary content or short preview.

Automatic deployment to PyPI

It would be best if we were to implement automatic PyPI deployment via travis-ci to keep the versioning consistent. Our testing is not very sufficient, but, being able to release more often is a good thing.

A good example of implementing the basic auth for automatically deploying to PyPI is shown below:
https://medium.com/@mikkokotila/deploying-python-packages-to-pypi-with-travis-works-9a6597781556

@severb I assume graypy is uploaded under your account. Would it be possible for you to implement such a feature. You could essentially go hands free after this for maintaining graypy.

Not working with IP address hosts

This is working from the command line:

echo -e '{"version": "1.1","host":"example.org","short_message":"WOOORRRKIIING","full_message":"Backtrace here\n\nmore stuff","level":1,"_user_id":9001,"_some_info":"foo","_some_env_var":"bar"}\0' | nc -w 1 -u 104.197.106.62 12201

However, when I try the examples given in graypy documentation, it is not working. No errors, but I cannot see the logs on Graylog.

import logging
logger = logging.getLogger('projectname')
logger.debug('Please, work! :) ')

This is my setup:

'gelf': {
    'class': 'graypy.GELFHandler',
    'host': '104.197.106.62',
    'port': 12201,
}

and

'projectname': {
     'handlers': ['gelf'],
     'level': 'DEBUG',
 }

Please, note that when I do 'host': 'localhost' it is working on the local Graylog server. That's why I think that the problem may be in 'host': '104.197.106.62'. Is DNS name required? or am I doing something wrong?

Thank you!

String values in extra and in filter are passed with the quotation marks

My filter:

class ContextInfoFilter(logging.Filter):
    def filter(self, record):
        record.friend="yes"
        record.user = user.id
        return True
logger.addFilter(ContextInfoFilter())
logger.info("hi graylog")

Graylog logs:

{
  user: "u'serge'", //the u' and ' should not be logged
  friend: "'yes'", //the ' surrounding yes should not be logged
  ...
}

Here is a screenshot from Graylog UI showing the issue:
image

HTTPS support

I've got two ideas on how to add this feature: add a flag in the GELFHTTPHandler or create a new GELFHTTPSHandler.

For both of them there is a very low code effort, what do you think about them?
How can I open a PR?

Graypy allows chunk size greater than 128

According to the specification "A message MUST NOT consist of more than 128 chunks.".
https://docs.graylog.org/en/3.0/pages/gelf.html
There's a bug where graypy allows a chunk size between 128 and 256. The error is perceived when another API tries to decode a large gelf message encode by graypy.

On handler.py the validation should be on this line:

self.pieces = \ struct.pack('B', int(math.ceil(len(message) * 1.0 / size))) self.id = struct.pack('Q', random.randint(0, 0xFFFFFFFFFFFFFFFF))

I could send an PR for this but I'd have to choose an exception.

Regards!

Error when remote hostname does not (yet) exist

Hi,

I have a python script which creates a graylog server (and adds it's domain name). The script is itself setup to log to graylog (and to a file). When I run the script, it outputs:

Traceback (most recent call last):
  File "/usr/lib64/python2.7/logging/handlers.py", line 556, in emit
    self.send(s)
  File "/home/ec2-user/.virtualenvs/python27/lib/python2.7/site-packages/graypy/handler.py", line 40, in send
    DatagramHandler.send(self, s)
  File "/usr/lib64/python2.7/logging/handlers.py", line 607, in send
    self.sock.sendto(s, (self.host, self.port))
gaierror: [Errno -2] Name or service not known

because the domain name of the log server does not yet exist. Can the code be changed to suppress this output? It does not output anything if the DNS entry exists, but there is no server listening.

Truncate oversized GELFRabbitHandler messages

Is there a recommended way of handling large messages so they are not completely dropped by graylog? I added the following patch, but only having used graylog/GELF for a couple days, I imagine there is a better way to handle this case as it drops all but the base set of fields.

class GELFRabbitHandler(BaseGELFHandler, SocketHandler):
     def makePickle(self, record):
         message_dict = self._make_gelf_dict(record)
         data = json.dumps(message_dict)
         if len(data) > 32766:
             data = json.dumps({
                 'version': message_dict['version'],
                 'host': message_dict['host'],
                 'short_message': 'OVERSIZED_MESSAGE: ' + message_dict['short_message'][:2048],
                 'timestamp': message_dict['timestamp'],
                 'level': message_dict['level'],
                 'facility': message_dict['facility'],
             }, cls=self.serializer)
         return data

Why GELFHandler is deprecated?

I just run pip install graypy today on new machine that i using and them a get this error on older project.

AttributeError: module 'graypy' has no attribute 'GELFHandler'

Support custom JSON serializer

Running into an issue with certain objects not being JSON serializable using the GELFRabbitHandler and causing a crash.

Would it be possible to allow for a custom handler or handle the case of unserializable objects?

I have the following patch I use, but it is dependent on django for string references to the serializer from a dictConfig. I see BaseGELFHandler._pack_gelf_dict has the default option set that is not present in GELFRabbitHandler.makePickle. That might at least resolve the crash condition.

from django.utils.module_loading import import_string

class GELFRabbitHandler(BaseGELFHandler, SocketHandler):
    def __init__(self, url, exchange='logging.gelf', exchange_type='fanout',
                      virtual_host='/', routing_key='', serializer_class=None, **kwargs):
        ...
        self.serializer = import_string(serializer_class)

    def makePickle(self, record):
        message_dict = self._make_gelf_dict(record)
        return json.dumps(message_dict, cls=self.serializer)

Start keeping a changelog

Can this project start keeping a changelog? There have been a number of new releases without an indication to people using the library what changed from one version to the next. It makes it hard to stay up to date when each update is a mystery box.

Release 0.3.2

The feature of adding a Formatter to the GELFHandler is a life-saver. Please make a release!

I'd be more than happy to contribute.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.