add ability to work with protoset
Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
parent
a2a241cd78
commit
bac85a284d
2
.gitignore
vendored
2
.gitignore
vendored
@ -22,3 +22,5 @@
|
||||
go.work
|
||||
|
||||
config.yaml
|
||||
servicechecker
|
||||
*.protoset
|
||||
|
2
Makefile
2
Makefile
@ -1,2 +1,2 @@
|
||||
all:
|
||||
go build -o servicechecker ./cmd/servicechecker/*.go
|
||||
GOWORK=off go build -x -v -o servicechecker ./cmd/servicechecker/*.go
|
@ -2,22 +2,113 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
grpccli "go.unistack.org/micro-client-grpc/v3"
|
||||
jsonpbcodec "go.unistack.org/micro-codec-jsonpb/v3"
|
||||
protocodec "go.unistack.org/micro-codec-proto/v3"
|
||||
victoriametrics "go.unistack.org/micro-meter-victoriametrics/v3"
|
||||
"go.unistack.org/micro/v3/client"
|
||||
"go.unistack.org/micro/v3/logger/slog"
|
||||
"go.unistack.org/micro/v3/semconv"
|
||||
"go.unistack.org/servicechecker/pkg/config"
|
||||
"go.unistack.org/servicechecker/pkg/grpcconn"
|
||||
"google.golang.org/protobuf/reflect/protodesc"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
"google.golang.org/protobuf/types/dynamicpb"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
log := slog.NewLogger()
|
||||
l := slog.NewLogger()
|
||||
l.Init()
|
||||
m := victoriametrics.NewMeter()
|
||||
f, err := os.Open("config.yaml")
|
||||
if err != nil {
|
||||
log.Fatal(ctx, "failed to open config", err)
|
||||
l.Fatal(ctx, "failed to open config", err)
|
||||
}
|
||||
defer f.Close()
|
||||
cfg := &config.Config{}
|
||||
if err = cfg.Parse(f); err != nil {
|
||||
log.Fatal(ctx, "failed to open config", err)
|
||||
l.Fatal(ctx, "failed to open config", err)
|
||||
}
|
||||
|
||||
clients := make(map[string]client.Client)
|
||||
gcli := grpccli.NewClient(
|
||||
client.Codec("application/json", jsonpbcodec.NewCodec()),
|
||||
client.Codec("application/grpc", protocodec.NewCodec()),
|
||||
client.Codec("application/grpc+proto", protocodec.NewCodec()),
|
||||
client.Codec("application/grpc+json", jsonpbcodec.NewCodec()),
|
||||
client.ContentType("application/grpc"),
|
||||
client.Retries(0),
|
||||
// client.TLSConfig(&tls.Config{InsecureSkipVerify: true}),
|
||||
)
|
||||
protosetBuf, _ := os.ReadFile("card.protoset")
|
||||
fdset := &descriptorpb.FileDescriptorSet{}
|
||||
if err = protocodec.NewCodec().Unmarshal(protosetBuf, fdset); err != nil {
|
||||
l.Fatal(ctx, "failed to unmarshal protoset file", err)
|
||||
}
|
||||
|
||||
pfileoptions := protodesc.FileOptions{AllowUnresolvable: true}
|
||||
pfiles, err := pfileoptions.NewFiles(fdset)
|
||||
if err != nil {
|
||||
l.Fatal(ctx, "failed to use protoset file", err)
|
||||
}
|
||||
|
||||
gcli.Init()
|
||||
clients["grpc"] = gcli
|
||||
|
||||
for _, svc := range cfg.Services {
|
||||
c, ok := clients[svc.Type]
|
||||
if !ok {
|
||||
l.Error(ctx, fmt.Sprintf("unknown client %s", svc.Type))
|
||||
continue
|
||||
}
|
||||
pdesc, err := pfiles.FindDescriptorByName("card_proto.CardService")
|
||||
if err != nil {
|
||||
l.Error(ctx, "failed to find service "+svc.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
sdesc, ok := pdesc.(protoreflect.ServiceDescriptor)
|
||||
if !ok {
|
||||
l.Error(ctx, "failed to find service "+svc.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, check := range svc.Checks {
|
||||
mdesc := sdesc.Methods().ByName(protoreflect.Name(check.Name))
|
||||
if mdesc == nil {
|
||||
l.Error(ctx, "failed to find method "+check.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
req := dynamicpb.NewMessageType(mdesc.Input()).New()
|
||||
rsp := dynamicpb.NewMessageType(mdesc.Output()).New()
|
||||
|
||||
if err = jsonpbcodec.NewCodec().Unmarshal([]byte(check.Data), req); err != nil {
|
||||
l.Error(ctx, "failed to unmarshal", err)
|
||||
continue
|
||||
}
|
||||
labels := []string{"service", svc.Name, "endpoint", check.Name}
|
||||
m.Counter(semconv.ClientRequestInflight, labels...).Inc()
|
||||
ts := time.Now()
|
||||
err = grpcconn.Call(ctx, l, c, svc.Addr, time.Duration(check.Timeout),
|
||||
c.NewRequest("card_proto", "CardService."+check.Name, req),
|
||||
rsp)
|
||||
te := time.Since(ts)
|
||||
m.Summary(semconv.ClientRequestLatencyMicroseconds, labels...).Update(te.Seconds())
|
||||
m.Histogram(semconv.ClientRequestDurationSeconds, labels...).Update(te.Seconds())
|
||||
m.Counter(semconv.ClientRequestInflight, labels...).Dec()
|
||||
if err != nil {
|
||||
m.Counter(semconv.ClientRequestTotal, append(labels, "status", "failure")...).Inc()
|
||||
} else {
|
||||
m.Counter(semconv.ClientRequestTotal, append(labels, "status", "success")...).Inc()
|
||||
}
|
||||
}
|
||||
}
|
||||
m.Write(os.Stdout)
|
||||
}
|
||||
|
25
go.mod
25
go.mod
@ -2,4 +2,27 @@ module go.unistack.org/servicechecker
|
||||
|
||||
go 1.23.3
|
||||
|
||||
require go.unistack.org/micro/v3 v3.10.100
|
||||
require (
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/jhump/protoreflect/v2 v2.0.0-beta.2
|
||||
go.unistack.org/micro-client-grpc/v3 v3.11.10
|
||||
go.unistack.org/micro-codec-jsonpb/v3 v3.10.3
|
||||
go.unistack.org/micro-codec-proto/v3 v3.10.2
|
||||
go.unistack.org/micro-meter-victoriametrics/v3 v3.8.9
|
||||
go.unistack.org/micro-proto/v3 v3.4.1
|
||||
go.unistack.org/micro/v3 v3.10.100
|
||||
google.golang.org/protobuf v1.34.2
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/valyala/fastrand v1.1.0 // indirect
|
||||
github.com/valyala/histogram v1.2.0 // indirect
|
||||
go.unistack.org/metrics v0.0.1 // indirect
|
||||
golang.org/x/net v0.29.0 // indirect
|
||||
golang.org/x/sys v0.27.0 // indirect
|
||||
golang.org/x/text v0.18.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
|
||||
google.golang.org/grpc v1.67.0 // indirect
|
||||
)
|
||||
|
54
go.sum
54
go.sum
@ -1,4 +1,54 @@
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/jhump/protoreflect/v2 v2.0.0-beta.2 h1:qZU+rEZUOYTz1Bnhi3xbwn+VxdXkLVeEpAeZzVXLY88=
|
||||
github.com/jhump/protoreflect/v2 v2.0.0-beta.2/go.mod h1:4tnOYkB/mq7QTyS3YKtVtNrJv4Psqout8HA1U+hZtgM=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G8=
|
||||
github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ=
|
||||
github.com/valyala/histogram v1.2.0 h1:wyYGAZZt3CpwUiIb9AU/Zbllg1llXyrtApRS815OLoQ=
|
||||
github.com/valyala/histogram v1.2.0/go.mod h1:Hb4kBwb4UxsaNbbbh+RRz8ZR6pdodR57tzWUS3BUzXY=
|
||||
go.unistack.org/metrics v0.0.1 h1:sCnGO059ZccGC/D34iRH121eSk+7ci5+OY9cl5K7GKY=
|
||||
go.unistack.org/metrics v0.0.1/go.mod h1:1FY4R7EKJa9Oz2D6wlGScNerpl6igRs9Cx/3et4Rgs4=
|
||||
go.unistack.org/micro-client-grpc/v3 v3.11.10 h1:hbqCL4JLbTtPN1ee16EK6LqTbeIr6HynJJjCRWAu2kk=
|
||||
go.unistack.org/micro-client-grpc/v3 v3.11.10/go.mod h1:S1AIA2n3GZVxKdjpMcLJSXwBpC/OzAX91D6KxFzqjbc=
|
||||
go.unistack.org/micro-codec-jsonpb/v3 v3.10.3 h1:4GTNrhpwPCRqSuimlOdgViE+95IE4YeBNeOCTawSTeM=
|
||||
go.unistack.org/micro-codec-jsonpb/v3 v3.10.3/go.mod h1:6avGT/PKXgZFh2d4dhyUfkKRWXPwzL2CJHnRLqx9o3g=
|
||||
go.unistack.org/micro-codec-proto/v3 v3.10.2 h1:9iUQjBjTsd/RgIqB5rAQMZE0CYWngoW9pbrnfcFtbXM=
|
||||
go.unistack.org/micro-codec-proto/v3 v3.10.2/go.mod h1:54e1jb6aLL9obJUwJjtVupE5zY4PugTcMSqWDhz9aC4=
|
||||
go.unistack.org/micro-meter-victoriametrics/v3 v3.8.9 h1:ZXCS0eFiSdvcFYxpxV2Q77gfwAjpIRydwAEI1QBrwuQ=
|
||||
go.unistack.org/micro-meter-victoriametrics/v3 v3.8.9/go.mod h1:xODJQ0Nu/F8k34D/z2ITL91OskI/C674XCkugAxmc3Q=
|
||||
go.unistack.org/micro-proto/v3 v3.4.1 h1:UTjLSRz2YZuaHk9iSlVqqsA50JQNAEK2ZFboGqtEa9Q=
|
||||
go.unistack.org/micro-proto/v3 v3.4.1/go.mod h1:okx/cnOhzuCX0ggl/vToatbCupi0O44diiiLLsZ93Zo=
|
||||
go.unistack.org/micro/v3 v3.10.100 h1:yWOaU0ImCGm5k5MUzlIobJUOr+KLfrR/BoDZvcHyKxM=
|
||||
go.unistack.org/micro/v3 v3.10.100/go.mod h1:YzMldzHN9Ei+zy5t/Psu7RUWDZwUfrNYiStSQtTz90g=
|
||||
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
||||
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
|
||||
google.golang.org/grpc v1.67.0 h1:IdH9y6PF5MPSdAntIcpjQ+tXO41pcQsfZV2RxtQgVcw=
|
||||
google.golang.org/grpc v1.67.0/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
@ -1,6 +1,11 @@
|
||||
package config
|
||||
|
||||
import "io"
|
||||
import (
|
||||
"io"
|
||||
|
||||
mtime "go.unistack.org/micro/v3/util/time"
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Services []*Service `json:"services,omitempty" yaml:"services,omitempty"`
|
||||
@ -9,14 +14,17 @@ type Config struct {
|
||||
type Service struct {
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
Addr string `json:"addr,omitempty" yaml:"addr,omitempty"`
|
||||
Checks []Check `json:"checks,omitempty" yaml:"checks,omitempty"`
|
||||
Type string `json:"type,omitempty" yaml:"type,omitempty"`
|
||||
Reflection bool `json:"reflection,omitempty" yaml:"reflection,omitempty"`
|
||||
Protoset string `json:"protoset,omitempty" yaml:"protoset,omitempty"`
|
||||
Checks []*Check `json:"checks,omitempty" yaml:"checks,omitempty"`
|
||||
TLSVerify *bool `json:"tls_verify,omitempty" yaml:"tls_verify,omitempty"`
|
||||
}
|
||||
|
||||
type Check struct {
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
Type string `json:"type,omitempty" yaml:"type,omitempty"`
|
||||
Data string `json:"data,omitempty" yaml:"data,omitempty"`
|
||||
Timeout string `json:"timeout,omitempty" yaml:"timeout,omitempty"`
|
||||
Timeout mtime.Duration `json:"timeout,omitempty" yaml:"timeout,omitempty"`
|
||||
}
|
||||
|
||||
func (cfg *Config) Parse(r io.Reader) error {
|
||||
|
30
pkg/grpcconn/grpcconn.go
Normal file
30
pkg/grpcconn/grpcconn.go
Normal file
@ -0,0 +1,30 @@
|
||||
package grpcconn
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"go.unistack.org/micro/v3/client"
|
||||
"go.unistack.org/micro/v3/logger"
|
||||
)
|
||||
|
||||
func Call(ctx context.Context, l logger.Logger, c client.Client, addr string, td time.Duration, req client.Request, rsp interface{}) error {
|
||||
var err error
|
||||
uid, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
l.Error(ctx, "failed to generate x-request-id", err)
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.Call(ctx, req, rsp,
|
||||
client.WithAddress(addr),
|
||||
client.WithRequestTimeout(td),
|
||||
// client.WithContentType("application/json"),
|
||||
)
|
||||
if err != nil {
|
||||
l.Error(ctx, "call failed", "x-request-id", uid.String(), err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
14
pkg/grpcconn/protoset.go
Normal file
14
pkg/grpcconn/protoset.go
Normal file
@ -0,0 +1,14 @@
|
||||
//go:build ignore
|
||||
|
||||
package grpcconn
|
||||
|
||||
import (
|
||||
"github.com/emicklei/proto"
|
||||
"github.com/jhump/protoreflect/desc"
|
||||
)
|
||||
|
||||
var protoSets = map[string]*desc.FileDescriptor
|
||||
|
||||
func GetMessage(service string, method string) (proto.Message, error) {
|
||||
return nil, nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user