in plugins/inputs/win_eventlog/win_eventlog.go [136:280]
func (w *WinEventLog) Gather(acc telegraf.Accumulator) error {
var err error
if w.subscription == 0 {
w.subscription, err = w.evtSubscribe(w.EventlogName, w.Query)
if err != nil {
return fmt.Errorf("Windows Event Log subscription error: %v", err.Error())
}
}
w.Log.Debug("Subscription handle id:", w.subscription)
loop:
for {
events, err := w.fetchEvents(w.subscription)
if err != nil {
switch {
case err == ERROR_NO_MORE_ITEMS:
break loop
case err != nil:
w.Log.Error("Error getting events:", err.Error())
return err
}
}
for _, event := range events {
// Prepare fields names usage counter
var fieldsUsage = map[string]int{}
tags := map[string]string{}
fields := map[string]interface{}{}
evt := reflect.ValueOf(&event).Elem()
timeStamp := time.Now()
// Walk through all fields of Event struct to process System tags or fields
for i := 0; i < evt.NumField(); i++ {
fieldName := evt.Type().Field(i).Name
fieldType := evt.Field(i).Type().String()
fieldValue := evt.Field(i).Interface()
computedValues := map[string]interface{}{}
switch fieldName {
case "Source":
fieldValue = event.Source.Name
fieldType = reflect.TypeOf(fieldValue).String()
case "Execution":
fieldValue := event.Execution.ProcessID
fieldType = reflect.TypeOf(fieldValue).String()
fieldName = "ProcessID"
// Look up Process Name from pid
if should, _ := w.shouldProcessField("ProcessName"); should {
_, _, processName, err := GetFromSnapProcess(fieldValue)
if err == nil {
computedValues["ProcessName"] = processName
}
}
case "TimeCreated":
fieldValue = event.TimeCreated.SystemTime
fieldType = reflect.TypeOf(fieldValue).String()
if w.TimeStampFromEvent {
timeStamp, err = time.Parse(time.RFC3339Nano, fmt.Sprintf("%v", fieldValue))
if err != nil {
w.Log.Warnf("Error parsing timestamp %q: %v", fieldValue, err)
}
}
case "Correlation":
if should, _ := w.shouldProcessField("ActivityID"); should {
activityID := event.Correlation.ActivityID
if len(activityID) > 0 {
computedValues["ActivityID"] = activityID
}
}
if should, _ := w.shouldProcessField("RelatedActivityID"); should {
relatedActivityID := event.Correlation.RelatedActivityID
if len(relatedActivityID) > 0 {
computedValues["RelatedActivityID"] = relatedActivityID
}
}
case "Security":
computedValues["UserID"] = event.Security.UserID
// Look up UserName and Domain from SID
if should, _ := w.shouldProcessField("UserName"); should {
sid := event.Security.UserID
usid, err := syscall.StringToSid(sid)
if err == nil {
username, domain, _, err := usid.LookupAccount("")
if err == nil {
computedValues["UserName"] = fmt.Sprint(domain, "\\", username)
}
}
}
default:
}
if should, where := w.shouldProcessField(fieldName); should {
if where == "tags" {
strValue := fmt.Sprintf("%v", fieldValue)
if !w.shouldExcludeEmptyField(fieldName, "string", strValue) {
tags[fieldName] = strValue
fieldsUsage[fieldName]++
}
} else if where == "fields" {
if !w.shouldExcludeEmptyField(fieldName, fieldType, fieldValue) {
fields[fieldName] = fieldValue
fieldsUsage[fieldName]++
}
}
}
// Insert computed fields
for computedKey, computedValue := range computedValues {
if should, where := w.shouldProcessField(computedKey); should {
if where == "tags" {
tags[computedKey] = fmt.Sprintf("%v", computedValue)
fieldsUsage[computedKey]++
} else if where == "fields" {
fields[computedKey] = computedValue
fieldsUsage[computedKey]++
}
}
}
}
// Unroll additional XML
var xmlFields []EventField
if w.ProcessUserData {
fieldsUserData, xmlFieldsUsage := UnrollXMLFields(event.UserData.InnerXML, fieldsUsage, w.Separator)
xmlFields = append(xmlFields, fieldsUserData...)
fieldsUsage = xmlFieldsUsage
}
if w.ProcessEventData {
fieldsEventData, xmlFieldsUsage := UnrollXMLFields(event.EventData.InnerXML, fieldsUsage, w.Separator)
xmlFields = append(xmlFields, fieldsEventData...)
fieldsUsage = xmlFieldsUsage
}
uniqueXMLFields := UniqueFieldNames(xmlFields, fieldsUsage, w.Separator)
for _, xmlField := range uniqueXMLFields {
if !w.shouldExclude(xmlField.Name) {
fields[xmlField.Name] = xmlField.Value
}
}
// Pass collected metrics
acc.AddFields("win_eventlog", fields, tags, timeStamp)
}
}
return nil
}