From b5555f292484ad450f75b67b8cd72b6d52926cfd Mon Sep 17 00:00:00 2001 From: Gael Stehagen Date: Mon, 3 Jul 2023 14:07:18 +0200 Subject: [PATCH 1/4] Add access to emf map (#1) * Adds Build() to expose the EMF structure externally * bumped go version to 1.20 --- emf/logger.go | 22 +++++++++++++++++++--- emf/logger_test.go | 24 ++++++++++++++++++++++++ go.mod | 2 +- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/emf/logger.go b/emf/logger.go index 22223f4..425b013 100644 --- a/emf/logger.go +++ b/emf/logger.go @@ -195,6 +195,22 @@ func (l *Logger) MetricsFloatAs(m map[string]float64, unit MetricUnit) *Logger { // Log prints all Contexts and metric values to chosen output in Embedded Metric Format. func (l *Logger) Log() { + emf := l.build() + if len(emf) == 0 { + return + } + + buf, _ := json.Marshal(emf) + _, _ = fmt.Fprintln(l.out, string(buf)) +} + +// Build constructs the EMF structure as a map that includes all Contexts and metric values. +// The map is arranged according to Embedded Metric Format. +func (l *Logger) Build() map[string]interface{} { + return l.build() +} + +func (l *Logger) build() map[string]interface{} { var metrics []MetricDirective if len(l.defaultContext.metricDirective.Metrics) > 0 { metrics = append(metrics, l.defaultContext.metricDirective) @@ -206,7 +222,7 @@ func (l *Logger) Log() { } if len(metrics) == 0 { - return + return map[string]interface{}{} } l.values["_aws"] = Metadata{ @@ -214,8 +230,8 @@ func (l *Logger) Log() { Metrics: metrics, LogGroupName: l.logGroupName, } - buf, _ := json.Marshal(l.values) - _, _ = fmt.Fprintln(l.out, string(buf)) + + return l.values } // NewContext creates new context for given logger. diff --git a/emf/logger_test.go b/emf/logger_test.go index b35dd62..204deef 100644 --- a/emf/logger_test.go +++ b/emf/logger_test.go @@ -2,6 +2,7 @@ package emf_test import ( "bytes" + "encoding/json" "io/ioutil" "os" "testing" @@ -225,6 +226,11 @@ func TestEmf(t *testing.T) { } jsonassert.New(t).Assertf(buf.String(), string(f)) + + // test Build() to generate the same structure as Log() + metrics := logger.Build() + metricsJson, _ := json.Marshal(metrics) + jsonassert.New(t).Assertf(string(metricsJson), string(f)) }) } @@ -238,6 +244,14 @@ func TestEmf(t *testing.T) { } }) + t.Run("no metrics set, with build", func(t *testing.T) { + m := emf.New().Build() + + if len(m) > 0 { + t.Error("Map not empty") + } + }) + t.Run("new context, no metrics set", func(t *testing.T) { var buf bytes.Buffer logger := emf.New(emf.WithWriter(&buf)) @@ -248,6 +262,16 @@ func TestEmf(t *testing.T) { t.Error("Buffer not empty") } }) + + t.Run("new context, no metrics set, with build", func(t *testing.T) { + logger := emf.New() + logger.NewContext().Namespace("galaxy") + m := logger.Build() + + if len(m) > 0 { + t.Error("Map not empty") + } + }) } func setenv(t *testing.T, env map[string]string) { diff --git a/go.mod b/go.mod index bb83c80..3610f4d 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ module github.com/prozz/aws-embedded-metrics-golang -go 1.14 +go 1.20 require github.com/kinbiko/jsonassert v1.1.1 From 0b3ef6a51538d8093f80bad8b439e5661bd040b1 Mon Sep 17 00:00:00 2001 From: Gael Stehagen Date: Mon, 3 Jul 2023 14:37:59 +0200 Subject: [PATCH 2/4] Rename of module to separate from original (#2) --- README.md | 31 +++++++++++++++++++++---------- emf/logger_test.go | 2 +- go.mod | 2 +- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 3bd70d8..48cd509 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # aws-embedded-metrics-golang -![test](https://github.com/prozz/aws-embedded-metrics-golang/workflows/test/badge.svg?branch=master) -![golangci-lint](https://github.com/prozz/aws-embedded-metrics-golang/workflows/lint/badge.svg?branch=master) +![test](https://github.com/gaeste/aws-embedded-metrics-golang/workflows/test/badge.svg?branch=master) +![golangci-lint](https://github.com/gaeste/aws-embedded-metrics-golang/workflows/lint/badge.svg?branch=master) -Go implementation of AWS CloudWatch [Embedded Metric Format](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html) +Go implementation of [AWS CloudWatch Embedded Metric Format](https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html). -It's aim is to simplify reporting metrics to CloudWatch: +The aim is to simplify reporting metrics to CloudWatch: - using EMF avoids additional HTTP API calls to CloudWatch as metrics are logged in JSON format to stdout - no need for additional dependencies in your services (or mocks in tests) to report metrics from inside your code @@ -16,7 +16,7 @@ Supports namespaces, setting dimensions and properties as well as different cont ## Installation ```shell -go get github.com/prozz/aws-embedded-metrics-golang +go get github.com/gaeste/aws-embedded-metrics-golang ``` ## Usage @@ -24,13 +24,24 @@ go get github.com/prozz/aws-embedded-metrics-golang ``` emf.New().Namespace("mtg").Metric("totalWins", 1500).Log() -emf.New().Dimension("colour", "red"). - MetricAs("gameLength", 2, emf.Seconds).Log() +emf.New(). + Dimension("colour", "red"). + MetricAs("gameLength", 2, emf.Seconds). + Log() -emf.New().DimensionSet( +emf.New(). + DimensionSet( emf.NewDimension("format", "edh"), - emf.NewDimension("commander", "Muldrotha")). - MetricAs("wins", 1499, emf.Count).Log() + emf.NewDimension("commander", "Muldrotha") + ). + MetricAs("wins", 1499, emf.Count). + Log() + +metrics := emf.New(). + Namespace("mtg"). + Metric("totalWins", 1500). + Build() +log.With(metrics).Info("log message with metrics attached as named value pair") ``` You may also use the lib together with `defer`. diff --git a/emf/logger_test.go b/emf/logger_test.go index 204deef..c77da5d 100644 --- a/emf/logger_test.go +++ b/emf/logger_test.go @@ -7,8 +7,8 @@ import ( "os" "testing" + "github.com/gaeste/aws-embedded-metrics-golang/emf" "github.com/kinbiko/jsonassert" - "github.com/prozz/aws-embedded-metrics-golang/emf" ) func TestEmf(t *testing.T) { diff --git a/go.mod b/go.mod index 3610f4d..f4bb0ec 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/prozz/aws-embedded-metrics-golang +module github.com/gaeste/aws-embedded-metrics-golang go 1.20 From 0965e1e74beae6c5f9b42f0fa4ffdfb305d9946b Mon Sep 17 00:00:00 2001 From: Gael Stehagen Date: Mon, 3 Jul 2023 14:58:59 +0200 Subject: [PATCH 3/4] Update pipeline actions (#3) * Update pipeline actions * go 1.20 update --- .github/workflows/test.yml | 7 ++++--- emf/logger_test.go | 3 +-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 26ca9e4..b71ee72 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,12 +12,13 @@ jobs: runs-on: ubuntu-latest steps: - name: set up Go 1.x - uses: actions/setup-go@v2 + uses: actions/setup-go@v4 with: - go-version: ^1.14 + go-version: '1.20' + check-latest: true id: go - name: checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: modules run: go mod download - name: test diff --git a/emf/logger_test.go b/emf/logger_test.go index c77da5d..3340cb3 100644 --- a/emf/logger_test.go +++ b/emf/logger_test.go @@ -3,7 +3,6 @@ package emf_test import ( "bytes" "encoding/json" - "io/ioutil" "os" "testing" @@ -220,7 +219,7 @@ func TestEmf(t *testing.T) { logger.Log() println(buf.String()) - f, err := ioutil.ReadFile(tc.expected) + f, err := os.ReadFile(tc.expected) if err != nil { t.Fatal("unable to read file with expected json") } From 64c6088115ae2b5357b98e655574fe75bdcc60f3 Mon Sep 17 00:00:00 2001 From: Gael Stehagen Date: Mon, 3 Jul 2023 15:33:00 +0200 Subject: [PATCH 4/4] Build actions (#4) * Update pipeline actions * go 1.20 update