如何提取钩子中的zerolog事件字段

问题描述 投票:0回答:1

我编写了一个用于将 Azure 应用程序见解与 Zerolog 集成的代码,我不确定的一件事是如何获取挂钩函数内的事件字段,以便我可以将数据字段发布到 Azure 应用程序见解自定义属性字段中或者在那里任何其他更清洁的方法来实现这一目标。

有人认为 Zerolog 应该公开一个函数来获取字段吗?

package zeroappinsights

import (
    "context"
    "encoding/json"
    "github.com/gin-gonic/gin"
    "net/http"
    "os"
    "time"

    "github.com/microsoft/ApplicationInsights-Go/appinsights"
    "github.com/microsoft/ApplicationInsights-Go/appinsights/contracts"
    "github.com/rs/zerolog"
    "github.com/rs/zerolog/log"

    "github.com/org/package/constants"
    "github.com/org/package/models"
)

var levelMap = map[zerolog.Level]contracts.SeverityLevel{
    zerolog.ErrorLevel: contracts.Error,
    zerolog.InfoLevel:  contracts.Information,
    zerolog.DebugLevel: contracts.Verbose,
    zerolog.FatalLevel: contracts.Critical,
    zerolog.WarnLevel:  contracts.Warning,
}

var appInsightsProperties = []string{
    contracts.OperationId,
    contracts.OperationParentId,
    contracts.UserId,
    contracts.SessionId,
}

type TracingHook struct {
    env             constants.Environment
    telemetryClient appinsights.TelemetryClient
    file            *os.File
    eventsMap       map[string]string
}

func NewAITracing(serviceName, instrumentationKey string, env constants.Environment, eventsMap map[string]string) *TracingHook {
    client := appinsights.NewTelemetryClient(instrumentationKey)
    client.Context().Tags.Cloud().SetRole(serviceName)
    if env.IsLocal() {
        file, err := os.OpenFile(serviceName+".log", os.O_CREATE, 0644)
        if err != nil {
            return nil
        }

        return &TracingHook{
            telemetryClient: client,
            file:            file,
            env:             constants.Local,
        }
    }
    return &TracingHook{
        telemetryClient: client,
        file:            nil,
        env:             env,
        eventsMap:       eventsMap,
    }
}

func (h *TracingHook) Run(e *zerolog.Event, level zerolog.Level, msg string) {
    ctx := e.GetCtx()
    if appinsightsLevel, ok := levelMap[level]; ok {
        trace := appinsights.NewTraceTelemetry(msg, appinsightsLevel)
        for _, property := range appInsightsProperties {
            trace.Tags[property] = ctx.Value(property).(string)
        } 
        //I want to add more properties from the event to trace.Properties
        trace.Timestamp = time.Now().UTC()
        if h.env.IsLocal() {
            // Marshal the request into a JSON byte slice
            traceJSON, err := json.Marshal(trace)
            if err != nil {
                log.Printf("error marshaling request: %v", err)
                return
            }
            if _, err = h.file.Write(append(traceJSON, '\n')); err != nil {
                log.Printf("error occurred while writing to file: %v", err)
                return
            }
        } else {
            go h.telemetryClient.Track(trace)
        }
    }

}

func (h *TracingHook) LoggingMiddleware(logger zerolog.Logger) func(c *gin.Context) {
    return func(c *gin.Context) {
        startTime := time.Now().UTC()
        telemetry := appinsights.NewEventTelemetry(h.eventsMap[c.Request.URL.Path])
        h.telemetryClient.Track(telemetry)
        operationID := telemetry.Tags[contracts.OperationId]
        operationParentID := telemetry.Tags[contracts.OperationParentId]
        userID := telemetry.Tags[contracts.UserId]
        sessionID := telemetry.Tags[contracts.SessionId]

        if value, exists := c.Get("userProfile"); exists {
            profile := value.(models.UserProfile)
            userID = profile.ID
            sessionID = c.Request.Header.Get(constants.Session)
        }

        values := []string{operationID, operationParentID, userID, sessionID}

        ctx := c.Request.Context()
        for i, key := range appInsightsProperties {
            ctx = context.WithValue(ctx, key, values[i])
        }
        loggerContext := logger.WithContext(ctx)
        c.Set("loggerCtx", loggerContext)
        c.Next()

        duration := time.Since(startTime)
        request := appinsights.NewRequestTelemetry(c.Request.Method, c.Request.URL.Path, duration, http.StatusText(c.Writer.Status()))
        request.Timestamp = time.Now().UTC()
        tags := request.Tags
        tags[contracts.OperationId] = operationID
        tags[contracts.OperationParentId] = operationParentID
        tags[contracts.UserId] = userID
        tags[contracts.SessionId] = sessionID
        request.Tags = tags

        if h.env.IsLocal() {
            // Marshal the request into a JSON byte slice
            requestJSON, err := json.Marshal(request)
            if err != nil {
                log.Printf("error marshaling request: %v", err)
                return
            }
            if _, err = h.file.Write(append(requestJSON, '\n')); err != nil {
                log.Printf("error occurred while writing to file: %v", err)
                return
            }
            return
        }
        h.telemetryClient.Track(request)
    }
}

azure go azure-application-insights distributed-tracing zerolog
1个回答
0
投票

下面您可以看到挂钩函数,该函数从

Zerolog
事件中提取相关信息并将其添加到 Application Insights 遥测属性中。

  • 将 Azure Application Insights 与 Zerolog 集成并捕获自定义属性

代码:

package zeroappinsights

import (
    "context"
    "encoding/json"
    "net/http"
    "os"
    "time"

    "github.com/gin-gonic/gin"
    "github.com/microsoft/ApplicationInsights-Go/appinsights"
    "github.com/microsoft/ApplicationInsights-Go/appinsights/contracts"
    "github.com/rs/zerolog"
    "github.com/rs/zerolog/log"

    "github.com/org/package/constants"
    "github.com/org/package/models"
)

var levelMap = map[zerolog.Level]contracts.SeverityLevel{
    zerolog.ErrorLevel: contracts.Error,
    zerolog.InfoLevel:  contracts.Information,
    zerolog.DebugLevel: contracts.Verbose,
    zerolog.FatalLevel: contracts.Critical,
    zerolog.WarnLevel:  contracts.Warning,
}

var appInsightsProperties = []string{
    contracts.OperationId,
    contracts.OperationParentId,
    contracts.UserId,
    contracts.SessionId,
}

// ApplicationInsightsHook is a Zerolog hook that sends log entries to Application Insights
type ApplicationInsightsHook struct {
    client appinsights.TelemetryClient
}

// NewApplicationInsightsHook creates a new ApplicationInsightsHook
func NewApplicationInsightsHook(instrumentationKey string) *ApplicationInsightsHook {
    client := appinsights.NewTelemetryClient(instrumentationKey)
    return &ApplicationInsightsHook{client: client}
}

// Fire is called when a log event is fired.
func (hook *ApplicationInsightsHook) Fire(e *zerolog.Event) error {
    severity, ok := levelMap[e.Level()]
    if !ok {
        severity = contracts.Verbose
    }

    telemetry := appinsights.NewTraceTelemetry(e.Message().String(), severity)

    // Add custom properties
    e.Fields(func(key string, value interface{}) {
        telemetry.Properties[key] = fmt.Sprintf("%v", value)
    })

    // Add predefined properties
    for _, prop := range appInsightsProperties {
        if value, ok := e.Context[prop].(string); ok {
            telemetry.Properties[prop] = value
        }
    }

    hook.client.Track(telemetry)

    return nil
}

// Levels returns the log levels to enable for this hook.
func (hook *ApplicationInsightsHook) Levels() []zerolog.Level {
    return []zerolog.Level{
        zerolog.PanicLevel,
        zerolog.FatalLevel,
        zerolog.ErrorLevel,
        zerolog.WarnLevel,
        zerolog.InfoLevel,
        zerolog.DebugLevel,
    }
}

// SetLogger sets the logger for the hook.
func (hook *ApplicationInsightsHook) SetLogger(logger *zerolog.Logger) {
    *logger = logger.Hook(hook)
}

// Usage:
func main() {
    // Initialize the Application Insights hook
    aiHook := NewApplicationInsightsHook("your-instrumentation-key")

    // Create a Zerolog logger and set the hook
    logger := zerolog.New(os.Stdout).With().Timestamp().Logger()
    aiHook.SetLogger(&logger)

    // Use the logger as usual
    logger.Info().Str("customField", "customValue").Msg("Log message")
}
  • 通过这个

    ApplicationInsightsHook
    结构体被创建并实现
    zerolog.Hook
    接口。

  • 当日志事件触发时,会调用

    Fire
    方法,它从 Zerolog 事件中提取相关信息(包括自定义字段),并将它们添加到 Application Insights 遥测中。

enter image description here

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.