Skip to content

Commit

Permalink
[docs] Flesh out documentation about creating transactions (elastic#944)
Browse files Browse the repository at this point in the history
* Flesh out documentation about creating transactions

Also moved the documentation to a (hopefully) more intuitive location
and added a link from the set-up docs.

* Apply suggestions from code review

Co-authored-by: Brandon Morelli <[email protected]>

* Lowercase spans and transactions, backtick Client

Co-authored-by: Brandon Morelli <[email protected]>
  • Loading branch information
2 people authored and beniwohli committed Sep 14, 2021
1 parent 1f472a8 commit 22a814b
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 35 deletions.
61 changes: 58 additions & 3 deletions docs/custom-instrumentation.asciidoc
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
[[instrumenting-custom-code]]
=== Instrumenting custom code

[float]
[[instrumenting-custom-code-spans]]
==== Creating Additional Spans in a Transaction

Elastic 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.

You can apply the `@elasticapm.capture_span()` decorator to achieve exactly that.
It can also be used as a context manager in the following way:
Assuming you're using one of our <<set-up, supported frameworks>>, you can
apply the `@elasticapm.capture_span()` decorator to achieve exactly that. If
you're not using a supported framework, see
<<instrumenting-custom-code-transactions, 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:

[source,python]
----
Expand Down Expand Up @@ -48,4 +57,50 @@ async def coffee_maker(strength):

NOTE: `asyncio` support is only available in Python 3.7+.

See <<api-capture-span, the API docs>> for more information on `capture_span`.
See <<api-capture-span, the API docs>> for more information on `capture_span`.

[float]
[[instrumenting-custom-code-transactions]]
==== Creating New Transactions

It's important to note that `elasticapm.capture_span` only works if there is
an existing transaction. If you're not using one of our <<set-up, 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,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.

[source,python]
----
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.
35 changes: 4 additions & 31 deletions docs/how-the-agent-works.asciidoc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[[how-the-agent-works]]
=== How the Agent works

To gather APM events (called Transactions and Spans), errors and metrics,
To gather APM events (called transactions and spans), errors and metrics,
the Python agent instruments your application in a few different ways.
These events, are then sent to the APM Server.
The APM Server converts them to a format suitable for Elasticsearch, and sends them to an Elasticsearch cluster.
Expand All @@ -17,7 +17,7 @@ framework integration, instrumentation, and background collection.
To collect data about incoming requests and background tasks,
we integrate with frameworks like <<django-support,Django>>, <<flask-support,Flask>> and Celery.
Whenever possible, framework integrations make use of hooks and signals provided by the framework.
Examples of this are
Examples of this are:

* `request_started`, `request_finished`, and `got_request_exception` signals from `django.core.signals`
* `request_started`, `request_finished`, and `got_request_exception` signals from `flask.signals`
Expand All @@ -31,35 +31,8 @@ E.g. for Django, you need to add `elasticapm.contrib.django` to `INSTALLED_APPS`
==== What if you are not using a framework

If you're not using a supported framework, for example, a simple Python script, you can still
leverage the agent's <<automatic-instrumentation,automatic instrumentation>>.

In order to collect the Spans generated by the supported libraries, you need to invoke `elasticapm.instrument()`
(just once, at the initalization 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 `elasticapm.Client` can be setup programmatically or using the environment variables.

[source,python]
----
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()
elasticapm.instrument()
client.begin_transaction('main')
main()
client.end_transaction('main')
----
leverage the agent's <<automatic-instrumentation,automatic instrumentation>>. Check out
our docs on <<instrumenting-custom-code, instrumenting custom code>>.

[float]
[[how-it-works-instrumentation]]
Expand Down
2 changes: 1 addition & 1 deletion docs/set-up.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ To get you off the ground, we’ve prepared guides for setting up the Agent with
* <<tornado-support,Tornado>>
* <<starlette-support,Starlette/FastAPI>>

For custom instrumentation, see the <<api>>.
For custom instrumentation, see <<instrumenting-custom-code, Instrumenting Custom Code>>.

include::./django.asciidoc[]

Expand Down

0 comments on commit 22a814b

Please sign in to comment.