livekit-protocol 0.8.2

Livekit protocol and utilities for the Rust SDK
Documentation
package logger

import (
	"io"
	"testing"

	"go.uber.org/zap/zapcore"

	"github.com/livekit/protocol/logger/testutil"
	"github.com/livekit/protocol/logger/zaputil"
	"github.com/livekit/protocol/utils/must"
)

var benchSink Logger

type loggerBenchCase struct {
	label string
	conf  *Config
	opts  []ZapLoggerOption
}

func (c loggerBenchCase) logger(b *testing.B) ZapLogger {
	b.Helper()
	return must.Get(NewZapLogger(c.conf, c.opts...))
}

func derivationBenchCases() []loggerBenchCase {
	return []loggerBenchCase{
		{label: "console", conf: &Config{}},
		{label: "json", conf: &Config{JSON: true}},
		{label: "console tee", conf: &Config{}, opts: withDiscardTee()},
		{label: "json tee", conf: &Config{JSON: true}, opts: withDiscardTee()},
	}
}

func withDiscardTee() []ZapLoggerOption {
	return []ZapLoggerOption{WithTee(zaputil.NewTee(testutil.NewJSONCoreFactory(zapcore.AddSync(io.Discard))))}
}

func BenchmarkLoggerWithComponent(b *testing.B) {
	for _, c := range derivationBenchCases() {
		b.Run(c.label, func(b *testing.B) {
			root := c.logger(b)
			branch := root.WithComponentLeveler(zaputil.NewComponentLeveler(root.Leveler(), FixedComponentLevel(zapcore.DebugLevel)))

			// One repeated component, so this measures the cache rather than resolution.
			b.Run("root", func(b *testing.B) {
				b.ReportAllocs()
				for range b.N {
					benchSink = root.WithComponent("rtc")
				}
			})

			b.Run("branch leveler", func(b *testing.B) {
				b.ReportAllocs()
				for range b.N {
					benchSink = branch.WithComponent("rtc")
				}
			})
		})
	}
}

func BenchmarkLoggerWithComponentLeveler(b *testing.B) {
	for _, c := range derivationBenchCases() {
		b.Run(c.label, func(b *testing.B) {
			root := c.logger(b)
			lv := zaputil.NewComponentLeveler(root.Leveler(), FixedComponentLevel(zapcore.DebugLevel))

			b.ReportAllocs()
			for range b.N {
				benchSink = root.WithComponentLeveler(lv)
			}
		})
	}
}

func BenchmarkLoggerWithValues(b *testing.B) {
	for _, c := range derivationBenchCases() {
		b.Run(c.label, func(b *testing.B) {
			root := c.logger(b)

			b.Run("root", func(b *testing.B) {
				b.ReportAllocs()
				for range b.N {
					benchSink = root.WithValues("participant", "PA_1234")
				}
			})

			b.Run("derived", func(b *testing.B) {
				derived := root.WithValues("room", "RM_1234")
				b.ReportAllocs()
				for range b.N {
					benchSink = derived.WithValues("participant", "PA_1234")
				}
			})
		})
	}
}

func BenchmarkLoggerWithDeferredValues(b *testing.B) {
	for _, c := range derivationBenchCases() {
		b.Run(c.label, func(b *testing.B) {
			root := c.logger(b)

			b.Run("derive", func(b *testing.B) {
				b.ReportAllocs()
				for range b.N {
					benchSink, _ = root.WithDeferredValues()
				}
			})

			b.Run("derive and resolve", func(b *testing.B) {
				b.ReportAllocs()
				for range b.N {
					l, resolver := root.WithDeferredValues()
					resolver.Resolve("participant", "PA_1234")
					benchSink = l
				}
			})
		})
	}
}

func BenchmarkLoggerWrite(b *testing.B) {
	silenceStderr(b)

	cases := []loggerBenchCase{
		{label: "console", conf: &Config{Level: "debug"}},
		{label: "json", conf: &Config{JSON: true, Level: "debug"}},
		{label: "level disabled", conf: &Config{Level: "info"}},
		{label: "console tee", conf: &Config{Level: "debug"}, opts: withDiscardTee()},
		{label: "json tee", conf: &Config{JSON: true, Level: "debug"}, opts: withDiscardTee()},
	}

	for _, c := range cases {
		b.Run(c.label, func(b *testing.B) {
			root := c.logger(b)

			b.Run("plain", func(b *testing.B) {
				b.ReportAllocs()
				for range b.N {
					root.Debugw("bench", "participant", "PA_1234")
				}
			})

			b.Run("deferred", func(b *testing.B) {
				l, resolver := root.WithDeferredValues()
				resolver.Resolve("room", "RM_1234")
				b.ReportAllocs()
				for range b.N {
					l.Debugw("bench", "participant", "PA_1234")
				}
			})

			b.Run("deferred flush", func(b *testing.B) {
				b.ReportAllocs()
				for range b.N {
					l, resolver := root.WithDeferredValues()
					l.Debugw("bench", "participant", "PA_1234")
					resolver.Resolve("room", "RM_1234")
				}
			})
		})
	}
}