Skip to content

Commit 7d3b301

Browse files
authored
Feature/sphinx docs (severb#100)
* sphinx docs build support * simplifying and reworking docs * fixing variable name shadow issue
1 parent 5766c9a commit 7d3b301

19 files changed

+477
-191
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ instance/
6767
# Sphinx documentation
6868
docs/_build/
6969

70+
# Sphinx API documentation
71+
docs/api/
72+
7073
# PyBuilder
7174
target/
7275

.travis.yml

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ stages:
44
- lint
55
- test
66
- build
7-
# TODO: needs additional setup
8-
# - deploy
7+
- deploy
98

109
before_install:
1110
- pip install codecov
@@ -14,19 +13,13 @@ install:
1413
- pip install .
1514

1615
before_script:
17-
- cd tests/config
18-
- bash create_ssl_certs.sh -h localhost -i 127.0.0.1
19-
- cd ../..
20-
- docker-compose -f tests/config/docker-compose.yml down
21-
- docker-compose -f tests/config/docker-compose.yml up -d
22-
- sleep 40
23-
- "curl -u admin:admin 'http://127.0.0.1:9000/api/search/universal/relative?query=test&range=5&fields=message' || true"
16+
- bash tests/config/start_local_graylog_server.sh
2417

2518
script:
2619
- python setup.py test
2720

2821
after_script:
29-
- docker-compose -f tests/config/docker-compose.yml down
22+
- bash tests/config/stop_local_graylog_server.sh
3023

3124
after_success:
3225
- codecov
@@ -76,6 +69,15 @@ jobs:
7669
script:
7770
- python setup.py bdist_wheel
7871
after_script: skip
72+
- name: "sphinx docs"
73+
python:
74+
- 3.6
75+
install:
76+
- pip install .[docs,amqp]
77+
before_script: skip
78+
script:
79+
- sphinx-build docs/ build/
80+
after_script: skip
7981
- stage: deploy
8082
deploy:
8183
python:

MANIFEST.in

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
include LICENSE
22
include README.rst
3-
recursive-include tests *.py
3+
recursive-include tests *.py
4+
recursive-include tests/config *

README.rst

Lines changed: 116 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,83 @@
1-
|PyPI_Status|
2-
|Build_Status|
3-
|Coverage_Status|
1+
######
2+
graypy
3+
######
4+
5+
.. image:: https://img.shields.io/pypi/v/graypy.svg
6+
:target: https://pypi.python.org/pypi/graypy
7+
:alt: PyPI Status
8+
9+
.. image:: https://travis-ci.org/severb/graypy.svg?branch=master
10+
:target: https://travis-ci.org/severb/graypy
11+
:alt: Build Status
12+
13+
.. image:: https://readthedocs.org/projects/graypy/badge/?version=stable
14+
:target: https://graypy.readthedocs.io/en/stable/?badge=stable
15+
:alt: Documentation Status
16+
17+
.. image:: https://codecov.io/gh/severb/graypy/branch/master/graph/badge.svg
18+
:target: https://codecov.io/gh/severb/graypy
19+
:alt: Coverage Status
420

521
Description
622
===========
723

8-
Python logging handlers that send messages in the Graylog Extended
9-
Log Format (GELF_).
24+
Python logging handlers that send log messages in the
25+
Graylog Extended Log Format (GELF_).
26+
27+
graypy supports sending GELF logs to both Graylog2 and Graylog3 servers.
1028

1129
Installing
1230
==========
1331

1432
Using pip
1533
---------
1634

17-
Install the basic graypy python logging handlers
35+
Install the basic graypy python logging handlers:
1836

19-
.. code-block:: bash
37+
.. code-block:: console
2038
2139
pip install graypy
2240
23-
Install with requirements for ``GELFRabbitHandler``
41+
Install with requirements for ``GELFRabbitHandler``:
2442

25-
.. code-block:: bash
43+
.. code-block:: console
2644
2745
pip install graypy[amqp]
2846
2947
Using easy_install
3048
------------------
3149

32-
Install the basic graypy python logging handlers
50+
Install the basic graypy python logging handlers:
3351

34-
.. code-block:: bash
52+
.. code-block:: console
3553
36-
easy_install graypy
54+
easy_install graypy
3755
38-
Install with requirements for ``GELFRabbitHandler``
56+
Install with requirements for ``GELFRabbitHandler``:
3957

40-
.. code-block:: bash
58+
.. code-block:: console
4159
42-
easy_install graypy[amqp]
60+
easy_install graypy[amqp]
4361
4462
Usage
4563
=====
4664

47-
Messages are sent to Graylog2 using a custom handler for the builtin logging
48-
library in GELF format
65+
graypy sends GELF logs to a Graylog server via subclasses of the python
66+
`logging.Handler`_ class.
4967

50-
.. code-block:: python
68+
Below is the list of ready to run GELF logging handlers defined by graypy:
5169

52-
import logging
53-
import graypy
54-
55-
my_logger = logging.getLogger('test_logger')
56-
my_logger.setLevel(logging.DEBUG)
57-
58-
handler = graypy.GELFUDPHandler('localhost', 12201)
59-
my_logger.addHandler(handler)
70+
* ``GELFUDPHandler`` - UDP log forwarding
71+
* ``GELFTCPHandler`` - TCP log forwarding
72+
* ``GELFTLSHandler`` - TCP log forwarding with TLS support
73+
* ``GELFHTTPHandler`` - HTTP log forwarding
74+
* ``GELFRabbitHandler`` - RabbitMQ log forwarding
6075

61-
my_logger.debug('Hello Graylog2.')
76+
UDP Logging
77+
-----------
6278

63-
Alternately, use ``GELFRabbitHandler`` to send messages to RabbitMQ and
64-
configure your Graylog2 server to consume messages via AMQP. This prevents
65-
log messages from being lost due to dropped UDP packets (``GELFUDPHandler``
66-
sends messages to Graylog2 using UDP). You will need to configure RabbitMQ
67-
with a 'gelf_log' queue and bind it to the 'logging.gelf' exchange so
68-
messages are properly routed to a queue that can be consumed by
69-
Graylog2 (the queue and exchange names may be customized to your liking)
79+
UDP Log forwarding to a locally hosted Graylog server can be easily done with
80+
the ``GELFUDPHandler``:
7081

7182
.. code-block:: python
7283
@@ -76,12 +87,21 @@ Graylog2 (the queue and exchange names may be customized to your liking)
7687
my_logger = logging.getLogger('test_logger')
7788
my_logger.setLevel(logging.DEBUG)
7889
79-
handler = graypy.GELFRabbitHandler('amqp://guest:guest@localhost/', exchange='logging.gelf')
90+
handler = graypy.GELFUDPHandler('localhost', 12201)
8091
my_logger.addHandler(handler)
8192
82-
my_logger.debug('Hello Graylog2.')
93+
my_logger.debug('Hello Graylog.')
8394
84-
Tracebacks are added as full messages
95+
RabbitMQ Logging
96+
----------------
97+
98+
Alternately, use ``GELFRabbitHandler`` to send messages to RabbitMQ and
99+
configure your Graylog server to consume messages via AMQP. This prevents log
100+
messages from being lost due to dropped UDP packets (``GELFUDPHandler`` sends
101+
messages to Graylog using UDP). You will need to configure RabbitMQ with a
102+
``gelf_log`` queue and bind it to the ``logging.gelf`` exchange so messages
103+
are properly routed to a queue that can be consumed by Graylog (the queue and
104+
exchange names may be customized to your liking).
85105

86106
.. code-block:: python
87107
@@ -91,29 +111,22 @@ Tracebacks are added as full messages
91111
my_logger = logging.getLogger('test_logger')
92112
my_logger.setLevel(logging.DEBUG)
93113
94-
handler = graypy.GELFUDPHandler('localhost', 12201)
114+
handler = graypy.GELFRabbitHandler('amqp://guest:guest@localhost/', exchange='logging.gelf')
95115
my_logger.addHandler(handler)
96116
97-
try:
98-
puff_the_magic_dragon()
99-
except NameError:
100-
my_logger.debug('No dragons here.', exc_info=1)
117+
my_logger.debug('Hello Graylog.')
101118
102-
103-
For more detailed usage information please see the documentation provided
104-
within graypy's handler's docstrings.
105-
106-
Using with Django
107-
=================
119+
Django Logging
120+
--------------
108121

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

112125
.. code-block:: python
113126
114127
LOGGING = {
115-
...
116-
128+
'version': 1,
129+
# other dictConfig keys here...
117130
'handlers': {
118131
'graypy': {
119132
'level': 'WARNING',
@@ -122,7 +135,6 @@ new handler in your ``settings.py``:
122135
'port': 12201,
123136
},
124137
},
125-
126138
'loggers': {
127139
'django.request': {
128140
'handlers': ['graypy'],
@@ -132,29 +144,57 @@ new handler in your ``settings.py``:
132144
},
133145
}
134146
135-
Custom fields
136-
=============
147+
Traceback Logging
148+
-----------------
149+
150+
By default log captured exception tracebacks are added to the GELF log as
151+
``full_message`` fields:
152+
153+
.. code-block:: python
154+
155+
import logging
156+
import graypy
157+
158+
my_logger = logging.getLogger('test_logger')
159+
my_logger.setLevel(logging.DEBUG)
160+
161+
handler = graypy.GELFUDPHandler('localhost', 12201)
162+
my_logger.addHandler(handler)
163+
164+
try:
165+
puff_the_magic_dragon()
166+
except NameError:
167+
my_logger.debug('No dragons here.', exc_info=1)
168+
169+
Default Logging Fields
170+
----------------------
171+
172+
By default a number of debugging logging fields are automatically added to the
173+
GELF log if available:
137174

138-
A number of custom fields are automatically added if available:
139175
* function
140176
* pid
141177
* process_name
142178
* thread_name
143179

144-
You can disable these additional fields if you don't want them by adding
145-
an the ``debugging_fields=False`` to the handler:
180+
You can disable automatically adding these debugging logging fields by
181+
specifying ``debugging_fields=False`` in the handler's constructor:
146182

147183
.. code-block:: python
148184
149185
handler = graypy.GELFUDPHandler('localhost', 12201, debugging_fields=False)
150186
151-
graypy also supports additional fields to be included in the messages sent
152-
to Graylog2. This can be done by using Python's LoggerAdapter_ and
153-
Filter_. In general, LoggerAdapter makes it easy to add static information
154-
to your log messages and Filters give you more flexibility, for example to
155-
add additional information based on the message that is being logged.
187+
Adding Custom Logging Fields
188+
----------------------------
189+
190+
graypy also supports including custom fields in the GELF logs sent to Graylog.
191+
This can be done by using Python's LoggerAdapter_ and Filter_ classes.
192+
193+
Using LoggerAdapter
194+
^^^^^^^^^^^^^^^^^^^
156195

157-
Example using LoggerAdapter_
196+
LoggerAdapter_ makes it easy to add static information to your GELF log
197+
messages:
158198

159199
.. code-block:: python
160200
@@ -170,9 +210,13 @@ Example using LoggerAdapter_
170210
my_adapter = logging.LoggerAdapter(logging.getLogger('test_logger'),
171211
{'username': 'John'})
172212
173-
my_adapter.debug('Hello Graylog2 from John.')
213+
my_adapter.debug('Hello Graylog from John.')
174214
175-
Example using Filter_
215+
Using Filter
216+
^^^^^^^^^^^^
217+
218+
Filter_ gives more flexibility and allows for dynamic information to be
219+
added to your GELF logs:
176220

177221
.. code-block:: python
178222
@@ -183,7 +227,7 @@ Example using Filter_
183227
def __init__(self):
184228
# In an actual use case would dynamically get this
185229
# (e.g. from memcache)
186-
self.username = "John"
230+
self.username = 'John'
187231
188232
def filter(self, record):
189233
record.username = self.username
@@ -197,25 +241,17 @@ Example using Filter_
197241
198242
my_logger.addFilter(UsernameFilter())
199243
200-
my_logger.debug('Hello Graylog2 from John.')
244+
my_logger.debug('Hello Graylog from John.')
201245
202-
Contributors:
246+
Contributors
247+
============
203248

204249
* Sever Banesiu
205250
* Daniel Miller
206251
* Tushar Makkar
207252
* Nathan Klapstein
208253

209-
.. _GELF: http://docs.graylog.org/en/latest/pages/gelf.html
210-
.. _LoggerAdapter: http://docs.python.org/howto/logging-cookbook.html#using-loggeradapters-to-impart-contextual-information
211-
.. _Filter: http://docs.python.org/howto/logging-cookbook.html#using-filters-to-impart-contextual-information
212-
213-
.. |Build_Status| image:: https://travis-ci.org/severb/graypy.svg?branch=master
214-
:target: https://travis-ci.org/severb/graypy
215-
216-
217-
.. |Coverage_Status| image:: https://codecov.io/gh/severb/graypy/branch/master/graph/badge.svg
218-
:target: https://codecov.io/gh/severb/graypy
219-
220-
.. |PyPI_Status| image:: https://img.shields.io/pypi/v/graypy.svg
221-
:target: https://pypi.python.org/pypi/graypy
254+
.. _GELF: https://docs.graylog.org/en/latest/pages/gelf.html
255+
.. _logging.Handler: https://docs.python.org/3/library/logging.html#logging.Handler
256+
.. _LoggerAdapter: https://docs.python.org/howto/logging-cookbook.html#using-loggeradapters-to-impart-contextual-information
257+
.. _Filter: https://docs.python.org/howto/logging-cookbook.html#using-filters-to-impart-contextual-information

0 commit comments

Comments
 (0)