Skip to content

Commit e795df5

Browse files
update lambda support page
1 parent 5c8c776 commit e795df5

File tree

1 file changed

+39
-213
lines changed

1 file changed

+39
-213
lines changed

docs/reference/lambda-support.md

Lines changed: 39 additions & 213 deletions
Original file line numberDiff line numberDiff line change
@@ -1,220 +1,26 @@
11
---
22
mapped_pages:
33
- https://www.elastic.co/guide/en/apm/agent/python/current/lambda-support.html
4+
sub:
5+
apm-lambda-ext-v: ver-1-5-7
6+
apm-python-v: ver-6-23-0
47
---
58

69
# Monitoring AWS Lambda Python Functions [lambda-support]
710

811
The Python APM Agent can be used with AWS Lambda to monitor the execution of your AWS Lambda functions.
912

10-
```
11-
Note: The Centralized Agent Configuration on the Elasticsearch APM currently does NOT support AWS Lambda.
12-
```
13+
:::{note}
14+
The Centralized Agent Configuration on the Elasticsearch APM currently does NOT support AWS Lambda.
15+
:::
1316

1417

1518
## Prerequisites [_prerequisites]
1619

1720
You need an APM Server to send APM data to. Follow the [APM Quick start](docs-content://solutions/observability/apps/application-performance-monitoring-apm.md) if you have not set one up yet. For the best-possible performance, we recommend setting up APM on {{ecloud}} in the same AWS region as your AWS Lambda functions.
1821

22+
## Step 1: Add the APM Layers to your Lambda function [add_the_apm_layers_to_your_lambda_function]
1923

20-
## Step 1: Select the AWS Region and Architecture [_step_1_select_the_aws_region_and_architecture]
21-
22-
<style>
23-
[role="lambda-selector"] {
24-
padding: 20px;
25-
display: flex;
26-
flex-direction: column;
27-
align-items: center;
28-
position: relative;
29-
border: 1px solid hsl(219, 1%, 72%);
30-
border-radius: 0.2em 0.2em 0 0;
31-
overflow: visible;
32-
font-family: inherit;
33-
font-size: inherit;
34-
background: hsl(220, 43%, 99%);
35-
margin-top: 20px;
36-
margin-bottom: 20px;
37-
}
38-
39-
[role="lambda-selector-content"] {
40-
display: flex;
41-
flex-direction: row;
42-
justify-content: space-evenly;
43-
margin-top: 10px;
44-
column-gap: 50px;
45-
}
46-
47-
[role="lambda-selector-input"] {
48-
display: flex;
49-
flex-direction: row;
50-
justify-content: flex-start;
51-
column-gap: 5px;
52-
}
53-
54-
[role="select-input"] {
55-
border: none;
56-
margin-left: 1px;
57-
color: #2b4590;
58-
font-weight: bold;
59-
border-radius: 5px;
60-
}
61-
62-
[role="lambda-selector-header"] {
63-
align-self: flex-start;
64-
}
65-
66-
#fallback-extension-arn-selector-section {
67-
display: none;
68-
}
69-
70-
#fallback-agent-arn-selector-section {
71-
display: none;
72-
}
73-
</style>
74-
75-
<script>
76-
const lambdaAttributesUpdateListeners = [];
77-
const layerArnPattern = /arn:aws:lambda:[^:]*:[^:]*:layer:[^:]*:\d*/g;
78-
79-
const updateLambdaAttributes = () => {
80-
const region = document.getElementById("lambda-aws-region").value;
81-
const arch = document.getElementById("lambda-arch").value;
82-
lambdaAttributesUpdateListeners.forEach(listener => listener(region, arch));
83-
};
84-
85-
const replaceAgentDockerImageParams = async (importStatement, copyStatement) => {
86-
const containerTab = document.getElementById("container-tab-layer");
87-
containerTab.innerHTML = containerTab.innerHTML.replace(/AGENT_IMPORT/, importStatement);
88-
containerTab.innerHTML = containerTab.innerHTML.replace(/AGENT_COPY/, copyStatement);
89-
}
90-
91-
const updateExtensionDockerImageArch = (region, arch) => {
92-
document.querySelectorAll(`[role="replaceLambdaArch"]`).forEach(span => {
93-
span.innerHTML = arch;
94-
});
95-
};
96-
97-
const addArnGenerator = async (type, ghRepo, arnPattern) => {
98-
const tabs = document.getElementsByName("lambda-tabpanel");
99-
const rgx = type === 'agent' ? /AGENT_ARN/ : /EXTENSION_ARN/;
100-
tabs.forEach(tab => {
101-
tab.innerHTML = tab.innerHTML.replace(rgx, `<span role="replace${type}Arn"></span>`)
102-
.replace(/IMAGE_ARCH/, `<span role="replaceLambdaArch"></span>`);
103-
});
104-
105-
var version = undefined;
106-
var releaseArns = [];
107-
108-
const retrieveLatestLayerVersion = async () => {
109-
var latestRelease = await fetch(`https://api.github.com/repos/elastic/${ghRepo}/releases/latest`).then(data => {
110-
return data.status >= 400 ? undefined : data.json();
111-
});
112-
113-
if (latestRelease) {
114-
releaseArns = latestRelease.body.match(layerArnPattern);
115-
version = latestRelease.tag_name.replace("v","ver-").replace(/\./g, '-');
116-
} else {
117-
document.getElementById("default-arn-selector-section").style.display = "none";
118-
const fallbackSection = document.getElementById(`fallback-${type}-arn-selector-section`);
119-
if(fallbackSection){
120-
fallbackSection.innerHTML = fallbackSection.innerHTML.replace(/RELEASE_LINK/, `https://github.com/elastic/${ghRepo}/releases/latest`);
121-
fallbackSection.style.display = "block";
122-
}
123-
}
124-
};
125-
126-
const updateARN = (region, arch) => {
127-
var arn = `<SELECTED_${type.toUpperCase()}_LAYER_ARN>`;
128-
if(version && releaseArns.length > 0){
129-
const arnWithoutLayerVersion = arnPattern.replace(/\$\{region\}/, region).replace(/\$\{arch\}/, arch).replace(/\$\{version\}/, version);
130-
const lookedUpArn = releaseArns.find(a => a.startsWith(arnWithoutLayerVersion));
131-
if(lookedUpArn){
132-
arn = lookedUpArn;
133-
}
134-
}
135-
document.querySelectorAll(`[role="replace${type}Arn"]`).forEach(span => {
136-
span.innerHTML = arn;
137-
});
138-
};
139-
140-
lambdaAttributesUpdateListeners.push(updateARN);
141-
await retrieveLatestLayerVersion();
142-
updateLambdaAttributes();
143-
}
144-
145-
window.addEventListener("DOMContentLoaded", async () => {
146-
const arnInputs = document.querySelectorAll('[role="select-input"]');
147-
148-
arnInputs.forEach(input => {
149-
input.addEventListener("change", e => updateLambdaAttributes());
150-
});
151-
152-
lambdaAttributesUpdateListeners.push(updateExtensionDockerImageArch);
153-
updateLambdaAttributes();
154-
});
155-
</script>
156-
157-
<p id="fallback-extension-arn-selector-section">Pick the right ARN from <a target="_blank" href="RELEASE_LINK">this release table for the APM Lambda Extension Layer</a>.</p>
158-
<p id="fallback-agent-arn-selector-section">In addition, pick the right ARN from <a target="_blank" href="RELEASE_LINK">this release table for the APM Agent Layer</a>.</p>
159-
<div id="default-arn-selector-section" role="lambda-selector">
160-
<div role="lambda-selector-header">Select the AWS region and architecture of your Lambda function. This documentation will update based on your selections.</div>
161-
<div role="lambda-selector-content">
162-
<div role="lambda-selector-input">
163-
<div>region:</div>
164-
<select id="lambda-aws-region" role="select-input">
165-
<option value="af-south-1">af-south-1</option>
166-
<option value="ap-east-1">ap-east-1</option>
167-
<option value="ap-northeast-1">ap-northeast-1</option>
168-
<option value="ap-northeast-2">ap-northeast-2</option>
169-
<option value="ap-northeast-3">ap-northeast-3</option>
170-
<option value="ap-south-1">ap-south-1</option>
171-
<option value="ap-southeast-1">ap-southeast-1</option>
172-
<option value="ap-southeast-2">ap-southeast-2</option>
173-
<option value="ap-southeast-3">ap-southeast-3</option>
174-
<option value="ca-central-1">ca-central-1</option>
175-
<option value="eu-central-1">eu-central-1</option>
176-
<option value="eu-north-1">eu-north-1</option>
177-
<option value="eu-south-1">eu-south-1</option>
178-
<option value="eu-west-1">eu-west-1</option>
179-
<option value="eu-west-2">eu-west-2</option>
180-
<option value="eu-west-3">eu-west-3</option>
181-
<option value="me-south-1">me-south-1</option>
182-
<option value="sa-east-1">sa-east-1</option>
183-
<option value="us-east-1" selected="selected">us-east-1</option>
184-
<option value="us-east-2">us-east-2</option>
185-
<option value="us-west-1">us-west-1</option>
186-
<option value="us-west-2">us-west-2</option>
187-
</select>
188-
</div>
189-
<div role="lambda-selector-input">
190-
<div>architecture:</div>
191-
<select id="lambda-arch" role="select-input">
192-
<option value="x86_64">x86_64</option>
193-
<option value="arm64">arm64</option>
194-
</select>
195-
</div>
196-
</div>
197-
</div>
198-
::::{warning}
199-
The selected *AWS region* and the *architecture* must match the AWS region and architecture of your AWS Lambda function!
200-
::::
201-
202-
203-
204-
## Step 2: Add the APM Layers to your Lambda function [_step_2_add_the_apm_layers_to_your_lambda_function]
205-
206-
<script>
207-
window.addEventListener("DOMContentLoaded", async () => {
208-
addArnGenerator('extension', 'apm-aws-lambda', 'arn:aws:lambda:${region}:267093732750:layer:elastic-apm-extension-${version}-${arch}');
209-
});
210-
</script>
211-
<script>
212-
window.addEventListener("DOMContentLoaded", async () => {
213-
addArnGenerator('agent', 'apm-agent-python', 'arn:aws:lambda:${region}:267093732750:layer:elastic-apm-python-${version}');
214-
replaceAgentDockerImageParams('FROM docker.elastic.co/observability/apm-agent-python:latest AS python-agent',
215-
'COPY --from=python-agent /opt/python/ /opt/python/');
216-
});
217-
</script>
21824
Both the [{{apm-lambda-ext}}](apm-aws-lambda://reference/index.md) and the Python APM Agent are added to your Lambda function as [AWS Lambda Layers](https://docs.aws.amazon.com/lambda/latest/dg/invocation-layers.html). Therefore, you need to add the corresponding Layer ARNs (identifiers) to your Lambda function.
21925

22026
:::::::{tab-set}
@@ -225,7 +31,20 @@ To add the layers to your Lambda function through the AWS Management Console:
22531
1. Navigate to your function in the AWS Management Console
22632
2. Scroll to the Layers section and click the *Add a layer* button ![image of layer configuration section in AWS Console](../images/config-layer.png "")
22733
3. Choose the *Specify an ARN* radio button
228-
4. Copy and paste the following ARNs of the {{apm-lambda-ext}} layer and the APM agent layer in the *Specify an ARN* text input:<br> APM Extension layer:<br> <span style="font-size:10pt"><b>EXTENSION_ARN</b></span><br> APM agent layer:<br> <span style="font-size:10pt"><b>AGENT_ARN</b></span> ![image of choosing a layer in AWS Console](../images/choose-a-layer.png "")
34+
4. Copy and paste the following ARNs of the {{apm-lambda-ext}} layer and the APM agent layer in the *Specify an ARN* text input:
35+
* APM Extension layer:
36+
```
37+
arn:aws:lambda:{AWS_REGION}:267093732750:layer:elastic-apm-extension-{{apm-lambda-ext-v}}-{ARCHITECTURE}:1 <1>
38+
```
39+
1. Replace `{AWS_REGION}` with the AWS region of your Lambda function and `{ARCHITECTURE}` with its architecture.
40+
41+
* APM agent layer:
42+
```
43+
arn:aws:lambda:{AWS_REGION}:267093732750:layer:elastic-apm-python-{{apm-python-v}}:1 <1>
44+
```
45+
1. Replace `{AWS_REGION}` with the AWS region of your Lambda function.
46+
47+
![image of choosing a layer in AWS Console](../images/choose-a-layer.png "")
22948
5. Click the *Add* button
23049
::::::
23150
@@ -234,9 +53,11 @@ To add the Layer ARNs of the {{apm-lambda-ext}} and the APM agent through the AW
23453
23554
```bash
23655
aws lambda update-function-configuration --function-name yourLambdaFunctionName \
237-
--layers EXTENSION_ARN \
238-
AGENT_ARN
56+
--layers arn:aws:lambda:{AWS_REGION}:267093732750:layer:elastic-apm-extension-{{apm-lambda-ext-v}}-{ARCHITECTURE}:1 \ <1>
57+
arn:aws:lambda:{AWS_REGION}:267093732750:layer:elastic-apm-python-{{apm-python-v}}:1 <2>
23958
```
59+
1. Replace `{AWS_REGION}` with the AWS region of your Lambda function and `{ARCHITECTURE}` with its architecture.
60+
2. Replace `{AWS_REGION}` with the AWS region of your Lambda function.
24061
::::::
24162

24263
::::::{tab-item} SAM
@@ -250,10 +71,12 @@ Resources:
25071
Properties:
25172
...
25273
Layers:
253-
- EXTENSION_ARN
254-
- AGENT_ARN
74+
- arn:aws:lambda:{AWS_REGION}:267093732750:layer:elastic-apm-extension-{{apm-lambda-ext-v}}-{ARCHITECTURE}:1 <1>
75+
- arn:aws:lambda:{AWS_REGION}:267093732750:layer:elastic-apm-python-{{apm-python-v}}:1 <2>
25576
...
25677
```
78+
1. Replace `{AWS_REGION}` with the AWS region of your Lambda function and `{ARCHITECTURE}` with its architecture.
79+
2. Replace `{AWS_REGION}` with the AWS region of your Lambda function.
25780
::::::
25881

25982
::::::{tab-item} Serverless
@@ -265,10 +88,12 @@ functions:
26588
yourLambdaFunction:
26689
handler: ...
26790
layers:
268-
- EXTENSION_ARN
269-
- AGENT_ARN
91+
- arn:aws:lambda:{AWS_REGION}:267093732750:layer:elastic-apm-extension-{{apm-lambda-ext-v}}-{ARCHITECTURE}:1 <1>
92+
- arn:aws:lambda:{AWS_REGION}:267093732750:layer:elastic-apm-python-{{apm-python-v}}:1 <2>
27093
...
27194
```
95+
1. Replace `{AWS_REGION}` with the AWS region of your Lambda function and `{ARCHITECTURE}` with its architecture.
96+
2. Replace `{AWS_REGION}` with the AWS region of your Lambda function.
27297
::::::
27398

27499
::::::{tab-item} Terraform
@@ -278,35 +103,36 @@ To add the{{apm-lambda-ext}} and the APM agent to your function add the ARNs to
278103
...
279104
resource "aws_lambda_function" "your_lambda_function" {
280105
...
281-
layers = ["EXTENSION_ARN", "AGENT_ARN"]
106+
layers = ["arn:aws:lambda:{AWS_REGION}:267093732750:layer:elastic-apm-extension-{{apm-lambda-ext-v}}-{ARCHITECTURE}:1", "arn:aws:lambda:{AWS_REGION}:267093732750:layer:elastic-apm-python-{{apm-python-v}}:1"] <1>
282107
}
283108
...
284109
```
110+
1. Replace `{AWS_REGION}` with the AWS region of your Lambda function and `{ARCHITECTURE}` with its architecture.
285111
::::::
286112

287113
::::::{tab-item} Container Image
288114
To add the {{apm-lambda-ext}} and the APM agent to your container-based function extend the Dockerfile of your function image as follows:
289115

290116
```Dockerfile
291117
FROM docker.elastic.co/observability/apm-lambda-extension-IMAGE_ARCH:latest AS lambda-extension
292-
AGENT_IMPORT
118+
FROM docker.elastic.co/observability/apm-agent-python:latest AS python-agent
293119

294120
# FROM ... <-- this is the base image of your Lambda function
295121

296122
COPY --from=lambda-extension /opt/elastic-apm-extension /opt/extensions/elastic-apm-extension
297-
AGENT_COPY
123+
COPY --from=python-agent /opt/python/ /opt/python/
298124

299125
# ...
300126
```
301127
::::::
302128

303129
:::::::
304130

305-
## Step 3: Configure APM on AWS Lambda [_step_3_configure_apm_on_aws_lambda]
131+
## Step 2: Configure APM on AWS Lambda [configure_apm_on_aws_lambda]
306132

307133
The {{apm-lambda-ext}} and the APM Python agent are configured through environment variables on the AWS Lambda function.
308134

309-
For the minimal configuration, you will need the *APM Server URL* to set the destination for APM data and an *{{apm-guide-ref}}/secret-token.html[APM Secret Token]*. If you prefer to use an [APM API key](docs-content://solutions/observability/apps/api-keys.md) instead of the APM secret token, use the `ELASTIC_APM_API_KEY` environment variable instead of `ELASTIC_APM_SECRET_TOKEN` in the following configuration.
135+
For the minimal configuration, you will need the *APM Server URL* to set the destination for APM data and an [APM Secret Token](docs-content://solutions/observability/apps/secret-token.md). If you prefer to use an [APM API key](docs-content://solutions/observability/apps/api-keys.md) instead of the APM secret token, use the `ELASTIC_APM_API_KEY` environment variable instead of `ELASTIC_APM_SECRET_TOKEN` in the following configuration.
310136

311137
For production environments, we recommend [using the AWS Secrets Manager to store your APM authentication key](apm-aws-lambda://reference/aws-lambda-secrets-manager.md) instead of providing the secret value as plaintext in the environment variables.
312138

0 commit comments

Comments
 (0)