聊聊zerolog的encoder

作者:神秘网友 发布时间:2021-01-12 20:21:52

聊聊zerolog的encoder

本文主要研究一下zerolog的encoder

encoder

github.com/rs/zerolog@v1.20.0/encoder.go

type encoder interface {
    AppendArrayDelim(dst []byte) []byte
    AppendArrayEnd(dst []byte) []byte
    AppendArrayStart(dst []byte) []byte
    AppendBeginMarker(dst []byte) []byte
    AppendBool(dst []byte, val bool) []byte
    AppendBools(dst []byte, vals []bool) []byte
    AppendBytes(dst, s []byte) []byte
    AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool) []byte
    AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool) []byte
    AppendEndMarker(dst []byte) []byte
    AppendFloat32(dst []byte, val float32) []byte
    AppendFloat64(dst []byte, val float64) []byte
    AppendFloats32(dst []byte, vals []float32) []byte
    AppendFloats64(dst []byte, vals []float64) []byte
    AppendHex(dst, s []byte) []byte
    AppendIPAddr(dst []byte, ip net.IP) []byte
    AppendIPPrefix(dst []byte, pfx net.IPNet) []byte
    AppendInt(dst []byte, val int) []byte
    AppendInt16(dst []byte, val int16) []byte
    AppendInt32(dst []byte, val int32) []byte
    AppendInt64(dst []byte, val int64) []byte
    AppendInt8(dst []byte, val int8) []byte
    AppendInterface(dst []byte, i interface{}) []byte
    AppendInts(dst []byte, vals []int) []byte
    AppendInts16(dst []byte, vals []int16) []byte
    AppendInts32(dst []byte, vals []int32) []byte
    AppendInts64(dst []byte, vals []int64) []byte
    AppendInts8(dst []byte, vals []int8) []byte
    AppendKey(dst []byte, key string) []byte
    AppendLineBreak(dst []byte) []byte
    AppendMACAddr(dst []byte, ha net.HardwareAddr) []byte
    AppendNil(dst []byte) []byte
    AppendObjectData(dst []byte, o []byte) []byte
    AppendString(dst []byte, s string) []byte
    AppendStrings(dst []byte, vals []string) []byte
    AppendTime(dst []byte, t time.Time, format string) []byte
    AppendTimes(dst []byte, vals []time.Time, format string) []byte
    AppendUint(dst []byte, val uint) []byte
    AppendUint16(dst []byte, val uint16) []byte
    AppendUint32(dst []byte, val uint32) []byte
    AppendUint64(dst []byte, val uint64) []byte
    AppendUint8(dst []byte, val uint8) []byte
    AppendUints(dst []byte, vals []uint) []byte
    AppendUints16(dst []byte, vals []uint16) []byte
    AppendUints32(dst []byte, vals []uint32) []byte
    AppendUints64(dst []byte, vals []uint64) []byte
    AppendUints8(dst []byte, vals []uint8) []byte
}

encoder接口定义了一系列的Append方法

AppendMarker

github.com/rs/zerolog@v1.20.0/internal/json/types.go

// AppendBeginMarker inserts a map start into the dst byte array.
func (Encoder) AppendBeginMarker(dst []byte) []byte {
    return append(dst, {)
}

// AppendEndMarker inserts a map end into the dst byte array.
func (Encoder) AppendEndMarker(dst []byte) []byte {
    return append(dst, })
}

AppendBeginMarker及AppendEndMarker用于追加map start和end

AppendArray

github.com/rs/zerolog@v1.20.0/internal/json/types.go

// AppendArrayStart adds markers to indicate the start of an array.
func (Encoder) AppendArrayStart(dst []byte) []byte {
    return append(dst, [)
}

// AppendArrayEnd adds markers to indicate the end of an array.
func (Encoder) AppendArrayEnd(dst []byte) []byte {
    return append(dst, ])
}

AppendArrayStart及AppendArrayEnd用于追加array start和end

AppendLineBreak

github.com/rs/zerolog@v1.20.0/internal/json/types.go

// AppendLineBreak appends a line break.
func (Encoder) AppendLineBreak(dst []byte) []byte {
    return append(dst, \n)
}

AppendLineBreak用于追加换行符

AppendInterface

github.com/rs/zerolog@v1.20.0/internal/json/types.go

// AppendInterface marshals the input interface to a string and
// appends the encoded string to the input byte slice.
func (e Encoder) AppendInterface(dst []byte, i interface{}) []byte {
    marshaled, err := json.Marshal(i)
    if err != nil {
        return e.AppendString(dst, fmt.Sprintf(marshaling error: %v, err))
    }
    return append(dst, marshaled...)
}

AppendInterface方法使用json来序列化interface

AppendObjectData

github.com/rs/zerolog@v1.20.0/internal/json/types.go

// AppendObjectData takes in an object that is already in a byte array
// and adds it to the dst.
func (Encoder) AppendObjectData(dst []byte, o []byte) []byte {
    // Three conditions apply here:
    // 1. new content starts with { - which should be dropped   OR
    // 2. new content starts with { - which should be replaced with ,
    //    to separate with existing content OR
    // 3. existing content has already other fields
    if o[0] == { {
        if len(dst)  1 {
            dst = append(dst, ,)
        }
        o = o[1:]
    } else if len(dst)  1 {
        dst = append(dst, ,)
    }
    return append(dst, o...)
}

AppendObjectData用于追加byte数组

Context

github.com/rs/zerolog@v1.20.0/context.go

// Context configures a new sub-logger with contextual fields.
type Context struct {
    l Logger
}

// Logger returns the logger with the context previously set.
func (c Context) Logger() Logger {
    return c.l
}

func (c Context) Array(key string, arr LogArrayMarshaler) Context {
    c.l.context = enc.AppendKey(c.l.context, key)
    if arr, ok := arr.(*Array); ok {
        c.l.context = arr.write(c.l.context)
        return c
    }
    var a *Array
    if aa, ok := arr.(*Array); ok {
        a = aa
    } else {
        a = Arr()
        arr.MarshalZerologArray(a)
    }
    c.l.context = a.write(c.l.context)
    return c
}

// Object marshals an object that implement the LogObjectMarshaler interface.
func (c Context) Object(key string, obj LogObjectMarshaler) Context {
    e := newEvent(levelWriterAdapter{ioutil.Discard}, 0)
    e.Object(key, obj)
    c.l.context = enc.AppendObjectData(c.l.context, e.buf)
    putEvent(e)
    return c
}

// EmbedObject marshals and Embeds an object that implement the LogObjectMarshaler interface.
func (c Context) EmbedObject(obj LogObjectMarshaler) Context {
    e := newEvent(levelWriterAdapter{ioutil.Discard}, 0)
    e.EmbedObject(obj)
    c.l.context = enc.AppendObjectData(c.l.context, e.buf)
    putEvent(e)
    return c
}

func (c Context) RawJSON(key string, b []byte) Context {
    c.l.context = appendJSON(enc.AppendKey(c.l.context, key), b)
    return c
}

// Interface adds the field key with obj marshaled using reflection.
func (c Context) Interface(key string, i interface{}) Context {
    c.l.context = enc.AppendInterface(enc.AppendKey(c.l.context, key), i)
    return c
}

Context提供了各种类型的方法,其里头执行的是encoder的对应类型的Append方法

With

github.com/rs/zerolog@v1.20.0/log.go

type Logger struct {
    w       LevelWriter
    level   Level
    sampler Sampler
    context []byte
    hooks   []Hook
}

// With creates a child logger with the field added to its context.
func (l Logger) With() Context {
    context := l.context
    l.context = make([]byte, 0, 500)
    if context != nil {
        l.context = append(l.context, context...)
    } else {
        // This is needed for AppendKey to not check len of input
        // thus making it inlinable
        l.context = enc.AppendBeginMarker(l.context)
    }
    return Context{l}
}

With方法创建一个新的Context,包装了当前的logger;logger的context属性为byte数组;Context提供的各种类型的Append方法最后都作为byte数组追加到logger的context属性中

newEvent

github.com/rs/zerolog@v1.20.0/log.go

func (l *Logger) newEvent(level Level, done func(string)) *Event {
    enabled := l.should(level)
    if !enabled {
        return nil
    }
    e := newEvent(l.w, level)
    e.done = done
    e.ch = l.hooks
    if level != NoLevel {
        e.Str(LevelFieldName, LevelFieldMarshalFunc(level))
    }
    if l.context != nil  len(l.context)  1 {
        e.buf = enc.AppendObjectData(e.buf, l.context)
    }
    return e
}

newEvent方法会将logger的context属性通过encoder的AppendObjectData方法拷贝到event的buf中

实例
func withDemo() {
    logger := zerolog.New(os.Stderr).With().Timestamp().Str(key, value).Logger()
    logger.Info().Str(k1, v1).Msg(hello world)
    logger.Info().Str(k2, v2).Msg(hello world)
}

输出

{level:info,key:value,k1:v1,time:2021-01-04T23:45:10+08:00,message:hello world}
{level:info,key:value,k2:v2,time:2021-01-04T23:45:10+08:00,message:hello world}
小结

encoder接口定义了一系列的Append方法;Context提供了各种类型的方法,其里头执行的是encoder的对应类型的Append方法;With方法创建一个新的Context,包装了当前的logger;logger的context属性为byte数组;Context提供的各种类型的Append方法最后都作为byte数组追加到logger的context属性中;newEvent方法会将logger的context属性通过encoder的AppendObjectData方法拷贝到event的buf中。

doc
  • zerolog

聊聊zerolog的encoder 相关文章

  1. 聊聊zerolog的diode.Writer

    序 本文主要研究一下zerolog的diode.Writer diode.Writer github.com/rs/zerolog@v1.20.0/diode/diode.go // Writer is a io.Writer wrapper that uses a diode to make Write lock-free,// non-blocking and thread safe.type Writer struct { w io.Writer

  2. 聊聊zerolog的Formatter

    序 本文主要研究一下zerolog的Formatter Formatter github.com/rs/zerolog@v1.20.0/console.go // Formatter transforms the input into a formatted string.type Formatter func(interface{}) string Formatter接口定义了一个func用于将interface{}转换为st

  3. 最全总结 | 聊聊 Python 办公自动化之 Word(中)

    1. 前言 上一篇文章,对 Word 写入数据的一些常见操作进行了总结 最全总结 | 聊聊 Python 办公自动化之 Word(上) 相比写入数据,读取数据同样很实用! 本篇文章,将谈谈如何全面读取一个 Word 文档中的数据,并会指出一些要注意的点 2. 基本信息 我们同样

  4. 最全总结 | 聊聊 Python 办公自动化之 Excel(中)

    最全总结 | 聊聊 Python 办公自动化之 Excel(中) 聊聊 Python 数据处理全家桶(Memca 篇) 点击上方“AirPython”,选择“加为星标” 第一时间关注 Python 技术干货! 上一篇文章中,我们聊到使用xlrd、xlwt、xlutils 这一组合操作 Excel 的方法 最全总结 |

  5. 中秋前夕,聊聊canvas

    中秋前夕,聊聊canvas 首先上图: 今天,我们前端群问了一个这样的问题,然后就开始了激烈的讨论。 那么下面咱们一起来看看这个问题,这个问题问了两个小问题: 1.如何在 canvas 上绘制多边形? 2.鼠标怎么选中绘制的某一个图形? 那么咱们就来分为两个问题解

  6. 面试官:聊聊对Vue.js框架的理解

    面试官:聊聊对Vue.js框架的理解 开发者(KaiFaX) 面向全栈工程师的开发者 专注于前端、Java/Python/Go/PHP的技术社区 作者 |yacan8 来源 | https://github.com/yacan8/blog/issues/26 本文为一次前端技术分享的演讲稿,所以尽力不贴 Vue.js 的源码,因为贴

  7. 聊聊 Python 的双向队列

    Python教程 今天介绍双向队列。 虽然可以使用 Python 列表的 .append 和 .pop 方法模拟栈或者队列,但删除列表的第一个元素或者在第一个元素之前添加一个新元素,都非常耗时。因为需要把列表中的所有元素向后移动。 Python 的双向队列使用 collections.deque

  8. 【Web技术】756- 聊聊如何设计组件

    【Web技术】756- 聊聊如何设计组件 作者:我想写文章啊 来源:https://juejin.im/post/6878099828497186823 现今的web开发通过前后端分离的技术拆分为了web后端开发与web前端开发,值得指出的是,web前端开发早已不是传统意义上的开发模式了,转而变成了 web

  9. 聊聊监控

    聊聊监控 之前说要聊聊监控,这篇来填坑了。 指标 《踩坑记:Goroutine泄漏》开篇那张截图,展示了单个服务进程启动的 Goroutine 数量;除此之外,我们的服务进程在后台还采集了很多其他指标,例如: 当前存活在堆上的对象所占空间 这些数据是哪儿来的呢?run

  10. Monitoring of a Dynamic System Based on Autoencoders

    Monitoring of a Dynamic System Based on Autoencoders 这篇论文主要解决的是工业设备的异常检测问题。工业设备的异常检测主要面临2个问题:一是,模型需要具有 实时性 ,能够适应工业设备和生产环境的突然变化;二是,模型需要能够适应工业设备的 长期演化

每天更新java,php,javaScript,go,python,nodejs,vue,android,mysql等相关技术教程,教程由网友分享而来,欢迎大家分享IT技术教程到本站,帮助自己同时也帮助他人!

Copyright 2020, All Rights Reserved. Powered by 跳墙网(www.tqwba.com)|网站地图|关键词