Commits

wump  committed 2447cf2

documentation

  • Participants
  • Parent commits c5d5069
  • Branches tostring

Comments (0)

Files changed (19)

 include/*
 *.egg-info/*
 bin/*
+doc/_static/*
+doc/_templates/*
+doc/_build/*
+Evax Software <contact@evax.fr>
+Wladimir van der Laan <laanwj@gmail.com>
+1.0 (??)
+----------------
+
+* Wladimir van der Laan <laanwj@gmail.com>
+
+  - Add Sphinx-based documentation and docstrings
+
+  - Emitter for syslog messages, and associated convenience classes
+
+  - Fixes for RFC 5424 edge cases
+
+  - Allow multiple of the same key in STRUCTURED-DATA by representing
+    the parameters using a multidict
+
 0.9 (28/01/2011)
 ----------------
 

File doc/Makefile

+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = _build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html      to make standalone HTML files"
+	@echo "  dirhtml   to make HTML files named index.html in directories"
+	@echo "  pickle    to make pickle files"
+	@echo "  json      to make JSON files"
+	@echo "  htmlhelp  to make HTML files and a HTML help project"
+	@echo "  qthelp    to make HTML files and a qthelp project"
+	@echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  changes   to make an overview of all changed/added/deprecated items"
+	@echo "  linkcheck to check all external links for integrity"
+	@echo "  doctest   to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	-rm -rf $(BUILDDIR)/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/loggerglue.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/loggerglue.qhc"
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+	      "run these through (pdf)latex."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."

File doc/apireference.rst

+=================
+ API reference
+=================
+
+.. toctree::
+   :maxdepth: 2
+
+   loggerglue.rfc5424.rst
+   loggerglue.constants.rst
+   loggerglue.emitter.rst
+   loggerglue.logger.rst
+   loggerglue.server.rst
+
+# -*- coding: utf-8 -*-
+#
+# loggerglue documentation build configuration file, created by
+# sphinx-quickstart on Thu Mar 24 18:01:54 2011.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.append(os.path.abspath('..'))
+
+# -- General configuration -----------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.autodoc']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'loggerglue'
+copyright = u'2011, Evax Software <contact@evax.fr>, Wladimir van der Laan <laanwj@gmail.com>'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = '1.0'
+# The full version, including alpha/beta/rc tags.
+release = '1.0'
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# List of directories, relative to source directory, that shouldn't be searched
+# for source files.
+exclude_trees = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  Major themes that come with
+# Sphinx are currently 'default' and 'sphinxdoc'.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_use_modindex = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'loggergluedoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'loggerglue.tex', u'loggerglue Documentation',
+   u'Evax Software \\textless{}contact@evax.fr\\textgreater{}, Wladimir van der Laan \\textless{}laanwj@gmail.com\\textgreater{}', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
+autoclass_content = 'both'

File doc/gettingstarted.rst

+=================
+ Getting Started
+=================
+
+.. toctree::
+   :maxdepth: 2
+
+loggerglue is intended to be a general purpose glue layer for the syslog protocol as decribed in RFC5424_ and RFC5425_.
+
+This package includes:
+
+    * a pyparsing parser for rfc5424
+    * a wrapper class for rfc5424 syslog entries
+    * a SyslogServer class supporting TLS (rcf5425)
+    * classes for constructing and emitting rfc5424 syslog entries
+
+To make use of RFC5424 functionality such as sending structured data with messages, you need a recent syslog 
+that supports the protocol, such as rsyslog_.
+
+Examples
+========
+
+Client example
+------------------------
+
+Log a simple message with structured data to the local syslog daemon:
+
+::
+
+    >>> from loggerglue import logger
+    >>> from loggerglue.rfc5424 import SDElement
+    >>> from loggerglue.constants import *
+    >>> l = logger.Logger()
+    >>> l.log(prival=LOG_INFO|LOG_USER, 
+              msg="Test message", 
+              structured_data=[
+                  SDElement("origin", 
+                      [("software","test script"), ("swVersion","0.0.1")])
+              ])
+
+
+A trivial server example
+------------------------
+
+A simple TLS enabled server can be built as follows:
+
+::
+
+    from loggerglue.server import SyslogServer, SyslogHandler
+
+    class SimpleHandler(SyslogHandler):
+        def handle_entry(self, entry):
+            print 'On %s from %s: %s' % \
+                    (entry.timestamp, entry.hostname, entry.msg)
+
+    s = SyslogServer(('127.0.0.1', 6514), SimpleHandler,
+                    keyfile='loggerglue-key.pem',
+                    certfile='loggerglue-cert.pem')
+    s.serve_forever()
+
+Here's an example rsyslog configuration:
+
+::
+
+    $IncludeConfig /etc/rsyslog.d/*.conf
+
+    $DefaultNetstreamDriverCAFile /path/to/loggerglue-ca-cert.pem
+    $DefaultNetstreamDriver gtls
+    $ActionSendStreamDriverMode 1
+    $ActionSendStreamDriverAuthMode anon
+
+    *.* @@(o)localhost:6514;RSYSLOG_SyslogProtocol23Format
+
+A more advanced server example
+------------------------------
+
+In this exemple we index the log data as it comes using Woosh.
+
+::
+
+    from loggerglue.server import SyslogServer, SyslogHandler
+    from whoosh import index
+    from whoosh.fields import *
+    import os.path
+
+    schema = Schema(prio=ID(stored=True),
+                    timestamp=DATETIME(stored=True),
+                    hostname=ID(stored=True),
+                    app_name=ID(stored=True),
+                    procid=ID(stored=True),
+                    msgid=ID(stored=True),
+                    msg=TEXT(stored=True)
+                    )
+
+    if os.path.exists('indexdir'):
+        ix = index.open_dir('indexdir')
+    else:
+        os.mkdir('indexdir')
+        ix = index.create_in('indexdir', schema)
+
+    class SimpleHandler(SyslogHandler):
+        def handle_entry(self, entry):
+            writer = ix.writer()
+            writer.add_document(prio=entry.prival,
+                                timestamp=entry.timestamp,
+                                hostname=entry.hostname,
+                                app_name=entry.app_name,
+                                procid=entry.procid,
+                                msgid=entry.msgid,
+                                msg=entry.msg)
+            writer.commit()
+
+    s = SyslogServer(('127.0.0.1', 6514), SimpleHandler,
+                    keyfile='loggerglue-key.pem',
+                    certfile='loggerglue-cert.pem')
+    s.serve_forever()
+
+And now a small search tool:
+
+::
+
+    from whoosh import index
+    from whoosh.qparser import QueryParser
+
+    import sys
+    if len(sys.argv) == 1:
+        print 'usage: %s <search terms>' % sys.argv[0]
+        sys.exit(1)
+
+    ix = index.open_dir('indexdir')
+    searcher = ix.searcher()
+    query = QueryParser('msg').parse(' '.join(sys.argv[1:]))
+    results = searcher.search(query)
+    print '%d results\n' % len(results)
+    for r in results:
+        print '%s\n' % str(r)
+    searcher.close()
+
+
+
+.. _RFC5424: http://tools.ietf.org/html/rfc5424
+.. _RFC5425: http://tools.ietf.org/html/rfc5425
+.. _rsyslog: http://www.rsyslog.com/
+

File doc/index.rst

+==============================================================
+ loggerglue - Syslog protocol (RFC5424 and RFC5425) utilities
+==============================================================
+
+loggerglue is intended to be a general purpose glue layer for the syslog protocol as decribed in RFC5424_ and RFC5425_.
+
+
+Contents:
+
+.. toctree::
+   :maxdepth: 2
+
+   gettingstarted.rst
+   apireference.rst
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
+.. _RFC5424: http://tools.ietf.org/html/rfc5424
+.. _RFC5425: http://tools.ietf.org/html/rfc5425

File doc/loggerglue.constants.rst

+:mod:`loggerglue.constants` --- Syslog constants
+====================================================================================
+
+.. automodule:: loggerglue.constants
+   :members:
+   :show-inheritance:
+
+

File doc/loggerglue.emitter.rst

+:mod:`loggerglue.emitter` --- Emit syslog messages over the network or a local socket
+=====================================================================================
+
+.. automodule:: loggerglue.emitter
+   :members:
+   :show-inheritance:
+
+

File doc/loggerglue.logger.rst

+:mod:`loggerglue.logger` --- Convenience class for logging RFC5424-formatted messages
+======================================================================================
+
+.. automodule:: loggerglue.logger
+   :members:
+   :show-inheritance:
+
+

File doc/loggerglue.rfc5424.rst

+:mod:`loggerglue.rfc5424` --- Parser and log record wrapper classes
+====================================================================================
+
+.. automodule:: loggerglue.rfc5424
+   :members:
+   :show-inheritance:
+
+

File doc/loggerglue.server.rst

+:mod:`loggerglue.server` --- Syslog server
+====================================================================================
+
+.. automodule:: loggerglue.server
+   :members:
+   :show-inheritance:
+
+

File doc/make.bat

+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+set SPHINXBUILD=sphinx-build
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+	set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+	:help
+	echo.Please use `make ^<target^>` where ^<target^> is one of
+	echo.  html      to make standalone HTML files
+	echo.  dirhtml   to make HTML files named index.html in directories
+	echo.  pickle    to make pickle files
+	echo.  json      to make JSON files
+	echo.  htmlhelp  to make HTML files and a HTML help project
+	echo.  qthelp    to make HTML files and a qthelp project
+	echo.  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter
+	echo.  changes   to make an overview over all changed/added/deprecated items
+	echo.  linkcheck to check all external links for integrity
+	echo.  doctest   to run all doctests embedded in the documentation if enabled
+	goto end
+)
+
+if "%1" == "clean" (
+	for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+	del /q /s %BUILDDIR%\*
+	goto end
+)
+
+if "%1" == "html" (
+	%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+	goto end
+)
+
+if "%1" == "dirhtml" (
+	%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+	echo.
+	echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+	goto end
+)
+
+if "%1" == "pickle" (
+	%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+	echo.
+	echo.Build finished; now you can process the pickle files.
+	goto end
+)
+
+if "%1" == "json" (
+	%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+	echo.
+	echo.Build finished; now you can process the JSON files.
+	goto end
+)
+
+if "%1" == "htmlhelp" (
+	%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+	echo.
+	echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+	goto end
+)
+
+if "%1" == "qthelp" (
+	%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+	echo.
+	echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+	echo.^> qcollectiongenerator %BUILDDIR%\qthelp\loggerglue.qhcp
+	echo.To view the help file:
+	echo.^> assistant -collectionFile %BUILDDIR%\qthelp\loggerglue.ghc
+	goto end
+)
+
+if "%1" == "latex" (
+	%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+	echo.
+	echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+	goto end
+)
+
+if "%1" == "changes" (
+	%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+	echo.
+	echo.The overview file is in %BUILDDIR%/changes.
+	goto end
+)
+
+if "%1" == "linkcheck" (
+	%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+	echo.
+	echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+	goto end
+)
+
+if "%1" == "doctest" (
+	%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+	echo.
+	echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+	goto end
+)
+
+:end

File loggerglue/constants.py

-"""Syslog constants."""
+"""The syslog constants are replicated here because not all systems have the (binary) syslog module. 
+RFC5424 priority values are a combination of a priority and facility code, for example:
 
-# priorities (these are ordered)
-LOG_EMERG     = 0       #  system is unusable
-LOG_ALERT     = 1       #  action must be taken immediately
-LOG_CRIT      = 2       #  critical conditions
-LOG_ERR       = 3       #  error conditions
-LOG_WARNING   = 4       #  warning conditions
-LOG_NOTICE    = 5       #  normal but significant condition
-LOG_INFO      = 6       #  informational
-LOG_DEBUG     = 7       #  debug-level messages
+    prival = LOG_ALERT | LOG_DAEMON
 
-#  facility codes
-LOG_KERN      = 0<<3    #  kernel messages
-LOG_USER      = 1<<3    #  random user-level messages
-LOG_MAIL      = 2<<3    #  mail system
-LOG_DAEMON    = 3<<3    #  system daemons
-LOG_AUTH      = 4<<3    #  security/authorization messages
-LOG_SYSLOG    = 5<<3    #  messages generated internally by syslogd
-LOG_LPR       = 6<<3    #  line printer subsystem
-LOG_NEWS      = 7<<3    #  network news subsystem
-LOG_UUCP      = 8<<3    #  UUCP subsystem
-LOG_CRON      = 9<<3    #  clock daemon
-LOG_AUTHPRIV  = 10<<3   #  security/authorization messages (private)
+Priorities
+----------
 
-#  other codes through 15 reserved for system use
-LOG_LOCAL0    = 16<<3   #  reserved for local use
-LOG_LOCAL1    = 17<<3   #  reserved for local use
-LOG_LOCAL2    = 18<<3   #  reserved for local use
-LOG_LOCAL3    = 19<<3   #  reserved for local use
-LOG_LOCAL4    = 20<<3   #  reserved for local use
-LOG_LOCAL5    = 21<<3   #  reserved for local use
-LOG_LOCAL6    = 22<<3   #  reserved for local use
-LOG_LOCAL7    = 23<<3   #  reserved for local use
+============== =====================
+Constant        Description
+============== =====================
+LOG_EMERG       System is unusable
+LOG_ALERT       Action must be taken immediately
+LOG_CRIT        Critical conditions
+LOG_ERR         Error conditions
+LOG_WARNING     Warning conditions
+LOG_NOTICE      Normal but significant condition
+LOG_INFO        Informational
+LOG_DEBUG       Debug-level messages
+============== =====================
 
+Facility codes
+--------------
+
+=============  ===========================================
+Constant        Description
+=============  ===========================================
+LOG_KERN        Kernel messages
+LOG_USER        Random user-level messages
+LOG_MAIL        Mail system
+LOG_DAEMON      System daemons
+LOG_AUTH        Security/authorization messages
+LOG_SYSLOG      Messages generated internally by syslogd
+LOG_LPR         Line printer subsystem
+LOG_NEWS        Network news subsystem
+LOG_UUCP        UUCP subsystem
+LOG_CRON        Clock daemon
+LOG_AUTHPRIV    Security/authorization messages (private)
+LOG_LOCAL0      Reserved for local use
+LOG_LOCAL1      Reserved for local use
+LOG_LOCAL2      Reserved for local use
+LOG_LOCAL3      Reserved for local use
+LOG_LOCAL4      Reserved for local use
+LOG_LOCAL5      Reserved for local use
+LOG_LOCAL6      Reserved for local use
+LOG_LOCAL7      Reserved for local use
+=============  ===========================================
+"""
+
+LOG_EMERG     = 0
+LOG_ALERT     = 1
+LOG_CRIT      = 2
+LOG_ERR       = 3
+LOG_WARNING   = 4
+LOG_NOTICE    = 5
+LOG_INFO      = 6
+LOG_DEBUG     = 7
+
+LOG_KERN      = 0<<3
+LOG_USER      = 1<<3
+LOG_MAIL      = 2<<3
+LOG_DAEMON    = 3<<3
+LOG_AUTH      = 4<<3
+LOG_SYSLOG    = 5<<3
+LOG_LPR       = 6<<3
+LOG_NEWS      = 7<<3
+LOG_UUCP      = 8<<3
+LOG_CRON      = 9<<3
+LOG_AUTHPRIV  = 10<<3
+LOG_LOCAL0    = 16<<3
+LOG_LOCAL1    = 17<<3
+LOG_LOCAL2    = 18<<3
+LOG_LOCAL3    = 19<<3
+LOG_LOCAL4    = 20<<3
+LOG_LOCAL5    = 21<<3
+LOG_LOCAL6    = 22<<3
+LOG_LOCAL7    = 23<<3
+

File loggerglue/emitter.py

 SYSLOG_DEFAULT_PORT             = 514
 
 class SyslogEmitter(object):
+    """
+    Base class for syslog emitters. 
+    
+    A syslog emitter provides
+    two methods, one to send messages and one to close the connection.
+    All emitters are set up such that the connection is re-established
+    once when a network issue happens. If the re-connection attempt fails,
+    a socket exception is thrown.
+    
+    Derived classes have specific constructors describing the address
+    to send messages to.
+    """
     def close(self):
         """
         Closes the socket.
 
     def emit(self, msg):
         """
-        Emit a record.
+        Emit a log record.
         """
         pass
 
 class UDPSyslogEmitter(SyslogEmitter):
+    """
+    Syslog emitter through UDP.
+    
+    Sends syslog messages over UDP. As UDP is an unreliable protocol,
+    use of this class is discouraged. The only use-case would be 
+    sending messages to a syslog server that does not support TCP.
+    """
     def __init__(self, address=('localhost', SYSLOG_DEFAULT_PORT)):
         """Create a Syslog emitter that sends messages through UDP.
         
-        Keyword arguments:
-        address -- address to send messages to, as (host,port) tuple
+        **Arguments**
+        
+            *address* 
+                address to send messages to, as `(host,port)` tuple
         """
         self.address = address
         self._connect(address)
         """
         self.socket.sendto(str(msg), self.address)
 
-class UNIXSyslogEmitter(object):
+class UNIXSyslogEmitter(SyslogEmitter):
     def __init__(self, address='/dev/log'):
         """Create a Syslog emitter that sends messages through a UNIX
-        socket.
+        socket. This is useful for sending messages to a local
+        syslog daemon.        
         
-        Keyword arguments:
-        address -- address to send messages to, as string. Defaults to '/dev/log'.
+        **Arguments**
+        
+            *address*
+                Address to send messages to, as string. Defaults to '/dev/log'.
         """
         self.address = address
         self._connect(address)
             self._connect(self.address)
             self.socket.send(str(msg)+'\000')
 
-class TCPSyslogEmitter(object):
+class TCPSyslogEmitter(SyslogEmitter):
+    """
+    Syslog emitter that sends messages through a TCP socket. Optionally supports TLS.
+    """
     def __init__(self, address=('localhost', SYSLOG_DEFAULT_PORT),\
         octet_based_framing=True, **ssl_args):
-        """Create a Syslog emitter that sends messages through a TCP
-        socket.
-        
-        Keyword arguments:
-        address -- address to send messages to, as (host, port) tuple.
-        use_tls -- Use TLS for encrypting the connection
-        ssl_args -- Arguments to pass to ssl.wrap_socket
+        """ 
+        **Arguments**
+            *address*
+                Address to send messages to, specify this as `(host, port)` tuple.
+
+            *octet_based_framing*
+                Use RFC5425 octet-based framing instead of line-based framing. Use
+                this when sending multiline messages.
+                
+            *keyfile*, *certfile*, *server_side*, *cert_reqs*, *ssl_version*, *ca_certs*, *ciphers*
+                Arguments to pass through to :func:`ssl.wrap_socket`. Providing any of these arguments
+                enables TLS.
         """
         self.address = address
         self.octet_based_framing = octet_based_framing

File loggerglue/logger.py

 class Logger(object):
     """
     Convenience class to log RFC5424 messages to the
-    local syslog daemon.
+    local syslog daemon (by default) or a remote
+    syslog receiver.
     """
 
     def __init__(self, emitter=None, hostname=None, app_name=None, procid=None):
         """
-        Create a new logger object.
-        
-        Keyword arguments:
-        emitter -- Emitter object to send syslog messages, default to Unix socket /dev/log
-        hostname -- Hostname to send with log messages, defaults to current hostname
-        app_name -- Application name to send with log messages, defaults to application name
-        procid -- Process ID to send with log messages, default to current process ID
+        **Arguments**
+            *emitter*
+                Emitter object to send syslog messages, default to Unix socket /dev/log
+                
+            *hostname*
+                Hostname to send with log messages, defaults to system hostname
+                
+            *app_name*
+                Application name to send with log messages, defaults to application name
+                
+            *procid*
+                Process ID to send with log messages, default to current process ID
         """
         if hostname is None:
             # Compute host name to submit to syslog
         Log a message. 
 
         Example:
-        >>> logger.log("test", prival=LOG_DEBUG|LOG_MAIL)
+        
+           >>> logger.log("test", prival=LOG_DEBUG|LOG_MAIL)
 
-        Keyword arguments:
-        msg -- Human readable message to log
-        msgid -- Message identifier
-        structured_data -- Structured data to attach to log message
-        prival -- Priority and facility of message (defaults to INFO|USER)
-        timestamp -- UTC time of log message (default to current time)
+        **Arguments**
+            *msg*
+                Human readable message to log
+            *msgid*
+                Message identifier
+            *structured_data*
+                Structured data to attach to log message
+            *prival*
+                Priority and facility of message (defaults to INFO|USER)
+            *timestamp*
+                UTC time of log message (default to current time)
         """
         if timestamp is None:
             timestamp = datetime.utcnow()

File loggerglue/rfc5424.py

 # -*- coding: utf-8 -*-
 """
-A parser for the Syslog Protocol
-(RFC5424 - http://tools.ietf.org/search/rfc5424)
+A parser for the Syslog Protocol (RFC5424 - http://tools.ietf.org/search/rfc542)
+
 Copyright © 2011 Evax Software <contact@evax.fr>
 """
 from datetime import datetime, timedelta
             setattr(self, k, v)
 
 class SDElement(object):
+    """
+    An SD-ELEMENT consists of a name and parameter name-value pairs.
+    """
     def __init__(self, sd_id, sd_params):
+        """
+        **arguments**
+            *sd_id*
+                SD-IDs are case-sensitive and uniquely identify the type and purpose
+                of the SD-ELEMENT.
+            
+            *sd_params*
+                Key/value pairs attached to this SD-ELEMENT. This can be any iterable
+                that yields tuples, a dict or a :class:`~loggerglue.utils.multidict.OrderedMultiDict`
+                (An SD-PARAM key may be repeated multiple times inside an SD-ELEMENT)
+                
+        **attributes**
+            *id*
+                SD-ID for this structured data element.
+                
+            *sd_params*
+                Key/value pairs attached to this SD-ELEMENT, represented as 
+                a multidict.
+            
+            *params*
+                Key/value pairs attached to this SD-ELEMENT, represented as
+                a class instance (for convenience, so that parameters can
+                be addressed with `elmt.params.origin`). If there are multiple
+                values for a key, the *last* element is returned.
+                
+        """
         self.id = sd_id
         self.sd_params = OrderedMultiDict(sd_params)
         self.params = Params(self.sd_params)
         
     def __str__(self):
-        '''Convert SDElement to string'''
+        """Convert SDElement to formatted string"""
         rv = ['[', self.id]
         for (k,v) in self.sd_params.allitems():
             rv += [' ',k,'="',escape_param_value(v),'"']
         self.elements = elements
         
     def __str__(self):
-        '''Convert StructuredData to string'''
+        """Convert StructuredData to string"""
         return ''.join([str(e) for e in self.elements])
 
     @classmethod
             return None
     
 class SyslogEntry(object):
-    """A class representing a syslog entry."""
+    """
+    A class representing a syslog entry.
+    """
     def __init__(self, prival=DEFAULT_PRIVAL, version=1, timestamp=None, 
             hostname=None, app_name=None, procid=None, msgid=None,
             structured_data=None, msg=None):
+        """
+        **arguments/attributes**
+            
+            *prival*
+                RFC5424 priority values are a combination of a priority and facility, for example `LOG_ALERT | LOG_DAEMON`.
+                See :mod:`loggerglue.constants`.
+            
+            *version*
+                Version of syslog entry. There is usually no need to change this.
+            
+            *timestamp*
+                Timestamp (as a datetime object).
+            
+            *hostname*
+                The HOSTNAME field SHOULD contain the hostname and the domain name of the originator.
+            
+            *app_name*
+                The APP-NAME field SHOULD identify the device or application that
+                originated the message.  It is a string without further semantics.
+                It is intended for filtering messages on a relay or collector.
+            
+            *procid*
+                PROCID is a value that is included in the message, having no
+                interoperable meaning, except that a change in the value indicates
+                there has been a discontinuity in syslog reporting. 
+            
+            *msgid*
+                The MSGID SHOULD identify the type of message.
+            
+            *structured_data*
+                STRUCTURED-DATA provides a mechanism to express information in a well
+                defined, easily parseable and interpretable data format.
+            
+            *msg*
+                The MSG part contains a free-form message that provides information
+                about the event.
+
+        """
         self.prival = prival
         self.version = version
         self.timestamp = timestamp
         )
         
     def __str__(self):
-        '''Convert SyslogEntry to string'''
+        """Convert SyslogEntry to string"""
         rv = ['<', str(self.prival), '>', str(self.version), ' ']
         if self.timestamp is None:
             rv.append('-')
 
     @classmethod
     def from_line(cls, line):
-        """Returns a SyslogEntry object from a syslog line."""
+        """Returns a parsed SyslogEntry object from a syslog `line`."""
         try:
             r = syslog_msg.parseString(line.strip())
             return cls.parse(r)

File loggerglue/server.py

 from loggerglue.rfc5424 import SyslogEntry
 
 class SyslogHandler(SocketServer.BaseRequestHandler):
-
+    """
+    Handler for syslog connections. An instance of this class is created for each incoming connection.
+    
+    Subclasses must implement `handle_entry` and may implement `handle_error`.
+    """
     def setup(self):
         if not self.server.use_tls:
             self.connection = self.request.makefile()
                 self.handle_entry(syslog_entry)
 
     def handle_entry(self, syslog_entry):
+        """Handle an incoming syslog entry. Subclasses must implement this.
+        """
         raise NotImplemented('Subclasses must implement this method')
 
     def handle_error(self, data):
-        """Implementing this method is optional."""
+        """Handle an error. Subclasses can implemnt this.
+        
+        Implementing this method is optional.
+        """
         pass
 
 class SyslogServer(SocketServer.TCPServer, SocketServer.ThreadingMixIn):
+    """
+    TCP Syslog server based on SocketServer.
+    """
     allow_reuse_address = True
 
     _allowed_ssl_args = ('keyfile', 'certfile', 'cert_reqs', 'ssl_version',
     def __init__(self, server_address, RequestHandlerClass,
                  bind_and_activate=True,
                  **ssl_args):
+        """
+        **arguments**
+            *server_address*
+                Address to bind to, as a tuple `(host,port)`. Example: `('127.0.0.1',1234)`.
+            
+            *RequestHandlerClass*
+                Class to instantiate for connections. Pass a subclass of 
+                :class:`~loggerglue.server.SyslogHandler`.
+            
+            *bind_and_activate*
+                Automatically  call server_bind and server_activate.
+            
+            *keyfile*, *certfile*, *server_side*, *cert_reqs*, *ssl_version*, *ca_certs*, *ciphers*
+                Arguments to pass through to :func:`ssl.wrap_socket`. Providing any of these arguments
+                enables TLS.
+        """
         self.use_tls = False
         if ssl_args:
             for arg in ssl_args: