From ed6d8ae6254aadc24bf8f132b3013e10a360e940 Mon Sep 17 00:00:00 2001 From: Pavlo Sumkin Date: Tue, 8 Oct 2024 22:19:19 +0200 Subject: [PATCH] chore(deps): Bump github.com/gwos/tcg/sdk from v8.7.2 to v8.8.0 (#15947) Co-authored-by: Pavlo Sumkin Co-authored-by: VladislavSenkevich --- go.mod | 2 +- go.sum | 4 +- plugins/outputs/groundwork/groundwork.go | 76 +++------------- plugins/outputs/groundwork/groundwork_test.go | 54 ++++++++++++ plugins/outputs/groundwork/log_adapter.go | 87 +++++++++++++++++++ 5 files changed, 154 insertions(+), 69 deletions(-) create mode 100644 plugins/outputs/groundwork/log_adapter.go diff --git a/go.mod b/go.mod index 3b27613ae..5dc959299 100644 --- a/go.mod +++ b/go.mod @@ -108,7 +108,7 @@ require ( github.com/gorilla/websocket v1.5.3 github.com/gosnmp/gosnmp v1.38.0 github.com/grid-x/modbus v0.0.0-20240503115206-582f2ab60a18 - github.com/gwos/tcg/sdk v0.0.0-20231124052037-1e832b843240 + github.com/gwos/tcg/sdk v0.0.0-20240830123415-f8a34bba6358 github.com/harlow/kinesis-consumer v0.3.6-0.20240916192723-43900507c911 github.com/hashicorp/consul/api v1.29.2 github.com/hashicorp/go-uuid v1.0.3 diff --git a/go.sum b/go.sum index 83ac8a2de..ede21f484 100644 --- a/go.sum +++ b/go.sum @@ -1485,8 +1485,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1 github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= -github.com/gwos/tcg/sdk v0.0.0-20231124052037-1e832b843240 h1:dQUb3aqhbE1Z/QximDiPfBbTkq90Pf6p2f4k5M2puus= -github.com/gwos/tcg/sdk v0.0.0-20231124052037-1e832b843240/go.mod h1:H3CAtDtRLVPIkShWzarGiKYVZqrBtWNJMMRtfqJ3rXI= +github.com/gwos/tcg/sdk v0.0.0-20240830123415-f8a34bba6358 h1:QmKzhYk6KMjUutu9Sy4DyOkRgj1Dv+iFnea4t8KrCZg= +github.com/gwos/tcg/sdk v0.0.0-20240830123415-f8a34bba6358/go.mod h1:h40FJV0HuULqXSSKf7kfCbOxEcQAD74a5e2LC2+rYiQ= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/harlow/kinesis-consumer v0.3.6-0.20240916192723-43900507c911 h1:eLNkr0OcBl7pzM6DCLSgVp3VQyS5ZrLnanXPqH5EmE0= diff --git a/plugins/outputs/groundwork/groundwork.go b/plugins/outputs/groundwork/groundwork.go index bf61c56db..5c770a7c9 100644 --- a/plugins/outputs/groundwork/groundwork.go +++ b/plugins/outputs/groundwork/groundwork.go @@ -2,7 +2,6 @@ package groundwork import ( - "bytes" "context" _ "embed" "encoding/json" @@ -12,7 +11,7 @@ import ( "strings" "github.com/gwos/tcg/sdk/clients" - "github.com/gwos/tcg/sdk/logper" + "github.com/gwos/tcg/sdk/log" "github.com/gwos/tcg/sdk/transit" "github.com/hashicorp/go-uuid" @@ -95,28 +94,16 @@ func (g *Groundwork) Init() error { username.Destroy() password.Destroy() - logper.SetLogger( - func(fields interface{}, format string, a ...interface{}) { - g.Log.Error(adaptLog(fields, format, a...)) - }, - func(fields interface{}, format string, a ...interface{}) { - g.Log.Warn(adaptLog(fields, format, a...)) - }, - func(fields interface{}, format string, a ...interface{}) { - g.Log.Info(adaptLog(fields, format, a...)) - }, - func(fields interface{}, format string, a ...interface{}) { - g.Log.Debug(adaptLog(fields, format, a...)) - }, - func() bool { return g.Log.Level() >= telegraf.Debug }, - ) + /* adapt SDK logger */ + log.Logger = newLogger(g.Log).WithGroup("tcg.sdk") + return nil } func (g *Groundwork) Connect() error { err := g.client.Connect() if err != nil { - return fmt.Errorf("could not log in: %w", err) + return fmt.Errorf("could not login: %w", err) } return nil } @@ -124,7 +111,7 @@ func (g *Groundwork) Connect() error { func (g *Groundwork) Close() error { err := g.client.Disconnect() if err != nil { - return fmt.Errorf("could not log out: %w", err) + return fmt.Errorf("could not logout: %w", err) } return nil } @@ -346,15 +333,15 @@ func (g *Groundwork) parseMetric(metric telegraf.Metric) (metricMeta, *transit.M } if m, ok := metric.GetTag("message"); ok { - serviceObject.LastPluginOutput = m + serviceObject.LastPluginOutput = strings.ToValidUTF8(m, "?") } else if m, ok := metric.GetField("message"); ok { switch m := m.(type) { case string: - serviceObject.LastPluginOutput = m + serviceObject.LastPluginOutput = strings.ToValidUTF8(m, "?") case []byte: - serviceObject.LastPluginOutput = string(m) + serviceObject.LastPluginOutput = strings.ToValidUTF8(string(m), "?") default: - serviceObject.LastPluginOutput = fmt.Sprintf("%v", m) + serviceObject.LastPluginOutput = strings.ToValidUTF8(fmt.Sprintf("%v", m), "?") } } @@ -395,46 +382,3 @@ func validStatus(status string) bool { } return false } - -func adaptLog(fields interface{}, format string, a ...interface{}) string { - buf := &bytes.Buffer{} - if format != "" { - fmt.Fprintf(buf, format, a...) - } - fmtField := func(k string, v interface{}) { - format := " %s:" - if len(k) == 0 { - format = " " - } - if _, ok := v.(int); ok { - format += "%d" - } else { - format += "%q" - } - fmt.Fprintf(buf, format, k, v) - } - if ff, ok := fields.(interface { - LogFields() (map[string]interface{}, map[string][]byte) - }); ok { - m1, m2 := ff.LogFields() - for k, v := range m1 { - fmtField(k, v) - } - for k, v := range m2 { - fmtField(k, v) - } - } else if ff, ok := fields.(map[string]interface{}); ok { - for k, v := range ff { - fmtField(k, v) - } - } else if ff, ok := fields.([]interface{}); ok { - for _, v := range ff { - fmtField("", v) - } - } - out := buf.Bytes() - if len(out) > 1 { - out = append(bytes.ToUpper(out[0:1]), out[1:]...) - } - return string(out) -} diff --git a/plugins/outputs/groundwork/groundwork_test.go b/plugins/outputs/groundwork/groundwork_test.go index a1b8b18fc..de073f7b6 100644 --- a/plugins/outputs/groundwork/groundwork_test.go +++ b/plugins/outputs/groundwork/groundwork_test.go @@ -1,6 +1,7 @@ package groundwork import ( + "bytes" "encoding/json" "fmt" "io" @@ -13,6 +14,8 @@ import ( "github.com/stretchr/testify/require" "github.com/influxdata/telegraf" + "github.com/influxdata/telegraf/config" + "github.com/influxdata/telegraf/logger" "github.com/influxdata/telegraf/testutil" ) @@ -23,6 +26,57 @@ const ( customAppType = "SYSLOG" ) +func TestWriteWithDebug(t *testing.T) { + // Generate test metric with default name to test Write logic + intMetric := testutil.TestMetric(42, "IntMetric") + srvTok := "88fcf0de5bf7-530b-ee84-d385-cc6761ce" + + // Simulate Groundwork server that should receive custom metrics + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + body, err := io.ReadAll(r.Body) + require.NoError(t, err) + + // Decode body to use in assertions below + var obj transit.ResourcesWithServicesRequest + err = json.Unmarshal(body, &obj) + require.NoError(t, err) + + // Check if server gets proper data + require.Equal(t, "IntMetric", obj.Resources[0].Services[0].Name) + require.Equal(t, int64(42), *obj.Resources[0].Services[0].Metrics[0].Value.IntegerValue) + + // Send back details + ans := "Content-type: application/json\n\n" + `{"message":"` + srvTok + `"}` + _, err = fmt.Fprintln(w, ans) + require.NoError(t, err) + })) + + i := Groundwork{ + Server: server.URL, + AgentID: defaultTestAgentID, + Username: config.NewSecret([]byte(`tu ser`)), + Password: config.NewSecret([]byte(`pu ser`)), + DefaultAppType: defaultAppType, + DefaultHost: defaultHost, + DefaultServiceState: string(transit.ServiceOk), + ResourceTag: "host", + Log: testutil.Logger{}, + } + + buf := new(bytes.Buffer) + require.NoError(t, logger.SetupLogging(&logger.Config{Debug: true})) + logger.RedirectLogging(buf) + + require.NoError(t, i.Init()) + require.NoError(t, i.Write([]telegraf.Metric{intMetric})) + + require.NoError(t, logger.CloseLogging()) + require.Contains(t, buf.String(), defaultTestAgentID) + require.Contains(t, buf.String(), srvTok) + + server.Close() +} + func TestWriteWithDefaults(t *testing.T) { // Generate test metric with default name to test Write logic intMetric := testutil.TestMetric(42, "IntMetric") diff --git a/plugins/outputs/groundwork/log_adapter.go b/plugins/outputs/groundwork/log_adapter.go new file mode 100644 index 000000000..4b4f9902e --- /dev/null +++ b/plugins/outputs/groundwork/log_adapter.go @@ -0,0 +1,87 @@ +package groundwork + +import ( + "context" + "encoding/json" + "log/slog" //nolint:depguard // Required for wrapping internal logging facility + "strings" + + "github.com/influxdata/telegraf" +) + +// newLogger creates telegraf.Logger adapter for slog.Logger +func newLogger(l telegraf.Logger) *slog.Logger { + return slog.New(&tlgHandler{Log: l}) +} + +// tlgHandler translates slog.Record into telegraf.Logger call +// inspired by https://github.com/golang/example/blob/master/slog-handler-guide/README.md +type tlgHandler struct { + attrs []slog.Attr + groups []string + + Log telegraf.Logger +} + +// Enabled implements slog.Handler interface +// It interprets errors as errors and everything else as debug. +func (h *tlgHandler) Enabled(_ context.Context, level slog.Level) bool { + if level == slog.LevelError { + return h.Log.Level() >= telegraf.Error + } + return h.Log.Level() >= telegraf.Debug +} + +// Handle implements slog.Handler interface +// It interprets errors as errors and everything else as debug. +func (h *tlgHandler) Handle(_ context.Context, r slog.Record) error { + attrs := make([]slog.Attr, 0, 2+len(h.attrs)+r.NumAttrs()) + attrs = append(attrs, + slog.String("logger", strings.Join(h.groups, ",")), + slog.String("message", r.Message), + ) + attrs = append(attrs, h.attrs...) + + r.Attrs(func(attr slog.Attr) bool { + if v, ok := attr.Value.Any().(json.RawMessage); ok { + attrs = append(attrs, slog.String(attr.Key, string(v))) + return true + } + attrs = append(attrs, attr) + return true + }) + + if r.Level == slog.LevelError { + h.Log.Error(attrs) + } else { + h.Log.Debug(attrs) + } + + return nil +} + +// WithAttrs implements slog.Handler interface +func (h *tlgHandler) WithAttrs(attrs []slog.Attr) slog.Handler { + nested := &tlgHandler{Log: h.Log} + nested.attrs = append(nested.attrs, h.attrs...) + nested.groups = append(nested.groups, h.groups...) + + for _, attr := range attrs { + if v, ok := attr.Value.Any().(json.RawMessage); ok { + nested.attrs = append(nested.attrs, slog.String(attr.Key, string(v))) + continue + } + nested.attrs = append(nested.attrs, attr) + } + + return nested +} + +// WithGroup implements slog.Handler interface +func (h *tlgHandler) WithGroup(name string) slog.Handler { + nested := &tlgHandler{Log: h.Log} + nested.attrs = append(nested.attrs, h.attrs...) + nested.groups = append(nested.groups, h.groups...) + nested.groups = append(nested.groups, name) + return nested +}