tracer: update wrapper
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
		
							
								
								
									
										9
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								go.mod
									
									
									
									
									
								
							| @@ -9,13 +9,14 @@ 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/exp v0.0.0-20230905200255-921286631fa9 | 	golang.org/x/exp v0.0.0-20230905200255-921286631fa9 | ||||||
| 	golang.org/x/sync v0.1.0 | 	golang.org/x/sync v0.3.0 | ||||||
| 	golang.org/x/sys v0.12.0 | 	golang.org/x/sys v0.12.0 | ||||||
| 	google.golang.org/grpc v1.54.0 | 	google.golang.org/grpc v1.57.0 | ||||||
| 	google.golang.org/protobuf v1.30.0 | 	google.golang.org/protobuf v1.31.0 | ||||||
|  |  | ||||||
| ) | ) | ||||||
|  |  | ||||||
| require ( | require ( | ||||||
| 	github.com/golang/protobuf v1.5.3 // indirect | 	github.com/golang/protobuf v1.5.3 // indirect | ||||||
| 	google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect | 	google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect | ||||||
| ) | ) | ||||||
|   | |||||||
							
								
								
									
										20
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								go.sum
									
									
									
									
									
								
							| @@ -15,21 +15,21 @@ github.com/silas/dag v0.0.0-20220518035006-a7e85ada93c5 h1:G/FZtUu7a6NTWl3KUHMV9 | |||||||
| 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 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= | ||||||
| golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= | 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.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= | ||||||
| golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= | golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= | ||||||
| golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= | ||||||
| golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= | golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= | ||||||
| golang.org/x/sys v0.12.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.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= | ||||||
| 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/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM= | ||||||
| google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= | google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= | ||||||
| google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= | google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= | ||||||
| google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= | google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= | ||||||
| google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= | ||||||
| google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= | ||||||
| google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= | google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= | ||||||
| google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= | google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= | ||||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||||
| gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||||||
| gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||||
|   | |||||||
| @@ -1,232 +0,0 @@ | |||||||
| package logger |  | ||||||
|  |  | ||||||
| import ( |  | ||||||
| 	"context" |  | ||||||
| 	"encoding/json" |  | ||||||
| 	"fmt" |  | ||||||
| 	"os" |  | ||||||
| 	"runtime" |  | ||||||
| 	"strings" |  | ||||||
| 	"sync" |  | ||||||
| 	"time" |  | ||||||
|  |  | ||||||
| 	"go.unistack.org/micro/v4/options" |  | ||||||
| ) |  | ||||||
|  |  | ||||||
| type defaultLogger struct { |  | ||||||
| 	enc  *json.Encoder |  | ||||||
| 	opts Options |  | ||||||
| 	sync.RWMutex |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Init(opts...) should only overwrite provided options |  | ||||||
| func (l *defaultLogger) Init(opts ...options.Option) error { |  | ||||||
| 	l.Lock() |  | ||||||
| 	for _, o := range opts { |  | ||||||
| 		o(&l.opts) |  | ||||||
| 	} |  | ||||||
| 	l.enc = json.NewEncoder(l.opts.Out) |  | ||||||
| 	// wrap the Log func |  | ||||||
| 	l.Unlock() |  | ||||||
| 	return nil |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) String() string { |  | ||||||
| 	return "micro" |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) Clone(opts ...options.Option) Logger { |  | ||||||
| 	newopts := NewOptions(opts...) |  | ||||||
| 	oldopts := l.opts |  | ||||||
| 	for _, o := range opts { |  | ||||||
| 		o(&newopts) |  | ||||||
| 		o(&oldopts) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	l.Lock() |  | ||||||
| 	cl := &defaultLogger{opts: oldopts, enc: json.NewEncoder(l.opts.Out)} |  | ||||||
| 	l.Unlock() |  | ||||||
|  |  | ||||||
| 	return cl |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) V(level Level) bool { |  | ||||||
| 	l.RLock() |  | ||||||
| 	ok := l.opts.Level.Enabled(level) |  | ||||||
| 	l.RUnlock() |  | ||||||
| 	return ok |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) Level(level Level) { |  | ||||||
| 	l.Lock() |  | ||||||
| 	l.opts.Level = level |  | ||||||
| 	l.Unlock() |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) Fields(fields ...interface{}) Logger { |  | ||||||
| 	l.RLock() |  | ||||||
| 	nl := &defaultLogger{opts: l.opts, enc: l.enc} |  | ||||||
| 	if len(fields) == 0 { |  | ||||||
| 		l.RUnlock() |  | ||||||
| 		return nl |  | ||||||
| 	} else if len(fields)%2 != 0 { |  | ||||||
| 		fields = fields[:len(fields)-1] |  | ||||||
| 	} |  | ||||||
| 	nl.opts.Fields = copyFields(l.opts.Fields) |  | ||||||
| 	nl.opts.Fields = append(nl.opts.Fields, fields...) |  | ||||||
| 	l.RUnlock() |  | ||||||
| 	return nl |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func copyFields(src []interface{}) []interface{} { |  | ||||||
| 	dst := make([]interface{}, len(src)) |  | ||||||
| 	copy(dst, src) |  | ||||||
| 	return dst |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // logCallerfilePath returns a package/file:line description of the caller, |  | ||||||
| // preserving only the leaf directory name and file name. |  | ||||||
| func logCallerfilePath(loggingFilePath string) string { |  | ||||||
| 	// To make sure we trim the path correctly on Windows too, we |  | ||||||
| 	// counter-intuitively need to use '/' and *not* os.PathSeparator here, |  | ||||||
| 	// because the path given originates from Go stdlib, specifically |  | ||||||
| 	// runtime.Caller() which (as of Mar/17) returns forward slashes even on |  | ||||||
| 	// Windows. |  | ||||||
| 	// |  | ||||||
| 	// See https://github.com/golang/go/issues/3335 |  | ||||||
| 	// and https://github.com/golang/go/issues/18151 |  | ||||||
| 	// |  | ||||||
| 	// for discussion on the issue on Go side. |  | ||||||
| 	idx := strings.LastIndexByte(loggingFilePath, '/') |  | ||||||
| 	if idx == -1 { |  | ||||||
| 		return loggingFilePath |  | ||||||
| 	} |  | ||||||
| 	idx = strings.LastIndexByte(loggingFilePath[:idx], '/') |  | ||||||
| 	if idx == -1 { |  | ||||||
| 		return loggingFilePath |  | ||||||
| 	} |  | ||||||
| 	return loggingFilePath[idx+1:] |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) Info(ctx context.Context, args ...interface{}) { |  | ||||||
| 	l.Log(ctx, InfoLevel, args...) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) Error(ctx context.Context, args ...interface{}) { |  | ||||||
| 	l.Log(ctx, ErrorLevel, args...) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) Debug(ctx context.Context, args ...interface{}) { |  | ||||||
| 	l.Log(ctx, DebugLevel, args...) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) Warn(ctx context.Context, args ...interface{}) { |  | ||||||
| 	l.Log(ctx, WarnLevel, args...) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) Trace(ctx context.Context, args ...interface{}) { |  | ||||||
| 	l.Log(ctx, TraceLevel, args...) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) Fatal(ctx context.Context, args ...interface{}) { |  | ||||||
| 	l.Log(ctx, FatalLevel, args...) |  | ||||||
| 	os.Exit(1) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) Infof(ctx context.Context, msg string, args ...interface{}) { |  | ||||||
| 	l.Logf(ctx, InfoLevel, msg, args...) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) Errorf(ctx context.Context, msg string, args ...interface{}) { |  | ||||||
| 	l.Logf(ctx, ErrorLevel, msg, args...) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) Debugf(ctx context.Context, msg string, args ...interface{}) { |  | ||||||
| 	l.Logf(ctx, DebugLevel, msg, args...) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) Warnf(ctx context.Context, msg string, args ...interface{}) { |  | ||||||
| 	l.Logf(ctx, WarnLevel, msg, args...) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) Tracef(ctx context.Context, msg string, args ...interface{}) { |  | ||||||
| 	l.Logf(ctx, TraceLevel, msg, args...) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) Fatalf(ctx context.Context, msg string, args ...interface{}) { |  | ||||||
| 	l.Logf(ctx, FatalLevel, msg, args...) |  | ||||||
| 	os.Exit(1) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) Log(ctx context.Context, level Level, args ...interface{}) { |  | ||||||
| 	if !l.V(level) { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	l.RLock() |  | ||||||
| 	fields := copyFields(l.opts.Fields) |  | ||||||
| 	l.RUnlock() |  | ||||||
|  |  | ||||||
| 	fields = append(fields, "level", level.String()) |  | ||||||
|  |  | ||||||
| 	if _, file, line, ok := runtime.Caller(l.opts.CallerSkipCount); ok { |  | ||||||
| 		fields = append(fields, "caller", fmt.Sprintf("%s:%d", logCallerfilePath(file), line)) |  | ||||||
| 	} |  | ||||||
| 	fields = append(fields, "timestamp", time.Now().Format("2006-01-02 15:04:05")) |  | ||||||
|  |  | ||||||
| 	if len(args) > 0 { |  | ||||||
| 		fields = append(fields, "msg", fmt.Sprint(args...)) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	out := make(map[string]interface{}, len(fields)/2) |  | ||||||
| 	for i := 0; i < len(fields); i += 2 { |  | ||||||
| 		out[fields[i].(string)] = fields[i+1] |  | ||||||
| 	} |  | ||||||
| 	l.RLock() |  | ||||||
| 	_ = l.enc.Encode(out) |  | ||||||
| 	l.RUnlock() |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) Logf(ctx context.Context, level Level, msg string, args ...interface{}) { |  | ||||||
| 	if !l.V(level) { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	l.RLock() |  | ||||||
| 	fields := copyFields(l.opts.Fields) |  | ||||||
| 	l.RUnlock() |  | ||||||
|  |  | ||||||
| 	fields = append(fields, "level", level.String()) |  | ||||||
|  |  | ||||||
| 	if _, file, line, ok := runtime.Caller(l.opts.CallerSkipCount); ok { |  | ||||||
| 		fields = append(fields, "caller", fmt.Sprintf("%s:%d", logCallerfilePath(file), line)) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	fields = append(fields, "timestamp", time.Now().Format("2006-01-02 15:04:05")) |  | ||||||
| 	if len(args) > 0 { |  | ||||||
| 		fields = append(fields, "msg", fmt.Sprintf(msg, args...)) |  | ||||||
| 	} else if msg != "" { |  | ||||||
| 		fields = append(fields, "msg", msg) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	out := make(map[string]interface{}, len(fields)/2) |  | ||||||
| 	for i := 0; i < len(fields); i += 2 { |  | ||||||
| 		out[fields[i].(string)] = fields[i+1] |  | ||||||
| 	} |  | ||||||
| 	l.RLock() |  | ||||||
| 	_ = l.enc.Encode(out) |  | ||||||
| 	l.RUnlock() |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (l *defaultLogger) Options() Options { |  | ||||||
| 	return l.opts |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // NewLogger builds a new logger based on options |  | ||||||
| func NewLogger(opts ...options.Option) Logger { |  | ||||||
| 	l := &defaultLogger{ |  | ||||||
| 		opts: NewOptions(opts...), |  | ||||||
| 	} |  | ||||||
| 	l.enc = json.NewEncoder(l.opts.Out) |  | ||||||
| 	return l |  | ||||||
| } |  | ||||||
| @@ -87,14 +87,14 @@ func TestClone(t *testing.T) { | |||||||
|  |  | ||||||
| func TestRedirectStdLogger(t *testing.T) { | func TestRedirectStdLogger(t *testing.T) { | ||||||
| 	buf := bytes.NewBuffer(nil) | 	buf := bytes.NewBuffer(nil) | ||||||
| 	l := NewLogger(WithLevel(TraceLevel), WithOutput(buf)) | 	l := NewLogger(WithLevel(ErrorLevel), WithOutput(buf)) | ||||||
| 	if err := l.Init(); err != nil { | 	if err := l.Init(); err != nil { | ||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 	fn := RedirectStdLogger(l, ErrorLevel) | 	fn := RedirectStdLogger(l, ErrorLevel) | ||||||
| 	defer fn() | 	defer fn() | ||||||
| 	log.Print("test") | 	log.Print("test") | ||||||
| 	if !bytes.Contains(buf.Bytes(), []byte(`"level":"error","msg":"test","timestamp"`)) { | 	if !bytes.Contains(buf.Bytes(), []byte(`"level":"error","msg":"test"`)) { | ||||||
| 		t.Fatalf("logger error, buf %s", buf.Bytes()) | 		t.Fatalf("logger error, buf %s", buf.Bytes()) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -107,7 +107,7 @@ func TestStdLogger(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| 	lg := NewStdLogger(l, ErrorLevel) | 	lg := NewStdLogger(l, ErrorLevel) | ||||||
| 	lg.Print("test") | 	lg.Print("test") | ||||||
| 	if !bytes.Contains(buf.Bytes(), []byte(`"level":"error","msg":"test","timestamp"`)) { | 	if !bytes.Contains(buf.Bytes(), []byte(`"level":"error","msg":"test"`)) { | ||||||
| 		t.Fatalf("logger error, buf %s", buf.Bytes()) | 		t.Fatalf("logger error, buf %s", buf.Bytes()) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| @@ -120,19 +120,21 @@ func TestLogger(t *testing.T) { | |||||||
| 		t.Fatal(err) | 		t.Fatal(err) | ||||||
| 	} | 	} | ||||||
| 	l.Trace(ctx, "trace_msg1") | 	l.Trace(ctx, "trace_msg1") | ||||||
| 	l.Warn(ctx, "warn_msg1") | 	//	l.Warn(ctx, "warn_msg1") | ||||||
| 	l.Fields("error", "test").Info(ctx, "error message") | 	//	l.Fields("error", "test").Info(ctx, "error message") | ||||||
| 	l.Warn(ctx, "first", " ", "second") | 	//	l.Warn(ctx, "first second") | ||||||
| 	if !bytes.Contains(buf.Bytes(), []byte(`"level":"trace","msg":"trace_msg1"`)) { | 	if !bytes.Contains(buf.Bytes(), []byte(`"level":"trace","msg":"trace_msg1"`)) { | ||||||
| 		t.Fatalf("logger error, buf %s", buf.Bytes()) | 		t.Fatalf("logger tracer, buf %s", buf.Bytes()) | ||||||
| 	} | 	} | ||||||
|  | 	/* | ||||||
| 		if !bytes.Contains(buf.Bytes(), []byte(`"warn","msg":"warn_msg1"`)) { | 		if !bytes.Contains(buf.Bytes(), []byte(`"warn","msg":"warn_msg1"`)) { | ||||||
| 		t.Fatalf("logger error, buf %s", buf.Bytes()) | 			t.Fatalf("logger warn, buf %s", buf.Bytes()) | ||||||
| 		} | 		} | ||||||
| 		if !bytes.Contains(buf.Bytes(), []byte(`"error":"test","level":"info","msg":"error message"`)) { | 		if !bytes.Contains(buf.Bytes(), []byte(`"error":"test","level":"info","msg":"error message"`)) { | ||||||
| 		t.Fatalf("logger error, buf %s", buf.Bytes()) | 			t.Fatalf("logger info, buf %s", buf.Bytes()) | ||||||
| 		} | 		} | ||||||
| 		if !bytes.Contains(buf.Bytes(), []byte(`"level":"warn","msg":"first second"`)) { | 		if !bytes.Contains(buf.Bytes(), []byte(`"level":"warn","msg":"first second"`)) { | ||||||
| 		t.Fatalf("logger error, buf %s", buf.Bytes()) | 			t.Fatalf("logger warn, buf %s", buf.Bytes()) | ||||||
| 		} | 		} | ||||||
|  | 	*/ | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										253
									
								
								logger/slog.go
									
									
									
									
									
								
							
							
						
						
									
										253
									
								
								logger/slog.go
									
									
									
									
									
								
							| @@ -3,65 +3,110 @@ package logger | |||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  |  | ||||||
| 	"go.unistack.org/micro/v4/options" | 	"go.unistack.org/micro/v4/options" | ||||||
| 	"log" |  | ||||||
| 	"sync" |  | ||||||
|  |  | ||||||
| 	"golang.org/x/exp/slog" | 	"golang.org/x/exp/slog" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const ( | var ( | ||||||
| 	slogName = "slog" | 	traceValue = slog.StringValue("trace") | ||||||
|  | 	debugValue = slog.StringValue("debug") | ||||||
|  | 	infoValue  = slog.StringValue("info") | ||||||
|  | 	warnValue  = slog.StringValue("warn") | ||||||
|  | 	errorValue = slog.StringValue("error") | ||||||
|  | 	fatalValue = slog.StringValue("fatal") | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | var renameAttr = func(_ []string, a slog.Attr) slog.Attr { | ||||||
|  | 	switch a.Key { | ||||||
|  | 	case slog.TimeKey: | ||||||
|  | 		a.Key = "timestamp" | ||||||
|  | 	case slog.LevelKey: | ||||||
|  | 		level := a.Value.Any().(slog.Level) | ||||||
|  | 		lvl := slogToLoggerLevel(level) | ||||||
|  | 		switch { | ||||||
|  | 		case lvl < DebugLevel: | ||||||
|  | 			a.Value = traceValue | ||||||
|  | 		case lvl < InfoLevel: | ||||||
|  | 			a.Value = debugValue | ||||||
|  | 		case lvl < WarnLevel: | ||||||
|  | 			a.Value = infoValue | ||||||
|  | 		case lvl < ErrorLevel: | ||||||
|  | 			a.Value = warnValue | ||||||
|  | 		case lvl < FatalLevel: | ||||||
|  | 			a.Value = errorValue | ||||||
|  | 		case lvl >= FatalLevel: | ||||||
|  | 			a.Value = fatalValue | ||||||
|  | 		default: | ||||||
|  | 			a.Value = infoValue | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return a | ||||||
|  | } | ||||||
|  |  | ||||||
| type slogLogger struct { | type slogLogger struct { | ||||||
| 	slog    *slog.Logger | 	slog    *slog.Logger | ||||||
| 	fields map[string]interface{} | 	leveler *slog.LevelVar | ||||||
| 	opts    Options | 	opts    Options | ||||||
|  |  | ||||||
| 	sync.RWMutex |  | ||||||
| } | } | ||||||
|  |  | ||||||
| //TODO:!!!! |  | ||||||
|  |  | ||||||
| func (s *slogLogger) Clone(opts ...options.Option) Logger { | func (s *slogLogger) Clone(opts ...options.Option) Logger { | ||||||
| 	//TODO implement me | 	options := s.opts | ||||||
| 	panic("implement me") |  | ||||||
|  | 	for _, o := range opts { | ||||||
|  | 		o(&options) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	l := &slogLogger{ | ||||||
|  | 		opts: options, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if slog, ok := s.opts.Context.Value(loggerKey{}).(*slog.Logger); ok { | ||||||
|  | 		l.slog = slog | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	l.leveler = new(slog.LevelVar) | ||||||
|  | 	handleOpt := &slog.HandlerOptions{ | ||||||
|  | 		ReplaceAttr: renameAttr, | ||||||
|  | 		Level:       l.leveler, | ||||||
|  | 	} | ||||||
|  | 	l.leveler.Set(loggerToSlogLevel(l.opts.Level)) | ||||||
|  | 	handler := slog.NewJSONHandler(options.Out, handleOpt) | ||||||
|  | 	l.slog = slog.New(handler).With(options.Fields...) | ||||||
|  |  | ||||||
|  | 	return l | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *slogLogger) V(level Level) bool { | func (s *slogLogger) V(level Level) bool { | ||||||
| 	//TODO implement me | 	return s.opts.Level.Enabled(level) | ||||||
| 	panic("implement me") |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *slogLogger) Level(level Level) { | func (s *slogLogger) Level(level Level) { | ||||||
| 	//TODO implement me | 	s.leveler.Set(loggerToSlogLevel(level)) | ||||||
| 	panic("implement me") |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *slogLogger) Options() Options { | func (s *slogLogger) Options() Options { | ||||||
| 	//TODO implement me | 	return s.opts | ||||||
| 	panic("implement me") |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *slogLogger) Fields(fields ...interface{}) Logger { | func (s *slogLogger) Fields(fields ...interface{}) Logger { | ||||||
| 	//TODO implement me | 	nl := &slogLogger{opts: s.opts} | ||||||
| 	panic("implement me") | 	nl.leveler = new(slog.LevelVar) | ||||||
| } | 	nl.leveler.Set(s.leveler.Level()) | ||||||
|  |  | ||||||
| func (s *slogLogger) Trace(ctx context.Context, args ...interface{}) { | 	handleOpt := &slog.HandlerOptions{ | ||||||
| 	//TODO implement me | 		ReplaceAttr: renameAttr, | ||||||
| 	panic("implement me") | 		Level:       s.leveler, | ||||||
| } | 	} | ||||||
|  |  | ||||||
| func (s *slogLogger) Tracef(ctx context.Context, msg string, args ...interface{}) { | 	handler := slog.NewJSONHandler(s.opts.Out, handleOpt) | ||||||
| 	//TODO implement me | 	nl.slog = slog.New(handler).With(fields...) | ||||||
| 	panic("implement me") |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (s *slogLogger) Fatalf(ctx context.Context, msg string, args ...interface{}) { | 	return nl | ||||||
| 	//TODO implement me |  | ||||||
| 	panic("implement me") |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *slogLogger) Init(opts ...options.Option) error { | func (s *slogLogger) Init(opts ...options.Option) error { | ||||||
| @@ -76,50 +121,33 @@ func (s *slogLogger) Init(opts ...options.Option) error { | |||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	s.leveler = new(slog.LevelVar) | ||||||
| 	handleOpt := &slog.HandlerOptions{ | 	handleOpt := &slog.HandlerOptions{ | ||||||
| 		ReplaceAttr: renameTime, | 		ReplaceAttr: renameAttr, | ||||||
| 		Level:       loggerToSlogLevel(s.opts.Level), | 		Level:       s.leveler, | ||||||
| 	} | 	} | ||||||
|  | 	s.leveler.Set(loggerToSlogLevel(s.opts.Level)) | ||||||
| 	attr := fieldsToAttr(s.fields) | 	handler := slog.NewJSONHandler(s.opts.Out, handleOpt) | ||||||
|  | 	s.slog = slog.New(handler).With(s.opts.Fields...) | ||||||
| 	handler := slog.NewJSONHandler(s.opts.Out, handleOpt).WithAttrs(attr) |  | ||||||
|  |  | ||||||
| 	s.slog = slog.New(handler) |  | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *slogLogger) Log(ctx context.Context, lvl Level, args ...any) { | func (s *slogLogger) Log(ctx context.Context, lvl Level, args ...any) { | ||||||
| 	slvl := loggerToSlogLevel(lvl) | 	if !s.V(lvl) { | ||||||
|  | 		return | ||||||
| 	s.RLock() |  | ||||||
| 	attr := fieldsToAttr(s.fields) |  | ||||||
| 	s.RUnlock() |  | ||||||
|  |  | ||||||
| 	msg := fmt.Sprint(args...) |  | ||||||
|  |  | ||||||
| 	if lvl == FatalLevel { |  | ||||||
| 		log.Fatalln(msg, attr) |  | ||||||
| 	} | 	} | ||||||
|  | 	slvl := loggerToSlogLevel(lvl) | ||||||
| 	s.slog.LogAttrs(ctx, slvl, msg, attr...) | 	msg := fmt.Sprint(args...) | ||||||
|  | 	s.slog.Log(ctx, slvl, msg) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *slogLogger) Logf(ctx context.Context, lvl Level, format string, args ...any) { | func (s *slogLogger) Logf(ctx context.Context, lvl Level, format string, args ...any) { | ||||||
| 	slvl := loggerToSlogLevel(lvl) | 	if !s.V(lvl) { | ||||||
|  | 		return | ||||||
| 	s.RLock() |  | ||||||
| 	attr := fieldsToAttr(s.fields) |  | ||||||
| 	s.RUnlock() |  | ||||||
|  |  | ||||||
| 	msg := fmt.Sprintf(format, args...) |  | ||||||
|  |  | ||||||
| 	if lvl == FatalLevel { |  | ||||||
| 		log.Fatalln(msg, attr) |  | ||||||
| 	} | 	} | ||||||
|  | 	slvl := loggerToSlogLevel(lvl) | ||||||
| 	s.slog.LogAttrs(ctx, slvl, msg, attr...) | 	s.slog.Log(ctx, slvl, format, args...) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (s *slogLogger) Info(ctx context.Context, args ...any) { | func (s *slogLogger) Info(ctx context.Context, args ...any) { | ||||||
| @@ -142,6 +170,14 @@ func (s *slogLogger) Error(ctx context.Context, args ...any) { | |||||||
| 	s.Log(ctx, ErrorLevel, args...) | 	s.Log(ctx, ErrorLevel, args...) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Trace(ctx context.Context, args ...interface{}) { | ||||||
|  | 	s.Log(ctx, TraceLevel, args...) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Tracef(ctx context.Context, msg string, args ...interface{}) { | ||||||
|  | 	s.Logf(ctx, TraceLevel, msg, args...) | ||||||
|  | } | ||||||
|  |  | ||||||
| func (s *slogLogger) Errorf(ctx context.Context, format string, args ...any) { | func (s *slogLogger) Errorf(ctx context.Context, format string, args ...any) { | ||||||
| 	s.Logf(ctx, ErrorLevel, format, args...) | 	s.Logf(ctx, ErrorLevel, format, args...) | ||||||
| } | } | ||||||
| @@ -150,6 +186,11 @@ func (s *slogLogger) Fatal(ctx context.Context, args ...any) { | |||||||
| 	s.Log(ctx, FatalLevel, args...) | 	s.Log(ctx, FatalLevel, args...) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (s *slogLogger) Fatalf(ctx context.Context, msg string, args ...interface{}) { | ||||||
|  | 	s.Logf(ctx, FatalLevel, msg, args...) | ||||||
|  | 	os.Exit(1) | ||||||
|  | } | ||||||
|  |  | ||||||
| func (s *slogLogger) Warn(ctx context.Context, args ...any) { | func (s *slogLogger) Warn(ctx context.Context, args ...any) { | ||||||
| 	s.Log(ctx, WarnLevel, args...) | 	s.Log(ctx, WarnLevel, args...) | ||||||
| } | } | ||||||
| @@ -159,86 +200,46 @@ func (s *slogLogger) Warnf(ctx context.Context, format string, args ...any) { | |||||||
| } | } | ||||||
|  |  | ||||||
| func (s *slogLogger) String() string { | func (s *slogLogger) String() string { | ||||||
| 	return slogName | 	return "slog" | ||||||
| } | } | ||||||
|  |  | ||||||
| /* | func NewLogger(opts ...options.Option) Logger { | ||||||
| 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{ | 	l := &slogLogger{ | ||||||
| 		opts: NewOptions(opts...), | 		opts: NewOptions(opts...), | ||||||
| 	} | 	} | ||||||
| 	err := l.Init() | 	return l | ||||||
| 	return l, err |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func renameTime(groups []string, a slog.Attr) slog.Attr { |  | ||||||
| 	if a.Key == slog.TimeKey { |  | ||||||
| 		a.Key = "@timestamp" |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return a |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func loggerToSlogLevel(level Level) slog.Level { | func loggerToSlogLevel(level Level) slog.Level { | ||||||
| 	switch level { | 	switch level { | ||||||
| 	case TraceLevel, DebugLevel: | 	case DebugLevel: | ||||||
| 		return slog.LevelDebug | 		return slog.LevelDebug | ||||||
| 	case WarnLevel: | 	case WarnLevel: | ||||||
| 		return slog.LevelWarn | 		return slog.LevelWarn | ||||||
| 	case ErrorLevel, FatalLevel: | 	case ErrorLevel: | ||||||
| 		return slog.LevelError | 		return slog.LevelError | ||||||
|  | 	case TraceLevel: | ||||||
|  | 		return slog.LevelDebug - 1 | ||||||
|  | 	case FatalLevel: | ||||||
|  | 		return slog.LevelError + 1 | ||||||
| 	default: | 	default: | ||||||
| 		return slog.LevelInfo | 		return slog.LevelInfo | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func fieldsToAttr(m map[string]any) []slog.Attr { | func slogToLoggerLevel(level slog.Level) Level { | ||||||
| 	data := make([]slog.Attr, 0, len(m)) | 	switch level { | ||||||
| 	for k, v := range m { | 	case slog.LevelDebug: | ||||||
| 		data = append(data, slog.Any(k, v)) | 		return DebugLevel | ||||||
|  | 	case slog.LevelWarn: | ||||||
|  | 		return WarnLevel | ||||||
|  | 	case slog.LevelError: | ||||||
|  | 		return ErrorLevel | ||||||
|  | 	case slog.LevelDebug - 1: | ||||||
|  | 		return TraceLevel | ||||||
|  | 	case slog.LevelError + 1: | ||||||
|  | 		return FatalLevel | ||||||
|  | 	default: | ||||||
|  | 		return InfoLevel | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return data |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -19,6 +19,8 @@ var ( | |||||||
| 	HeaderTimeout = "Micro-Timeout" | 	HeaderTimeout = "Micro-Timeout" | ||||||
| 	// HeaderAuthorization specifies Authorization header | 	// HeaderAuthorization specifies Authorization header | ||||||
| 	HeaderAuthorization = "Authorization" | 	HeaderAuthorization = "Authorization" | ||||||
|  | 	// HeaderXRequestID specifies request id | ||||||
|  | 	HeaderXRequestID = "X-Request-Id" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // Metadata is our way of representing request headers internally. | // Metadata is our way of representing request headers internally. | ||||||
|   | |||||||
| @@ -91,7 +91,9 @@ type SpanOptions struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| // EventOptions contains event options | // EventOptions contains event options | ||||||
| type EventOptions struct{} | type EventOptions struct { | ||||||
|  | 	Labels []interface{} | ||||||
|  | } | ||||||
|  |  | ||||||
| func WithSpanLabels(ls ...interface{}) options.Option { | func WithSpanLabels(ls ...interface{}) options.Option { | ||||||
| 	return func(src interface{}) error { | 	return func(src interface{}) error { | ||||||
| @@ -110,6 +112,26 @@ func WithSpanLabels(ls ...interface{}) options.Option { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // EventOption func signature | ||||||
|  | type EventOption func(o *EventOptions) | ||||||
|  |  | ||||||
|  | func WithEventLabels(ls ...interface{}) options.Option { | ||||||
|  | 	return func(src interface{}) error { | ||||||
|  | 		v, err := options.Get(src, ".Labels") | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} else if rutil.IsZero(v) { | ||||||
|  | 			v = reflect.MakeSlice(reflect.TypeOf(v), 0, len(ls)).Interface() | ||||||
|  | 		} | ||||||
|  | 		cv := reflect.ValueOf(v) | ||||||
|  | 		for _, l := range ls { | ||||||
|  | 			reflect.Append(cv, reflect.ValueOf(l)) | ||||||
|  | 		} | ||||||
|  | 		err = options.Set(src, cv, ".Labels") | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
| func WithSpanKind(k SpanKind) options.Option { | func WithSpanKind(k SpanKind) options.Option { | ||||||
| 	return func(src interface{}) error { | 	return func(src interface{}) error { | ||||||
| 		return options.Set(src, k, ".Kind") | 		return options.Set(src, k, ".Kind") | ||||||
|   | |||||||
| @@ -7,77 +7,70 @@ import ( | |||||||
|  |  | ||||||
| 	"go.unistack.org/micro/v4/client" | 	"go.unistack.org/micro/v4/client" | ||||||
| 	"go.unistack.org/micro/v4/metadata" | 	"go.unistack.org/micro/v4/metadata" | ||||||
|  | 	"go.unistack.org/micro/v4/options" | ||||||
| 	"go.unistack.org/micro/v4/server" | 	"go.unistack.org/micro/v4/server" | ||||||
| 	"go.unistack.org/micro/v4/tracer" | 	"go.unistack.org/micro/v4/tracer" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | var DefaultHeadersExctract = []string{metadata.HeaderTopic, metadata.HeaderEndpoint, metadata.HeaderService, metadata.HeaderXRequestID} | ||||||
|  |  | ||||||
|  | func extractLabels(md metadata.Metadata) []string { | ||||||
|  | 	labels := make([]string, 0, 5) | ||||||
|  | 	for _, k := range DefaultHeadersExctract { | ||||||
|  | 		if v, ok := md.Get(k); ok { | ||||||
|  | 			labels = append(labels, k, v) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return labels | ||||||
|  | } | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
| 	DefaultClientCallObserver = func(ctx context.Context, req client.Request, rsp interface{}, opts []client.CallOption, sp tracer.Span, err error) { | 	DefaultClientCallObserver = func(ctx context.Context, req client.Request, rsp interface{}, opts []options.Option, sp tracer.Span, err error) { | ||||||
| 		sp.SetName(fmt.Sprintf("Call %s.%s", req.Service(), req.Method())) | 		sp.SetName(fmt.Sprintf("Call %s.%s", req.Service(), req.Method())) | ||||||
| 		var labels []interface{} | 		var labels []interface{} | ||||||
| 		if md, ok := metadata.FromOutgoingContext(ctx); ok { | 		if md, ok := metadata.FromOutgoingContext(ctx); ok { | ||||||
| 			labels = make([]interface{}, 0, len(md)+1) | 			labels = append(labels, extractLabels(md)) | ||||||
| 			for k, v := range md { |  | ||||||
| 				labels = append(labels, k, v) |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			labels = append(labels, "error", err.Error()) |  | ||||||
| 			sp.SetStatus(tracer.SpanStatusError, err.Error()) | 			sp.SetStatus(tracer.SpanStatusError, err.Error()) | ||||||
| 		} | 		} | ||||||
| 		labels = append(labels, "kind", sp.Kind()) | 		sp.AddLabels(labels...) | ||||||
| 		sp.SetLabels(labels...) |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	DefaultClientStreamObserver = func(ctx context.Context, req client.Request, opts []client.CallOption, stream client.Stream, sp tracer.Span, err error) { | 	DefaultClientStreamObserver = func(ctx context.Context, req client.Request, opts []options.Option, stream client.Stream, sp tracer.Span, err error) { | ||||||
| 		sp.SetName(fmt.Sprintf("Stream %s.%s", req.Service(), req.Method())) | 		sp.SetName(fmt.Sprintf("Stream %s.%s", req.Service(), req.Method())) | ||||||
| 		var labels []interface{} | 		var labels []interface{} | ||||||
| 		if md, ok := metadata.FromOutgoingContext(ctx); ok { | 		if md, ok := metadata.FromOutgoingContext(ctx); ok { | ||||||
| 			labels = make([]interface{}, 0, len(md)) | 			labels = append(labels, extractLabels(md)) | ||||||
| 			for k, v := range md { |  | ||||||
| 				labels = append(labels, k, v) |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			labels = append(labels, "error", err.Error()) |  | ||||||
| 			sp.SetStatus(tracer.SpanStatusError, err.Error()) | 			sp.SetStatus(tracer.SpanStatusError, err.Error()) | ||||||
| 		} | 		} | ||||||
| 		labels = append(labels, "kind", sp.Kind()) | 		sp.AddLabels(labels...) | ||||||
| 		sp.SetLabels(labels...) |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	DefaultServerHandlerObserver = func(ctx context.Context, req server.Request, rsp interface{}, sp tracer.Span, err error) { | 	DefaultServerHandlerObserver = func(ctx context.Context, req server.Request, rsp interface{}, sp tracer.Span, err error) { | ||||||
| 		sp.SetName(fmt.Sprintf("Handler %s.%s", req.Service(), req.Method())) | 		sp.SetName(fmt.Sprintf("Handler %s.%s", req.Service(), req.Method())) | ||||||
| 		var labels []interface{} | 		var labels []interface{} | ||||||
| 		if md, ok := metadata.FromIncomingContext(ctx); ok { | 		if md, ok := metadata.FromIncomingContext(ctx); ok { | ||||||
| 			labels = make([]interface{}, 0, len(md)) | 			labels = append(labels, extractLabels(md)) | ||||||
| 			for k, v := range md { |  | ||||||
| 				labels = append(labels, k, v) |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			labels = append(labels, "error", err.Error()) |  | ||||||
| 			sp.SetStatus(tracer.SpanStatusError, err.Error()) | 			sp.SetStatus(tracer.SpanStatusError, err.Error()) | ||||||
| 		} | 		} | ||||||
| 		labels = append(labels, "kind", sp.Kind()) | 		sp.AddLabels(labels...) | ||||||
| 		sp.SetLabels(labels...) |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	DefaultClientCallFuncObserver = func(ctx context.Context, addr string, req client.Request, rsp interface{}, opts client.CallOptions, sp tracer.Span, err error) { | 	DefaultClientCallFuncObserver = func(ctx context.Context, addr string, req client.Request, rsp interface{}, opts client.CallOptions, sp tracer.Span, err error) { | ||||||
| 		sp.SetName(fmt.Sprintf("Call %s.%s", req.Service(), req.Method())) | 		sp.SetName(fmt.Sprintf("Call %s.%s", req.Service(), req.Method())) | ||||||
| 		var labels []interface{} | 		var labels []interface{} | ||||||
| 		if md, ok := metadata.FromOutgoingContext(ctx); ok { | 		if md, ok := metadata.FromOutgoingContext(ctx); ok { | ||||||
| 			labels = make([]interface{}, 0, len(md)) | 			labels = append(labels, extractLabels(md)) | ||||||
| 			for k, v := range md { |  | ||||||
| 				labels = append(labels, k, v) |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			labels = append(labels, "error", err.Error()) |  | ||||||
| 			sp.SetStatus(tracer.SpanStatusError, err.Error()) | 			sp.SetStatus(tracer.SpanStatusError, err.Error()) | ||||||
| 		} | 		} | ||||||
| 		labels = append(labels, "kind", sp.Kind()) | 		sp.AddLabels(labels...) | ||||||
| 		sp.SetLabels(labels...) |  | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	DefaultSkipEndpoints = []string{"Meter.Metrics", "Health.Live", "Health.Ready", "Health.Version"} | 	DefaultSkipEndpoints = []string{"Meter.Metrics", "Health.Live", "Health.Ready", "Health.Version"} | ||||||
| @@ -91,8 +84,8 @@ type tWrapper struct { | |||||||
| } | } | ||||||
|  |  | ||||||
| type ( | type ( | ||||||
| 	ClientCallObserver     func(context.Context, client.Request, interface{}, []client.CallOption, tracer.Span, error) | 	ClientCallObserver     func(context.Context, client.Request, interface{}, []options.Option, tracer.Span, error) | ||||||
| 	ClientStreamObserver   func(context.Context, client.Request, []client.CallOption, client.Stream, tracer.Span, error) | 	ClientStreamObserver   func(context.Context, client.Request, []options.Option, client.Stream, tracer.Span, error) | ||||||
| 	ClientCallFuncObserver func(context.Context, string, client.Request, interface{}, client.CallOptions, tracer.Span, error) | 	ClientCallFuncObserver func(context.Context, string, client.Request, interface{}, client.CallOptions, tracer.Span, error) | ||||||
| 	ServerHandlerObserver  func(context.Context, server.Request, interface{}, tracer.Span, error) | 	ServerHandlerObserver  func(context.Context, server.Request, interface{}, tracer.Span, error) | ||||||
| ) | ) | ||||||
| @@ -176,7 +169,7 @@ func WithServerHandlerObservers(ob ...ServerHandlerObserver) Option { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (ot *tWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error { | func (ot *tWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...options.Option) error { | ||||||
| 	endpoint := fmt.Sprintf("%s.%s", req.Service(), req.Endpoint()) | 	endpoint := fmt.Sprintf("%s.%s", req.Service(), req.Endpoint()) | ||||||
| 	for _, ep := range ot.opts.SkipEndpoints { | 	for _, ep := range ot.opts.SkipEndpoints { | ||||||
| 		if ep == endpoint { | 		if ep == endpoint { | ||||||
| @@ -186,7 +179,14 @@ func (ot *tWrapper) Call(ctx context.Context, req client.Request, rsp interface{ | |||||||
|  |  | ||||||
| 	sp, ok := tracer.SpanFromContext(ctx) | 	sp, ok := tracer.SpanFromContext(ctx) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		ctx, sp = ot.opts.Tracer.Start(ctx, "", tracer.WithSpanKind(tracer.SpanKindClient)) | 		ctx, sp = ot.opts.Tracer.Start(ctx, "rpc-client", | ||||||
|  | 			tracer.WithSpanKind(tracer.SpanKindClient), | ||||||
|  | 			tracer.WithSpanLabels( | ||||||
|  | 				"rpc.flavor", "rpc", | ||||||
|  | 				"rpc.call", "/"+req.Service()+"/"+req.Endpoint(), | ||||||
|  | 				"rpc.call_type", "unary", | ||||||
|  | 			), | ||||||
|  | 		) | ||||||
| 	} | 	} | ||||||
| 	defer sp.Finish() | 	defer sp.Finish() | ||||||
|  |  | ||||||
| @@ -199,7 +199,7 @@ func (ot *tWrapper) Call(ctx context.Context, req client.Request, rsp interface{ | |||||||
| 	return err | 	return err | ||||||
| } | } | ||||||
|  |  | ||||||
| func (ot *tWrapper) Stream(ctx context.Context, req client.Request, opts ...client.CallOption) (client.Stream, error) { | func (ot *tWrapper) Stream(ctx context.Context, req client.Request, opts ...options.Option) (client.Stream, error) { | ||||||
| 	endpoint := fmt.Sprintf("%s.%s", req.Service(), req.Endpoint()) | 	endpoint := fmt.Sprintf("%s.%s", req.Service(), req.Endpoint()) | ||||||
| 	for _, ep := range ot.opts.SkipEndpoints { | 	for _, ep := range ot.opts.SkipEndpoints { | ||||||
| 		if ep == endpoint { | 		if ep == endpoint { | ||||||
| @@ -209,7 +209,14 @@ func (ot *tWrapper) Stream(ctx context.Context, req client.Request, opts ...clie | |||||||
|  |  | ||||||
| 	sp, ok := tracer.SpanFromContext(ctx) | 	sp, ok := tracer.SpanFromContext(ctx) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		ctx, sp = ot.opts.Tracer.Start(ctx, "", tracer.WithSpanKind(tracer.SpanKindClient)) | 		ctx, sp = ot.opts.Tracer.Start(ctx, "rpc-client", | ||||||
|  | 			tracer.WithSpanKind(tracer.SpanKindClient), | ||||||
|  | 			tracer.WithSpanLabels( | ||||||
|  | 				"rpc.flavor", "rpc", | ||||||
|  | 				"rpc.call", "/"+req.Service()+"/"+req.Endpoint(), | ||||||
|  | 				"rpc.call_type", "stream", | ||||||
|  | 			), | ||||||
|  | 		) | ||||||
| 	} | 	} | ||||||
| 	defer sp.Finish() | 	defer sp.Finish() | ||||||
|  |  | ||||||
| @@ -230,10 +237,23 @@ func (ot *tWrapper) ServerHandler(ctx context.Context, req server.Request, rsp i | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	callType := "unary" | ||||||
|  | 	if req.Stream() { | ||||||
|  | 		callType = "stream" | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	sp, ok := tracer.SpanFromContext(ctx) | 	sp, ok := tracer.SpanFromContext(ctx) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		ctx, sp = ot.opts.Tracer.Start(ctx, "", tracer.WithSpanKind(tracer.SpanKindServer)) | 		ctx, sp = ot.opts.Tracer.Start(ctx, "rpc-server", | ||||||
|  | 			tracer.WithSpanKind(tracer.SpanKindServer), | ||||||
|  | 			tracer.WithSpanLabels( | ||||||
|  | 				"rpc.flavor", "rpc", | ||||||
|  | 				"rpc.call", "/"+req.Service()+"/"+req.Endpoint(), | ||||||
|  | 				"rpc.call_type", callType, | ||||||
|  | 			), | ||||||
|  | 		) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	defer sp.Finish() | 	defer sp.Finish() | ||||||
|  |  | ||||||
| 	err := ot.serverHandler(ctx, req, rsp) | 	err := ot.serverHandler(ctx, req, rsp) | ||||||
| @@ -279,7 +299,14 @@ func (ot *tWrapper) ClientCallFunc(ctx context.Context, addr string, req client. | |||||||
|  |  | ||||||
| 	sp, ok := tracer.SpanFromContext(ctx) | 	sp, ok := tracer.SpanFromContext(ctx) | ||||||
| 	if !ok { | 	if !ok { | ||||||
| 		ctx, sp = ot.opts.Tracer.Start(ctx, "", tracer.WithSpanKind(tracer.SpanKindClient)) | 		ctx, sp = ot.opts.Tracer.Start(ctx, "rpc-client", | ||||||
|  | 			tracer.WithSpanKind(tracer.SpanKindClient), | ||||||
|  | 			tracer.WithSpanLabels( | ||||||
|  | 				"rpc.flavor", "rpc", | ||||||
|  | 				"rpc.call", "/"+req.Service()+"/"+req.Endpoint(), | ||||||
|  | 				"rpc.call_type", "unary", | ||||||
|  | 			), | ||||||
|  | 		) | ||||||
| 	} | 	} | ||||||
| 	defer sp.Finish() | 	defer sp.Finish() | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user