pkg/extensionevents/extension_events.go (99 lines of code) (raw):

// Copyright (c) Microsoft Corporation. // Licensed under the MIT License. package extensionevents import ( "encoding/json" "fmt" "io/ioutil" "os" "path" "strconv" "time" "github.com/Azure/azure-extension-platform/pkg/handlerenv" "github.com/Azure/azure-extension-platform/pkg/logging" ) const ( eventLevelCritical = "Critical" eventLevelError = "Error" eventLevelWarning = "Warning" eventLevelVerbose = "Verbose" eventLevelInformational = "Informational" ) type extensionEvent struct { Version string `json:"Version"` Timestamp string `json:"Timestamp"` TaskName string `json:"TaskName"` EventLevel string `json:"EventLevel"` Message string `json:"Message"` EventPid string `json:"EventPid"` EventTid string `json:"EventTid"` OperationID string `json:"OperationId"` } // ExtensionEventManager allows extensions to log events that will be collected // by the Guest Agent type ExtensionEventManager struct { extensionLogger logging.ILogger eventsFolder string operationID string prefix string } func (eem *ExtensionEventManager) logEvent(taskName string, eventLevel string, message string) { if eem.eventsFolder == "" { eem.extensionLogger.Warn("EventsFolder not set. Not writing event.") return } extensionVersion := os.Getenv("AZURE_GUEST_AGENT_EXTENSION_VERSION") timestamp := time.Now().UTC().Format(time.RFC3339Nano) pid := fmt.Sprintf("%v", os.Getpid()) tid := getThreadID() fullMessage := message if eem.prefix != "" { fullMessage = eem.prefix + message } extensionEvent := extensionEvent{ Version: extensionVersion, Timestamp: timestamp, TaskName: taskName, EventLevel: eventLevel, Message: fullMessage, EventPid: pid, EventTid: tid, OperationID: eem.operationID, } // File name is the unix time in milliseconds fileName := strconv.FormatInt(time.Now().UTC().UnixNano()/1000, 10) filePath := path.Join(eem.eventsFolder, fileName) + ".json" b, err := json.Marshal(extensionEvent) if err != nil { eem.extensionLogger.Error("Unable to serialize extension event: <%v>", err) return } err = ioutil.WriteFile(filePath, b, 0644) if err != nil { eem.extensionLogger.Error("Unable to write event file: <%v>", err) } } // New creates a new instance of the ExtensionEventManager func New(el logging.ILogger, he *handlerenv.HandlerEnvironment) *ExtensionEventManager { eem := &ExtensionEventManager{ extensionLogger: el, eventsFolder: he.EventsFolder, operationID: "", } return eem } // "SetOperationId()" sets operation Id passed by user while logging extension events // This is made as separate function (not included in "logEvent()") to enable users to set Operation ID globally for their extension. // "operationID" corresponds to "Context3" column in 'GuestAgentGenericLogs' table (Rdos cluster) func (eem *ExtensionEventManager) SetOperationID(operationID string) { eem.operationID = operationID } // "SetPrefix()" sets a prefix to use for all messages // The prefix will continue to be used until "SetPrefix()" is called with an empty string func (eem *ExtensionEventManager) SetPrefix(prefix string) { eem.prefix = prefix } // LogCriticalEvent writes a message with critical status for the extension func (eem *ExtensionEventManager) LogCriticalEvent(taskName string, message string) { eem.logEvent(taskName, eventLevelCritical, message) } // LogErrorEvent writes a message with error status for the extension func (eem *ExtensionEventManager) LogErrorEvent(taskName string, message string) { eem.logEvent(taskName, eventLevelError, message) } // LogWarningEvent writes a message with warning status for the extension func (eem *ExtensionEventManager) LogWarningEvent(taskName string, message string) { eem.logEvent(taskName, eventLevelWarning, message) } // LogVerboseEvent writes a message with verbose status for the extension func (eem *ExtensionEventManager) LogVerboseEvent(taskName string, message string) { eem.logEvent(taskName, eventLevelVerbose, message) } // LogInformationalEvent writes a message with informational status for the extension func (eem *ExtensionEventManager) LogInformationalEvent(taskName string, message string) { eem.logEvent(taskName, eventLevelInformational, message) }