forked from aws/aws-lambda-runtime-interface-emulator
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathruntimelogs.go
More file actions
135 lines (115 loc) · 4.22 KB
/
runtimelogs.go
File metadata and controls
135 lines (115 loc) · 4.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package handler
import (
"bytes"
"errors"
"fmt"
"io"
"net/http"
"strings"
"go.amzn.com/lambda/core"
"go.amzn.com/lambda/rapi/rendering"
"go.amzn.com/lambda/telemetry"
"github.com/google/uuid"
log "github.com/sirupsen/logrus"
)
type runtimeLogsHandler struct {
registrationService core.RegistrationService
telemetrySubscription telemetry.SubscriptionAPI
}
func (h *runtimeLogsHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
agentName, err := h.verifyAgentID(writer, request)
if err != nil {
log.Errorf("Agent Verification Error: %s", err)
switch err := err.(type) {
case *ErrAgentIdentifierUnknown:
rendering.RenderForbiddenWithTypeMsg(writer, request, errAgentIdentifierUnknown, "Unknown extension %s", err.agentID.String())
h.telemetrySubscription.RecordCounterMetric(telemetry.SubscribeClientErr, 1)
default:
rendering.RenderInternalServerError(writer, request)
h.telemetrySubscription.RecordCounterMetric(telemetry.SubscribeServerErr, 1)
}
return
}
delete(request.Header, LambdaAgentIdentifier)
body, err := h.getBody(writer, request)
if err != nil {
log.Error(err)
rendering.RenderInternalServerError(writer, request)
h.telemetrySubscription.RecordCounterMetric(telemetry.SubscribeServerErr, 1)
return
}
respBody, status, headers, err := h.telemetrySubscription.Subscribe(agentName, bytes.NewReader(body), request.Header, request.RemoteAddr)
if err != nil {
log.Errorf("Telemetry API error: %s", err)
switch err {
case telemetry.ErrTelemetryServiceOff:
rendering.RenderForbiddenWithTypeMsg(writer, request,
h.telemetrySubscription.GetServiceClosedErrorType(), "%s", h.telemetrySubscription.GetServiceClosedErrorMessage())
h.telemetrySubscription.RecordCounterMetric(telemetry.SubscribeClientErr, 1)
default:
rendering.RenderInternalServerError(writer, request)
h.telemetrySubscription.RecordCounterMetric(telemetry.SubscribeServerErr, 1)
}
return
}
rendering.RenderRuntimeLogsResponse(writer, respBody, status, headers)
switch status / 100 {
case 2: // 2xx
if strings.Contains(string(respBody), "OK") {
h.telemetrySubscription.RecordCounterMetric(telemetry.NumSubscribers, 1)
}
h.telemetrySubscription.RecordCounterMetric(telemetry.SubscribeSuccess, 1)
case 4: // 4xx
h.telemetrySubscription.RecordCounterMetric(telemetry.SubscribeClientErr, 1)
case 5: // 5xx
h.telemetrySubscription.RecordCounterMetric(telemetry.SubscribeServerErr, 1)
}
}
type ErrAgentIdentifierUnknown struct {
agentID uuid.UUID
}
func NewErrAgentIdentifierUnknown(agentID uuid.UUID) *ErrAgentIdentifierUnknown {
return &ErrAgentIdentifierUnknown{
agentID: agentID,
}
}
func (e *ErrAgentIdentifierUnknown) Error() string {
return fmt.Sprintf("Unknown agent %s tried to call /runtime/logs", e.agentID.String())
}
func (h *runtimeLogsHandler) verifyAgentID(writer http.ResponseWriter, request *http.Request) (string, error) {
agentID, ok := request.Context().Value(AgentIDCtxKey).(uuid.UUID)
if !ok {
return "", errors.New("internal error: agent ID not set in context")
}
agentName, found := h.getAgentName(agentID)
if !found {
return "", NewErrAgentIdentifierUnknown(agentID)
}
return agentName, nil
}
func (h *runtimeLogsHandler) getAgentName(agentID uuid.UUID) (string, bool) {
if agent, found := h.registrationService.FindExternalAgentByID(agentID); found {
return agent.Name, true
} else if agent, found := h.registrationService.FindInternalAgentByID(agentID); found {
return agent.Name, true
} else {
return "", false
}
}
func (h *runtimeLogsHandler) getBody(writer http.ResponseWriter, request *http.Request) ([]byte, error) {
body, err := io.ReadAll(request.Body)
if err != nil {
return nil, fmt.Errorf("Failed to read error body: %s", err)
}
return body, nil
}
// NewRuntimeTelemetrySubscriptionHandler returns a new instance of http handler
// for serving /runtime/logs
func NewRuntimeTelemetrySubscriptionHandler(registrationService core.RegistrationService, telemetrySubscription telemetry.SubscriptionAPI) http.Handler {
return &runtimeLogsHandler{
registrationService: registrationService,
telemetrySubscription: telemetrySubscription,
}
}