Skip to content

Commit 758f26c

Browse files
authored
[enhancement] add couple missing zapcore types (#18)
1 parent ff4dcb1 commit 758f26c

File tree

6 files changed

+146
-13
lines changed

6 files changed

+146
-13
lines changed

.github/workflows/test.yml

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: Run Tests
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
tags:
9+
- v*
10+
11+
pull_request:
12+
13+
workflow_dispatch:
14+
15+
jobs:
16+
test-projects:
17+
strategy:
18+
matrix:
19+
project: ["otelslog", "otelzap", "otelzerolog"]
20+
runs-on: ubuntu-latest
21+
defaults:
22+
run:
23+
working-directory: ${{ matrix.project }}
24+
steps:
25+
- name: Checkout
26+
uses: actions/checkout@v4
27+
28+
- name: Setup Golang with cache
29+
id: golang-with-cache
30+
uses: magnetikonline/action-golang-cache@v5
31+
with:
32+
go-version-file: ${{ matrix.project }}/go.mod
33+
34+
- name: Set up gotestfmt
35+
run: go install github.com/gotesttools/gotestfmt/v2/cmd/gotestfmt@v2.5.0
36+
37+
- name: Run tests
38+
run: |
39+
set -euo pipefail
40+
go test -json -v ./... 2>&1 | gotestfmt -hide empty-packages

otelslog/otel_handler_test.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@ package otelslog
33
import (
44
"bytes"
55
"context"
6+
"log/slog"
7+
"os"
8+
"testing"
9+
610
"github.com/agoda-com/opentelemetry-logs-go/exporters/stdout/stdoutlogs"
711
"github.com/stretchr/testify/assert"
8-
"log/slog"
912

1013
sdk "github.com/agoda-com/opentelemetry-logs-go/sdk/logs"
1114
"go.opentelemetry.io/otel/sdk/resource"
1215
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
13-
"os"
14-
"testing"
1516
)
1617

1718
// configure common attributes for all logs
@@ -42,7 +43,7 @@ func TestNewOtelHandler(t *testing.T) {
4243
)
4344

4445
handler := NewOtelHandler(loggerProvider, &HandlerOptions{
45-
level: slog.LevelInfo,
46+
Level: slog.LevelInfo,
4647
}).
4748
WithAttrs([]slog.Attr{slog.String("first", "value1")}).
4849
WithGroup("group1").
@@ -58,5 +59,6 @@ func TestNewOtelHandler(t *testing.T) {
5859

5960
actual := buf.String()
6061

61-
assert.Contains(t, actual, "INFO hello slog [scopeInfo: github.com/agoda-com/otelslog:0.0.1] {host.name=CLX4NV72V6, service.name=otelslog-example, service.version=1.0.0, first=value1, group1.second=value2, group1.group2.myKey=myValue}")
62+
assert.Contains(t, actual, "INFO hello slog [scopeInfo: github.com/agoda-com/otelslog:0.0.1] {host.name=")
63+
assert.Contains(t, actual, "service.name=otelslog-example, service.version=1.0.0, first=value1, group1.second=value2, group1.group2.myKey=myValue}")
6264
}

otelzap/conv.go

+27-1
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,16 @@ limitations under the License.
1717
package otelzap
1818

1919
import (
20+
"encoding/base64"
21+
"fmt"
22+
"math"
23+
"reflect"
24+
"time"
25+
2026
otel "github.com/agoda-com/opentelemetry-logs-go/logs"
2127
"go.opentelemetry.io/otel/attribute"
2228
semconv "go.opentelemetry.io/otel/semconv/v1.20.0"
2329
"go.uber.org/zap/zapcore"
24-
"math"
2530
)
2631

2732
// otelLevel zap level to otlp level converter
@@ -82,6 +87,27 @@ func otelAttribute(f zapcore.Field) []attribute.KeyValue {
8287
return []attribute.KeyValue{}
8388
case zapcore.SkipType:
8489
return []attribute.KeyValue{}
90+
case zapcore.BinaryType:
91+
return []attribute.KeyValue{attribute.String(f.Key, base64.StdEncoding.EncodeToString(f.Interface.([]byte)))}
92+
case zapcore.ByteStringType:
93+
return []attribute.KeyValue{attribute.String(f.Key, string(f.Interface.([]byte)))}
94+
case zapcore.DurationType:
95+
return []attribute.KeyValue{attribute.Float64(f.Key, float64(f.Integer)/float64(time.Second))}
96+
case zapcore.TimeType:
97+
if f.Interface != nil {
98+
return []attribute.KeyValue{attribute.Int64(f.Key, time.Unix(0, f.Integer).In(f.Interface.(*time.Location)).Unix())}
99+
}
100+
return []attribute.KeyValue{attribute.Int64(f.Key, time.Unix(0, f.Integer).Unix())} // Fall back to UTC if location is nil.
101+
case zapcore.TimeFullType:
102+
return []attribute.KeyValue{attribute.Int64(f.Key, f.Interface.(time.Time).Unix())}
103+
case zapcore.StringerType:
104+
if stinger, ok := f.Interface.(fmt.Stringer); ok {
105+
return []attribute.KeyValue{attribute.Stringer(f.Key, stinger)}
106+
}
107+
if v := reflect.ValueOf(f.Interface); v.Kind() == reflect.Ptr && v.IsNil() {
108+
return []attribute.KeyValue{attribute.String(f.Key, "<nil>")}
109+
}
110+
return []attribute.KeyValue{}
85111
}
86112
// unhandled types will be treated as string
87113
return []attribute.KeyValue{attribute.String(f.Key, f.String)}

otelzap/conv_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package otelzap
2+
3+
import (
4+
"bytes"
5+
"errors"
6+
"fmt"
7+
"testing"
8+
"time"
9+
10+
"github.com/stretchr/testify/assert"
11+
"go.opentelemetry.io/otel/attribute"
12+
semconv "go.opentelemetry.io/otel/semconv/v1.20.0"
13+
"go.uber.org/zap"
14+
"go.uber.org/zap/zapcore"
15+
)
16+
17+
var (
18+
testFieldKey = "test-123"
19+
testNow = time.Now()
20+
)
21+
22+
func TestOTeLAttributeMapping(t *testing.T) {
23+
tests := []struct {
24+
Input zapcore.Field
25+
Expected []attribute.KeyValue
26+
}{
27+
{Input: zap.Bool(testFieldKey, true), Expected: []attribute.KeyValue{attribute.Bool(testFieldKey, true)}},
28+
{Input: zap.Float64(testFieldKey, 123.123), Expected: []attribute.KeyValue{attribute.Float64(testFieldKey, 123.123)}},
29+
{Input: zap.Int(testFieldKey, 123), Expected: []attribute.KeyValue{attribute.Int64(testFieldKey, 123)}},
30+
{Input: zap.String(testFieldKey, "hello"), Expected: []attribute.KeyValue{attribute.String(testFieldKey, "hello")}},
31+
{Input: zap.ByteString(testFieldKey, []byte("hello")), Expected: []attribute.KeyValue{attribute.String(testFieldKey, "hello")}},
32+
{Input: zap.Binary(testFieldKey, []byte{1, 0, 0, 1}), Expected: []attribute.KeyValue{attribute.String(testFieldKey, "AQAAAQ==")}},
33+
{Input: zap.Duration(testFieldKey, time.Minute), Expected: []attribute.KeyValue{attribute.Float64(testFieldKey, time.Minute.Seconds())}},
34+
{Input: zap.Time(testFieldKey, testNow), Expected: []attribute.KeyValue{attribute.Int64(testFieldKey, testNow.Unix())}},
35+
{Input: zap.Stringer(testFieldKey, bytes.NewBuffer([]byte("hello"))), Expected: []attribute.KeyValue{attribute.String(testFieldKey, "hello")}},
36+
{Input: zap.Error(errors.New("world")), Expected: []attribute.KeyValue{semconv.ExceptionMessage("world")}},
37+
{Input: zap.Skip(), Expected: []attribute.KeyValue{}},
38+
}
39+
40+
for _, test := range tests {
41+
t.Run(fmt.Sprintf("%+v", test.Input), func(t *testing.T) {
42+
output := otelAttribute(test.Input)
43+
assert.ElementsMatch(t, test.Expected, output)
44+
})
45+
}
46+
}

otelzap/go.mod

+4
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,20 @@ go 1.20
44

55
require (
66
github.com/agoda-com/opentelemetry-logs-go v0.3.0
7+
github.com/stretchr/testify v1.8.4
78
go.opentelemetry.io/otel v1.18.0
89
go.opentelemetry.io/otel/sdk v1.18.0
910
go.opentelemetry.io/otel/trace v1.18.0
1011
go.uber.org/zap v1.26.0
1112
)
1213

1314
require (
15+
github.com/davecgh/go-spew v1.1.1 // indirect
1416
github.com/go-logr/logr v1.2.4 // indirect
1517
github.com/go-logr/stdr v1.2.2 // indirect
18+
github.com/pmezard/go-difflib v1.0.0 // indirect
1619
go.opentelemetry.io/otel/metric v1.18.0 // indirect
1720
go.uber.org/multierr v1.10.0 // indirect
1821
golang.org/x/sys v0.12.0 // indirect
22+
gopkg.in/yaml.v3 v3.0.1 // indirect
1923
)

otelzap/go.sum

+22-7
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,33 @@
1-
github.com/agoda-com/opentelemetry-logs-go v0.2.0/go.mod h1:bjUiOkH82zqgjLmxk0v9axmV5b9Ty+1qlixsrAMTLwQ=
1+
github.com/agoda-com/opentelemetry-logs-go v0.3.0 h1:d2lMVUfCDeLzVgTxMeSU8IWaMXjwD4sVKigEZBGwcsw=
22
github.com/agoda-com/opentelemetry-logs-go v0.3.0/go.mod h1:k3QR1O5AOl+dFC7pkrK9wWmoD72jjDONPFHi9dAgLJc=
3+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
4+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
35
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
6+
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
47
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
8+
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
59
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
6-
go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0=
10+
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
11+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
12+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
13+
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
14+
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
15+
go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs=
716
go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI=
8-
go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o=
17+
go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ=
918
go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k=
10-
go.opentelemetry.io/otel/sdk v1.17.0/go.mod h1:U87sE0f5vQB7hwUoW98pW5Rz4ZDuCFBZFNUBlSgmDFQ=
19+
go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY=
1120
go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M=
12-
go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY=
21+
go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10=
1322
go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0=
23+
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
24+
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
1425
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
15-
go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
26+
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
1627
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
17-
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
28+
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
1829
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
30+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
31+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
32+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
33+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0 commit comments

Comments
 (0)