【问题标题】:Is it possible to write a test to test the order of keys logged是否可以编写一个测试来测试记录的键的顺序
【发布时间】:2021-03-01 12:06:32
【问题描述】:

Logrus 按字母顺序记录键,这是我想要和需要的,但我想编写一个测试以确保它不会更改,我尝试添加挂钩,但我认为我无法访问完整日志使用我使用WithFields 添加的自定义上下文,我只能获取消息记录示例

func TestSomething(t*testing.T){
  logger, hook := test.NewNullLogger()
  logger.WithField("correlationId","123").WithField("id","1").Info("hello")

  assert.Equal(t, 1, len(hook.Entries))
  assert.Equal(t, logrus.(Level, hook.LastEntry().Level)
  assert.Equal(t, "Hello", hook.LastEntry().Message)

  hook.Reset()
  assert.Nil(t, hook.LastEntry())
}

我想测试message 在输出中出现在t 之前

log.SetFormatter(&log.JSONFormatter{
        FieldMap: log.FieldMap{
            log.FieldKeyMsg: "message",
            log.FieldKeyTime: "t",
        },
    })
    logger := log.WithFields(
        log.Fields{
            "id":        context.id,
            "correlationId":       context.CorrelationId,
        },

【问题讨论】:

  • 地图是无序的,因此您无法测试顺序。如果日志包保证输出是有序的,那么测试日志包本身就不是你的代码关心的问题了。

标签: go logrus


【解决方案1】:

Logrus 按字母顺序记录键

不,实际上没有。 FieldMap 实际上只是一个标准的围棋地图(如您所见 here)。同一个文件显示了如何处理字段映射的 JSON 编组。那里没有任何迹象表明正在进行任何特定的键排序。

很有可能,由于映射键的散列方式,在您的特定情况下,在您的平台上,使用您的 logrus 和 go 编译器的特定版本,输出似乎是按字母顺序排列的。但是,不能保证永远都是这样。如果您为不同的架构/操作系统(GOARCHGOOS)编译相同的代码,则输出可能不同。事情现在看起来是按字母顺序排列的,但这只是巧合。编写测试以确保您的运气没有耗尽不是测试的重点。

根据定义,地图是无序的数据结构。如果您希望日志输出按字母顺序排列,那么您可以为 logrus 编写自己的格式化程序,遍历字段映射,将所有键(作为字符串)添加到切片中,对所述切片进行排序,然后遍历排序后的键以按字母顺序打印出按键。再说一次,我真的很想知道你的用例是什么来证明这样的事情。


没错,仔细观察,encoding/json 包似乎确实将地图编组为 JSON 对象,keys being sorted

地图值编码为 JSON 对象。映射的键类型必须是字符串、整数类型或实现encoding.TextMarshaler。通过应用以下规则对映射键进行排序并用作 JSON 对象键,但要遵守上面为字符串值描述的 UTF-8 强制

这很好,只要标准库没有改变(或者你不决定将它换成行为不同的替代品),你应该很好。使用不同的格式化程序时,也不能保证这种行为。您的一开始是确保更换日志记录包不会破坏这种行为。在这种情况下,您正在测试错误的东西......它不是日志记录包本身,而是您正在使用的 json 编码包(编组器)。

您基本上是在寻找一种方法来测试是否有人将替代编组包插入您正在使用的外部包中。如果下一个版本的 logrus 最终切换到包 like ffjson,那么您的测试将失败,尽管您只是更改了日志包的版本,并且除此之外没有进行任何其他更改。单元测试并不是执行此操作的最佳方法。你可以维护你自己的 logrus 包的分支,或者只是在你的 go.mod 文件中锁定一个已知的好版本,然后收工。

【讨论】:

  • 我有一个奇怪的用例,集中式日志记录系统使用消息键的内容来覆盖实际日志的时间戳值 - 我从this comment 得到 json 已排序按字母顺序,看起来是 json marshaler 为我排序它们。
  • 另外,编写测试的重点是,如果有人尝试切换日志库并且该库没有按照现在的方式排序,那么他们就会知道。 :)
  • 我没有看到编组器按字母顺序输出字段的证据。自从发布该评论以来,这可能已经改变,并且可能会随着未来版本的 go 改变。尽管如此,我会尽量避免以适合我的日志系统的方式编写我的应用程序。我宁愿写一些东西来摄取我的应用程序的日志输出并在事后进行所需的任何处理。它使应用程序的运行时保持清洁,并卸载日志内容的排序,让我的应用程序发挥最佳性能
  • this golang.org/src/encoding/json/encode.go?#796 表明确实如此,现在它对于这个奇怪的用例来说已经足够了。
  • 确实,仔细查看了encoding/json 文档,它确实提到了排序。问题是:监督排序的是 json 编码包。 logrus 的行为没有什么特别之处。如果 logrus 切换到不同的 json 编码包,您可能会看到不同的行为。更新了我的答案以反映这一点
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-06-26
  • 1970-01-01
  • 2012-12-15
  • 1970-01-01
  • 2014-02-24
  • 1970-01-01
  • 2011-01-25
相关资源
最近更新 更多