【问题标题】:Google Stackdriver log entry record field logging.googleapis.com/severity vs severityGoogle Stackdriver 日志条目记录字段 logging.googleapis.com/severity 与严重性
【发布时间】:2022-07-03 16:30:04
【问题描述】:

我有一个通用日志包,用于包装 Stackdriver 的日志 - 获取上下文、严重性等并将其转换为 LogEntry 即:

func Log(ctx context.Context, severity Severity, format string, a ...interface{}) {
    log.Println(Entry{Severity: severity, Message: fmt.Sprintf(format, a...), Component: "arbitrary-property", Trace: GetTraceId(ctx)})
}

入口结构看起来像这样

type Entry struct {
    Message  string   `json:"message"`
    Severity Severity `json:"severity,omitempty"`
    Trace    string   `json:"logging.googleapis.com/trace,omitempty"`

    // Logs Explorer allows filtering and display of this as `jsonPayload.component`.
    Component string `json:"component,omitempty"`
}

这个包是全球性的,用于 Cloud Run 和 Compute Engine 中的多项服务。

Compute Engine 中的日志使用Google Ops Agent 提取 如果我希望日志严重性与操作代理一起使用,我需要根据文档使用此 json 密钥 logging.googleapis.com/severityhttps://cloud.google.com/stackdriver/docs/solutions/agents/ops-agent/configuration#special-fields 否则,严重性仍然是jsonPayload 的一部分,并且严重性不适用于日志条目。 但这与这里的文档冲突:https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry 这里它说 json 字段应该是简单的 severity 没有前缀 logging.googleapis.com/。 如果我使用这个结构

type Entry struct {
    ...
    Severity Severity `json:"severity,omitempty"`
}

如果我使用这个结构,它不能与 Ops Agent 一起工作

type Entry struct {
    ...
    Severity Severity `json:"logging.googleapis.com/severity,omitempty"`
}

它适用于 Ops Agent,但不适用于 Cloud Run(我只是将 logging.googleapis.com/severity 视为 jsonPayload 的一部分,严重性不适用)。 这是预期的行为吗?有没有不创建两个包的解决方法?

【问题讨论】:

    标签: go stackdriver google-cloud-ops-agent


    【解决方案1】:

    这是预期的行为。对于这种特殊情况没有解决方法,因此您需要构建两个包。

    在 Cloud Run 中,您可以阅读 here 关于消息中的特殊 JSON 字段,当您将结构化日志作为 JSON 字典提供时,一些特殊字段会从 jsonPayload 中剥离并写入相应字段生成的LogEntry,如special fields 的文档中所述。

    例如,如果您的 JSON 包含 severity 属性,它会从 jsonPayload 中删除,并显示为日志条目的 severitymessage 属性用作日志条目的主要显示文本(如果存在)。有关特殊属性的更多信息,请阅读Logging Resource 部分。

    【讨论】:

    • 这个答案有用吗?
    • No.. 写两个包不是一个合适的解决方案,因为我有一种情况,我在两个不同的项目中拥有相同的服务(代码),一个开发和一个生产,开发在云上运行,在计算引擎上生产
    【解决方案2】:

    我最终写了两个结构并使用fmt.Stringer 只写了一个日志函数。这对 IMO 来说很糟糕,因为它需要处理两个结构(即,您将字段添加到一个,您还需要记住添加到第二个),但我找不到更好的。在我看来,这像是 GCP 中的某种错误,我猜它是由两个不同的团队编写的,否则我看不出有什么理由不使用相同的 json 字段名称。

    var useOpsAgent bool
    
    func SetUseOpsAgent(v bool) {
        useOpsAgent = v
    }
    
    // for cloud run
    type Entry struct {
        Message  string            `json:"message"`
        Severity Severity          `json:"severity,omitempty"`
        Trace    string            `json:"logging.googleapis.com/trace,omitempty"`
        Component string `json:"component,omitempty"`
    }
    
    // for compute engine
    type EntryOA struct {
        Message   string            `json:"message"`
        Severity  Severity          `json:"logging.googleapis.com/severity,omitempty"`
        Trace     string            `json:"logging.googleapis.com/trace,omitempty"`
        Component string            `json:"component,omitempty"`
    }
    
    func Log(ctx context.Context, severity Severity, format string, a ...interface{}) {
        var logEntry fmt.Stringer = Entry{Severity: severity, Message: fmt.Sprintf(format, a...), Component: "arbitrary-property", Trace: GetTraceId(ctx)}
        if useOpsAgent {
            logEntry = EntryOA{Severity: severity, Message: fmt.Sprintf(format, a...), Component: "arbitrary-property", Trace: GetTraceId(ctx)}
        }
        log.Println(logEntry)
    }
    

    然后在main.go中使用时:

    func init() {
        loglib.SetUseOpsAgent(true)
    }
    

    【讨论】:

      猜你喜欢
      • 2019-07-26
      • 2018-06-13
      • 2022-10-20
      • 1970-01-01
      • 2018-08-23
      • 2020-11-10
      • 1970-01-01
      • 2019-10-01
      • 2018-12-24
      相关资源
      最近更新 更多