Package: bes
bes is a flexiblebulk uploaderforElastic Search.  At the
moment, it only supports index uploadsover UDP.  You can retrieve
the logged data from Elastic Search and analyze it dynamically usingKibana(source).  This package just makes the initial upload to
Elastic Search as painless as possible.The connection parameters and other configuration options are stored
inbes.DEFAULT.  Override them as you see fit (e.g. to connect to
a remote Elastic Search server):>>> import bes
>>> bes.DEFAULT['host'] = 'my-es-server.example.com'Then log away:>>> bes.log(type='record', user='jdoe', action='swims')If you are so inclined, you can override theDEFAULTindexon a
per-call basis:>>> bes.log(index='my-index', type='my-type', user='jdoe', action='bikes')The log generated by the above will look like:{
  "@timestamp": "2013-09-26T16:34:09.179048",
  "@version": 1,
  "action": "bikes",
  "user": "jdoe"
}following Jordan Sissel’snew formatforLogstash:You should specify a uniquetypefor each record you create, because
Elastic Search doesn’t recalculate itsmappingif you post a new
event that uses an old key with a new data type.  If you are only
logging a single record type, you can configure a global default:>>> bes.DEFAULT['type'] = 'record'
>>> bes.log(user='jdoe', action='runs')DjangoAlthough the core of the library is framework-agnostic, we’ll be using
this to log events in aDjangowebsite.  There are a few helpers for
extracting information fromHttpRequestto make this as easy as
possible.  Drop it into yourviewswith somthing like:import django.http
imort django.shortcuts
import bes.django
from polls.models import Poll

def detail(request, poll_id):
    try:
        p = Poll.objects.get(pk=poll_id)
    except Poll.DoesNotExist:
        bes.django.log_user_request_path(
            request=request, type='404', poll_id=poll_id)
        raise django.http.Http404
    bes.django.log_user_request_path(
        request=request, type='poll-detail',
        poll_id=poll_id, poll_name=p.name)
    return django.shortcutsrender_to_response(
        'polls/detail.html', {'poll': p})You can also override bes’ defaults in your Django config:BULK_ELASTIC_SEARCH_LOGGING_HOST = 'my-es-server.example.com'The Django config names match the uppercasedDEFAULTkeys with aBULK_ELASTIC_SEARCH_LOGGING_prefix (for example,host→BULK_ELASTIC_SEARCH_LOGGING_HOST).TracingTo log activity for critical functions, bes has tracing decorators:import bes.trace

@bes.trace.trace()
def my_function():
    return 1 + 2 / 3By default this logs withbes.logusing the decorated function’s
name (e.g.my_function) as the log type.  You can override this if
you want something different:def my_logger(*args, **kwargs):
    print((args, kwargs))

@bes.trace.trace(type='my-type', logger=my_logger)
def my_function():
    return 1 + 2 / 3Additionaltracearguments are passed straight through to the
logger:@bes.trace.trace(index='my-index', type='my-type', sport='triathalon')
def my_function():
    return 1 + 2 / 3By default, you’ll get separate logged messages before the decorated
function starts, after it completes, or if it raises an exception.  Anactionargument is passed to the logger in each case, with values
ofstart,complete, anderrorrespectively.  In the error
case, the logger is also passed the string-ified exception
(error=str(e)) to help with debugging the problem.  If you don’t
want one or more of these logged messages, you can turn them off:@bes.trace.trace(start=False, error=False, complete=False):
def my_function():
    return 1 + 2 / 3although if you turn them all off, you’re not going to get any
messages at all ;).The trace decorator useswrapt(if it’s installed) to create
introspection-preserving decorators.  If wrapt is not installed, we
fallback to the builtinfunctools.wrapswhich handles the basics
like docstrings, but doesn’t do as well for more involved
introspection (e.g.inspect.getsource).TestingTesting uses unittest’sautomatic test discovery.  Run the test
suite with:$ python -m unittest discoverFor Python <3.3, the test suite requires the externalmockpackage,
which is bundled asunittest.mockin Python 3.3.