Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python apm agent doesn't captured spans in aws lambda functions #1711

Closed
sharanraj124 opened this issue Dec 13, 2022 · 2 comments
Closed

Python apm agent doesn't captured spans in aws lambda functions #1711

sharanraj124 opened this issue Dec 13, 2022 · 2 comments
Labels
agent-python community Issues opened by the community triage Issues awaiting triage

Comments

@sharanraj124
Copy link

sharanraj124 commented Dec 13, 2022

Hi, I added an elastic APM agent in my lambda function transaction are captured perfectly, I don't see any database calls in my dashboard

import sys
import json
import pymysql
import logging
from elasticapm import capture_serverless



rds_host = "******"
name = "admin"
password = "***"
db_name = "***"
port = 3306

logger = logging.getLogger()
logger.setLevel(logging.INFO)

try:
    conn = pymysql.connect(host=rds_host, user=name, passwd=password, db=db_name, connect_timeout=5)
except pymysql.MySQLError as e:
    logger.error("ERROR: Unexpected error: Could not connect to MySql instance.")
    logger.error(e)
    sys.exit()

logger.info("SUCCESS: Connection to RDS mysql instance succeeded")

@capture_serverless()
def lambda_handler(event, context):

    sql = "INSERT INTO `user` (`firstName`, `lastName`,  `gender`, `birthday`,`email`, `phone`, `shippingAddress`, `billingAddress`) VALUES(%s, %s, %s, %s, %s, %s, %s, %s)"
    val = (event["firstName"], event["lastName"], event["gender"], event["birthday"], event["email"], event["phone"], event["shipping_address_id"], event["billing_address_id"])

    with conn.cursor() as cur:
        cur.execute(sql, val)
        conn.commit()

    return {
        'statusCode': 200,
        'body': json.dumps('Data has been inserted successfully')
    }
@github-actions github-actions bot added agent-python community Issues opened by the community triage Issues awaiting triage labels Dec 13, 2022
@basepi
Copy link
Contributor

basepi commented Dec 13, 2022

The pymysql instrumentation creates a proxy object on pymysql.connect().

The problem is, that we don't instrument pymysql until the handler is invoked.

We may be able to improve this -- you'll note in the comment that we're trying not to create multiple client instances. But now that we have get_client() I don't think it should matter, we can check if a client has already been created.

For now, I think you would need to do something like this (untested):

import sys
import json
import pymysql
import logging
from elasticapm import capture_serverless


rds_host = "******"
name = "admin"
password = "***"
db_name = "***"
port = 3306

logger = logging.getLogger()
logger.setLevel(logging.INFO)

conn = None


@capture_serverless()
def lambda_handler(event, context):
    global conn
    if not conn:
        try:
            conn = pymysql.connect(host=rds_host, user=name, passwd=password, db=db_name, connect_timeout=5)
        except pymysql.MySQLError as e:
            logger.error("ERROR: Unexpected error: Could not connect to MySql instance.")
            logger.error(e)
            sys.exit()

        logger.info("SUCCESS: Connection to RDS mysql instance succeeded")

    sql = "INSERT INTO `user` (`firstName`, `lastName`,  `gender`, `birthday`,`email`, `phone`, `shippingAddress`, `billingAddress`) VALUES(%s, %s, %s, %s, %s, %s, %s, %s)"
    val = (event["firstName"], event["lastName"], event["gender"], event["birthday"], event["email"], event["phone"], event["shipping_address_id"], event["billing_address_id"])

    with conn.cursor() as cur:
        cur.execute(sql, val)
        conn.commit()

    return {
        'statusCode': 200,
        'body': json.dumps('Data has been inserted successfully')
    }

Even if we fixed the issue where we don't instrument until the function is called, you would still need to move your connection code below the @capture_serverless() call. But for now it needs to be inside the function.

@basepi
Copy link
Contributor

basepi commented Dec 14, 2022

Actually I just remembered why we can't move it out of the decorator: We allow config via the **kwargs to the decorator. That may be something that's not super important to support, but that's the reason it's set up the way it is.

I will note, we're currently working on a no-code-changes instrumentation system, which will eventually include support for lambda. This will mean you will just add our lambda layer (which will include both the python agent and the extension) and environment variables and everything should just work. We don't have an ETA on that feature, but it should solve your use case much more cleanly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
agent-python community Issues opened by the community triage Issues awaiting triage
Projects
None yet
Development

No branches or pull requests

2 participants