> ## Documentation Index
> Fetch the complete documentation index at: https://docs.honeycomb.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Export Data with AWS Lambda + Honeycomb Lambda Extension

> Receive log messages from your Lambda function and send them to Honeycomb as events using the Honeycomb Lambda Extension, available as a layer or container.

export const honeytail = {
  "version": "1.10.0",
  "deb_amd64": {
    "sha256": "3db441215f97eaed068aa0531c986cf5405957e3e8e26b22c16b571091caf917",
    "url": "https://honeycomb.io/download/honeytail/v1.10.0/honeytail_1.10.0_amd64.deb"
  },
  "deb_arm64": {
    "sha256": "4220756e5a941cde6a484cb4cfde184eb189aaf29170df301a874eb143e960ed",
    "url": "https://honeycomb.io/download/honeytail/v1.10.0/honeytail_1.10.0_arm64.deb"
  },
  "rpm": {
    "sha256": "b23215a9301b20b2e2262a0823c9e761e8b57e1a62fd5cec35f697fce41fa863",
    "url": "https://honeycomb.io/download/honeytail/v1.10.0/honeytail-1.10.0-1.x86_64.rpm"
  },
  "bin_linux_amd64": {
    "sha256": "c9cc7dd1aa2b12afeb30b089061870f3407d2df0119e7c2807fec648b603e2d5",
    "url": "https://honeycomb.io/download/honeytail/v1.10.0/honeytail-linux-amd64"
  },
  "bin_linux_arm64": {
    "sha256": "1dd37227788548c4ed44592554e3c90e374c4d796c444dde9f372db8618bc7fa",
    "url": "https://honeycomb.io/download/honeytail/v1.10.0/honeytail-linux-arm64"
  },
  "bin_darwin_amd64": {
    "sha256": "9a3da0f48fe21b1e610ac6b63130dfb8118a9a0ec16abae13350edba02d85e4d",
    "url": "https://honeycomb.io/download/honeytail/v1.10.0/honeytail-darwin-amd64"
  },
  "bin_name": "honeytail"
};

export const honeycomb_lambda_extension = {
  "repo_name": "honeycombio/honeycomb-lambda-extension",
  "_comment": "was v11.2.0 in front version tag in front matter for content/integrations/aws/lambda/honeycomb-lambda-extension.md. Think it can/should be updated to current version, but should check.",
  "version": "11.6.0",
  "layers": {
    "af-south-1": {
      "arm64": "arn:aws:lambda:af-south-1:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:af-south-1:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "ap-east-1": {
      "arm64": "arn:aws:lambda:ap-east-1:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:ap-east-1:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "ap-northeast-1": {
      "arm64": "arn:aws:lambda:ap-northeast-1:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:ap-northeast-1:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "ap-northeast-2": {
      "arm64": "arn:aws:lambda:ap-northeast-2:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:ap-northeast-2:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "ap-northeast-3": {
      "arm64": "arn:aws:lambda:ap-northeast-3:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:ap-northeast-3:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "ap-south-1": {
      "arm64": "arn:aws:lambda:ap-south-1:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:ap-south-1:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "ap-southeast-1": {
      "arm64": "arn:aws:lambda:ap-southeast-1:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:ap-southeast-1:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "ap-southeast-2": {
      "arm64": "arn:aws:lambda:ap-southeast-2:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:ap-southeast-2:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "ap-southeast-3": {
      "arm64": "arn:aws:lambda:ap-southeast-3:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:ap-southeast-3:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "ca-central-1": {
      "arm64": "arn:aws:lambda:ca-central-1:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:ca-central-1:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "eu-central-1": {
      "arm64": "arn:aws:lambda:eu-central-1:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:eu-central-1:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "eu-north-1": {
      "arm64": "arn:aws:lambda:eu-north-1:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:eu-north-1:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "eu-south-1": {
      "arm64": "arn:aws:lambda:eu-south-1:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:eu-south-1:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "eu-west-1": {
      "arm64": "arn:aws:lambda:eu-west-1:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:eu-west-1:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "eu-west-2": {
      "arm64": "arn:aws:lambda:eu-west-2:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:eu-west-2:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "eu-west-3": {
      "arm64": "arn:aws:lambda:eu-west-3:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:eu-west-3:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "me-south-1": {
      "arm64": "arn:aws:lambda:me-south-1:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:me-south-1:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "sa-east-1": {
      "arm64": "arn:aws:lambda:sa-east-1:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:sa-east-1:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "us-east-1": {
      "arm64": "arn:aws:lambda:us-east-1:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1"
    },
    "us-east-2": {
      "arm64": "arn:aws:lambda:us-east-2:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:us-east-2:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "us-west-1": {
      "arm64": "arn:aws:lambda:us-west-1:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:us-west-1:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "us-west-2": {
      "arm64": "arn:aws:lambda:us-west-2:702835727665:layer:honeycomb-lambda-extension-arm64-v11-6-0:1",
      "x86_64": "arn:aws:lambda:us-west-2:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "ap-southeast-4": {
      "x86_64": "arn:aws:lambda:ap-southeast-4:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "eu-central-2": {
      "x86_64": "arn:aws:lambda:eu-central-2:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "eu-south-2": {
      "x86_64": "arn:aws:lambda:eu-south-2:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    },
    "me-central-1": {
      "x86_64": "arn:aws:lambda:me-central-1:702835727665:layer:honeycomb-lambda-extension-x86_64-v11-6-0:1"
    }
  }
};

export const LambdaLayerSelector = ({version, layers}) => {
  const [selectedRegion, setSelectedRegion] = React.useState('');
  const [selectedArch, setSelectedArch] = React.useState('');
  const [copied, setCopied] = React.useState(false);
  const handleRegionChange = newRegion => {
    setSelectedRegion(newRegion);
    if (!newRegion || !layers[newRegion]) {
      return;
    }
    const availableArchs = Object.keys(layers[newRegion]);
    if (availableArchs.length === 1) {
      setSelectedArch(availableArchs[0]);
    } else if (selectedArch && !availableArchs.includes(selectedArch)) {
      setSelectedArch('');
    }
  };
  const currentArn = selectedRegion && selectedArch ? layers[selectedRegion]?.[selectedArch] || '' : '';
  const isArchAvailable = selectedRegion && selectedArch && layers[selectedRegion]?.[selectedArch] !== undefined;
  const handleCopy = async () => {
    try {
      await navigator.clipboard.writeText(currentArn);
      setCopied(true);
      setTimeout(() => setCopied(false), 2000);
    } catch (err) {
      console.error('Failed to copy:', err);
    }
  };
  const regions = Object.keys(layers).sort();
  return <div className="bg-gray-50 dark:bg-gray-800/50 border border-gray-200 dark:border-gray-700 rounded-lg p-6">
      <div>
        <p>
          Select your AWS region and architecture to get the appropriate Lambda layer ARN for version {version}.
        </p>
      </div>

      <div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4 mt-6">
        <div>
          <label htmlFor="region-select" style={{
    fontWeight: '700'
  }} className="block text-sm font-bold mb-2">
            AWS Region
          </label>
          <select id="region-select" value={selectedRegion} onChange={e => handleRegionChange(e.target.value)} className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
            <option value="">Select a region...</option>
            {regions.map(region => <option key={region} value={region}>
                {region}
              </option>)}
          </select>
        </div>

        <div>
          <label htmlFor="arch-select" style={{
    fontWeight: '700'
  }} className="block text-sm font-bold mb-2">
            Architecture
          </label>
          <select id="arch-select" value={selectedArch} onChange={e => setSelectedArch(e.target.value)} className="w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
            <option value="">Select an architecture...</option>
            {selectedRegion && layers[selectedRegion] && Object.keys(layers[selectedRegion]).map(arch => <option key={arch} value={arch}>
                  {arch === 'x86_64' ? 'x86_64' : arch.toUpperCase()}
                </option>)}
          </select>
        </div>
      </div>

      {selectedRegion && selectedArch && isArchAvailable ? <div className="space-y-4">
          <div>
            <p className="text-sm font-medium mb-2">Layer ARN:</p>
            <div className="flex items-start gap-2">
              <div className="flex-1">
                <CodeBlock language="text">
                  {currentArn}
                </CodeBlock>
              </div>
            </div>
          </div>

          <div>
            <p>You can add the extension as a Lambda Layer with the AWS CLI tool:</p>
            <CodeBlock language="shell" wrap>
      {`aws lambda update-function-configuration --function-name YourFunctionName --layers "${currentArn}"`}
            </CodeBlock>
          </div>

          <div>
            <p className="text-sm font-medium mb-2">You can also use infrastructure-as-code tools, such as <a href="https://www.terraform.io/">Terraform:</a></p>
            <CodeBlock language="terraform" wrap>
{`resource "aws_lambda_function" "extensions-demo-example-lambda" {
  function_name = "HoneycombExtensionExample"
  ...
  layers = ["${currentArn}"]
}`}
            </CodeBlock>
          </div>
        </div> : selectedRegion && selectedArch ? <div className="bg-yellow-50 border border-yellow-200 rounded-md p-4">
          <p className="text-sm text-yellow-800">
            <strong>Note:</strong> {selectedArch} architecture is not available in the {selectedRegion} region. 
            Please select x86_64 architecture for this region.
          </p>
        </div> : null}
    </div>;
};

If not yet ready to use OpenTelemetry, you can use the [Honeycomb Lambda Extension](https://github.com/honeycombio/honeycomb-lambda-extension).
This extension is designed to run alongside your Lambda Function.
It integrates with the [Lambda Logs API](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-logs-api.html) and receives log messages from your lambda function, which are then sent to Honeycomb as events.
Structured log messages sent to `stdout` or `stderr` from your lambda function will be sent to Honeycomb as events.

The extension can be run inside a container or added as a Lambda Layer.

<img src="https://mintcdn.com/honeycomb/ZEhop91RpDyv3q2S/_assets/images/aws/lambda-extension-container.png?fit=max&auto=format&n=ZEhop91RpDyv3q2S&q=85&s=a4ab6d36ecf524db5a01b7f21f0bf56c" alt="Overview of Lambda Extension" width="481" height="281" data-path="_assets/images/aws/lambda-extension-container.png" />

### How It Works

[AWS Lambda Extensions](https://aws.amazon.com/blogs/compute/introducing-aws-lambda-extensions-in-preview/) allow you to extend the functionality of Lambda functions through configuration as Lambda Layers or run inside a container image.

Extensions run alongside the Lambda Runtime and can read data environment variables from the environment.

Once the Honeycomb Lambda Extension is configured, any structured logs emitted to `stdout` or `stderr` by your Lambda function will be parsed by the extension and sent to a dataset that you specify in Honeycomb.

<Note>
  Logs emitted in a Lambda invocation will be parsed during the following invocation, and any remaining logs will be parsed whenever the Lambda runtime shuts down.
  This means that you may experience some delay in seeing events arrive in Honeycomb, especially if your Lambda function receives low traffic.
</Note>

### Architectures

The [Honeycomb Lambda Extension](https://github.com/honeycombio/honeycomb-lambda-extension) is available as an [external extension](https://docs.aws.amazon.com/lambda/latest/dg/using-extensions.html) pre-built in a lambda layer for either `x86_64` or `arm64` architectures.

<Note>
  Graviton2 `arm64` is supported in most, but not all regions.
  See [AWS Lambda Pricing](https://aws.amazon.com/lambda/pricing/) for which regions are supported.
</Note>

### Installing as a Lambda Layer

To start using the [Honeycomb Lambda Extension](https://github.com/honeycombio/honeycomb-lambda-extension), add the extension to your function as a [Lambda Layer](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html).

<LambdaLayerSelector version={honeycomb_lambda_extension.version} layers={honeycomb_lambda_extension.layers} />

Add the following environment variables to your Lambda function configuration:

* `LIBHONEY_DATASET` - The Honeycomb [dataset](/get-started/best-practices/organizing-data/#datasets-group-data-together) you would like events to be sent to. This could be the service name representing the function or a generic dataset name representing the data.
* `LIBHONEY_API_KEY` - Your Honeycomb API Key (also called Write Key).

As well as the following optional environment variable:

* `LIBHONEY_API_HOST` - Mostly used for testing purposes, or to be compatible with proxies.
  Defaults to `<https://api.honeycomb.io/>`.
* `LOGS_API_DISABLE_PLATFORM_MSGS` - Optional.
  Set to "true" in order to disable "platform" messages from the logs API.
* `HONEYCOMB_DEBUG` - Optional.
  Set to "true" to enable debug statements and troubleshoot issues.
  Enabling this will subscribe to Libhoney's [response queue](/send-data/go/libhoney/#handling-responses) and log the success or failure of sending events to Honeycomb.
* `HONEYCOMB_BATCH_SEND_TIMEOUT` - Optional.
  Default: "15s" (15 seconds; refer to note below about timeout durations).
  The timeout for the complete HTTP request/response cycle for sending a batch of events Honeycomb.
  A batch send that times out has a single built-in retry; total time a lambda invocation may spend waiting is double this value.
  A very low duration may result in duplicate events, if Honeycomb data ingest is successful but slower than this timeout (rare, but possible).
* `HONEYCOMB_CONNECT_TIMEOUT` - Optional.
  Default: 3s (3 seconds; refer to note below about timeout durations).
  The timeout for establishing a TCP connection to Honeycomb.
  This is useful when there are connectivity issues between your Lambda environment and Honeycomb, allowing upload requests to fail faster and avoid waiting for the longer batch send timeout to elapse.

<Note>
  TIMEOUT options should be given a value in a format parseable as a duration, such as "1m", "15s", or "750ms".
  There are other valid time units ("ns", "us"/"µs", "h"), but their use does not fit a timeout for HTTP connections made in the AWS Lambda compute environment.
</Note>

### Installing in a Container Image

AWS Lambda functions can now be packaged and deployed as [container images](https://docs.aws.amazon.com/lambda/latest/dg/images-create.html).
This allows developers to leverage the flexibility and familiarity of container tooling, workflows and dependencies.

<AWSLambdaConainerImage />

AWS Lambda provides a number of [base images](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-images.html#runtimes-images-lp) you can use.
You can also use a custom base image, and adjust the examples accordingly.

### Performance Implications

The Honeycomb Lambda Extension runs independently of your Lambda Function and does not add to your Lambda Function's execution time or add any additional latency.
However, it does increase your Lambda Function's size in proportion with the size of the Honeycomb Lambda Extension binary.

## Examples

Below are some structured logging examples using some libraries we are familiar with at Honeycomb.
Feel free to use your own!

### Go

```go theme={}
import (
  log "github.com/sirupsen/logrus"
)

log.SetFormatter(&log.JSONFormatter{})

func Handler(ctx context.Context) error {
  // Measure execution time
  startTime := time.Now()

  // ...

  // Get the Lambda context object
  lc, _ := lambdacontext.FromContext(ctx)

  log.WithFields(log.Fields{
    "function_name": lambdacontext.FunctionName,
    "function_version": lambdacontext.FunctionVersion,
    "request_id": lc.AwsRequestID,
    "duration_ms": time.Since(startTime).Milliseconds(),
    // The sample rate on the event is forwarded to honeycomb - we
    // assume the event has already been properly sampled.
    "samplerate": 10,
    // other fields of interest
  }).Info("Hello World from Lambda!")
}
```

### Python

```python theme={}
import structlog
structlog.configure(processors=[structlog.processors.JSONRenderer()])
log = structlog.get_logger()

def handler(event, context):
    # measure execution time
    start_time = datetime.datetime.now()

    # ...

    log.msg(
        "Hello World from Lambda!",
        function_name=context.function_name,
        function_version=context.function_version,
        request_id=context.aws_request_id,
        duration_ms=(datetime.datetime.now() - start_time).total_seconds() * 1000,
        # other fields of interest
    )
```

### JavaScript

```javascript theme={}
var bunyan = require('bunyan');
var log = bunyan.createLogger();


module.exports.handler = (event, context, callback) => {
  // Measure execution time
  let startTime = Date.now();

  // ...

  log.info({
    functionName: context.functionName,
    functionVersion: context.functionVersion,
    requestId: context.awsRequestId,
    // Example fields - send anything that seems relevant!
    userId: event.UserId,
    userAction: event.UserAction,
    latencyMs: Date.now() - startTime,
  },
  'Hello World from Lambda!');
}
```

<Note>
  Do not use `console.log` to write structured log lines in Lambda.
  Lambda uses a patched version of `console.log`, injecting extra information with each line that does not work correctly with the Honeycomb Extension Lambda Logs integration.
</Note>
