add google/slog logger
This commit is contained in:
		
				
					committed by
					
						 Евстигнеев Денис Сергеевич
						Евстигнеев Денис Сергеевич
					
				
			
			
				
	
			
			
			
						parent
						
							e724425ce2
						
					
				
				
					commit
					c346ac43dd
				
			
							
								
								
									
										3
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								go.mod
									
									
									
									
									
								
							| @@ -9,12 +9,13 @@ require ( | |||||||
| 	github.com/patrickmn/go-cache v2.1.0+incompatible | 	github.com/patrickmn/go-cache v2.1.0+incompatible | ||||||
| 	github.com/silas/dag v0.0.0-20220518035006-a7e85ada93c5 | 	github.com/silas/dag v0.0.0-20220518035006-a7e85ada93c5 | ||||||
| 	golang.org/x/sync v0.1.0 | 	golang.org/x/sync v0.1.0 | ||||||
| 	golang.org/x/sys v0.7.0 | 	golang.org/x/sys v0.12.0 | ||||||
| 	google.golang.org/grpc v1.54.0 | 	google.golang.org/grpc v1.54.0 | ||||||
| 	google.golang.org/protobuf v1.30.0 | 	google.golang.org/protobuf v1.30.0 | ||||||
| ) | ) | ||||||
|  |  | ||||||
| require ( | require ( | ||||||
| 	github.com/golang/protobuf v1.5.3 // indirect | 	github.com/golang/protobuf v1.5.3 // indirect | ||||||
|  | 	golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect | ||||||
| 	google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect | 	google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect | ||||||
| ) | ) | ||||||
|   | |||||||
							
								
								
									
										3
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								go.sum
									
									
									
									
									
								
							| @@ -13,11 +13,14 @@ github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaR | |||||||
| github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= | github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= | ||||||
| github.com/silas/dag v0.0.0-20220518035006-a7e85ada93c5 h1:G/FZtUu7a6NTWl3KUHMV9jkLAh/Rvtf03NWMHaEDl+E= | github.com/silas/dag v0.0.0-20220518035006-a7e85ada93c5 h1:G/FZtUu7a6NTWl3KUHMV9jkLAh/Rvtf03NWMHaEDl+E= | ||||||
| github.com/silas/dag v0.0.0-20220518035006-a7e85ada93c5/go.mod h1:7RTUFBdIRC9nZ7/3RyRNH1bdqIShrDejd1YbLwgPS+I= | github.com/silas/dag v0.0.0-20220518035006-a7e85ada93c5/go.mod h1:7RTUFBdIRC9nZ7/3RyRNH1bdqIShrDejd1YbLwgPS+I= | ||||||
|  | golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= | ||||||
|  | golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= | ||||||
| golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= | golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= | ||||||
| golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= | golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= | ||||||
| golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||||
| golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= | golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= | ||||||
| golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
|  | golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
| golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= | golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
| google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= | google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= | ||||||
|   | |||||||
							
								
								
									
										259
									
								
								logger/slog.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								logger/slog.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,259 @@ | |||||||
|  | package logger | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"context" | ||||||
|  | 	"fmt" | ||||||
|  | 	"go.unistack.org/micro/v4/options" | ||||||
|  | 	"log" | ||||||
|  | 	"sync" | ||||||
|  |  | ||||||
|  | 	"golang.org/x/exp/slog" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | const ( | ||||||
|  | 	slogName = "slog" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | type slogLogger struct { | ||||||
|  | 	slog   *slog.Logger | ||||||
|  | 	fields map[string]interface{} | ||||||
|  | 	opts   Options | ||||||
|  |  | ||||||
|  | 	sync.RWMutex | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //TODO:!!!! | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Clone(opts ...options.Option) Logger { | ||||||
|  | 	//TODO implement me | ||||||
|  | 	panic("implement me") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) V(level Level) bool { | ||||||
|  | 	//TODO implement me | ||||||
|  | 	panic("implement me") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Level(level Level) { | ||||||
|  | 	//TODO implement me | ||||||
|  | 	panic("implement me") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Options() Options { | ||||||
|  | 	//TODO implement me | ||||||
|  | 	panic("implement me") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Fields(fields ...interface{}) Logger { | ||||||
|  | 	//TODO implement me | ||||||
|  | 	panic("implement me") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Trace(ctx context.Context, args ...interface{}) { | ||||||
|  | 	//TODO implement me | ||||||
|  | 	panic("implement me") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Tracef(ctx context.Context, msg string, args ...interface{}) { | ||||||
|  | 	//TODO implement me | ||||||
|  | 	panic("implement me") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Fatalf(ctx context.Context, msg string, args ...interface{}) { | ||||||
|  | 	//TODO implement me | ||||||
|  | 	panic("implement me") | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Init(opts ...options.Option) error { | ||||||
|  | 	for _, o := range opts { | ||||||
|  | 		if err := o(&s.opts); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if slog, ok := s.opts.Context.Value(loggerKey{}).(*slog.Logger); ok { | ||||||
|  | 		s.slog = slog | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	handleOpt := &slog.HandlerOptions{ | ||||||
|  | 		ReplaceAttr: renameTime, | ||||||
|  | 		Level:       loggerToSlogLevel(s.opts.Level), | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	attr := fieldsToAttr(s.fields) | ||||||
|  |  | ||||||
|  | 	handler := slog.NewJSONHandler(s.opts.Out, handleOpt).WithAttrs(attr) | ||||||
|  |  | ||||||
|  | 	s.slog = slog.New(handler) | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Log(ctx context.Context, lvl Level, args ...any) { | ||||||
|  | 	slvl := loggerToSlogLevel(lvl) | ||||||
|  |  | ||||||
|  | 	s.RLock() | ||||||
|  | 	attr := fieldsToAttr(s.fields) | ||||||
|  | 	s.RUnlock() | ||||||
|  |  | ||||||
|  | 	msg := fmt.Sprint(args...) | ||||||
|  |  | ||||||
|  | 	if lvl == FatalLevel { | ||||||
|  | 		log.Fatalln(msg, attr) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if slvl == slog.LevelError { | ||||||
|  | 		l := s.slog.With(slog.Any("ProcStatus", "ERROR"), slog.Any("ErrorText", msg)) | ||||||
|  | 		l.LogAttrs(ctx, slvl, "", attr...) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	s.slog.LogAttrs(ctx, slvl, msg, attr...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Logf(ctx context.Context, lvl Level, format string, args ...any) { | ||||||
|  | 	slvl := loggerToSlogLevel(lvl) | ||||||
|  |  | ||||||
|  | 	s.RLock() | ||||||
|  | 	attr := fieldsToAttr(s.fields) | ||||||
|  | 	s.RUnlock() | ||||||
|  |  | ||||||
|  | 	msg := fmt.Sprintf(format, args...) | ||||||
|  |  | ||||||
|  | 	if lvl == FatalLevel { | ||||||
|  | 		log.Fatalln(msg, attr) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if slvl == slog.LevelError { | ||||||
|  | 		l := s.slog.With(slog.Any("ProcStatus", "ERROR"), slog.Any("ErrorText", msg)) | ||||||
|  | 		l.LogAttrs(ctx, slvl, "", attr...) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	s.slog.LogAttrs(ctx, slvl, msg, attr...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Info(ctx context.Context, args ...any) { | ||||||
|  | 	s.Log(ctx, InfoLevel, args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Infof(ctx context.Context, format string, args ...interface{}) { | ||||||
|  | 	s.Logf(ctx, InfoLevel, format, args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Debug(ctx context.Context, args ...any) { | ||||||
|  | 	s.Log(ctx, DebugLevel, args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Debugf(ctx context.Context, format string, args ...any) { | ||||||
|  | 	s.Logf(ctx, DebugLevel, format, args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Error(ctx context.Context, args ...any) { | ||||||
|  | 	s.Log(ctx, ErrorLevel, args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Errorf(ctx context.Context, format string, args ...any) { | ||||||
|  | 	s.Logf(ctx, ErrorLevel, format, args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Fatal(ctx context.Context, args ...any) { | ||||||
|  | 	s.Log(ctx, FatalLevel, args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Warn(ctx context.Context, args ...any) { | ||||||
|  | 	s.Log(ctx, WarnLevel, args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Warnf(ctx context.Context, format string, args ...any) { | ||||||
|  | 	s.Logf(ctx, WarnLevel, format, args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) String() string { | ||||||
|  | 	return slogName | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  | func (s *slogLogger) Fields(fields map[string]interface{}) Logger { | ||||||
|  | 	nfields := make(map[string]interface{}, len(s.fields)) | ||||||
|  |  | ||||||
|  | 	s.Lock() | ||||||
|  | 	for k, v := range s.fields { | ||||||
|  | 		nfields[k] = v | ||||||
|  | 	} | ||||||
|  | 	s.Unlock() | ||||||
|  |  | ||||||
|  | 	for k, v := range fields { | ||||||
|  | 		nfields[k] = v | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	keys := make([]string, 0, len(nfields)) | ||||||
|  | 	for k := range nfields { | ||||||
|  | 		keys = append(keys, k) | ||||||
|  | 	} | ||||||
|  | 	sort.Strings(keys) | ||||||
|  |  | ||||||
|  | 	attr := make([]slog.Attr, 0, len(nfields)) | ||||||
|  | 	for _, k := range keys { | ||||||
|  | 		attr = append(attr, slog.Any(k, fields[k])) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	handleOpt := &slog.HandlerOptions{ | ||||||
|  | 		ReplaceAttr: renameTime, | ||||||
|  | 		Level:       loggerToSlogLevel(s.opts.Level), | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	handler := slog.NewJSONHandler(s.opts.Out, handleOpt).WithAttrs(attr) | ||||||
|  |  | ||||||
|  | 	zl := &slogLogger{ | ||||||
|  | 		slog:   slog.New(handler), | ||||||
|  | 		opts:   s.opts, | ||||||
|  | 		fields: make(map[string]interface{}), | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return zl | ||||||
|  | } | ||||||
|  |  | ||||||
|  | */ | ||||||
|  |  | ||||||
|  | func NewSlogLogger(opts ...options.Option) (Logger, error) { | ||||||
|  | 	l := &slogLogger{ | ||||||
|  | 		opts: NewOptions(opts...), | ||||||
|  | 	} | ||||||
|  | 	err := l.Init() | ||||||
|  | 	return l, err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func renameTime(groups []string, a slog.Attr) slog.Attr { | ||||||
|  | 	if a.Key == slog.TimeKey { | ||||||
|  | 		a.Key = "@timestamp" | ||||||
|  | 	} | ||||||
|  | 	if a.Key == slog.MessageKey { | ||||||
|  | 		a.Key = "message" | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return a | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func loggerToSlogLevel(level Level) slog.Level { | ||||||
|  | 	switch level { | ||||||
|  | 	case TraceLevel, DebugLevel: | ||||||
|  | 		return slog.LevelDebug | ||||||
|  | 	case WarnLevel: | ||||||
|  | 		return slog.LevelWarn | ||||||
|  | 	case ErrorLevel, FatalLevel: | ||||||
|  | 		return slog.LevelError | ||||||
|  | 	default: | ||||||
|  | 		return slog.LevelInfo | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func fieldsToAttr(m map[string]any) []slog.Attr { | ||||||
|  | 	data := make([]slog.Attr, 0, len(m)) | ||||||
|  | 	for k, v := range m { | ||||||
|  | 		data = append(data, slog.Any(k, v)) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return data | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user