forked from elastic/beats
-
Notifications
You must be signed in to change notification settings - Fork 9
/
event.go
187 lines (159 loc) · 5.38 KB
/
event.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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
package sys
import (
"encoding/xml"
"fmt"
"time"
)
// UnmarshalEventXML unmarshals the given XML into a new Event.
func UnmarshalEventXML(rawXML []byte) (Event, error) {
var event Event
err := xml.Unmarshal(rawXML, &event)
return event, err
}
// Event holds the data from a log record.
type Event struct {
// System
Provider Provider `xml:"System>Provider"`
EventIdentifier EventIdentifier `xml:"System>EventID"`
Version uint8 `xml:"System>Version"`
LevelRaw uint8 `xml:"System>Level"`
TaskRaw uint16 `xml:"System>Task"`
OpcodeRaw uint8 `xml:"System>Opcode"`
TimeCreated TimeCreated `xml:"System>TimeCreated"`
RecordID uint64 `xml:"System>EventRecordID"`
Correlation Correlation `xml:"System>Correlation"`
Execution Execution `xml:"System>Execution"`
Channel string `xml:"System>Channel"`
Computer string `xml:"System>Computer"`
User SID `xml:"System>Security"`
EventData EventData `xml:"EventData"`
UserData UserData `xml:"UserData"`
// RenderingInfo
Message string `xml:"RenderingInfo>Message"`
Level string `xml:"RenderingInfo>Level"`
Task string `xml:"RenderingInfo>Task"`
Opcode string `xml:"RenderingInfo>Opcode"`
Keywords []string `xml:"RenderingInfo>Keywords>Keyword"`
// ProcessingErrorData
RenderErrorCode uint32 `xml:"ProcessingErrorData>ErrorCode"`
RenderErrorDataItemName string `xml:"ProcessingErrorData>DataItemName"`
RenderErr string
}
// Provider identifies the provider that logged the event. The Name and GUID
// attributes are included if the provider used an instrumentation manifest to
// define its events; otherwise, the EventSourceName attribute is included if a
// legacy event provider (using the Event Logging API) logged the event.
type Provider struct {
Name string `xml:"Name,attr"`
GUID string `xml:"Guid,attr"`
EventSourceName string `xml:"EventSourceName,attr"`
}
// Correlation contains activity identifiers that consumers can use to group
// related events together.
type Correlation struct {
ActivityID string `xml:"ActivityID,attr"`
RelatedActivityID string `xml:"RelatedActivityID,attr"`
}
// Execution contains information about the process and thread that logged the
// event.
type Execution struct {
ProcessID uint32 `xml:"ProcessID,attr"`
ThreadID uint32 `xml:"ThreadID,attr"`
// Only available for events logged to an event tracing log file (.etl file).
ProcessorID uint32 `xml:"ProcessorID,attr"`
SessionID uint32 `xml:"SessionID,attr"`
KernelTime uint32 `xml:"KernelTime,attr"`
UserTime uint32 `xml:"UserTime,attr"`
ProcessorTime uint32 `xml:"ProcessorTime,attr"`
}
// EventIdentifier is the identifer that the provider uses to identify a
// specific event type.
type EventIdentifier struct {
Qualifiers uint16 `xml:"Qualifiers,attr"`
ID uint32 `xml:",chardata"`
}
// TimeCreated contains the system time of when the event was logged.
type TimeCreated struct {
SystemTime time.Time
}
// UnmarshalXML unmarshals an XML dataTime string.
func (t *TimeCreated) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
attrs := struct {
SystemTime string `xml:"SystemTime,attr"`
RawTime uint64 `xml:"RawTime,attr"`
}{}
err := d.DecodeElement(&attrs, &start)
if err != nil {
return err
}
if attrs.SystemTime != "" {
// This works but XML dateTime is really ISO8601.
t.SystemTime, err = time.Parse(time.RFC3339Nano, attrs.SystemTime)
} else if attrs.RawTime != 0 {
// The units for RawTime are not specified in the documentation. I think
// it is only used in event tracing so this shouldn't be a problem.
err = fmt.Errorf("failed to unmarshal TimeCreated RawTime='%d'", attrs.RawTime)
}
return err
}
// EventData contains the event data. The EventData section is used if the
// message provider template does not contain a UserData section.
type EventData struct {
Pairs []KeyValue `xml:",any"`
}
// UserData contains the event data.
type UserData struct {
Name xml.Name
Pairs []KeyValue
}
// UnmarshalXML unmarshals UserData XML.
func (u *UserData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
// Assume that UserData has the same general key-value structure as
// EventData does.
in := struct {
Pairs []KeyValue `xml:",any"`
}{}
// Read tokens until we find the first StartElement then unmarshal it.
for {
t, err := d.Token()
if err != nil {
return err
}
if se, ok := t.(xml.StartElement); ok {
err = d.DecodeElement(&in, &se)
if err != nil {
return err
}
u.Name = se.Name
u.Pairs = in.Pairs
d.Skip()
break
}
}
return nil
}
// KeyValue is a key value pair of strings.
type KeyValue struct {
Key string
Value string
}
// UnmarshalXML unmarshals an arbitrary XML element into a KeyValue. The key
// becomes the name of the element or value of the Name attribute if it exists.
// The value is the character data contained within the element.
func (kv *KeyValue) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
elem := struct {
XMLName xml.Name
Name string `xml:"Name,attr"`
Value string `xml:",chardata"`
}{}
err := d.DecodeElement(&elem, &start)
if err != nil {
return err
}
kv.Key = elem.XMLName.Local
if elem.Name != "" {
kv.Key = elem.Name
}
kv.Value = elem.Value
return nil
}