Telemetry API로 확장용 실시간 원격 측정 데이터 접근하기
Telemetry API로 확장용 실시간 원격 측정 데이터 접근하기 (Accessing real-time telemetry data for extensions using the Telemetry API)
Telemetry API는 확장(extension)이 Lambda에서 직접 원격 측정 데이터를 받을 수 있게 해줘요. 함수 초기화와 호출 동안 Lambda는 로그, 플랫폼 지표, 플랫폼 트레이스를 포함한 원격 측정을 자동으로 캡처해요. Telemetry API는 확장이 이 원격 측정 데이터를 Lambda에서 거의 실시간으로 직접 접근할 수 있게 해줘요.
Lambda 실행 환경 안에서 Lambda 확장을 원격 측정 스트림에 구독할 수 있어요. 구독 후 Lambda는 모든 원격 측정 데이터를 확장에게 자동으로 보내요. 그런 다음 데이터를 처리·필터링·전달해 Amazon Simple Storage Service(Amazon S3) 버킷이나 타사 관측성 도구 제공자 같은 선호하는 대상으로 보낼 수 있어요.
중요
Lambda Telemetry API는 Lambda Logs API를 대체해요. Logs API가 완전히 작동하지만 앞으로는 Telemetry API만 사용할 것을 권장해요. Telemetry API나 Logs API 중 하나로 확장을 원격 측정 스트림에 구독할 수 있어요. 둘 중 하나로 구독한 후 다른 API로 구독하려 하면 오류가 반환돼요.
참고
Lambda Managed Instances는 Telemetry API의 2025-01-29 스키마 버전만 지원해요. Managed Instance 함수의 원격 측정 스트림에 구독할 때 구독 요청에
"schemaVersion": "2025-01-29"를 사용해야 해요. 이전 스키마 버전을 사용하면 Lambda가 이벤트를 거부해요.
2025-01-29 스키마 버전은 하위 호환되며 Lambda Managed Instances와 Lambda(기본값) 함수 모두에 사용할 수 있어요. 두 배포 모델에서의 호환성을 위해 모든 새 확장에 이 버전을 사용하는 것을 권장해요.
확장은 Telemetry API로 세 가지 서로 다른 원격 측정 스트림에 구독할 수 있어요.
- 플랫폼 원격 측정(Platform telemetry) – 실행 환경 런타임 수명 주기, 확장 수명 주기, 함수 호출과 관련된 이벤트와 오류를 설명하는 로그, 지표, 트레이스.
- 함수 로그(Function logs) – Lambda 함수 코드가 생성하는 커스텀 로그.
- 확장 로그(Extension logs) – Lambda 확장 코드가 생성하는 커스텀 로그.
참고
확장이 원격 측정 스트림에 구독해도 Lambda는 로그와 지표를 CloudWatch로, 트레이스는 X-Ray로(추적을 활성화한 경우) 계속 보내요.
본문
Telemetry API로 확장 만들기
Lambda 확장은 실행 환경의 독립 프로세스로 실행돼요. 확장은 함수 호출이 완료된 후에도 계속 실행될 수 있어요. 확장은 별도 프로세스이므로 함수 코드와 다른 언어로 작성할 수 있어요. Golang이나 Rust 같은 컴파일 언어로 확장을 작성할 것을 권장해요. 이렇게 하면 확장이 자체 포함 이진 파일이 되어 어떤 지원 런타임과도 호환될 수 있어요.
Telemetry API를 사용해 원격 측정 데이터를 받고 처리하는 확장을 만드는 4단계 프로세스는 다음과 같아요.
- Lambda Extensions API를 사용해 확장을 등록합니다. 이렇게 하면 다음 단계에서 필요한
Lambda-Extension-Identifier를 얻습니다. - 원격 측정 리스너를 만듭니다. 기본 HTTP 또는 TCP 서버일 수 있습니다. Lambda는 원격 측정 리스너의 URI를 사용해 원격 측정 데이터를 확장에게 보냅니다.
- Telemetry API의 Subscribe API를 사용해 확장을 원하는 원격 측정 스트림에 구독합니다. 이 단계에서는 원격 측정 리스너의 URI가 필요합니다.
- 원격 측정 리스너를 통해 Lambda에서 원격 측정 데이터를 받습니다. 이 데이터에 Amazon S3로의 전달이나 외부 관측성 서비스로의 전송 같은 커스텀 처리를 할 수 있습니다.
참고
Lambda 함수의 실행 환경은 수명 주기의 일부로 여러 번 시작·중지될 수 있어요. 일반적으로 확장 코드는 함수 호출 중과 종료(Shutdown) 단계에서 최대 2초 동안 실행돼요. 원격 측정이 리스너에 도착할 때 배치하는 것을 권장해요. 그런 다음
Invoke와Shutdown수명 주기 이벤트를 사용해 각 배치를 원하는 대상으로 보내세요.
확장 등록
원격 측정 데이터를 구독하기 전에 Lambda 확장을 등록해야 해요. 등록은 확장 초기화 단계에서 발생해요. 다음 예시는 확장을 등록하는 HTTP 요청이에요.
POST http://${AWS_LAMBDA_RUNTIME_API}/2020-01-01/extension/register
Lambda-Extension-Name: lambda_extension_name
{
'events': [ 'INVOKE', 'SHUTDOWN']
}
요청이 성공하면 구독자는 HTTP 200 성공 응답을 받아요. 응답 헤더에는 Lambda-Extension-Identifier가 포함돼요. 응답 본문에는 함수의 다른 속성이 포함돼요.
HTTP/1.1 200 OK
Lambda-Extension-Identifier: a1b2c3d4-5678-90ab-cdef-EXAMPLE11111
{
"functionName": "lambda_function",
"functionVersion": "$LATEST",
"handler": "lambda_handler",
"accountId": "123456789012"
}
원격 측정 리스너 만들기
Lambda 확장에는 Telemetry API의 들어오는 요청을 처리하는 리스너가 있어야 해요. 다음 코드는 Golang으로 된 예시 원격 측정 리스너 구현이에요.
// Starts the server in a goroutine where the log events will be sent
func (s *TelemetryApiListener) Start() (string, error) {
address := listenOnAddress()
l.Info("[listener:Start] Starting on address", address)
s.httpServer = &http.Server{Addr: address}
http.HandleFunc("/", s.http_handler)
go func() {
err := s.httpServer.ListenAndServe()
if err != http.ErrServerClosed {
l.Error("[listener:goroutine] Unexpected stop on Http Server:", err)
s.Shutdown()
} else {
l.Info("[listener:goroutine] Http Server closed:", err)
}
}()
return fmt.Sprintf("http://%s/", address), nil
}
// http_handler handles the requests coming from the Telemetry API.
// Everytime Telemetry API sends log events, this function will read them from the response body
// and put into a synchronous queue to be dispatched later.
// Logging or printing besides the error cases below is not recommended if you have subscribed to
// receive extension logs. Otherwise, logging here will cause Telemetry API to send new logs for
// the printed lines which may create an infinite loop.
func (s *TelemetryApiListener) http_handler(w http.ResponseWriter, r *http.Request) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
l.Error("[listener:http_handler] Error reading body:", err)
return
}
// Parse and put the log messages into the queue
var slice []interface{}
_ = json.Unmarshal(body, &slice)
for _, el := range slice {
s.LogEventsQueue.Put(el)
}
l.Info("[listener:http_handler] logEvents received:", len(slice), " LogEventsQueue length:", s.LogEventsQueue.Len())
slice = nil
}
대상 프로토콜 지정
Telemetry API로 원격 측정을 받도록 구독할 때 대상 URI에 더해 대상 프로토콜을 지정할 수 있어요.
{
"destination": {
"protocol": "HTTP",
"URI": "http://sandbox.localdomain:8080"
}
}
Lambda는 원격 측정을 받는 두 가지 프로토콜을 허용해요.
- HTTP(권장) – Lambda는 JSON 형식의 레코드 배열로 로컬 HTTP 엔드포인트(
http://sandbox.localdomain:${PORT}/${PATH})에 원격 측정을 전달합니다.$PATH파라미터는 선택 사항입니다. Lambda는 HTTP만 지원하며 HTTPS는 지원하지 않습니다. Lambda는 POST 요청으로 원격 측정을 전달합니다. - TCP – Lambda는 NDJSON(Newline delimited JSON) 형식으로 TCP 포트에 원격 측정을 전달합니다.
참고
TCP보다 HTTP를 사용할 것을 강력히 권장해요. TCP에서는 Lambda 플랫폼이 애플리케이션 계층에 원격 측정을 전달했는지 확인할 수 없어요. 따라서 확장이 크래시하면 원격 측정을 잃을 수 있어요. HTTP에는 이 제한이 없어요.
원격 측정을 받도록 구독하기 전에 로컬 HTTP 리스너나 TCP 포트를 설정하세요. 설정 중 다음을 참고하세요.
- Lambda는 실행 환경 안의 대상에만 원격 측정을 보냅니다.
- 리스너가 없거나 POST 요청이 오류를 만나면 Lambda는 (백오프와 함께) 원격 측정 전송을 재시도합니다. 원격 측정 리스너가 크래시하면 Lambda가 실행 환경을 다시 시작한 후 원격 측정 수신을 재개합니다.
- Lambda는 포트 9001을 예약합니다. 다른 포트 번호 제한이나 권장 사항은 없습니다.
메모리 사용과 버퍼링 구성
실행 환경의 메모리 사용은 구독자 수에 따라 선형적으로 늘어나요. 각 구독은 원격 측정 데이터를 저장하는 새 메모리 버퍼를 열기 때문에 메모리 리소스를 소비해요. 버퍼 메모리 사용은 실행 환경의 전체 메모리 소비에 기여해요.
Telemetry API로 원격 측정을 받도록 구독할 때 원격 측정 데이터를 버퍼링하고 배치로 구독자에게 전달하는 옵션을 선택할 수 있어요. 메모리 사용을 최적화하려면 버퍼링 구성을 지정할 수 있어요.
{
"buffering": {
"maxBytes": 256*1024,
"maxItems": 1000,
"timeoutMs": 100
}
}
| 파라미터 | 설명 | 기본값과 한도 |
|---|---|---|
| maxBytes | 메모리에 버퍼링할 최대 원격 측정량(바이트) | 기본값: 262,144. 최소: 262,144. 최대: 1,048,576 |
| maxItems | 메모리에 버퍼링할 최대 이벤트 수 | 기본값: 10,000. 최소: 1,000. 최대: 10,000 |
| timeoutMs | 배치를 버퍼링할 최대 시간(밀리초) | 기본값: 1,000. 최소: 25. 최대: 30,000 |
버퍼링을 설정할 때 다음 사항을 참고하세요.
- 입력 스트림 중 하나가 닫히면 Lambda가 로그를 플러시합니다. 예를 들어 런타임이 크래시하면 이렇게 될 수 있습니다.
- 각 구독자는 구독 요청에서 자신의 버퍼링 구성을 커스터마이즈할 수 있습니다.
- 데이터를 읽을 버퍼 크기를 결정할 때
2 * maxBytes + metadataBytes만큼 큰 payload를 받을 수 있다고 예상하세요. 여기서 maxBytes는 버퍼링 설정의 구성 요소입니다. Lambda는 각 레코드에 다음과 유사한 메타데이터를 추가합니다.{ "time": "2022-08-20T12:31:32.123Z", "type": "function", "record": "Hello World" } - 구독자가 들어오는 원격 측정을 충분히 빨리 처리하지 못하거나 함수 코드가 매우 높은 로그 볼륨을 생성하면 Lambda는 메모리 사용을 제한하기 위해 레코드를 버릴 수 있습니다. 이때 Lambda는
platform.logsDropped이벤트를 보냅니다.
Telemetry API에 구독 요청 보내기
Lambda 확장은 Telemetry API에 구독 요청을 보내 원격 측정 데이터를 받도록 구독할 수 있어요. 구독 요청은 확장이 구독하려는 이벤트 유형에 대한 정보를 담아야 해요. 또한 요청은 전달 대상 정보와 버퍼링 구성을 포함할 수 있어요.
구독 요청을 보내기 전에 확장 ID(Lambda-Extension-Identifier)가 있어야 해요. Extensions API로 확장을 등록하면 API 응답에서 확장 ID를 얻어요.
구독은 확장 초기화 단계에서 발생해요. 다음 예시는 플랫폼 원격 측정, 함수 로그, 확장 로그 세 가지 원격 측정 스트림 모두를 구독하는 HTTP 요청이에요.
PUT http://${AWS_LAMBDA_RUNTIME_API}/2022-07-01/telemetry HTTP/1.1
{
"schemaVersion": "2025-01-29",
"types": [
"platform",
"function",
"extension"
],
"buffering": {
"maxItems": 1000,
"maxBytes": 256*1024,
"timeoutMs": 100
},
"destination": {
"protocol": "HTTP",
"URI": "http://sandbox.localdomain:8080"
}
}
요청이 성공하면 구독자는 HTTP 200 성공 응답을 받아요.
HTTP/1.1 200 OK
"OK"
인바운드 Telemetry API 메시지
Telemetry API로 구독한 후 확장은 POST 요청을 통해 Lambda에서 자동으로 원격 측정을 받기 시작해요. 각 POST 요청 본문에는 Event 객체의 배열이 포함돼요. 각 Event는 다음 스키마를 가져요.
{
time: String,
type: String,
record: Object
}
time속성은 Lambda 플랫폼이 이벤트를 생성한 시점을 정의합니다. 이는 이벤트가 실제로 발생한 시점과 다릅니다. time의 문자열 값은 ISO 8601 형식의 타임스탬프입니다.type속성은 이벤트 유형을 정의합니다.record속성은 원격 측정 데이터를 담은 JSON 객체를 정의합니다. 이 JSON 객체의 스키마는 type에 따라 달라집니다.
동시 호출의 이벤트 순서
Lambda Managed Instances의 경우 여러 함수 호출이 같은 실행 환경 안에서 동시에 실행될 수 있어요. 이 경우 서로 다른 동시 호출 사이의 platform.start와 platform.report 이벤트 순서는 보장되지 않아요. 확장은 병렬로 실행되는 여러 호출의 이벤트를 처리해야 하며 순차적 순서를 가정하면 안 돼요.
이벤트를 특정 호출에 올바르게 귀속하려면 확장이 이 플랫폼 이벤트에 있는 requestId 필드를 사용해야 해요. 각 호출에는 해당 호출의 모든 이벤트에서 일관된 고유 요청 ID가 있어, 확장이 순서가 어긋나 도착해도 이벤트를 올바르게 상호 연관시킬 수 있어요.
다음 표는 모든 Event 객체 유형을 요약하고 각 이벤트 유형의 Telemetry API Event 스키마 참조에 연결해요.
| 카테고리 | 이벤트 유형 | 설명 |
|---|---|---|
| 플랫폼 이벤트 | platform.initStart | 함수 초기화 시작 |
| 플랫폼 이벤트 | platform.initRuntimeDone | 함수 초기화 완료 |
| 플랫폼 이벤트 | platform.initReport | 함수 초기화 보고 |
| 플랫폼 이벤트 | platform.start | 함수 호출 시작 |
| 플랫폼 이벤트 | platform.runtimeDone | 런타임이 이벤트 처리를 성공 또는 실패로 완료 |
| 플랫폼 이벤트 | platform.report | 함수 호출 보고 |
| 플랫폼 이벤트 | platform.restoreStart | 런타임 복원 시작 |
| 플랫폼 이벤트 | platform.restoreRuntimeDone | 런타임 복원 완료 |
| 플랫폼 이벤트 | platform.restoreReport | 런타임 복원 보고 |
| 플랫폼 이벤트 | platform.telemetrySubscription | 확장이 Telemetry API 구독 |
| 플랫폼 이벤트 | platform.logsDropped | Lambda가 로그 항목 삭제 |
| 함수 로그 | function | 함수 코드의 로그 줄 |
| 확장 로그 | extension | 확장 코드의 로그 줄 |