cloud-game/pkg/logger/logger.go
sergystepanov 2b81c3fb87
Some optimizations (#387)
- Fixed broken image cache for the first stage RGBA frames. It was not a thread-safe one, which led to image tearing (parts of old images in multiple consecutive frames).
- 180 flip function for the OpenGL coordinate system has been moved into the rotation part.
- Optimized YUV converter.
- Optimized color converters:
  - Use __restrict pointers.
  - Draw image pixels with the faster bitwise operators and pointer arithmetic as 32/16bit LE numbers (may break on ARM devices like RPi). 
  - Pass uints for less num conversions.
  - Much faster XRGB -> RGBA conversion with Go's stdlib 32bit flip.
- Wrapped RGBA images into a custom struct in order to bypass opacity tests for the standard Go png functions, which needed for the PNG file export. Before that we set RGBx opacity byte explicitly during the pixel format conversions (much slower).
- Made Libretro core shutdown more deterministic. When we run a C core separately from the main Go process we have to make sure that the C core is not doing anything in its syscall while we stopping the emulator. Basically, a blocking call may be suspended on the Go's side while the other goroutines have no knowledge of that.
- Less info level logs.
- Added recording user label.
- Enabled RTCP sender reports by default, which may help with A/V sync.
- Check onMessage webrtc handler if it's set. May crash the program if not.
- Fixed some make dirs permissions.
- Enabled console colors (since MS has finally fixed their bloody Terminal).
- Disable log in some tests.
- Updated deps.
2023-01-31 22:22:03 +03:00

185 lines
5.3 KiB
Go

package logger
import (
"fmt"
"io"
"os"
"strconv"
"time"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
// Level defines log levels.
type Level int8
const (
DebugLevel Level = iota
InfoLevel
WarnLevel
ErrorLevel
FatalLevel
PanicLevel
NoLevel
Disabled
TraceLevel Level = -1
// Values less than TraceLevel are handled as numbers.
)
func (l Level) String() string {
switch l {
case TraceLevel:
return zerolog.LevelTraceValue
case DebugLevel:
return zerolog.LevelDebugValue
case InfoLevel:
return zerolog.LevelInfoValue
case WarnLevel:
return zerolog.LevelWarnValue
case ErrorLevel:
return zerolog.LevelErrorValue
case FatalLevel:
return zerolog.LevelFatalValue
case PanicLevel:
return zerolog.LevelPanicValue
case Disabled:
return "disabled"
case NoLevel:
return ""
}
return strconv.Itoa(int(l))
}
var pid = os.Getpid()
type Logger struct {
logger *zerolog.Logger
}
func New(isDebug bool) *Logger {
logLevel := zerolog.InfoLevel
if isDebug {
logLevel = zerolog.DebugLevel
}
zerolog.SetGlobalLevel(logLevel)
logger := zerolog.New(os.Stderr).With().Timestamp().Fields(map[string]any{"pid": pid}).Logger()
return &Logger{logger: &logger}
}
func NewConsole(isDebug bool, tag string, noColor bool) *Logger {
logLevel := zerolog.InfoLevel
if isDebug {
logLevel = zerolog.DebugLevel
}
zerolog.SetGlobalLevel(logLevel)
zerolog.TimeFieldFormat = time.RFC3339Nano
output := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: "15:04:05.0000", NoColor: noColor,
PartsOrder: []string{
zerolog.TimestampFieldName,
"pid",
zerolog.LevelFieldName,
zerolog.CallerFieldName,
"s",
"d",
"c",
"m",
zerolog.MessageFieldName,
},
FieldsExclude: []string{"s", "c", "d", "m", "pid"},
}
if output.NoColor {
output.FormatMessage = func(i any) string {
if i == nil {
return ""
}
return fmt.Sprintf("%v", i)
}
}
//multi := zerolog.MultiLevelWriter(output, os.Stdout)
logger := zerolog.New(output).With().
Str("pid", fmt.Sprintf("%4x", pid)).
Str("s", tag).
Str("m", "").
Str("d", " ").
Str("c", " ").
// Str("tag", tag). use when a file writer
Timestamp().Logger()
return &Logger{logger: &logger}
}
func SetGlobalLevel(l Level) {
zerolog.SetGlobalLevel(zerolog.Level(l))
}
func Default() *Logger { return &Logger{logger: &log.Logger} }
// GetLevel returns the current Level of l.
func (l *Logger) GetLevel() Level { return Level(l.logger.GetLevel()) }
// Output duplicates the global logger and sets w as its output.
func (l *Logger) Output(w io.Writer) zerolog.Logger { return l.logger.Output(w) }
// With creates a child logger with the field added to its context.
func (l *Logger) With() zerolog.Context { return l.logger.With() }
// Level creates a child logger with the minimum accepted level set to level.
func (l *Logger) Level(level Level) zerolog.Logger { return l.logger.Level(zerolog.Level(level)) }
// Sample returns a logger with the s sampler.
func (l *Logger) Sample(s zerolog.Sampler) zerolog.Logger { return l.logger.Sample(s) }
// Hook returns a logger with the h Hook.
func (l *Logger) Hook(h zerolog.Hook) zerolog.Logger { return l.logger.Hook(h) }
// Debug starts a new message with debug level.
// You must call Msg on the returned event in order to send the event.
func (l *Logger) Debug() *zerolog.Event { return l.logger.Debug() }
func (l *Logger) Trace() *zerolog.Event { return l.logger.Trace() }
// Info starts a new message with info level.
// You must call Msg on the returned event in order to send the event.
func (l *Logger) Info() *zerolog.Event { return l.logger.Info() }
// Warn starts a new message with warn level.
// You must call Msg on the returned event in order to send the event.
func (l *Logger) Warn() *zerolog.Event { return l.logger.Warn() }
// Error starts a new message with error level.
func (l *Logger) Error() *zerolog.Event { return l.logger.Error() }
// Fatal starts a new message with fatal level. The os.Exit(1) function
// is called by the Msg method.
// You must call Msg on the returned event in order to send the event.
func (l *Logger) Fatal() *zerolog.Event { return l.logger.Fatal() }
// Panic starts a new message with panic level. The message is also sent
// to the panic function.
// You must call Msg on the returned event in order to send the event.
func (l *Logger) Panic() *zerolog.Event { return l.logger.Panic() }
// WithLevel starts a new message with level.
// You must call Msg on the returned event in order to send the event.
func (l *Logger) WithLevel(level zerolog.Level) *zerolog.Event { return l.logger.WithLevel(level) }
// Log starts a new message with no level. Setting zerolog.GlobalLevel to
// zerolog.Disabled will still disable events produced by this method.
// You must call Msg on the returned event in order to send the event.
func (l *Logger) Log() *zerolog.Event { return l.logger.Log() }
// Print sends a log event using debug level and no extra field.
// Arguments are handled in the manner of fmt.Print.
func (l *Logger) Print(v ...any) { l.logger.Print(v...) }
// Printf sends a log event using debug level and no extra field.
// Arguments are handled in the manner of fmt.Printf.
func (l *Logger) Printf(format string, v ...any) { l.logger.Printf(format, v...) }
// Extend adds some additional context to the existing logger.
func (l *Logger) Extend(ctx zerolog.Context) *Logger {
logger := ctx.Logger()
return &Logger{logger: &logger}
}