/
eventdata.go
107 lines (91 loc) · 3.15 KB
/
eventdata.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
/*
Copyright 2017 Heptio Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package sinks
import (
"encoding/json"
"fmt"
"io"
"github.com/crewjam/rfc5424"
jsoniter "github.com/json-iterator/go"
"github.com/json-iterator/go/extra"
v1 "k8s.io/api/core/v1"
"github.com/nytlabs/gojsonexplode"
)
// EventData encodes an eventrouter event and previous event, with a verb for
// whether the event is created or updated.
type EventData struct {
Verb string `json:"verb"`
Event *v1.Event `json:"event"`
OldEvent *v1.Event `json:"old_event,omitempty"`
}
// NewEventData constructs an EventData struct from an old and new event,
// setting the verb accordingly
func NewEventData(eNew *v1.Event, eOld *v1.Event) EventData {
var eData EventData
if eOld == nil {
eData = EventData{
Verb: "ADDED",
Event: eNew,
}
} else {
eData = EventData{
Verb: "UPDATED",
Event: eNew,
OldEvent: eOld,
}
}
return eData
}
// WriteRFC5424 writes the current event data to the given io.Writer using
// RFC5424 (syslog over TCP) syntax.
func (e *EventData) WriteRFC5424(w io.Writer) (int64, error) {
var eJSONBytes []byte
var err error
if eJSONBytes, err = json.Marshal(e); err != nil {
return 0, fmt.Errorf("failed to json serialize event: %v", err)
}
// Each message should look like an RFC5424 syslog message:
// <NumberOfBytes/ASCII encoded integer><Space character><RFC5424 message:NumberOfBytes long>
//
// Note: There are some restrictions on length and character space for
// Hostname and AppName, see
// https://github.com/crewjam/rfc5424/blob/master/marshal.go#L90. There's no
// attempt at trying to clean them up here because hostnames and component
// names already adhere to this convention in practice.
msg := rfc5424.Message{
Priority: rfc5424.Daemon,
Timestamp: e.Event.LastTimestamp.Time,
Hostname: e.Event.Source.Host,
AppName: e.Event.Source.Component,
Message: eJSONBytes,
}
return msg.WriteTo(w)
}
// WriteFlattenedJSON writes the json to the file in the below format
// 1) Flattens the json into a not nested key:value
// 2) Convert the json into snake format
// Eg: {"event_involved_object_kind":"pod", "event_metadata_namespace":"kube-system"}
func (e *EventData) WriteFlattenedJSON(w io.Writer) (int64, error) {
var eJSONBytes []byte
var err error
extra.SetNamingStrategy(extra.LowerCaseWithUnderscores)
if eJSONBytes, err = jsoniter.Marshal(e); err != nil {
return 0, fmt.Errorf("failed to json serialize event: %v", err)
}
result, err := gojsonexplode.Explodejsonstr(string(eJSONBytes), "_")
if err != nil {
return 0, fmt.Errorf("failed to flatten json: %v", err)
}
written, err := w.Write([]byte(result))
return int64(written), err
}