What’s New in IOpipe for Python 1.8?

Michael Lavers
IOpipe Blog
Published in
4 min readJun 18, 2019

--

If you’re a Python developer building serverless applications, you’ve probably seen our series, “The Right Way™ to do Serverless in Python.”

However, it’s been a while since our last major feature release of our IOpipe Python agent. In that launch, we introduced auto HTTP tracing and have since made a number of refinements.

Now, we’re excited to announce the latest release of IOpipe for Python 1.8, providing user improvements to IOpipe’s monitoring and observability solution for AWS Lambda.

For developers who need real-time visibility into the most granular behaviors of their serverless application, this latest release includes enhancements to auto HTTP tracing, as well as a number of other features we think you’ll find useful.

Let’s take a look…

Auto HTTP Trace Filters

IOpipe automatically traces the HTTP requests your Lambda function makes and collects useful meta data about each request. This gives you instant visibility into which HTTP requests are being made, how long they’re taking, and if there are any errors. However, in some cases, there are times where you don’t want an HTTP request to be traced automatically, especially when dealing with PII. That’s where HTTP trace filters come in.

In 1.8, we’ve simplified how HTTP trace filters work. You still define an http_filter function to perform the filter, but now this function is passed two dicts, a request and a response. Your filter function can then do one of two things:

  • Raise an exception, which will cause IOpipe to discard the trace
  • Mutate the request and/or response data

The filter function also needs to return a tuple of the request and the response in the event that no exception is raised. An example filter might look like this:

def http_filter(request, response):
if request['url'].startswith('https://www.iopipe.com'):
# Exceptions raised will discard the trace
raise Exception(Do not trace this URL'
)
# You can also remove data from the trace
response['headers'].pop('Content-Type', None)

return request, response

And to use it:

from iopipe import IOpipe
from iopipe.conrib.trace import TracePlugin

iopipe = IOpipe(plugins=[TracePlugin(http_filter=http_filter)])

@iopipe
def handler(event, context):
# your lambda function here

In this example, we discard traces for HTTP requests to https://www.iopipe.com and we remove the Content-Type header from the response meta data. We hope this simpler method to filter enables a greater level of control over your HTTP traces.

Auto HTTP Trace Headers

As we mentioned earlier, auto HTTP traces collect useful meta data about an HTTP request. Among this meta data is the HTTP headers of a request and response. In 1.8 the HTTP headers IOpipe collects by default has been limited to the following:

  • Content-Length
  • Content-Type
  • Host
  • Server
  • User-Agent
  • x-amz-target

If you wanted to include the Cache-Control header in your traces, for example, you would use the new http_headers parameter introduced in 1.8:

iopipe = IOpipe(plugins=[TracePlugin(http_headers=['Cache-Control'])])

Be sure not to collect any sensitive headers such as Authorization.

Trace Decorator

In addition to HTTP traces, the tracing plugin also offers another new enhancement: trace decorators. Prior to 1.8, you could wrap the code you wanted to trace in a context manager like this:

from iopipe import IOpipe

iopipe = IOpipe()

@iopipe
def handler(event, context):
with context.iopipe.mark('expensive operation'):
# do something here

But in 1.8, you can now trace using a decorator:

from iopipe import IOpipe

iopipe = IOpipe()

@iopipe
def handler(event, context):
@context.iopipe.mark.decorator('expensive operation'):
def expensive_operation():
# do something here

expensive_operation()

Programmatically Disabling Reporting

Similar to HTTP trace filters, there may also be cases where you want to disable reporting entirely. Prior to 1.8, you could either set an IOPIPE_ENABLED environment variable to a falsy value or set the enabled parameter to False like this:

iopipe = IOpipe(enabled=False)

However this would disable reporting for all invocations. In 1.8, we introduce a disable method to allow you to programmatically disable reporting for a single invocation:

from iopipe import IOpipe

iopipe = IOpipe()

@iopipe
def handler(event, context):
if some_condition:
context.iopipe.disable()

And reporting will be disabled for the current invocation and re-enabled on the next invocation automatically.

Accessing Context

When using a WSGI interface like Zappa or Serverless WSGI, it can be tricky to access the Lambda context from within your chosen web framework. Django and Flask aren’t aware of a Lambda conttext, for example, and it can be tricky to find it within your WSGI environment.

To make this easier, in 1.8 IOpipe now provides the current Lambda context via a contextattribute:

from iopipe import IOpipe

iopipe = IOpipe()

Now all you need to do to access your Lambda context is to import your iopipe instance to where you need it:

# This should be where you instantiate IOpipe
from myapp.handlers import iopipe

# Be sure to check, can be None
if iopipe.context:
# do something with context

This skips the necessary steps to integrate IOpipe with your chosen framework, check the Framework Integration section for further instructions.

New Event Types

And last but not least, IOpipe now supports two new event types:

  • Application Load Balancer (ALB)
  • Simple Email Service (SES)

If you’re not a current IOpipe user, get started with your free trial today to function faster on AWS Lambda. No code changes required.

To learn more about IOpipe or schedule a demo, reach out here.

--

--