forked from wavefrontHQ/wavefront-lambda-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
reporter.go
131 lines (117 loc) · 4.54 KB
/
reporter.go
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
package wflambda
import (
"context"
"log"
"os"
"strings"
"time"
"github.com/aws/aws-lambda-go/lambdacontext"
"github.com/rcrowley/go-metrics"
"github.com/wavefronthq/go-metrics-wavefront"
)
// Increment counter if report is true
func incrementCounter(counter metrics.Counter, value int64, report bool) {
if report {
counter.Inc(value)
}
}
// Update gauge value if report is true
func updateGaugeFloat64(gauge metrics.GaugeFloat64, value float64, report bool) {
if report {
gauge.Update(value)
}
}
// Register the standard lambda metrics.
func registerStandardLambdaMetrics() {
// Register cold start counter.
csCounter = metrics.NewCounter()
csCounterName := wavefront.DeltaCounterName(getStandardLambdaMetricName("coldstarts", false))
wavefront.RegisterMetric(csCounterName, csCounter, nil)
csEventCounter = metrics.NewCounter()
wavefront.RegisterMetric(getStandardLambdaMetricName("coldstart", true), csEventCounter, nil)
// Register invocations counter.
invocationsCounter = metrics.NewCounter()
invocationsCounterName := wavefront.DeltaCounterName(getStandardLambdaMetricName("invocations", false))
wavefront.RegisterMetric(invocationsCounterName, invocationsCounter, nil)
invocationEventCounter = metrics.NewCounter()
wavefront.RegisterMetric(getStandardLambdaMetricName("invocation", true), invocationEventCounter, nil)
// Register Error counter
errCounter = metrics.NewCounter()
errCounterName := wavefront.DeltaCounterName(getStandardLambdaMetricName("errors", false))
wavefront.RegisterMetric(errCounterName, errCounter, nil)
errEventCounter = metrics.NewCounter()
wavefront.RegisterMetric(getStandardLambdaMetricName("error", true), errEventCounter, nil)
// Register duration gauge
durationGauge = metrics.NewGaugeFloat64()
wavefront.RegisterMetric(getStandardLambdaMetricName("duration", false), durationGauge, nil)
}
// Method to send all metrics in the registry to wavefront.
func reportMetrics(ctx context.Context) {
// Get standard lambda point tags
lc, ok := lambdacontext.FromContext(ctx)
if ok {
invokedFunctionArn := lc.InvokedFunctionArn
splitArn := strings.Split(invokedFunctionArn, ":")
// Expected formats for Lambda ARN are:
// https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html#arn-syntax-lambda
hostTags := map[string]string{
"LambdaArn": invokedFunctionArn,
"source": lambdacontext.FunctionName,
"FunctionName": lambdacontext.FunctionName,
"ExecutedVersion": lambdacontext.FunctionVersion,
"Region": splitArn[3],
"accountId": splitArn[4],
}
if splitArn[5] == "function" {
hostTags["Resource"] = splitArn[6]
if len(splitArn) == 8 {
hostTags["Resource"] += ":" + splitArn[7]
}
} else if splitArn[5] == "event-source-mappings" {
hostTags["EventSourceMappings"] = splitArn[6]
}
err := wavefront.WavefrontOnce(wavefront.WavefrontConfig{
DirectReporter: wavefront.NewDirectReporter(server, authToken),
Registry: metrics.DefaultRegistry,
DurationUnit: time.Nanosecond,
Prefix: "",
HostTags: hostTags,
})
if err != nil {
log.Println("ERROR :: ", err)
}
} else {
log.Println("ERROR :: Couldn't report points to wavefront as retrieving lambdaContext from AWS failed.")
}
}
// Util method that returns the standard lambda metric name.
// Ex:
// getStandardLambdaMetricName("invocation", true) returns "aws.lambda.wf.invocation_event"
// getStandardLambdaMetricName("invocations", false) returns "aws.lambda.wf.invocations"
func getStandardLambdaMetricName(metric string, isEvent bool) string {
const metric_prefix string = "aws.lambda.wf."
const metric_event_suffix string = "_event"
if isEvent {
return strings.Join([]string{metric_prefix, metric, metric_event_suffix}, "")
}
return strings.Join([]string{metric_prefix, metric}, "")
}
// Util method to validate the specified environment variables and return if standard lambda Metrics
// should be collected by the wrapper.
func getAndValidateLambdaEnvironment() bool {
// Validate environment variables required by wavefrontLambda wrapper.
server = os.Getenv("WAVEFRONT_URL")
if server == "" {
log.Panicf("Environment variable WAVEFRONT_URL is not set.")
}
authToken = os.Getenv("WAVEFRONT_API_TOKEN")
if authToken == "" {
log.Panicf("Environment variable WAVEFRONT_API_TOKEN is not set.")
}
reportStandardLambdaMetrics := os.Getenv("REPORT_STANDARD_METRICS")
reportStandardMetrics := true
if reportStandardLambdaMetrics == "False" || reportStandardLambdaMetrics == "false" {
reportStandardMetrics = false
}
return reportStandardMetrics
}