Golang中如何实现gcloud函数的Stackdriver结构化日志记录

Golang中如何实现gcloud函数的Stackdriver结构化日志记录 大家好!这是我在这个论坛的第一篇帖子,也是Go语言的新手。

我已经用Go语言开发了一个简单的函数,并将其部署在Google云函数中。它运行良好。 当我向标准输出打印内容时,我可以在Stackdriver的日志查看器中看到一行日志。

因此,我决定记录一个包含所有执行信息(接收到的参数、数据等)的JSON,并向标准输出打印一个包含所有相关信息的简单JSON。 当我在本地环境中向标准输出打印这个JSON时,一切正常。但是当我在云函数中打印相同的JSON时,Stackdriver日志记录的是一个奇怪的JSON。

这是我在控制台打印到标准输出的JSON: “{“ReceivedData”:[{“Key”:“SystemUser”,“Value”:“xxxxx”},“Key”:“password”,“Value”:“sdasdasd”},{“Key”:“Dominio”,“Value”:“abc123”},{“Key”:“NroSerie”,“Value”:“12345”},(…)”

当我在Google云函数中打印相同的JSON时,我在日志查看器中看到的是一个不同的JSON,包含许多奇怪的字段: “{“fields”:{“ReceivedData”:{“Kind”:{“ListValue”:{“values”:[{“Kind”:{“StructValue”:{“fields”:{“Key”:{“Kind”:{“StringValue”:“Velocidad”}},“Value”:{“Kind”:{(…)”

这是我代码的一部分。欢迎任何帮助!!

type Pair struct {
    Key   string `json:key`
    Value string `json:value`
}
type DataToLog struct {
    ReceivedData   []Pair `json:DataFromGet`
    ServerResponse string `json:ServerResponse`
    ServerData     string `json:ServerData`
    RemoteIP       string `json:RemoteIP`
    DataToQMT      DataToSend
}
func RequestHandler(w http.ResponseWriter, r *http.Request) {

    var log DataToLog

    (.. code that fills the struct...)

    byteArrayLog, _ := json.Marshal(log)
    fmt.Println(string(byteArrayLog))
}

谢谢


更多关于Golang中如何实现gcloud函数的Stackdriver结构化日志记录的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

嘿,我也遇到了同样的问题。你找到解决方案了吗?

更多关于Golang中如何实现gcloud函数的Stackdriver结构化日志记录的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


问题在于Google Cloud Functions的日志处理机制。当您直接打印JSON字符串时,Stackdriver会将其解析为结构化日志,但云函数的运行时环境会对日志进行额外的包装处理。

以下是正确的实现方式:

package main

import (
	"encoding/json"
	"fmt"
	"net/http"
)

type Pair struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}

type DataToLog struct {
	ReceivedData   []Pair `json:"DataFromGet"`
	ServerResponse string `json:"ServerResponse"`
	ServerData     string `json:"ServerData"`
	RemoteIP       string `json:"RemoteIP"`
}

func RequestHandler(w http.ResponseWriter, r *http.Request) {
	var log DataToLog
	
	// 填充结构体数据
	log.ReceivedData = []Pair{
		{Key: "SystemUser", Value: "xxxxx"},
		{Key: "password", Value: "sdasdasd"},
	}
	log.ServerResponse = "success"
	log.ServerData = "processed"
	log.RemoteIP = r.RemoteAddr

	// 方法1:使用json.Marshal并直接打印
	byteArrayLog, _ := json.Marshal(log)
	fmt.Println(string(byteArrayLog))

	// 方法2:使用json.MarshalIndent获得更易读的格式
	indentedLog, _ := json.MarshalIndent(log, "", "  ")
	fmt.Println(string(indentedLog))

	// 方法3:使用log包(推荐)
	jsonLog, _ := json.Marshal(log)
	fmt.Printf("{\"message\": %s}\n", string(jsonLog))
}

关键点:

  1. 确保结构体标签使用双引号:json:"key" 而不是 json:key
  2. 云函数环境会自动包装日志,但使用 fmt.Printf("{\"message\": %s}\n", jsonString) 格式可以确保Stackdriver正确解析
  3. 避免在JSON字符串中包含额外的转义字符

部署后,Stackdriver将正确显示结构化日志。

回到顶部