diff --git a/docs/GRPC-Reporter-Option.md b/docs/GRPC-Reporter-Option.md index 84ed74b..35366e6 100644 --- a/docs/GRPC-Reporter-Option.md +++ b/docs/GRPC-Reporter-Option.md @@ -2,12 +2,12 @@ `GRPCReporterOption` allows for functional options to adjust behaviour of a `gRPC` reporter to be created by `NewGRPCReporter`. -| Function | Describe | -| ---------- | --- | -| `reporter.WithLogger` | setup logger for gRPC reporter | -| `reporter.WithCheckInterval` | setup service and endpoint registry check interval | -| `reporter.WithMaxSendQueueSize` | setup send span queue buffer length | -| `reporter.WithInstanceProps` | setup service instance properties eg: org=SkyAPM | -| `reporter.WithTransportCredentials` | setup transport layer security | -| `reporter.WithAuthentication` | used Authentication for gRPC | -| `reporter.WithCDS` | setup CDS service | \ No newline at end of file +| Function | Describe | +|-------------------------------------|----------------------------------------------------| +| `reporter.WithLog` | setup log for gRPC reporter | +| `reporter.WithCheckInterval` | setup service and endpoint registry check interval | +| `reporter.WithMaxSendQueueSize` | setup send span queue buffer length | +| `reporter.WithInstanceProps` | setup service instance properties eg: org=SkyAPM | +| `reporter.WithTransportCredentials` | setup transport layer security | +| `reporter.WithAuthentication` | used Authentication for gRPC | +| `reporter.WithCDS` | setup CDS service | \ No newline at end of file diff --git a/logger/log.go b/logger/log.go new file mode 100644 index 0000000..840fbe9 --- /dev/null +++ b/logger/log.go @@ -0,0 +1,69 @@ +// +// Copyright 2022 SkyAPM org +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package logger + +import "log" + +type Log interface { + // Info logs to the INFO log. + Info(args ...interface{}) + // Infof logs to the INFO log. + Infof(format string, args ...interface{}) + // Warn logs to the WARNING and INFO logs. + Warn(args ...interface{}) + // Warnf logs to the WARNING and INFO logs. + Warnf(format string, args ...interface{}) + // Error logs to the ERROR, WARNING, and INFO logs. + Error(args ...interface{}) + // Errorf logs to the ERROR, WARNING, and INFO logs. + Errorf(format string, args ...interface{}) +} + +type defaultLogger struct { + logger *log.Logger +} + +func (d defaultLogger) Info(args ...interface{}) { + d.logger.Print(args...) +} + +func (d defaultLogger) Infof(format string, args ...interface{}) { + d.logger.Printf(format, args...) +} + +func (d defaultLogger) Warn(args ...interface{}) { + d.logger.Print(args...) +} + +func (d defaultLogger) Warnf(format string, args ...interface{}) { + d.logger.Printf(format, args...) +} + +func (d defaultLogger) Error(args ...interface{}) { + d.logger.Print(args...) +} + +func (d defaultLogger) Errorf(format string, args ...interface{}) { + d.logger.Printf(format, args...) +} + +// NewDefaultLogger Creates a new Log +func NewDefaultLogger(logger *log.Logger) Log { + return &defaultLogger{ + logger: logger, + } +} diff --git a/reporter/grpc.go b/reporter/grpc.go index 853bd7a..1f7b2fb 100644 --- a/reporter/grpc.go +++ b/reporter/grpc.go @@ -25,6 +25,7 @@ import ( "github.com/SkyAPM/go2sky" "github.com/SkyAPM/go2sky/internal/tool" + "github.com/SkyAPM/go2sky/logger" "google.golang.org/grpc" "google.golang.org/grpc/connectivity" "google.golang.org/grpc/credentials" @@ -45,7 +46,7 @@ const ( // NewGRPCReporter create a new reporter to send data to gRPC oap server. Only one backend address is allowed. func NewGRPCReporter(serverAddr string, opts ...GRPCReporterOption) (go2sky.Reporter, error) { r := &gRPCReporter{ - logger: log.New(os.Stderr, defaultLogPrefix, log.LstdFlags), + logger: logger.NewDefaultLogger(log.New(os.Stderr, defaultLogPrefix, log.LstdFlags)), sendCh: make(chan *agentv3.SegmentObject, maxSendQueueSize), checkInterval: defaultCheckInterval, } @@ -85,7 +86,15 @@ func NewGRPCReporter(serverAddr string, opts ...GRPCReporterOption) (go2sky.Repo type GRPCReporterOption func(r *gRPCReporter) // WithLogger setup logger for gRPC reporter -func WithLogger(logger *log.Logger) GRPCReporterOption { +// Deprecated: WithLog is recommended +func WithLogger(log *log.Logger) GRPCReporterOption { + return func(r *gRPCReporter) { + r.logger = logger.NewDefaultLogger(log) + } +} + +// WithLog setup log for gRPC reporter +func WithLog(logger logger.Log) GRPCReporterOption { return func(r *gRPCReporter) { r.logger = logger } @@ -137,7 +146,7 @@ type gRPCReporter struct { service string serviceInstance string instanceProps map[string]string - logger *log.Logger + logger logger.Log sendCh chan *agentv3.SegmentObject conn *grpc.ClientConn traceClient agentv3.TraceSegmentReportServiceClient @@ -223,13 +232,13 @@ func (r *gRPCReporter) Send(spans []go2sky.ReportedSpan) { defer func() { // recover the panic caused by close sendCh if err := recover(); err != nil { - r.logger.Printf("reporter segment err %v", err) + r.logger.Errorf("reporter segment err %v", err) } }() select { case r.sendCh <- segmentObject: default: - r.logger.Printf("reach max send buffer") + r.logger.Errorf("reach max send buffer") } } @@ -244,7 +253,7 @@ func (r *gRPCReporter) Close() { func (r *gRPCReporter) closeGRPCConn() { if r.conn != nil { if err := r.conn.Close(); err != nil { - r.logger.Print(err) + r.logger.Error(err) } } } @@ -258,14 +267,14 @@ func (r *gRPCReporter) initSendPipeline() { for { stream, err := r.traceClient.Collect(metadata.NewOutgoingContext(context.Background(), r.md)) if err != nil { - r.logger.Printf("open stream error %v", err) + r.logger.Errorf("open stream error %v", err) time.Sleep(5 * time.Second) continue StreamLoop } for s := range r.sendCh { err = stream.Send(s) if err != nil { - r.logger.Printf("send segment error %v", err) + r.logger.Errorf("send segment error %v", err) r.closeStream(stream) continue StreamLoop } @@ -298,7 +307,7 @@ func (r *gRPCReporter) initCDS(cdsWatchers []go2sky.AgentConfigChangeWatcher) { }) if err != nil { - r.logger.Printf("fetch dynamic configuration error %v", err) + r.logger.Errorf("fetch dynamic configuration error %v", err) time.Sleep(r.checkInterval) continue } @@ -316,7 +325,7 @@ func (r *gRPCReporter) initCDS(cdsWatchers []go2sky.AgentConfigChangeWatcher) { func (r *gRPCReporter) closeStream(stream agentv3.TraceSegmentReportService_CollectClient) { _, err := stream.CloseAndRecv() if err != nil && err != io.EOF { - r.logger.Printf("send closing error %v", err) + r.logger.Errorf("send closing error %v", err) } } @@ -352,7 +361,7 @@ func (r *gRPCReporter) check() { if !instancePropertiesSubmitted { err := r.reportInstanceProperties() if err != nil { - r.logger.Printf("report serviceInstance properties error %v", err) + r.logger.Errorf("report serviceInstance properties error %v", err) time.Sleep(r.checkInterval) continue } @@ -365,7 +374,7 @@ func (r *gRPCReporter) check() { }) if err != nil { - r.logger.Printf("send keep alive signal error %v", err) + r.logger.Errorf("send keep alive signal error %v", err) } time.Sleep(r.checkInterval) } diff --git a/reporter/grpc_test.go b/reporter/grpc_test.go index 414e790..5d4d288 100644 --- a/reporter/grpc_test.go +++ b/reporter/grpc_test.go @@ -21,10 +21,13 @@ import ( "fmt" "log" "os" + "reflect" "testing" "time" + "unsafe" "github.com/SkyAPM/go2sky" + "github.com/SkyAPM/go2sky/logger" "github.com/SkyAPM/go2sky/propagation" mock "github.com/SkyAPM/go2sky/reporter/grpc/management/mock_management" "github.com/golang/mock/gomock" @@ -133,7 +136,10 @@ func TestGRPCReporterOption(t *testing.T) { instanceProps["org"] = "SkyAPM" // log - logger := log.New(os.Stderr, "WithLogger", log.LstdFlags) + log1 := log.New(os.Stderr, "WithLogger", log.LstdFlags) + + // custom log + log2 := &testLog{} // tls creds, err := credentials.NewClientTLSFromFile("../test/test-data/certs/cert.crt", "SkyAPM.org") @@ -180,13 +186,24 @@ func TestGRPCReporterOption(t *testing.T) { }, { name: "with logger", - option: WithLogger(logger), + option: WithLogger(log1), verifyFunc: func(t *testing.T, reporter *gRPCReporter) { - if reporter.logger != logger { + log3 := reflect.ValueOf(reporter.logger).Elem().FieldByName("logger") + log3 = reflect.NewAt(log3.Type(), unsafe.Pointer(log3.UnsafeAddr())).Elem() + if log3.Interface() != log1 { t.Error("error are not set logger") } }, }, + { + name: "with log", + option: WithLog(log2), + verifyFunc: func(t *testing.T, reporter *gRPCReporter) { + if reporter.logger != log2 { + t.Error("error are not set log") + } + }, + }, { name: "with auth", option: WithAuthentication("test"), @@ -258,7 +275,7 @@ func TestGRPCReporter_reportInstanceProperties(t *testing.T) { func createGRPCReporter() *gRPCReporter { reporter := &gRPCReporter{ - logger: log.New(os.Stderr, "go2sky", log.LstdFlags), + logger: logger.NewDefaultLogger(log.New(os.Stderr, "go2sky", log.LstdFlags)), } return reporter } @@ -288,3 +305,31 @@ func (e instancePropertiesMatcher) Matches(x interface{}) bool { func (e instancePropertiesMatcher) String() string { return fmt.Sprintf("is equal to %v", e.x) } + +// testLog test only +type testLog struct { +} + +func (t testLog) Info(args ...interface{}) { + fmt.Print(args...) +} + +func (t testLog) Infof(format string, args ...interface{}) { + fmt.Printf(format, args...) +} + +func (t testLog) Warn(args ...interface{}) { + fmt.Print(args...) +} + +func (t testLog) Warnf(format string, args ...interface{}) { + fmt.Printf(format, args...) +} + +func (t testLog) Error(args ...interface{}) { + fmt.Print(args...) +} + +func (t testLog) Errorf(format string, args ...interface{}) { + fmt.Printf(format, args...) +}