The Python Agent APIs:

  • Let you programmatically define custom business transactions that would not automatically be detected by the agent.
  • Let you create custom exit calls to discover and monitor backends and that are not automatically detected by the agent.

If your instrumented application starts up and you do not see all the business transactions or backends that you expect to see, first check Python Supported Environments to see if your framework or exit point is supported. If not, you can use the APIs to instrument your code manually.

Custom Business Transactions

You can use the start_bt() and  end_bt() methods to surround the code that you want to monitor as a custom business transaction.

Or you can use the "bt" context manager. Consider using the bt context manager where you start and end the business transaction in the same code. For example, where you can wrap the whole business transaction in a with statement.

For example, given the code:

 setup()
 do_work()
 teardown()
PY

you want to report do_work() as a business transaction.

Use start_bt() and  end_bt()

This example uses start_bt() and end_bt() to create a business transaction named do_work.

from appdynamics.agent import api as appd        
setup()
 
bt_handle = appd.start_bt('do work')
try:
    do_work()
except Exception as exc:
    raise
finally:
    appd.end_bt(bt_handle, exc)

teardown()
PY

Use bt context manager

If the business transaction starts and ends in the same context, you can use the bt context manager instead. This is simpler:

setup()

with bt('do work'):
    do_work()

teardown()
PY

Custom Exit Calls

You can use the start_exit_call() and  end_exit_call() methods to create a custom exit call from a specific business transaction to a backend that the Python Agent does not automatically detect.

The business transaction must be a custom business transaction.

If you want to make a custom exit call from a business transaction that is normally automatically detected, you can exclude that business transaction to prevent it from being automatically detected and then create it as a custom business transaction. This enables you to get the BtHandle that you need to create the custom exit call. See Configure Python Web Custom Match and Exclude Rules for information on excluding a business transaction.

Given the code:

try:
    db = custom_db.connect(host='financials-lb', port=3456)
    all_employees = db.query_path('/financials/employees')
    individual_contributors = all_employees.filter(lambda r: r.level < 3)
    salaries_by_dept = individual_contributors.sum(value='salary', group='dept', as='total')

    for dept, total in salaries_by_dept.extract('dept', 'total'):
        report_salary_data(dept, total)
PY

You want to send the query via an exit call to a proprietary database.

You want the database to be labeled Financials Database in the Controller UI.

You want the backend properties that appear in the backend dashboard to appear as:

Host:

financials-lb

Port:

3456

Vendor:

custom db

The following examples assume you are wrapping the exit call in a custom business transaction named department rollup, created in another part of your code.

Use start_exit_call() and end_exit_call()

This example uses start_exit_call() and end_exit_call().

from appdynamics.agent import api as appd
appd.init()

# Set the identifying properties
FINANCIALS_ID_PROPS = {'Host': 'financials-lb', 'Port': 3456, 'Vendor': 'custom db'}

with appd.bt('department rollup') as bt_handle:
    # Start the exit call
    exit_call = appd.start_exit_call(bt_handle, appd.EXIT_DB, 'Financials Database', FINANCIALS_ID_PROPS)
    exc = None

    try:
        db = custom_db.connect(host='financials-lb', port=3456)
        all_employees = db.query_path('/financials/employees')
        individual_contributors = all_employees.filter(lambda r: r.level < 3)
        salaries_by_dept = individual_contributors.sum(value='salary', group='dept', as='total')

        for dept, total in salaries_by_dept.extract('dept', 'total'):
            report_salary_data(dept, total)
    except Exception as exc:
        raise  # Assuming something above handles exceptions for you
    finally:
        #End the exit call
        end_exit_call(exit_call, exc)

PY

Use exit_call context manager

If the business transaction starts and ends in the same context, you can use the simpler exit_call context manager instead.

from appdynamics.agent import api as appd
appd.init()

with appd.bt('department rollup') as bt_handle:
    with appd.exit_call(bt_handle, appd.EXIT_DB, 'Financials Database', FINANCIALS_ID_PROPS):
        db = custom_db.connect(host='financials-lb', port=3456)
        all_employees = db.query_path('/financials/employees')
        individual_contributors = all_employees.filter(lambda r: r.level < 3)
        salaries_by_dept = individual_contributors.sum(value='salary', group='dept', as='total')

        for dept, total in salaries_by_dept.extract('dept', 'total'):
            report_salary_data(dept, total)
PY

The next example starts a custom exit call to a Cassandra backend from a business transaction that was auto-detected by the Python Agent default Flask instrumentation. It uses the Flask import feature to get the request object which it passes to appd_get_active_bt_handle().

Get bt handle using the flask request context

from flask import request
from appdynamics.agent import api as appd

@app.route('/metrics/recent')
def metrics_recent():
    bt = appd.get_active_bt_handle(request)  # Get the active BT from the Flask request object
    with appd.exit_call(bt, appd.EXIT_DB, 'cassandra time-series', {'VENDOR': 'Cassandra', 'SERVER POOL': '10.0.0.1'}):
        load_recent_data_from_cassandra()
PY

Other supported frameworks have different mechanisms for getting the request object.