亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用 zap logger 將 protobuf 消息記錄為未轉義的 JSON 格式

使用 zap logger 將 protobuf 消息記錄為未轉義的 JSON 格式

Go
侃侃無極 2022-09-12 20:51:45
我有一個Go項目,我使用Zap結構化日志記錄來記錄結構的內容。這就是我初始化記錄器的方式:zapLog, err := zap.NewProductionConfig().Build()if err != nil {    panic(err)}最初,我從我自己的結構開始,帶有json標簽,一切都很完美:zapLog.Info("Event persisted", zap.Any("event", &event))結果:{"level":"info","ts":1626448680.69099,"caller":"persisters/log.go:56", "msg":"Event persisted","event":{"sourceType":4, "sourceId":"some-source-id",  "type":"updated", "value":"{...}", "context":{"foo":"bar"}}}我現在切換到原型布夫,我正在努力實現相同的結果。最初,在使用zap時,我只是得到了“反射地圖”版本。任何():zapLog.Info("Event persisted", zap.Any("event", &event)){"level":"info","ts":1626448680.69099,"caller":"persisters/log.go:56", "msg":"Event persisted","event":"sourceType:TYPE_X sourceId:\"some-source-id\",  type:\"updated\" value:{...}, context:<key: foo, value:bar>}我嘗試使用 jsonpb 編組器對對象進行編組,該編組器在自身上生成了正確的輸出,但是,當我在 中使用它時,字符串被轉義,因此我在每個引號前面得到一組額外的“\”。由于稍后會處理日志,因此這會導致問題,因此我想避免它:zap.String()m := jsonpb.Marshaler{}var buf bytes.Bufferif err := m.Marshal(&buf, msg); err != nil {    // handle error}zapLog.Info("Event persisted", zap.ByteString("event", buf.Bytes()))結果:{"level":"info","ts":1626448680.69099,"caller":"persisters/log.go:56", "msg":"Event persisted","event":"{\"sourceType\":\"TYPE_X\", \"sourceId\":\"some-source-id\",  \"type\":\"updated\", \"value\":\"{...}\", \"context\":{\"foo\":"bar\"}}"}然后,我嘗試使用最接近我需要的東西來代替它,除了枚舉被渲染為它們的數值(初始解沒有枚舉,所以這在protobuf之前的解決方案中也不起作用):zap.Reflect()zap.Any()zapLog.Info("Event persisted", zap.Reflect("event", &event))結果:{"level":"info","ts":1626448680.69099,"caller":"persisters/log.go:56", "msg":"Event persisted","event":{"sourceType":4, "sourceId":"some-source-id",  "type":"updated", "value":"{...}", "context":{"foo":"bar"}}}到目前為止,我看到的唯一選擇是編寫自己的函數:MarshalLogObject()但是由于它是一個復雜的結構,我寧愿使用一個不易出錯和維護較重的解決方案。理想情況下,我會告訴zap以某種方式使用jsonpb編組器,但我不知道這是否可能。
查看完整描述

2 回答

?
楊魅力

TA貢獻1811條經驗 獲得超6個贊

使用扎普。任何帶有 json 的內容。原始消息。您可以直接轉換 的字節輸出:jsonpb.Marshaler


 foo := &pb.FooMsg{

        Foo: "blah", 

        Bar:  1,

    }


    m := jsonpb.Marshaler{}

    var buf bytes.Buffer

    if err := m.Marshal(&buf, foo); err != nil {

        // handle error

    }


    logger, _ := zap.NewDevelopment()

    logger.Info("Event persisted", zap.Any("event", json.RawMessage(buf.Bytes())))

字節將打印為:


事件持久 {“事件”: {“foo”:“blah”,“bar”:“1”}}'


我相信這是最簡單的方法,但是我也知道一個包卡澤古蘇里/go-proto-zap-marshaler(我不隸屬于它),它生成實現作為原型插件。您可能也想看看。MarshalLogObject()


查看完整回答
反對 回復 2022-09-12
?
慕勒3428872

TA貢獻1848條經驗 獲得超6個贊

我使用了另一種方法來 json 化原型。


由于原型可以自然地封送,我只是將它們包裝在嚴格到json的封送處理器中。


您可以修改內部結構以使用原型(較新的 jsonpb)。


與上一個解決方案中的封送處理器不同,此封送處理程序不需要預先記錄處理。



type jsonObjectMarshaler struct {

    obj  any

}


func (j *jsonObjectMarshaler) MarshalJSON() ([]byte, error) {

    bytes, err := json.Marshal(j.obj)

    // bytes, err := protojson.Marshal(j.obj)

    if err != nil {

        return nil, fmt.Errorf("json marshaling failed: %w", err)

    }

    return bytes, nil

}


func ZapJsonable(key string, obj any) zap.Field {

    return zap.Reflect(key, &jsonObjectMarshaler{obj: obj})

}

然后使用它,只是


logger, _ := zap.NewDevelopment()

logger.Info("Event persisted", ZapJsonable("event", buf))


查看完整回答
反對 回復 2022-09-12
  • 2 回答
  • 0 關注
  • 219 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號