--- a/src/pyams_apm.egg-info/PKG-INFO Wed Feb 06 09:23:14 2019 +0100
+++ b/src/pyams_apm.egg-info/PKG-INFO Mon Nov 25 13:39:35 2019 +0100
@@ -6,9 +6,31 @@
Author: Thierry Florac
Author-email: tflorac@ulthar.net
License: ZPL
-Description:
- PyAMS APM
- =========
+Description: =================
+ PyAMS_apm package
+ =================
+
+ .. contents::
+
+
+ What is PyAMS
+ =============
+
+ PyAMS (Pyramid Application Management Suite) is a small suite of packages written for applications
+ and content management with the Pyramid framework.
+
+ **PyAMS** is actually mainly used to manage web sites through content management applications (CMS),
+ see PyAMS_content package), but many features are generic and can be used inside any kind of web
+ application.
+
+
+ What is PyAMS_apm ?
+ ===================
+
+ APM in an Elasticsearch module which can be used to monitor applications performances.
+
+ This package allows to integrate any Pyramid application with APM, providing a custom tween.
+ It also add instrumentation of several Python packages, like Chameleon or LDAP3.
History
--- a/src/pyams_apm.egg-info/requires.txt Wed Feb 06 09:23:14 2019 +0100
+++ b/src/pyams_apm.egg-info/requires.txt Mon Nov 25 13:39:35 2019 +0100
@@ -1,5 +1,5 @@
setuptools
-elastic-apm
+elasticapm
pyramid
[test]
--- a/src/pyams_apm/__init__.py Wed Feb 06 09:23:14 2019 +0100
+++ b/src/pyams_apm/__init__.py Mon Nov 25 13:39:35 2019 +0100
@@ -10,17 +10,15 @@
# FOR A PARTICULAR PURPOSE.
#
-__docformat__ = 'restructuredtext'
-
+"""PyAMS_apm package
-# import standard library
+This package provides an Elasticsearch APM integration for any Pyramid application.
+"""
-# import interfaces
-
-# import packages
+__docformat__ = 'restructuredtext'
def includeme(config):
"""pyams_apm features include"""
- from .include import include_package
+ from .include import include_package # pylint: disable=import-outside-toplevel
include_package(config)
--- a/src/pyams_apm/include.py Wed Feb 06 09:23:14 2019 +0100
+++ b/src/pyams_apm/include.py Mon Nov 25 13:39:35 2019 +0100
@@ -10,7 +10,10 @@
# FOR A PARTICULAR PURPOSE.
#
-__docformat__ = 'restructuredtext'
+"""PyAMS_apm.include module
+
+This module is used for Pyramid integration
+"""
import elasticapm
from elasticapm.instrumentation import register
@@ -18,8 +21,12 @@
from pyramid.interfaces import IApplicationCreated
+__docformat__ = 'restructuredtext'
+
+
@subscriber(IApplicationCreated)
-def handle_apm_application(event):
+def handle_apm_application(event): # pylint: disable=unused-argument
+ """Register custom instrumentations on application startup"""
register.register('pyams_apm.packages.ldap3.LDAP3OpenInstrumentation')
register.register('pyams_apm.packages.ldap3.LDAP3BindInstrumentation')
register.register('pyams_apm.packages.ldap3.LDAP3SearchInstrumentation')
--- a/src/pyams_apm/packages/__init__.py Wed Feb 06 09:23:14 2019 +0100
+++ b/src/pyams_apm/packages/__init__.py Mon Nov 25 13:39:35 2019 +0100
@@ -1,20 +1,1 @@
#
-# Copyright (c) 2008-2018 Thierry Florac <tflorac AT ulthar.net>
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-
-__docformat__ = 'restructuredtext'
-
-
-# import standard library
-
-# import interfaces
-
-# import packages
--- a/src/pyams_apm/packages/chameleon.py Wed Feb 06 09:23:14 2019 +0100
+++ b/src/pyams_apm/packages/chameleon.py Mon Nov 25 13:39:35 2019 +0100
@@ -10,30 +10,51 @@
# FOR A PARTICULAR PURPOSE.
#
-__docformat__ = 'restructuredtext'
+"""PyAMS_apm.packages.chameleon module
+This module adds APM instrumentation for Chameleon package
+"""
from elasticapm.instrumentation.packages.base import AbstractInstrumentedModule
from elasticapm.traces import capture_span
+__docformat__ = 'restructuredtext'
+
+
class ChameleonCookingInstrumentation(AbstractInstrumentedModule):
+ """Chameleon cooking instrumentation"""
+
name = "chameleon_cooking"
instrument_list = [("chameleon.template", "BaseTemplate.cook")]
def call(self, module, method, wrapped, instance, args, kwargs):
- with capture_span('COOK', "template.chameleon.cook",
- {'filename': instance.filename}, leaf=True):
+ # pylint: disable=too-many-arguments
+ """Wrapped method call"""
+ with capture_span('COOK',
+ span_type='template',
+ span_subtype='chameleon',
+ span_action='cook',
+ extra={'filename': instance.filename},
+ leaf=True):
return wrapped(*args, **kwargs)
class ChameleonRenderingInstrumentation(AbstractInstrumentedModule):
+ """Chameleon rendering instrumentation"""
+
name = "chameleon_rendering"
instrument_list = [("chameleon.template", "BaseTemplate.render")]
def call(self, module, method, wrapped, instance, args, kwargs):
- with capture_span('RENDER', "template.chameleon.render",
- {'filename': instance.filename}, leaf=True):
+ # pylint: disable=too-many-arguments
+ """Wrapped method call"""
+ with capture_span('RENDER',
+ span_type='template',
+ span_subtype='chameleon',
+ span_action='render',
+ extra={'filename': instance.filename},
+ leaf=True):
return wrapped(*args, **kwargs)
--- a/src/pyams_apm/packages/ldap3.py Wed Feb 06 09:23:14 2019 +0100
+++ b/src/pyams_apm/packages/ldap3.py Mon Nov 25 13:39:35 2019 +0100
@@ -10,13 +10,21 @@
# FOR A PARTICULAR PURPOSE.
#
-__docformat__ = 'restructuredtext'
+"""PyAMS_apm.packages.ldap3 module
+
+This module adds APM instrumentation to LDAP3 package
+"""
from elasticapm.instrumentation.packages.base import AbstractInstrumentedModule
from elasticapm.traces import capture_span
+__docformat__ = 'restructuredtext'
+
+
class LDAP3OpenInstrumentation(AbstractInstrumentedModule):
+ """LDAP3 connection opening instrumentation"""
+
name = "ldap.open"
instrument_list = [
@@ -25,26 +33,36 @@
]
def call(self, module, method, wrapped, instance, args, kwargs):
+ # pylint: disable=too-many-arguments
+ """Wrapped method call"""
with capture_span('LDAP.OPEN', "db.ldap", leaf=True):
return wrapped(*args, **kwargs)
class LDAP3BindInstrumentation(AbstractInstrumentedModule):
+ """LDAP3 bind instrumentation"""
+
name = "ldap.bind"
instrument_list = [("ldap3", "Connection.bind")]
def call(self, module, method, wrapped, instance, args, kwargs):
+ # pylint: disable=too-many-arguments
+ """Wrapped method call"""
with capture_span('LDAP.BIND', "db.ldap", leaf=True):
return wrapped(*args, **kwargs)
class LDAP3SearchInstrumentation(AbstractInstrumentedModule):
+ """LDAP3 search instrumentation"""
+
name = "ldap.search"
instrument_list = [("ldap3", "Connection.search")]
def call(self, module, method, wrapped, instance, args, kwargs):
+ # pylint: disable=too-many-arguments
+ """Wrapped method call"""
with capture_span('LDAP.SEARCH', "db.ldap", {
'db': {
'type': 'ldap',
@@ -55,6 +73,8 @@
class LDAP3GetResponseInstrumentation(AbstractInstrumentedModule):
+ """LDAP3 response getter instrumentation"""
+
name = "ldap.get_response"
instrument_list = [
@@ -63,5 +83,7 @@
]
def call(self, module, method, wrapped, instance, args, kwargs):
+ # pylint: disable=too-many-arguments
+ """Wrapped method call"""
with capture_span('LDAP.GET_RESPONSE', "db.ldap", leaf=True):
return wrapped(*args, **kwargs)
--- a/src/pyams_apm/tween.py Wed Feb 06 09:23:14 2019 +0100
+++ b/src/pyams_apm/tween.py Mon Nov 25 13:39:35 2019 +0100
@@ -10,7 +10,11 @@
# FOR A PARTICULAR PURPOSE.
#
-__docformat__ = 'restructuredtext'
+"""PyAMS_apm.tween module
+
+This module provides a custom tween which is used to integrate the Pyramid application
+with APM, sending requests frames to the APM server.
+"""
import sys
@@ -21,8 +25,11 @@
from pyramid.compat import reraise
from pyramid.settings import asbool
+__docformat__ = 'restructuredtext'
+
def list_from_setting(config, setting):
+ """Split configuration setting"""
value = config.get(setting)
if not value:
return None
@@ -30,6 +37,7 @@
def get_data_from_request(request):
+ """Extract main APM data from request properties"""
data = {
"headers": dict(**request.headers),
"method": request.method,
@@ -46,6 +54,7 @@
def get_data_from_response(response):
+ """Extract APM data from response properties"""
data = {"status_code": response.status_int}
if response.headers:
data["headers"] = {
@@ -55,7 +64,7 @@
return data
-class elastic_apm_tween_factory(object):
+class elastic_apm_tween_factory: # pylint: disable=invalid-name
"""Elasticsearch APM tween factory"""
def __init__(self, handler, registry):
@@ -89,7 +98,7 @@
transaction_result = response.status[0] + "xx"
elasticapm.set_context(lambda: get_data_from_response(response), "response")
return response
- except Exception:
+ except Exception: # pylint: disable=broad-except
transaction_result = '5xx'
self.client.capture_exception(
context={
@@ -107,6 +116,7 @@
view_name = ''
transaction_name = request.matched_route.pattern if request.matched_route else view_name
# prepend request method
- transaction_name = " ".join((request.method, transaction_name)) if transaction_name else ""
+ transaction_name = " ".join((request.method, transaction_name)) \
+ if transaction_name else ""
elasticapm.set_context(lambda: get_data_from_request(request), "request")
self.client.end_transaction(transaction_name, transaction_result)