Separate transaction for every resolver in AWS Lambda

mkaniaa
Mon, 28 Oct 2024 16:54:09 +0000
APM

Hello! I'm using Elastic APM v8.15.0 with an AWS Lambda function written in Node.js, integrated via elastic-apm-node v4.7.3. My Lambda function has three separate resolvers. Here’s my current configuration setup:

locals {
  lambda_fn_name                            = "${var.environment}_my_lambda_resolver"
  elastic_apm_send_strategy                 = "background"
  elastic_apm_verify_server_cert            = "false"
  elastic_apm_service_name                  = "my_lambda_service"
  elastic_apm_enabled                       = "true"
}

resource "aws_lambda_function" "my_lambda_function" {
  function_name = local.lambda_fn_name
  publish       = true
  role          = xyz
  image_uri     = xyz
  package_type  = "xyz"
  timeout       = 120

  environment {
    variables = {
      ELASTIC_APM_ENABLED                   = local.elastic_apm_enabled
      ELASTIC_APM_SERVICE_NAME              = local.elastic_apm_service_name
      ELASTIC_APM_SERVER_URL                = xyz
      ELASTIC_APM_API_KEY                   = xyz
      ELASTIC_APM_GLOBAL_LABELS             = true
      ELASTIC_APM_SEND_STRATEGY             = local.elastic_apm_send_strategy
      ELASTIC_APM_LAMBDA_VERIFY_SERVER_CERT = local.elastic_apm_verify_server_cert
      ELASTIC_APM_ENVIRONMENT               = var.environment
      NODE_OPTIONS                          = "-r elastic-apm-node/start"
    }
  }
}

I can see my Lambda function listed in the APM > Services section, but I’m running into three issues:

1. Separate Transactions per Resolver: Currently, only one transaction is shown per environment. Each resolver function’s calls are grouped under a single transaction, so I can’t differentiate which resolver each trace represents. I attempted to create individual transactions and spans within each resolver, but that resulted in losing the detailed trace samples, leaving only the initial call.

Here’s an example of the resolver setup:

const myResolverFunction: ResolverHandler<StatusArgs, StatusResult> = async (event, _context, _callback) => {
  const transaction = apm.startTransaction('myResolverFunction', 'resolver');

  try {
    const span = apm.startSpan('my_span');
    const data = await apiClient.runMyResolverOperations();
    span?.end();

    transaction.result = 'success';
    return {
      __typename: 'TaskBatch',
      ...data,
    };
  } catch (error: unknown) {
    transaction.result = 'error';
    if (error instanceof Error) {
      apm.captureError(error);
    } else {
      apm.captureError(String(error));
    }
    throw error;
  } finally {
    transaction.end();
  }
};

2. Trace Sample Order: The trace samples appear in a seemingly random order, which complicates analysis. I’d like them sorted by the time they were called.

3. Viewing API Request Bodies: While I can see all API calls made, the request bodies aren’t visible. Is there a way to configure APM to capture and display the full request body of each call?

Any guidance on achieving these three goals in my Elastic APM setup would be greatly appreciated! Thank you!

8 posts - 2 participants