1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
|
from os import getenv
try:
from werkzeug.exceptions import HTTPException
except ImportError:
HTTPException = None
from applicationinsights import TelemetryClient
from applicationinsights.channel import AsynchronousSender
from applicationinsights.channel import AsynchronousQueue
from applicationinsights.channel import TelemetryChannel
from applicationinsights.logging import LoggingHandler
from applicationinsights.requests import WSGIApplication
CONF_PREFIX = "APPINSIGHTS"
CONF_KEY = CONF_PREFIX + "_INSTRUMENTATIONKEY"
CONF_ENDPOINT_URI = CONF_PREFIX + "_ENDPOINT_URI"
CONF_DISABLE_REQUEST_LOGGING = CONF_PREFIX + "_DISABLE_REQUEST_LOGGING"
CONF_DISABLE_TRACE_LOGGING = CONF_PREFIX + "_DISABLE_TRACE_LOGGING"
CONF_DISABLE_EXCEPTION_LOGGING = CONF_PREFIX + "_DISABLE_EXCEPTION_LOGGING"
class AppInsights(object):
""" This class represents a Flask extension that enables request telemetry,
trace logging and exception logging for a Flask application. The telemetry
will be sent to Application Insights service using the supplied
instrumentation key.
The following Flask config variables can be used to configure the extension:
- Set ``APPINSIGHTS_INSTRUMENTATIONKEY`` to a string to provide the
instrumentation key to send telemetry to application insights.
Alternatively, this value can also be provided via an environment variable
of the same name.
- Set ``APPINSIGHTS_ENDPOINT_URI`` to a string to customize the telemetry
endpoint to which Application Insights will send the telemetry.
- Set ``APPINSIGHTS_DISABLE_REQUEST_LOGGING`` to ``False`` to disable
logging of Flask requests to Application Insights.
- Set ``APPINSIGHTS_DISABLE_TRACE_LOGGING`` to ``False`` to disable logging
of all log traces to Application Insights.
- Set ``APPINSIGHTS_DISABLE_EXCEPTION_LOGGING`` to ``False`` to disable
logging of all exceptions to Application Insights.
.. code:: python
from flask import Flask
from applicationinsights.flask.ext import AppInsights
# instantiate the Flask application
app = Flask(__name__)
app.config['APPINSIGHTS_INSTRUMENTATIONKEY'] = '<YOUR INSTRUMENTATION KEY GOES HERE>'
# log requests, traces and exceptions to the Application Insights service
appinsights = AppInsights(app)
# define a simple route
@app.route('/')
def hello_world():
return 'Hello World!'
# run the application
if __name__ == '__main__':
app.run()
"""
def __init__(self, app=None):
"""
Initialize a new instance of the extension.
Args:
app (flask.Flask). the Flask application for which to initialize the extension.
"""
self._key = None
self._endpoint_uri = None
self._channel = None
self._requests_middleware = None
self._trace_log_handler = None
self._exception_telemetry_client = None
if app:
self.init_app(app)
def init_app(self, app):
"""
Initializes the extension for the provided Flask application.
Args:
app (flask.Flask). the Flask application for which to initialize the extension.
"""
self._key = app.config.get(CONF_KEY) or getenv(CONF_KEY)
if not self._key:
return
self._endpoint_uri = app.config.get(CONF_ENDPOINT_URI)
sender = AsynchronousSender(self._endpoint_uri)
queue = AsynchronousQueue(sender)
self._channel = TelemetryChannel(None, queue)
self._init_request_logging(app)
self._init_trace_logging(app)
self._init_exception_logging(app)
@property
def context(self):
"""
Accesses the telemetry context.
Returns:
(applicationinsights.channel.TelemetryContext). The Application Insights telemetry context.
"""
return self._channel.context
def _init_request_logging(self, app):
"""
Sets up request logging unless ``APPINSIGHTS_DISABLE_REQUEST_LOGGING``
is set in the Flask config.
Args:
app (flask.Flask). the Flask application for which to initialize the extension.
"""
enabled = not app.config.get(CONF_DISABLE_REQUEST_LOGGING, False)
if not enabled:
return
self._requests_middleware = WSGIApplication(
self._key, app.wsgi_app, telemetry_channel=self._channel)
app.wsgi_app = self._requests_middleware
def _init_trace_logging(self, app):
"""
Sets up trace logging unless ``APPINSIGHTS_DISABLE_TRACE_LOGGING`` is
set in the Flask config.
Args:
app (flask.Flask). the Flask application for which to initialize the extension.
"""
enabled = not app.config.get(CONF_DISABLE_TRACE_LOGGING, False)
if not enabled:
return
self._trace_log_handler = LoggingHandler(
self._key, telemetry_channel=self._channel)
app.logger.addHandler(self._trace_log_handler)
def _init_exception_logging(self, app):
"""
Sets up exception logging unless ``APPINSIGHTS_DISABLE_EXCEPTION_LOGGING``
is set in the Flask config.
Args:
app (flask.Flask). the Flask application for which to initialize the extension.
"""
enabled = not app.config.get(CONF_DISABLE_EXCEPTION_LOGGING, False)
if not enabled:
return
exception_telemetry_client = TelemetryClient(
self._key, telemetry_channel=self._channel)
@app.errorhandler(Exception)
def exception_handler(exception):
if HTTPException and isinstance(exception, HTTPException):
return exception
try:
raise exception
except Exception:
exception_telemetry_client.track_exception()
finally:
raise exception
self._exception_telemetry_client = exception_telemetry_client
def flush(self):
"""Flushes the queued up telemetry to the service.
"""
if self._requests_middleware:
self._requests_middleware.flush()
if self._trace_log_handler:
self._trace_log_handler.flush()
if self._exception_telemetry_client:
self._exception_telemetry_client.flush()
|