Skip to content

Commit

Permalink
Develop (#13)
Browse files Browse the repository at this point in the history
* add client grpc interceptor

* add draft for slog logger

* fix lint

* fix lint

* fix lint

* fix lint

* fix lint

* fix error

* fix register

* change call string

* Update metrics/grpc_mw_client.go

Co-authored-by: Mikhail Barshev <[email protected]>

* fix mrs

---------

Co-authored-by: Mikhail Barshev <[email protected]>
  • Loading branch information
glebnaz and mike-barshev authored Nov 14, 2023
1 parent 91cb24a commit 46b9e11
Show file tree
Hide file tree
Showing 14 changed files with 422 additions and 1,577 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: set up go 1.18
- name: set up go 1.21
uses: actions/setup-go@v2
with:
go-version: 1.18
go-version: 1.21
id: go

- name: checkout
uses: actions/checkout@v2

- name: install golangci-lint and goveralls
run: |
curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b $GITHUB_WORKSPACE v1.46.2
curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b $GITHUB_WORKSPACE v1.54.0
- name: run linters
run: $GITHUB_WORKSPACE/golangci-lint run --config .golangci.yml ./...
2 changes: 1 addition & 1 deletion bin-deps.mk
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
GOLANGCI_BIN=$(LOCAL_BIN)/golangci-lint
$(GOLANGCI_BIN):
GOBIN=$(LOCAL_BIN) go install github.com/golangci/golangci-lint/cmd/golangci-lint
GOBIN=$(LOCAL_BIN) go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
35 changes: 28 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,25 +1,46 @@
module github.com/glebnaz/witcher

go 1.15
go 1.21

require (
github.com/antonfisher/nested-logrus-formatter v1.3.1
github.com/google/uuid v1.3.0
github.com/kelseyhightower/envconfig v1.4.0
github.com/klauspost/compress v1.16.5 // indirect
github.com/labstack/echo/v4 v4.10.2
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/montanaflynn/stats v0.7.1 // indirect
github.com/oklog/run v1.1.0
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.15.1
github.com/sirupsen/logrus v1.9.2
go.mongodb.org/mongo-driver v1.11.6
google.golang.org/grpc v1.55.0
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/fatih/color v1.15.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.1 // indirect
github.com/klauspost/compress v1.16.5 // indirect
github.com/labstack/gommon v0.4.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/montanaflynn/stats v0.7.1 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.10.0 // indirect
github.com/sirupsen/logrus v1.9.2
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
github.com/xdg-go/scram v1.1.2 // indirect
github.com/xdg-go/stringprep v1.0.4 // indirect
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
go.mongodb.org/mongo-driver v1.11.6
golang.org/x/crypto v0.9.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sync v0.2.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230526015343-6ee61e4f9d5f // indirect
google.golang.org/grpc v1.55.0
google.golang.org/protobuf v1.30.0 // indirect
)
1,555 changes: 5 additions & 1,550 deletions go.sum

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions log/context.go → log/context_logrus.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ import (
// for fields
type ctxFieldsKey string

var key = ctxFieldsKey("logrusFields")
var ctxKeyLogrusFields = ctxFieldsKey("logrusFields")

// for logrus.Entry
type ctxEntryKey string
type ctxEntryKeyFields string

var entryKey = ctxEntryKey("logrusEntry")
var entryKey = ctxEntryKeyFields("logrusEntry")

// AddFieldsToCTX adds fields to ctx
func AddFieldsToCTX(ctx context.Context, fields logrus.Fields) context.Context {
return context.WithValue(ctx, key, fields)
return context.WithValue(ctx, ctxKeyLogrusFields, fields)
}

func GetFieldsFromCTX(ctx context.Context) logrus.Fields {
fields, ok := ctx.Value(key).(logrus.Fields)
fields, ok := ctx.Value(ctxKeyLogrusFields).(logrus.Fields)
if !ok {
fields = logrus.Fields{}
}
Expand All @@ -31,7 +31,7 @@ func GetFieldsFromCTX(ctx context.Context) logrus.Fields {

// NewFromCTX returns a new logrus.Entry with fields from ctx
func NewFromCTX(ctx context.Context) *logrus.Entry {
fields, ok := ctx.Value(key).(logrus.Fields)
fields, ok := ctx.Value(ctxKeyLogrusFields).(logrus.Fields)
if !ok {
fields = logrus.Fields{}
}
Expand Down
28 changes: 28 additions & 0 deletions log/context_slog.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package log

import (
"context"
"log/slog"
)

type ctxKeySLOGAttr string

var ctxKeySlOGAttr = ctxKeySLOGAttr("attr")

// AddSLOGAttrToCTX adds slog attr to ctx
func AddSLOGAttrToCTX(ctx context.Context, attrs []slog.Attr) context.Context {
oldAttrs := GetSLOGAttrFromCTX(ctx)
if oldAttrs != nil {
attrs = append(oldAttrs, attrs...)
}
return context.WithValue(ctx, ctxKeySlOGAttr, attrs)
}

// GetSLOGAttrFromCTX returns slog attrs from ctx
func GetSLOGAttrFromCTX(ctx context.Context) []slog.Attr {
attrs, ok := ctx.Value(ctxKeySlOGAttr).([]slog.Attr)
if !ok {
attrs = nil
}
return attrs
}
25 changes: 25 additions & 0 deletions log/grpc_client_mw.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package log

import (
"context"

"google.golang.org/grpc"
)

// ClientLoggerUnaryInterceptor returns a new unary client interceptor for
// log from what to
func ClientLoggerUnaryInterceptor(from, to string) grpc.UnaryClientInterceptor {
return func(
ctx context.Context,
method string,
req, reply interface{},
cc *grpc.ClientConn,
invoker grpc.UnaryInvoker,
opts ...grpc.CallOption) error {
/////////////////////////////////////////////////

Debugf(ctx, "GRPC UNARY REQUEST[%s] from %s to %s", method, from, to)

return invoker(ctx, method, req, reply, cc, opts...)
}
}
35 changes: 35 additions & 0 deletions log/slog_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package log

import (
"context"
"log/slog"
)

type CTXAttrHandler struct {
slog.Handler
}

// NewCTXAttrHandler
//
// is a slog.Handler that adds slog.Attr to slog.Record from context.Context
func NewCTXAttrHandler(serviceName string, mainHandler slog.Handler) CTXAttrHandler {
mainHandler.WithAttrs([]slog.Attr{
slog.String("service", serviceName),
},
)

return CTXAttrHandler{
Handler: mainHandler,
}
}

func (p CTXAttrHandler) Handle(ctx context.Context, record slog.Record) error {
attrs := GetSLOGAttrFromCTX(ctx)
if attrs == nil {
return p.Handler.Handle(ctx, record)
}

record.AddAttrs(attrs...)

return p.Handler.Handle(ctx, record)
}
76 changes: 76 additions & 0 deletions log/slog_handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package log

import (
"bytes"
"context"
"log/slog"
"strings"
"testing"
)

func TestCTXAttrHandler(t *testing.T) {
type kv struct {
key string
value string
}

type args struct {
kv []kv
}
tests := []struct {
name string
args args
}{
{
name: "simple test with one attr in ctx",
args: args{
kv: []kv{
{
key: "req-id",
value: "123",
},
},
},
},
{
name: "simple test with two attr in ctx",
args: args{
kv: []kv{
{
key: "req-id",
value: "123",
},
{
key: "name",
value: "John Doe",
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
for _, kv := range tt.args.kv {
ctx = AddSLOGAttrToCTX(ctx, []slog.Attr{slog.String(kv.key, kv.value)})
}

buf := &bytes.Buffer{}
defer buf.Truncate(len(buf.Bytes()))

handler := NewCTXAttrHandler("test", slog.NewJSONHandler(buf, nil))
logger := slog.New(handler)
logger.InfoContext(ctx, "test")
str := buf.String()

for _, kv := range tt.args.kv {
if !strings.Contains(str, kv.key) {
t.Errorf("JSONCTXHandlerBase() = %v, want %v", str, kv.key)
}
if !strings.Contains(str, kv.value) {
t.Errorf("JSONCTXHandlerBase() = %v, want %v", str, kv.value)
}
}
})
}
}
35 changes: 28 additions & 7 deletions metrics/grpc_mw.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"context"
"time"

"github.com/prometheus/client_golang/prometheus"

"google.golang.org/grpc/status"

"google.golang.org/grpc"
Expand All @@ -25,14 +27,33 @@ func ServerMetricsUnaryInterceptor(namespace string) func(ctx context.Context,
info *grpc.UnaryServerInfo,
handler grpc.UnaryHandler) (interface{}, error) {

var serverRequestCounter = MustRegisterCounterVec("server_grpc_request_count",
namespace,
"server_request_count", []string{"method", "code"})
const nameCounter = "server_grpc_request_count"
const nameHistogram = "server_grpc_response_time"

keyCounter := nameCounter + namespace
keyHistogram := nameHistogram + namespace

var serverRequestCounter *prometheus.CounterVec
var serverResponseTime *prometheus.HistogramVec

var serverResponseTime = MustRegisterHistogramVec("server_grpc_response_time",
namespace,
"server response time in seconds",
TimeBucketsMedium, []string{"method"})
if _, ok := metricsCollector[keyCounter]; !ok {
serverRequestCounter = MustRegisterCounterVec(nameCounter,
namespace,
"server_request_count", []string{"method", "code"})
metricsCollector[keyCounter] = serverRequestCounter
} else {
serverRequestCounter = metricsCollector[keyCounter].(*prometheus.CounterVec)
}

if _, ok := metricsCollector[keyHistogram]; !ok {
serverResponseTime = MustRegisterHistogramVec(nameHistogram,
namespace,
"server response time in seconds",
TimeBucketsMedium, []string{"method"})
metricsCollector[keyHistogram] = serverResponseTime
} else {
serverResponseTime = metricsCollector[keyHistogram].(*prometheus.HistogramVec)
}

return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
startTime := time.Now()
Expand Down
Loading

0 comments on commit 46b9e11

Please sign in to comment.