Instrumenting custom code
editInstrumenting custom code
editCreating Additional Spans in a Transaction
editElastic APM instruments a variety of libraries out of the box, but sometimes you need to know how long a specific function took or how often it gets called.
Assuming you’re using one of our supported frameworks, you can
apply the @elasticapm.capture_span()
decorator to achieve exactly that. If
you’re not using a supported framework, see
Creating New Transactions.
elasticapm.capture_span
can be used either as a decorator or as a context
manager. The following example uses it both ways:
import elasticapm @elasticapm.capture_span() def coffee_maker(strength): fetch_water() with elasticapm.capture_span('near-to-machine'): insert_filter() for i in range(strength): pour_coffee() start_drip() fresh_pots()
Similarly, you can use elasticapm.async_capture_span
for instrumenting async
workloads:
import elasticapm @elasticapm.async_capture_span() async def coffee_maker(strength): await fetch_water() async with elasticapm.async_capture_span('near-to-machine'): await insert_filter() async for i in range(strength): await pour_coffee() start_drip() fresh_pots()
asyncio
support is only available in Python 3.7+.
See the API docs for more information on capture_span
.
Creating New Transactions
editIt’s important to note that elasticapm.capture_span
only works if there is
an existing transaction. If you’re not using one of our supported
frameworks, you need to create a Client
object and begin and end the
transactions yourself. You can even utilize the agent’s
automatic instrumentation!
To collect the spans generated by the supported libraries, you need
to invoke elasticapm.instrument()
(just once, at the initialization stage of
your application) and create at least one transaction. It is up to you to
determine what you consider a transaction within your application — it can
be the whole execution of the script or a part of it.
The example below will consider the whole execution as a single transaction
with two HTTP request spans in it. The config for elasticapm.Client
can be
passed in programmatically, and it will also utilize any config environment
variables available to it automatically.
import requests import time import elasticapm def main(): sess = requests.Session() for url in [ 'https://www.elastic.co', 'https://benchmarks.elastic.co' ]: resp = sess.get(url) time.sleep(1) if __name__ == '__main__': client = elasticapm.Client(service_name="foo", server_url="https://example.com:8200") elasticapm.instrument() # Only call this once, as early as possible. client.begin_transaction(transaction_type="script") main() client.end_transaction(name=__name__, result="success")
Note that you don’t need to do anything to send the data — the Client
object
will handle that before the script exits. Additionally, the Client
object should
be treated as a singleton — you should only create one instance and store/pass
around that instance for all transaction handling.