Skip to content

Commit 0efcbb5

Browse files
authored
Handle both object and string LogEventRecord types in json Unmarshal (#58)
* Handle both object and string LogEventRecord types in json Unmarshal * Fix test names * Change test name again * Update go.mod and go.sum * Use index to iterate instead * Improve error handling * Add test checking for error * Don't add the log event to the channel if error when unmarshalling record * Move function lower in file * Fix go mod and sum
1 parent 63afa0a commit 0efcbb5

File tree

6 files changed

+111
-7
lines changed

6 files changed

+111
-7
lines changed

apm-lambda-extension/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ go 1.14
55
require (
66
github.com/google/go-cmp v0.5.6 // indirect
77
github.com/pkg/errors v0.9.1
8+
github.com/stretchr/testify v1.7.0
89
gotest.tools v2.2.0+incompatible
910
)

apm-lambda-extension/go.sum

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,19 @@
1+
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
2+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
13
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
24
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
35
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
46
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
7+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
8+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
9+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
10+
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
11+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
512
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
613
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
14+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
15+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
16+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
17+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
718
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
819
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=

apm-lambda-extension/logsapi/client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ type SubEventType string
6161
const (
6262
// RuntimeDone event is sent when lambda function is finished it's execution
6363
RuntimeDone SubEventType = "platform.runtimeDone"
64+
Fault SubEventType = "platform.fault"
6465
)
6566

6667
// BufferingCfg is the configuration set for receiving logs from Logs API. Whichever of the conditions below is met first, the logs will be sent

apm-lambda-extension/logsapi/http_listener.go

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,15 @@ import (
2525
"net/http"
2626
"os"
2727
"time"
28+
29+
"github.com/pkg/errors"
2830
)
2931

3032
type LogEvent struct {
31-
Time time.Time `json:"time"`
32-
Type string `json:"type"`
33-
Record LogEventRecord `json:"record"`
33+
Time time.Time `json:"time"`
34+
Type string `json:"type"`
35+
RawRecord json.RawMessage `json:"record"`
36+
Record LogEventRecord
3437
}
3538

3639
type LogEventRecord struct {
@@ -101,10 +104,27 @@ func (h *LogsAPIHttpListener) http_handler(w http.ResponseWriter, r *http.Reques
101104
if err != nil {
102105
log.Println("error unmarshaling log event:", err)
103106
}
104-
// Send the log events to the channel
105-
for _, logEvent := range logEvents {
106-
h.logChannel <- logEvent
107+
108+
for idx := range logEvents {
109+
err = logEvents[idx].unmarshalRecord()
110+
if err != nil {
111+
log.Printf("Error unmarshalling log event: %+v", err)
112+
continue
113+
}
114+
h.logChannel <- logEvents[idx]
115+
}
116+
}
117+
118+
func (le *LogEvent) unmarshalRecord() error {
119+
if SubEventType(le.Type) != Fault {
120+
record := LogEventRecord{}
121+
err := json.Unmarshal([]byte(le.RawRecord), &record)
122+
if err != nil {
123+
return errors.New("Could not unmarshal log event raw record into record")
124+
}
125+
le.Record = record
107126
}
127+
return nil
108128
}
109129

110130
func (s *LogsAPIHttpListener) Shutdown() {

apm-lambda-extension/logsapi/http_listener_test.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@
1818
package logsapi
1919

2020
import (
21+
"encoding/json"
2122
"os"
2223
"testing"
24+
25+
"github.com/stretchr/testify/assert"
2326
)
2427

2528
func TestListenOnAddressWithEnvVariable(t *testing.T) {
@@ -44,3 +47,71 @@ func TestListenOnAddressDefault(t *testing.T) {
4447
t.Fail()
4548
}
4649
}
50+
51+
func Test_unmarshalRuntimeDoneRecordObject(t *testing.T) {
52+
jsonBytes := []byte(`
53+
{
54+
"time": "2021-10-20T08:13:03.278Z",
55+
"type": "platform.runtimeDone",
56+
"record": {
57+
"requestId": "61c0fdeb-f013-4f2a-b627-56278f5666b8"
58+
}
59+
}
60+
`)
61+
62+
var le LogEvent
63+
err := json.Unmarshal(jsonBytes, &le)
64+
if err != nil {
65+
t.Fail()
66+
}
67+
68+
err = le.unmarshalRecord()
69+
if err != nil {
70+
t.Fail()
71+
}
72+
73+
record := LogEventRecord{RequestId: "61c0fdeb-f013-4f2a-b627-56278f5666b8"}
74+
assert.Equal(t, record, le.Record)
75+
}
76+
77+
func Test_unmarshalFaultRecordString(t *testing.T) {
78+
jsonBytes := []byte(`
79+
{
80+
"time": "2021-10-20T08:13:03.278Z",
81+
"type": "platform.fault",
82+
"record": "Unknown application error occurred"
83+
}
84+
`)
85+
86+
var le LogEvent
87+
err := json.Unmarshal(jsonBytes, &le)
88+
if err != nil {
89+
t.Fail()
90+
}
91+
92+
err = le.unmarshalRecord()
93+
if err != nil {
94+
t.Fail()
95+
}
96+
97+
assert.Equal(t, "\"Unknown application error occurred\"", string(le.RawRecord))
98+
}
99+
100+
func Test_unmarshalRecordError(t *testing.T) {
101+
jsonBytes := []byte(`
102+
{
103+
"time": "2021-10-20T08:13:03.278Z",
104+
"type": "platform.runtimeDone",
105+
"record": "Unknown application error occurred"
106+
}
107+
`)
108+
109+
var le LogEvent
110+
err := json.Unmarshal(jsonBytes, &le)
111+
if err != nil {
112+
t.Fail()
113+
}
114+
115+
err = le.unmarshalRecord()
116+
assert.Error(t, err)
117+
}

apm-lambda-extension/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ func main() {
143143
log.Println("Function invocation is complete, not receiving any more log events")
144144
return
145145
case logEvent := <-logsChannel:
146-
log.Printf("Received log event %v\n", logEvent)
146+
log.Printf("Received log event %v\n", logEvent.Type)
147147
// Check the logEvent for runtimeDone and compare the RequestID
148148
// to the id that came in via the Next API
149149
if logsapi.SubEventType(logEvent.Type) == logsapi.RuntimeDone {

0 commit comments

Comments
 (0)