Merge branch 'go-kratos:main' into main

pull/2324/head
wang tingshun 2 years ago committed by GitHub
commit fce5d1b348
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .github/workflows/go.yml
  2. 3
      api/metadata/server.go
  3. 37
      app.go
  4. 16
      app_test.go
  5. 2
      cmd/kratos/internal/base/vcs_url.go
  6. 4
      cmd/kratos/internal/change/get.go
  7. 2
      cmd/kratos/version.go
  8. 2
      cmd/protoc-gen-go-errors/version.go
  9. 17
      cmd/protoc-gen-go-http/http.go
  10. 2
      cmd/protoc-gen-go-http/version.go
  11. 8
      config/config.go
  12. 41
      config/config_test.go
  13. 6
      config/env/env.go
  14. 4
      config/env/watcher.go
  15. 14
      config/file/file_test.go
  16. 4
      config/file/format_test.go
  17. 4
      config/file/watcher.go
  18. 14
      config/options_test.go
  19. 20
      config/reader.go
  20. 46
      config/reader_test.go
  21. 44
      config/value.go
  22. 71
      config/value_test.go
  23. 1
      contrib/config/apollo/README.md
  24. 5
      contrib/config/apollo/apollo.go
  25. 2
      contrib/config/apollo/go.mod
  26. 4
      contrib/config/apollo/go.sum
  27. 5
      contrib/config/apollo/watcher.go
  28. 9
      contrib/config/consul/README.md
  29. 2
      contrib/config/consul/go.mod
  30. 8
      contrib/config/consul/go.sum
  31. 15
      contrib/config/etcd/README.md
  32. 2
      contrib/config/etcd/go.mod
  33. 3
      contrib/config/etcd/go.sum
  34. 4
      contrib/config/kubernetes/config_test.go
  35. 3
      contrib/config/nacos/README.md
  36. 3
      contrib/config/nacos/go.mod
  37. 3
      contrib/config/polaris/README.md
  38. 4
      contrib/config/polaris/config.go
  39. 10
      contrib/config/polaris/watcher.go
  40. 2
      contrib/encoding/msgpack/go.mod
  41. 36
      contrib/log/aliyun/aliyun.go
  42. 54
      contrib/log/aliyun/aliyun_test.go
  43. 4
      contrib/log/aliyun/go.mod
  44. 4
      contrib/log/aliyun/go.sum
  45. 17
      contrib/log/fluent/fluent_test.go
  46. 2
      contrib/log/fluent/go.mod
  47. 2
      contrib/log/logrus/go.mod
  48. 2
      contrib/log/tencent/go.mod
  49. 36
      contrib/log/tencent/tencent.go
  50. 45
      contrib/log/tencent/tencent_test.go
  51. 2
      contrib/log/zap/go.mod
  52. 5
      contrib/metrics/datadog/go.mod
  53. 4
      contrib/metrics/prometheus/go.mod
  54. 18
      contrib/metrics/prometheus/go.sum
  55. 4
      contrib/opensergo/go.mod
  56. 3
      contrib/opensergo/go.sum
  57. 11
      contrib/opensergo/opensergo.go
  58. 11
      contrib/opensergo/opensergo_test.go
  59. 4
      contrib/registry/consul/go.mod
  60. 8
      contrib/registry/consul/go.sum
  61. 8
      contrib/registry/consul/registry.go
  62. 2
      contrib/registry/discovery/go.mod
  63. 6
      contrib/registry/etcd/go.mod
  64. 18
      contrib/registry/etcd/go.sum
  65. 4
      contrib/registry/etcd/registry.go
  66. 55
      contrib/registry/eureka/client.go
  67. 4
      contrib/registry/eureka/register.go
  68. 2
      contrib/registry/kubernetes/go.mod
  69. 2
      contrib/registry/nacos/go.mod
  70. 4
      contrib/registry/polaris/go.mod
  71. 32
      contrib/registry/polaris/go.sum
  72. 2
      contrib/registry/zookeeper/go.mod
  73. 4
      contrib/registry/zookeeper/register.go
  74. 7
      encoding/form/form.go
  75. 20
      encoding/form/form_test.go
  76. 9
      encoding/form/proto_decode.go
  77. 217
      encoding/form/proto_decode_test.go
  78. 16
      log/filter.go
  79. 13
      log/filter_test.go
  80. 4
      log/level.go
  81. 6
      log/level_test.go
  82. 25
      middleware/auth/jwt/jwt_test.go
  83. 29
      middleware/logging/logging_test.go
  84. 14
      middleware/metadata/metadata.go
  85. 67
      middleware/metadata/metadata_test.go
  86. 36
      options.go
  87. 36
      options_test.go
  88. 12
      selector/global.go
  89. 4
      selector/node/ewma/node.go
  90. 9
      selector/node/ewma/node_test.go
  91. 2
      selector/p2c/p2c_test.go
  92. 12
      transport/grpc/balancer.go
  93. 6
      transport/http/binding/bind_test.go
  94. 7
      transport/http/client_test.go
  95. 10
      transport/http/context_test.go
  96. 3
      transport/http/redirect_test.go
  97. 6
      transport/http/router_test.go
  98. 10
      transport/http/server.go
  99. 34
      transport/http/server_test.go
  100. 2
      version.go

@ -44,7 +44,7 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v3.3.0
uses: actions/setup-go@v3.3.1
with:
go-version: ${{ matrix.go }}

@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"io"
"sort"
"sync"
"google.golang.org/grpc"
@ -115,6 +116,8 @@ func (s *Server) ListServices(ctx context.Context, in *ListServicesRequest) (*Li
reply.Methods = append(reply.Methods, fmt.Sprintf("/%s/%s", name, method))
}
}
sort.Strings(reply.Services)
sort.Strings(reply.Methods)
return reply, nil
}

@ -89,8 +89,15 @@ func (a *App) Run() error {
a.mu.Lock()
a.instance = instance
a.mu.Unlock()
eg, ctx := errgroup.WithContext(NewContext(a.ctx, a))
sctx := NewContext(a.ctx, a)
eg, ctx := errgroup.WithContext(sctx)
wg := sync.WaitGroup{}
for _, fn := range a.opts.beforeStart {
if err = fn(sctx); err != nil {
return err
}
}
for _, srv := range a.opts.servers {
srv := srv
eg.Go(func() error {
@ -102,17 +109,23 @@ func (a *App) Run() error {
wg.Add(1)
eg.Go(func() error {
wg.Done() // here is to ensure server start has begun running before register, so defer is not needed
return srv.Start(NewContext(a.opts.ctx, a))
return srv.Start(sctx)
})
}
wg.Wait()
if a.opts.registrar != nil {
rctx, rcancel := context.WithTimeout(ctx, a.opts.registrarTimeout)
defer rcancel()
if err := a.opts.registrar.Register(rctx, instance); err != nil {
if err = a.opts.registrar.Register(rctx, instance); err != nil {
return err
}
}
for _, fn := range a.opts.afterStart {
if err = fn(sctx); err != nil {
return err
}
}
c := make(chan os.Signal, 1)
signal.Notify(c, a.opts.sigs...)
eg.Go(func() error {
@ -123,28 +136,36 @@ func (a *App) Run() error {
return a.Stop()
}
})
if err := eg.Wait(); err != nil && !errors.Is(err, context.Canceled) {
if err = eg.Wait(); err != nil && !errors.Is(err, context.Canceled) {
return err
}
return nil
for _, fn := range a.opts.afterStop {
err = fn(sctx)
}
return err
}
// Stop gracefully stops the application.
func (a *App) Stop() error {
func (a *App) Stop() (err error) {
sctx := NewContext(a.ctx, a)
for _, fn := range a.opts.beforeStop {
err = fn(sctx)
}
a.mu.Lock()
instance := a.instance
a.mu.Unlock()
if a.opts.registrar != nil && instance != nil {
ctx, cancel := context.WithTimeout(NewContext(a.ctx, a), a.opts.registrarTimeout)
defer cancel()
if err := a.opts.registrar.Deregister(ctx, instance); err != nil {
if err = a.opts.registrar.Deregister(ctx, instance); err != nil {
return err
}
}
if a.cancel != nil {
a.cancel()
}
return nil
return err
}
func (a *App) buildInstance() (*registry.ServiceInstance, error) {

@ -47,6 +47,22 @@ func TestApp(t *testing.T) {
Name("kratos"),
Version("v1.0.0"),
Server(hs, gs),
BeforeStart(func(_ context.Context) error {
t.Log("BeforeStart...")
return nil
}),
BeforeStop(func(_ context.Context) error {
t.Log("BeforeStop...")
return nil
}),
AfterStart(func(_ context.Context) error {
t.Log("AfterStart...")
return nil
}),
AfterStop(func(_ context.Context) error {
t.Log("AfterStop...")
return nil
}),
Registrar(&mockRegistry{service: make(map[string]*registry.ServiceInstance)}),
)
time.AfterFunc(time.Second, func() {

@ -8,7 +8,7 @@ import (
)
var (
scpSyntaxRe = regexp.MustCompile(`^([a-zA-Z0-9_]+)@([a-zA-Z0-9._-]+):(.*)$`)
scpSyntaxRe = regexp.MustCompile(`^(\w+)@([\w.-]+):(.*)$`)
scheme = []string{"git", "https", "http", "git+ssh", "ssh", "file", "ftp", "ftps"}
)

@ -43,7 +43,7 @@ func (g *GithubAPI) GetReleaseInfo(version string) ReleaseInfo {
if version != "latest" {
api = fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/tags/%s", g.Owner, g.Repo, version)
}
resp, code := requestGithubAPI(api, "GET", nil, g.Token)
resp, code := requestGithubAPI(api, http.MethodGet, nil, g.Token)
if code != http.StatusOK {
printGithubErrorInfo(resp)
}
@ -63,7 +63,7 @@ func (g *GithubAPI) GetCommitsInfo() []CommitInfo {
var list []CommitInfo
for {
url := fmt.Sprintf("https://api.github.com/repos/%s/%s/commits?pre_page=%d&page=%d&since=%s", g.Owner, g.Repo, prePage, page, info.PublishedAt)
resp, code := requestGithubAPI(url, "GET", nil, g.Token)
resp, code := requestGithubAPI(url, http.MethodGet, nil, g.Token)
if code != http.StatusOK {
printGithubErrorInfo(resp)
}

@ -1,4 +1,4 @@
package main
// release is the current kratos tool version.
const release = "v2.5.1"
const release = "v2.5.2"

@ -1,4 +1,4 @@
package main
// release is the current protoc-gen-go-errors version.
const release = "v2.5.1"
const release = "v2.5.2"

@ -2,6 +2,7 @@ package main
import (
"fmt"
"net/http"
"os"
"regexp"
"strings"
@ -85,7 +86,7 @@ func genService(gen *protogen.Plugin, file *protogen.File, g *protogen.Generated
sd.Methods = append(sd.Methods, buildHTTPRule(g, method, rule))
} else if !omitempty {
path := fmt.Sprintf("/%s/%s", service.Desc.FullName(), method.Desc.Name())
sd.Methods = append(sd.Methods, buildMethodDesc(g, method, "POST", path))
sd.Methods = append(sd.Methods, buildMethodDesc(g, method, http.MethodPost, path))
}
}
if len(sd.Methods) != 0 {
@ -119,19 +120,19 @@ func buildHTTPRule(g *protogen.GeneratedFile, m *protogen.Method, rule *annotati
switch pattern := rule.Pattern.(type) {
case *annotations.HttpRule_Get:
path = pattern.Get
method = "GET"
method = http.MethodGet
case *annotations.HttpRule_Put:
path = pattern.Put
method = "PUT"
method = http.MethodPut
case *annotations.HttpRule_Post:
path = pattern.Post
method = "POST"
method = http.MethodPost
case *annotations.HttpRule_Delete:
path = pattern.Delete
method = "DELETE"
method = http.MethodDelete
case *annotations.HttpRule_Patch:
path = pattern.Patch
method = "PATCH"
method = http.MethodPatch
case *annotations.HttpRule_Custom:
path = pattern.Custom.Path
method = pattern.Custom.Kind
@ -139,7 +140,7 @@ func buildHTTPRule(g *protogen.GeneratedFile, m *protogen.Method, rule *annotati
body = rule.Body
responseBody = rule.ResponseBody
md := buildMethodDesc(g, m, method, path)
if method == "GET" || method == "DELETE" {
if method == http.MethodGet || method == http.MethodDelete {
if body != "" {
_, _ = fmt.Fprintf(os.Stderr, "\u001B[31mWARN\u001B[m: %s %s body should not be declared.\n", method, path)
}
@ -213,7 +214,7 @@ func buildPathVars(path string) (res map[string]*string) {
if strings.HasSuffix(path, "/") {
fmt.Fprintf(os.Stderr, "\u001B[31mWARN\u001B[m: Path %s should not end with \"/\" \n", path)
}
pattern := regexp.MustCompile(`(?i){([a-z\.0-9_\s]*)=?([^{}]*)}`)
pattern := regexp.MustCompile(`(?i){([a-z.0-9_\s]*)=?([^{}]*)}`)
matches := pattern.FindAllStringSubmatch(path, -1)
res = make(map[string]*string, len(matches))
for _, m := range matches {

@ -1,4 +1,4 @@
package main
// release is the current protoc-gen-go-http version.
const release = "v2.5.1"
const release = "v2.5.2"

@ -15,13 +15,13 @@ import (
"github.com/go-kratos/kratos/v2/log"
)
var _ Config = (*config)(nil)
var (
// ErrNotFound is key not found.
ErrNotFound = errors.New("key not found")
// ErrTypeAssert is type assert error.
ErrTypeAssert = errors.New("type assert error")
_ Config = (*config)(nil)
)
// Observer is config observer.
@ -44,7 +44,7 @@ type config struct {
watchers []Watcher
}
// New new a config with options.
// New a config with options.
func New(opts ...Option) Config {
o := options{
decoder: defaultDecoder,
@ -62,11 +62,11 @@ func New(opts ...Option) Config {
func (c *config) watch(w Watcher) {
for {
kvs, err := w.Next()
if err != nil {
if errors.Is(err, context.Canceled) {
log.Infof("watcher's ctx cancel : %v", err)
return
}
if err != nil {
time.Sleep(time.Second)
log.Errorf("failed to watch next config: %v", err)
continue

@ -2,7 +2,6 @@ package config
import (
"errors"
"reflect"
"testing"
)
@ -124,7 +123,7 @@ func TestConfig(t *testing.T) {
)
err = c.Close()
if err != nil {
t.Fatal("t is not nil")
t.Fatal(err)
}
jSource := newTestJSONSource(_testJSON)
@ -139,21 +138,21 @@ func TestConfig(t *testing.T) {
err = cf.Load()
if err != nil {
t.Fatal("t is not nil")
t.Fatal(err)
}
val, err := cf.Value("data.database.driver").String()
driver, err := cf.Value("data.database.driver").String()
if err != nil {
t.Fatal("t is not nil")
t.Fatal(err)
}
if !reflect.DeepEqual(databaseDriver, val) {
t.Fatal(`databaseDriver is not equal to val`)
if databaseDriver != driver {
t.Fatal("databaseDriver is not equal to val")
}
err = cf.Watch("endpoints", func(key string, value Value) {
})
if err != nil {
t.Fatal("t is not nil")
t.Fatal(err)
}
jSource.sig <- struct{}{}
@ -162,24 +161,24 @@ func TestConfig(t *testing.T) {
var testConf testConfigStruct
err = cf.Scan(&testConf)
if err != nil {
t.Fatal("t is not nil")
t.Fatal(err)
}
if !reflect.DeepEqual(httpAddr, testConf.Server.HTTP.Addr) {
t.Fatal(`httpAddr is not equal to testConf.Server.HTTP.Addr`)
if httpAddr != testConf.Server.HTTP.Addr {
t.Errorf("testConf.Server.HTTP.Addr want: %s, got: %s", httpAddr, testConf.Server.HTTP.Addr)
}
if !reflect.DeepEqual(httpTimeout, testConf.Server.HTTP.Timeout) {
t.Fatal(`httpTimeout is not equal to testConf.Server.HTTP.Timeout`)
if httpTimeout != testConf.Server.HTTP.Timeout {
t.Errorf("testConf.Server.HTTP.Timeout want: %.1f, got: %.1f", httpTimeout, testConf.Server.HTTP.Timeout)
}
if !reflect.DeepEqual(true, testConf.Server.HTTP.EnableSSL) {
t.Fatal(`testConf.Server.HTTP.EnableSSL is not equal to true`)
if !testConf.Server.HTTP.EnableSSL {
t.Error("testConf.Server.HTTP.EnableSSL is not equal to true")
}
if !reflect.DeepEqual(grpcPort, testConf.Server.GRPC.Port) {
t.Fatal(`grpcPort is not equal to testConf.Server.GRPC.Port`)
if grpcPort != testConf.Server.GRPC.Port {
t.Errorf("testConf.Server.GRPC.Port want: %d, got: %d", grpcPort, testConf.Server.GRPC.Port)
}
if !reflect.DeepEqual(endpoint1, testConf.Endpoints[0]) {
t.Fatal(`endpoint1 is not equal to testConf.Endpoints[0]`)
if endpoint1 != testConf.Endpoints[0] {
t.Errorf("testConf.Endpoints[0] want: %s, got: %s", endpoint1, testConf.Endpoints[0])
}
if !reflect.DeepEqual(len(testConf.Endpoints), 2) {
t.Fatal(`len(testConf.Endpoints) is not equal to 2`)
if len(testConf.Endpoints) != 2 {
t.Error("len(testConf.Endpoints) is not equal to 2")
}
}

6
config/env/env.go vendored

@ -19,11 +19,11 @@ func (e *env) Load() (kv []*config.KeyValue, err error) {
return e.load(os.Environ()), nil
}
func (e *env) load(envStrings []string) []*config.KeyValue {
func (e *env) load(envs []string) []*config.KeyValue {
var kv []*config.KeyValue
for _, envstr := range envStrings {
for _, env := range envs {
var k, v string
subs := strings.SplitN(envstr, "=", 2) //nolint:gomnd
subs := strings.SplitN(env, "=", 2) //nolint:gomnd
k = subs[0]
if len(subs) > 1 {
v = subs[1]

@ -6,13 +6,13 @@ import (
"github.com/go-kratos/kratos/v2/config"
)
var _ config.Watcher = (*watcher)(nil)
type watcher struct {
ctx context.Context
cancel context.CancelFunc
}
var _ config.Watcher = (*watcher)(nil)
func NewWatcher() (config.Watcher, error) {
ctx, cancel := context.WithCancel(context.Background())
return &watcher{ctx: ctx, cancel: cancel}, nil

@ -121,10 +121,10 @@ func testWatchFile(t *testing.T, path string) {
}
kvs, err := watch.Next()
if err != nil {
t.Errorf(`watch.Next() error(%v)`, err)
t.Errorf("watch.Next() error(%v)", err)
}
if !reflect.DeepEqual(string(kvs[0].Value), _testJSONUpdate) {
t.Errorf(`string(kvs[0].Value(%v) is not equal to _testJSONUpdate(%v)`, kvs[0].Value, _testJSONUpdate)
t.Errorf("string(kvs[0].Value(%v) is not equal to _testJSONUpdate(%v)", kvs[0].Value, _testJSONUpdate)
}
newFilepath := filepath.Join(filepath.Dir(path), "test1.json")
@ -133,15 +133,15 @@ func testWatchFile(t *testing.T, path string) {
}
kvs, err = watch.Next()
if err == nil {
t.Errorf(`watch.Next() error(%v)`, err)
t.Errorf("watch.Next() error(%v)", err)
}
if kvs != nil {
t.Errorf(`watch.Next() error(%v)`, err)
t.Errorf("watch.Next() error(%v)", err)
}
err = watch.Stop()
if err != nil {
t.Errorf(`watch.Stop() error(%v)`, err)
t.Errorf("watch.Stop() error(%v)", err)
}
if err := os.Rename(newFilepath, path); err != nil {
@ -171,10 +171,10 @@ func testWatchDir(t *testing.T, path, file string) {
kvs, err := watch.Next()
if err != nil {
t.Errorf(`watch.Next() error(%v)`, err)
t.Errorf("watch.Next() error(%v)", err)
}
if !reflect.DeepEqual(string(kvs[0].Value), _testJSONUpdate) {
t.Errorf(`string(kvs[0].Value(%v) is not equal to _testJSONUpdate(%v)`, kvs[0].Value, _testJSONUpdate)
t.Errorf("string(kvs[0].Value(%s) is not equal to _testJSONUpdate(%v)", kvs[0].Value, _testJSONUpdate)
}
}

@ -1,6 +1,8 @@
package file
import "testing"
import (
"testing"
)
func TestFormat(t *testing.T) {
tests := []struct {

@ -10,6 +10,8 @@ import (
"github.com/go-kratos/kratos/v2/config"
)
var _ config.Watcher = (*watcher)(nil)
type watcher struct {
f *file
fw *fsnotify.Watcher
@ -18,8 +20,6 @@ type watcher struct {
cancel context.CancelFunc
}
var _ config.Watcher = (*watcher)(nil)
func newWatcher(f *file) (config.Watcher, error) {
fw, err := fsnotify.NewWatcher()
if err != nil {

@ -15,7 +15,7 @@ func TestDefaultDecoder(t *testing.T) {
target := make(map[string]interface{})
err := defaultDecoder(src, target)
if err != nil {
t.Fatal("err is not nil")
t.Fatal(err)
}
if !reflect.DeepEqual(target, map[string]interface{}{"service": []byte("config")}) {
t.Fatal(`target is not equal to map[string]interface{}{"service": "config"}`)
@ -29,7 +29,7 @@ func TestDefaultDecoder(t *testing.T) {
target = make(map[string]interface{})
err = defaultDecoder(src, target)
if err != nil {
t.Fatal("err is not nil")
t.Fatal(err)
}
if !reflect.DeepEqual(map[string]interface{}{
"service": map[string]interface{}{
@ -150,7 +150,7 @@ func TestDefaultResolver(t *testing.T) {
t.Run(test.name, func(t *testing.T) {
err := defaultResolver(data)
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
rd := reader{
values: data,
@ -161,25 +161,25 @@ func TestDefaultResolver(t *testing.T) {
case int:
if actual, err = v.Int(); err == nil {
if !reflect.DeepEqual(test.expect.(int), int(actual.(int64))) {
t.Fatal(`expect is not equal to actual`)
t.Fatal("expect is not equal to actual")
}
}
case string:
if actual, err = v.String(); err == nil {
if !reflect.DeepEqual(test.expect, actual) {
t.Fatal(`expect is not equal to actual`)
t.Fatal("expect is not equal to actual")
}
}
case bool:
if actual, err = v.Bool(); err == nil {
if !reflect.DeepEqual(test.expect, actual) {
t.Fatal(`expect is not equal to actual`)
t.Fatal("expect is not equal to actual")
}
}
case float64:
if actual, err = v.Float(); err == nil {
if !reflect.DeepEqual(test.expect, actual) {
t.Fatal(`expect is not equal to actual`)
t.Fatal("expect is not equal to actual")
}
}
default:

@ -8,11 +8,11 @@ import (
"strings"
"sync"
"github.com/go-kratos/kratos/v2/log"
"github.com/imdario/mergo"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
"github.com/go-kratos/kratos/v2/log"
)
// Reader is config reader.
@ -38,9 +38,7 @@ func newReader(opts options) Reader {
}
func (r *reader) Merge(kvs ...*KeyValue) error {
r.lock.Lock()
merged, err := cloneMap(r.values)
r.lock.Unlock()
merged, err := r.cloneMap()
if err != nil {
return err
}
@ -79,6 +77,12 @@ func (r *reader) Resolve() error {
return r.opts.resolver(r.values)
}
func (r *reader) cloneMap() (map[string]interface{}, error) {
r.lock.Lock()
defer r.lock.Unlock()
return cloneMap(r.values)
}
func cloneMap(src map[string]interface{}) (map[string]interface{}, error) {
// https://gist.github.com/soroushjp/0ec92102641ddfc3ad5515ca76405f4d
var buf bytes.Buffer
@ -90,12 +94,12 @@ func cloneMap(src map[string]interface{}) (map[string]interface{}, error) {
if err != nil {
return nil, err
}
var copy map[string]interface{}
err = dec.Decode(&copy)
var clone map[string]interface{}
err = dec.Decode(&clone)
if err != nil {
return nil, err
}
return copy, nil
return clone, nil
}
func convertMap(src interface{}) interface{} {

@ -29,7 +29,7 @@ func TestReader_Merge(t *testing.T) {
Format: "json",
})
if err == nil {
t.Fatal(`err is nil`)
t.Fatal("err is nil")
}
err = r.Merge(&KeyValue{
@ -38,15 +38,15 @@ func TestReader_Merge(t *testing.T) {
Format: "json",
})
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
vv, ok := r.Value("nice")
if !ok {
t.Fatal(`ok is false`)
t.Fatal("ok is false")
}
vvv, err := vv.String()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
if vvv != "boat" {
t.Fatal(`vvv is not equal to "boat"`)
@ -58,18 +58,18 @@ func TestReader_Merge(t *testing.T) {
Format: "json",
})
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
vv, ok = r.Value("x")
if !ok {
t.Fatal(`ok is false`)
t.Fatal("ok is false")
}
vvx, err := vv.Int()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
if int64(2) != vvx {
t.Fatal(`vvx is not equal to 2`)
if vvx != 2 {
t.Fatal("vvx is not equal to 2")
}
}
@ -118,27 +118,27 @@ a:
r := newReader(opts)
err := r.Merge(&test.kv)
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
vv, ok := r.Value("a.b.X")
if !ok {
t.Fatal(`ok is false`)
t.Fatal("ok is false")
}
vvv, err := vv.Int()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
if int64(1) != vvv {
t.Fatal(`vvv is not equal to 1`)
t.Fatal("vvv is not equal to 1")
}
vv, ok = r.Value("a.b.Y")
if !ok {
t.Fatal(`ok is false`)
t.Fatal("ok is false")
}
vvy, err := vv.String()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
if vvy != "lol" {
t.Fatal(`vvy is not equal to "lol"`)
@ -146,29 +146,29 @@ a:
vv, ok = r.Value("a.b.z")
if !ok {
t.Fatal(`ok is false`)
t.Fatal("ok is false")
}
vvz, err := vv.Bool()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
if !vvz {
t.Fatal(`vvz is not equal to true`)
t.Fatal("vvz is not equal to true")
}
_, ok = r.Value("aasasdg=234l.asdfk,")
if ok {
t.Fatal(`ok is true`)
t.Fatal("ok is true")
}
_, ok = r.Value("aas......asdg=234l.asdfk,")
if ok {
t.Fatal(`ok is true`)
t.Fatal("ok is true")
}
_, ok = r.Value("a.b.Y.")
if ok {
t.Fatal(`ok is true`)
t.Fatal("ok is true")
}
})
}
@ -192,11 +192,11 @@ func TestReader_Source(t *testing.T) {
Format: "json",
})
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
b, err := r.Source()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
if !reflect.DeepEqual([]byte(`{"a":{"b":{"X":1}}}`), b) {
t.Fatal("[]byte(`{\"a\":{\"b\":{\"X\":1}}}`) is not equal to b")

@ -1,7 +1,7 @@
package config
import (
stdjson "encoding/json"
"encoding/json"
"fmt"
"reflect"
"strconv"
@ -10,7 +10,7 @@ import (
"google.golang.org/protobuf/proto"
"github.com/go-kratos/kratos/v2/encoding/json"
kratosjson "github.com/go-kratos/kratos/v2/encoding/json"
)
var (
@ -36,6 +36,10 @@ type atomicValue struct {
atomic.Value
}
func (v *atomicValue) typeAssertError() error {
return fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load()))
}
func (v *atomicValue) Bool() (bool, error) {
switch val := v.Load().(type) {
case bool:
@ -43,7 +47,7 @@ func (v *atomicValue) Bool() (bool, error) {
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64, string:
return strconv.ParseBool(fmt.Sprint(val))
}
return false, fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load()))
return false, v.typeAssertError()
}
func (v *atomicValue) Int() (int64, error) {
@ -73,26 +77,30 @@ func (v *atomicValue) Int() (int64, error) {
case float64:
return int64(val), nil
case string:
return strconv.ParseInt(val, 10, 64) //nolint:gomnd
return strconv.ParseInt(val, 10, 64)
}
return 0, fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load()))
return 0, v.typeAssertError()
}
func (v *atomicValue) Slice() ([]Value, error) {
if vals, ok := v.Load().([]interface{}); ok {
var slices []Value
vals, ok := v.Load().([]interface{})
if !ok {
return nil, v.typeAssertError()
}
slices := make([]Value, 0, len(vals))
for _, val := range vals {
a := &atomicValue{}
a := new(atomicValue)
a.Store(val)
slices = append(slices, a)
}
return slices, nil
}
return nil, fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load()))
}
func (v *atomicValue) Map() (map[string]Value, error) {
if vals, ok := v.Load().(map[string]interface{}); ok {
vals, ok := v.Load().(map[string]interface{})
if !ok {
return nil, v.typeAssertError()
}
m := make(map[string]Value, len(vals))
for key, val := range vals {
a := new(atomicValue)
@ -100,8 +108,6 @@ func (v *atomicValue) Map() (map[string]Value, error) {
m[key] = a
}
return m, nil
}
return nil, fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load()))
}
func (v *atomicValue) Float() (float64, error) {
@ -131,9 +137,9 @@ func (v *atomicValue) Float() (float64, error) {
case float64:
return val, nil
case string:
return strconv.ParseFloat(val, 64) //nolint:gomnd
return strconv.ParseFloat(val, 64)
}
return 0.0, fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load()))
return 0.0, v.typeAssertError()
}
func (v *atomicValue) String() (string, error) {
@ -147,7 +153,7 @@ func (v *atomicValue) String() (string, error) {
case fmt.Stringer:
return val.String(), nil
}
return "", fmt.Errorf("type assert to %v failed", reflect.TypeOf(v.Load()))
return "", v.typeAssertError()
}
func (v *atomicValue) Duration() (time.Duration, error) {
@ -159,14 +165,14 @@ func (v *atomicValue) Duration() (time.Duration, error) {
}
func (v *atomicValue) Scan(obj interface{}) error {
data, err := stdjson.Marshal(v.Load())
data, err := json.Marshal(v.Load())
if err != nil {
return err
}
if pb, ok := obj.(proto.Message); ok {
return json.UnmarshalOptions.Unmarshal(data, pb)
return kratosjson.UnmarshalOptions.Unmarshal(data, pb)
}
return stdjson.Unmarshal(data, obj)
return json.Unmarshal(data, obj)
}
type errValue struct {

@ -6,17 +6,17 @@ import (
"time"
)
func Test_atomicValue_Bool(t *testing.T) {
func TestAtomicValue_Bool(t *testing.T) {
vlist := []interface{}{"1", "t", "T", "true", "TRUE", "True", true, 1, int32(1)}
for _, x := range vlist {
v := atomicValue{}
v.Store(x)
b, err := v.Bool()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
if !b {
t.Fatal(`b is not equal to true`)
t.Fatal("b is not equal to true")
}
}
@ -26,10 +26,10 @@ func Test_atomicValue_Bool(t *testing.T) {
v.Store(x)
b, err := v.Bool()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
if b {
t.Fatal(`b is not equal to false`)
t.Fatal("b is not equal to false")
}
}
@ -39,22 +39,22 @@ func Test_atomicValue_Bool(t *testing.T) {
v.Store(x)
_, err := v.Bool()
if err == nil {
t.Fatal(`err is nil`)
t.Fatal("err is nil")
}
}
}
func Test_atomicValue_Int(t *testing.T) {
func TestAtomicValue_Int(t *testing.T) {
vlist := []interface{}{"123123", float64(123123), int64(123123), int32(123123), 123123}
for _, x := range vlist {
v := atomicValue{}
v.Store(x)
b, err := v.Int()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
if b != 123123 {
t.Fatal(`b is not equal to 123123`)
t.Fatal("b is not equal to 123123")
}
}
@ -64,22 +64,22 @@ func Test_atomicValue_Int(t *testing.T) {
v.Store(x)
_, err := v.Int()
if err == nil {
t.Fatal(`err is nil`)
t.Fatal("err is nil")
}
}
}
func Test_atomicValue_Float(t *testing.T) {
func TestAtomicValue_Float(t *testing.T) {
vlist := []interface{}{"123123.1", 123123.1}
for _, x := range vlist {
v := atomicValue{}
v.Store(x)
b, err := v.Float()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
if b != 123123.1 {
t.Fatal(`b is not equal to 123123.1`)
t.Fatal("b is not equal to 123123.1")
}
}
@ -89,7 +89,7 @@ func Test_atomicValue_Float(t *testing.T) {
v.Store(x)
_, err := v.Float()
if err == nil {
t.Fatal(`err is nil`)
t.Fatal("err is nil")
}
}
}
@ -103,17 +103,17 @@ func (t ts) String() string {
return fmt.Sprintf("%s%d", t.Name, t.Age)
}
func Test_atomicValue_String(t *testing.T) {
func TestAtomicValue_String(t *testing.T) {
vlist := []interface{}{"1", float64(1), int64(1), 1, int64(1)}
for _, x := range vlist {
v := atomicValue{}
v.Store(x)
b, err := v.String()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
if b != "1" {
t.Fatal(`b is not equal to 1`)
t.Fatal("b is not equal to 1")
}
}
@ -121,7 +121,7 @@ func Test_atomicValue_String(t *testing.T) {
v.Store(true)
b, err := v.String()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
if b != "true" {
t.Fatal(`b is not equal to "true"`)
@ -134,48 +134,48 @@ func Test_atomicValue_String(t *testing.T) {
})
b, err = v.String()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
if b != "test10" {
t.Fatal(`b is not equal to "test10"`)
}
}
func Test_atomicValue_Duration(t *testing.T) {
func TestAtomicValue_Duration(t *testing.T) {
vlist := []interface{}{int64(5)}
for _, x := range vlist {
v := atomicValue{}
v.Store(x)
b, err := v.Duration()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
if b != time.Duration(5) {
t.Fatal(`b is not equal to time.Duration(5)`)
t.Fatal("b is not equal to time.Duration(5)")
}
}
}
func Test_atomicValue_Slice(t *testing.T) {
func TestAtomicValue_Slice(t *testing.T) {
vlist := []interface{}{int64(5)}
v := atomicValue{}
v.Store(vlist)
slices, err := v.Slice()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
for _, v := range slices {
b, err := v.Duration()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
if b != time.Duration(5) {
t.Fatal(`b is not equal to time.Duration(5)`)
t.Fatal("b is not equal to time.Duration(5)")
}
}
}
func Test_atomicValue_Map(t *testing.T) {
func TestAtomicValue_Map(t *testing.T) {
vlist := make(map[string]interface{})
vlist["5"] = int64(5)
vlist["text"] = "text"
@ -183,21 +183,21 @@ func Test_atomicValue_Map(t *testing.T) {
v.Store(vlist)
m, err := v.Map()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
for k, v := range m {
if k == "5" {
b, err := v.Duration()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
if b != time.Duration(5) {
t.Fatal(`b is not equal to time.Duration(5)`)
t.Fatal("b is not equal to time.Duration(5)")
}
} else {
b, err := v.String()
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
if b != "text" {
t.Fatal(`b is not equal to "text"`)
@ -206,20 +206,19 @@ func Test_atomicValue_Map(t *testing.T) {
}
}
func Test_atomicValue_Scan(t *testing.T) {
var err error
func TestAtomicValue_Scan(t *testing.T) {
v := atomicValue{}
err = v.Scan(&struct {
err := v.Scan(&struct {
A string `json:"a"`
}{"a"})
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
err = v.Scan(&struct {
A string `json:"a"`
}{"a"})
if err != nil {
t.Fatal(`err is not nil`)
t.Fatal(err)
}
}

@ -97,5 +97,4 @@ config := map[string]interface{}{
}
}
}
_ = config
```

@ -3,15 +3,14 @@ package apollo
import (
"strings"
"github.com/go-kratos/kratos/v2/config"
"github.com/go-kratos/kratos/v2/log"
"github.com/apolloconfig/agollo/v4"
"github.com/apolloconfig/agollo/v4/constant"
apolloConfig "github.com/apolloconfig/agollo/v4/env/config"
"github.com/apolloconfig/agollo/v4/extension"
"github.com/go-kratos/kratos/v2/config"
"github.com/go-kratos/kratos/v2/encoding"
"github.com/go-kratos/kratos/v2/log"
)
type apollo struct {

@ -3,7 +3,7 @@ module github.com/go-kratos/kratos/contrib/config/apollo/v2
go 1.16
require (
github.com/apolloconfig/agollo/v4 v4.2.0
github.com/apolloconfig/agollo/v4 v4.2.1
github.com/go-kratos/kratos/v2 v2.4.0
)

@ -63,8 +63,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apolloconfig/agollo/v4 v4.2.0 h1:FkE8acffsUhnRnjyi37eOq6JpfUhQKuNccG2jXB3Mco=
github.com/apolloconfig/agollo/v4 v4.2.0/go.mod h1:SuvTjtg0p4UlSzSbik+ibLRr6oR1xRsfy65QzP3GEAs=
github.com/apolloconfig/agollo/v4 v4.2.1 h1:+cTdSZbWfLLZpEQk2LEhSbkmjLH+rzyAAPb6buhPA+Q=
github.com/apolloconfig/agollo/v4 v4.2.1/go.mod h1:SuvTjtg0p4UlSzSbik+ibLRr6oR1xRsfy65QzP3GEAs=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=

@ -4,12 +4,11 @@ import (
"context"
"strings"
"github.com/go-kratos/kratos/v2/encoding"
"github.com/apolloconfig/agollo/v4/storage"
"github.com/go-kratos/kratos/v2/config"
"github.com/go-kratos/kratos/v2/encoding"
"github.com/go-kratos/kratos/v2/log"
"github.com/apolloconfig/agollo/v4/storage"
)
type watcher struct {

@ -2,11 +2,12 @@
```go
import (
"github.com/go-kratos/kratos/contrib/config/consul/v2"
"github.com/hashicorp/consul/api"
"github.com/go-kratos/kratos/contrib/config/consul/v2"
)
func main() {
func main() {
consulClient, err := api.NewClient(&api.Config{
Address: "127.0.0.1:8500",
})
@ -14,8 +15,8 @@ func main() {
panic(err)
}
cs, err := consul.New(consulClient, consul.WithPath("app/cart/configs/"))
//consul中需要标注文件后缀,kratos读取配置需要适配文件后缀
//The file suffix needs to be marked, and kratos needs to adapt the file suffix to read the configuration.
// consul中需要标注文件后缀,kratos读取配置需要适配文件后缀
// The file suffix needs to be marked, and kratos needs to adapt the file suffix to read the configuration.
if err != nil {
panic(err)
}

@ -4,7 +4,7 @@ go 1.15
require (
github.com/go-kratos/kratos/v2 v2.4.0
github.com/hashicorp/consul/api v1.14.0
github.com/hashicorp/consul/api v1.15.3
)
replace github.com/go-kratos/kratos/v2 => ../../../

@ -91,10 +91,10 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/consul/api v1.14.0 h1:Y64GIJ8hYTu+tuGekwO4G4ardXoiCivX9wv1iP/kihk=
github.com/hashicorp/consul/api v1.14.0/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ=
github.com/hashicorp/consul/sdk v0.10.0 h1:rGLEh2AWK4K0KCMvqWAz2EYxQqgciIfMagWZ0nVe5MI=
github.com/hashicorp/consul/sdk v0.10.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw=
github.com/hashicorp/consul/api v1.15.3 h1:WYONYL2rxTXtlekAqblR2SCdJsizMDIj/uXb5wNy9zU=
github.com/hashicorp/consul/api v1.15.3/go.mod h1:/g/qgcoBcEXALCNZgRRisyTW0nY86++L0KbeAMXYCeY=
github.com/hashicorp/consul/sdk v0.11.0 h1:HRzj8YSCln2yGgCumN5CL8lYlD3gBurnervJRJAZyC4=
github.com/hashicorp/consul/sdk v0.11.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=

@ -4,10 +4,11 @@
import (
"log"
cfg "github.com/go-kratos/kratos/contrib/config/etcd/v2"
"github.com/go-kratos/kratos/v2/config"
clientv3 "go.etcd.io/etcd/client/v3"
"google.golang.org/grpc"
cfg "github.com/go-kratos/kratos/contrib/config/etcd/v2"
"github.com/go-kratos/kratos/v2/config"
)
// create an etcd client
@ -30,12 +31,16 @@ if err != nil {
c := config.New(config.WithSource(source))
defer c.Close()
// load sources before get
if err := c.Load(); err != nil {
log.Fatalln(err)
}
// acquire config value
foo, err := c.Value("/app-config").String()
if err != nil {
log.Println(err)
log.Fatalln(err)
}
println(foo)
log.Println(foo)
```

@ -5,7 +5,7 @@ go 1.16
require (
github.com/go-kratos/kratos/v2 v2.4.0
go.etcd.io/etcd/client/v3 v3.5.4
google.golang.org/grpc v1.46.2
google.golang.org/grpc v1.50.1
)
replace github.com/go-kratos/kratos/v2 => ../../../

@ -271,8 +271,9 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.46.2 h1:u+MLGgVf7vRdjEYZ8wDFhAVNmhkbJ5hmrA1LMWK1CAQ=
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=

@ -8,14 +8,14 @@ import (
"strings"
"testing"
"github.com/go-kratos/kratos/v2/config"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
"github.com/go-kratos/kratos/v2/config"
)
const (

@ -2,9 +2,10 @@
```go
import (
kconfig "github.com/go-kratos/kratos/v2/config"
"github.com/nacos-group/nacos-sdk-go/clients"
"github.com/nacos-group/nacos-sdk-go/common/constant"
kconfig "github.com/go-kratos/kratos/v2/config"
)

@ -5,6 +5,9 @@ go 1.16
require (
github.com/go-kratos/kratos/v2 v2.4.0
github.com/nacos-group/nacos-sdk-go v1.0.9
)
require (
gopkg.in/yaml.v3 v3.0.1 // indirect
)

@ -5,18 +5,17 @@ import (
"log"
"github.com/polarismesh/polaris-go"
"github.com/go-kratos/kratos/contrib/config/polaris/v2"
)
func main() {
configApi, err := polaris.NewConfigAPI()
if err != nil {
log.Fatalln(err)
}
source, err := New(&configApi, WithNamespace("default"), WithFileGroup("default"), WithFileName("default.yaml"))
if err != nil {
log.Fatalln(err)
}

@ -6,9 +6,9 @@ import (
"path/filepath"
"strings"
"github.com/go-kratos/kratos/v2/config"
"github.com/polarismesh/polaris-go"
"github.com/go-kratos/kratos/v2/config"
)
// Option is polaris config option.

@ -5,11 +5,11 @@ import (
"path/filepath"
"strings"
"github.com/go-kratos/kratos/v2/config"
"github.com/go-kratos/kratos/v2/log"
"github.com/polarismesh/polaris-go"
"github.com/polarismesh/polaris-go/pkg/model"
"github.com/go-kratos/kratos/v2/config"
"github.com/go-kratos/kratos/v2/log"
)
type Watcher struct {
@ -28,7 +28,7 @@ func getFullPath(namespace string, fileGroup string, fileName string) string {
return fmt.Sprintf("%s/%s/%s", namespace, fileGroup, fileName)
}
func recieve(event model.ConfigFileChangeEvent) {
func receive(event model.ConfigFileChangeEvent) {
meta := event.ConfigFileMetadata
ec := eventChanMap[getFullPath(meta.GetNamespace(), meta.GetFileGroup(), meta.GetFileName())]
defer func() {
@ -42,7 +42,7 @@ func recieve(event model.ConfigFileChangeEvent) {
}
func newWatcher(configFile polaris.ConfigFile) *Watcher {
configFile.AddChangeListener(recieve)
configFile.AddChangeListener(receive)
fullPath := getFullPath(configFile.GetNamespace(), configFile.GetFileGroup(), configFile.GetFileName())
if _, ok := eventChanMap[fullPath]; !ok {

@ -3,7 +3,7 @@ module github.com/go-kratos/kratos/contrib/encoding/msgpack/v2
go 1.16
require (
github.com/go-kratos/kratos/v2 v2.5.1
github.com/go-kratos/kratos/v2 v2.5.2
github.com/vmihailenco/msgpack/v5 v5.3.5
)

@ -16,6 +16,7 @@ import (
// Logger see more detail https://github.com/aliyun/aliyun-log-go-sdk
type Logger interface {
log.Logger
GetProducer() *producer.Producer
Close() error
}
@ -81,22 +82,16 @@ func (a *aliyunLog) Close() error {
}
func (a *aliyunLog) Log(level log.Level, keyvals ...interface{}) error {
buf := level.String()
levelTitle := "level"
contents := make([]*sls.LogContent, 0)
contents := make([]*sls.LogContent, 0, len(keyvals)/2+1)
contents = append(contents, &sls.LogContent{
Key: &levelTitle,
Value: &buf,
Key: newString(level.Key()),
Value: newString(level.String()),
})
for i := 0; i < len(keyvals); i += 2 {
key := toString(keyvals[i])
value := toString(keyvals[i+1])
contents = append(contents, &sls.LogContent{
Key: &key,
Value: &value,
Key: newString(toString(keyvals[i])),
Value: newString(toString(keyvals[i+1])),
})
}
@ -104,9 +99,7 @@ func (a *aliyunLog) Log(level log.Level, keyvals ...interface{}) error {
Time: proto.Uint32(uint32(time.Now().Unix())),
Contents: contents,
}
err := a.producer.SendLog(a.opts.project, a.opts.logstore, "", "", logInst)
return err
return a.producer.SendLog(a.opts.project, a.opts.logstore, "", "", logInst)
}
// NewAliyunLog new a aliyun logger with options.
@ -128,6 +121,11 @@ func NewAliyunLog(options ...Option) Logger {
}
}
// newString string convert to *string
func newString(s string) *string {
return &s
}
// toString convert any type to string
func toString(v interface{}) string {
var key string
@ -138,23 +136,23 @@ func toString(v interface{}) string {
case float64:
key = strconv.FormatFloat(v, 'f', -1, 64)
case float32:
key = strconv.FormatFloat(float64(v), 'f', -1, 64)
key = strconv.FormatFloat(float64(v), 'f', -1, 32)
case int:
key = strconv.Itoa(v)
case uint:
key = strconv.Itoa(int(v))
key = strconv.FormatUint(uint64(v), 10)
case int8:
key = strconv.Itoa(int(v))
case uint8:
key = strconv.Itoa(int(v))
key = strconv.FormatUint(uint64(v), 10)
case int16:
key = strconv.Itoa(int(v))
case uint16:
key = strconv.Itoa(int(v))
key = strconv.FormatUint(uint64(v), 10)
case int32:
key = strconv.Itoa(int(v))
case uint32:
key = strconv.Itoa(int(v))
key = strconv.FormatUint(uint64(v), 10)
case int64:
key = strconv.FormatInt(v, 10)
case uint64:

@ -2,6 +2,7 @@ package aliyun
import (
"math"
"reflect"
"testing"
"github.com/go-kratos/kratos/v2/log"
@ -99,34 +100,45 @@ func TestLog(t *testing.T) {
}
}
func TestNewString(t *testing.T) {
ptr := newString("")
if kind := reflect.TypeOf(ptr).Kind(); kind != reflect.Ptr {
t.Errorf("want type: %v, got type: %v", reflect.Ptr, kind)
}
}
func TestToString(t *testing.T) {
tests := []struct {
name string
in interface{}
out string
}{
{math.MaxFloat64, "17976931348623157000000000000000000000000000000000000" +
"000000000000000000000000000000000000000000000000000000000000000000000000000" +
"000000000000000000000000000000000000000000000000000000000000000000000000000" +
"000000000000000000000000000000000000000000000000000000000000000000000000000" +
"0000000000000000000000000000000"},
{math.MaxFloat32, "340282346638528860000000000000000000000"},
{1<<((32<<(^uint(0)>>63))-1) - 1, "9223372036854775807"},
{uint(1<<(32<<(^uint(0)>>63)) - 1), "-1"},
{math.MaxInt8, "127"},
{math.MaxUint8, "255"},
{math.MaxInt16, "32767"},
{math.MaxUint16, "65535"},
{math.MaxInt32, "2147483647"},
{math.MaxUint32, "4294967295"},
{math.MaxInt64, "9223372036854775807"},
{uint64(math.MaxUint64), "18446744073709551615"},
{"abc", "abc"},
{false, "false"},
{[]byte("abc"), "abc"},
{"float64", 6.66, "6.66"},
{"max float64", math.MaxFloat64, "179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, //nolint:lll
{"float32", float32(6.66), "6.66"},
{"max float32", float32(math.MaxFloat32), "340282350000000000000000000000000000000"},
{"int", math.MaxInt64, "9223372036854775807"},
{"uint", uint(math.MaxUint64), "18446744073709551615"},
{"int8", int8(math.MaxInt8), "127"},
{"uint8", uint8(math.MaxUint8), "255"},
{"int16", int16(math.MaxInt16), "32767"},
{"uint16", uint16(math.MaxUint16), "65535"},
{"int32", int32(math.MaxInt32), "2147483647"},
{"uint32", uint32(math.MaxUint32), "4294967295"},
{"int64", int64(math.MaxInt64), "9223372036854775807"},
{"uint64", uint64(math.MaxUint64), "18446744073709551615"},
{"string", "abc", "abc"},
{"bool", false, "false"},
{"[]byte", []byte("abc"), "abc"},
{"struct", struct{ Name string }{}, `{"Name":""}`},
{"nil", nil, ""},
}
for _, test := range tests {
if toString(test.in) != test.out {
t.Fatalf("want: %s, got: %s", test.out, toString(test.in))
t.Run(test.name, func(t *testing.T) {
out := toString(test.in)
if test.out != out {
t.Fatalf("want: %s, got: %s", test.out, out)
}
})
}
}

@ -3,8 +3,8 @@ module github.com/go-kratos/kratos/contrib/log/aliyun/v2
go 1.16
require (
github.com/aliyun/aliyun-log-go-sdk v0.1.37
github.com/go-kratos/kratos/v2 v2.5.1
github.com/aliyun/aliyun-log-go-sdk v0.1.40
github.com/go-kratos/kratos/v2 v2.5.2
google.golang.org/protobuf v1.28.1
)

@ -12,8 +12,8 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/aliyun/aliyun-log-go-sdk v0.1.37 h1:GvswbgLqVOHNeMWssQ9zA+R7YVDP6arLUP92bKyGZNw=
github.com/aliyun/aliyun-log-go-sdk v0.1.37/go.mod h1:1QQ59pEJiVVXqKgbHcU6FWIgxT5RKBt+CT8AiQ2bEts=
github.com/aliyun/aliyun-log-go-sdk v0.1.40 h1:GNlRoTe9Fi7dfhIMHAnb+b5837/fIw8lqs1DRqaU1CM=
github.com/aliyun/aliyun-log-go-sdk v0.1.40/go.mod h1:1QQ59pEJiVVXqKgbHcU6FWIgxT5RKBt+CT8AiQ2bEts=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=

@ -11,19 +11,24 @@ import (
)
func TestMain(m *testing.M) {
if ln, err := net.Listen("tcp", ":24224"); err == nil {
defer ln.Close()
go func() {
for {
listener := func(ln net.Listener) {
conn, err := ln.Accept()
if err != nil {
return
}
defer conn.Close()
if _, err = io.ReadAll(conn); err != nil {
continue
_, err = io.ReadAll(conn)
if err != nil {
return
}
}
if ln, err := net.Listen("tcp", ":24224"); err == nil {
defer ln.Close()
go func() {
for {
listener(ln)
}
}()
}

@ -5,7 +5,7 @@ go 1.16
require (
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
github.com/fluent/fluent-logger-golang v1.9.0
github.com/go-kratos/kratos/v2 v2.5.1
github.com/go-kratos/kratos/v2 v2.5.2
github.com/kr/pretty v0.3.0 // indirect
github.com/tinylib/msgp v1.1.6 // indirect
)

@ -3,7 +3,7 @@ module github.com/go-kratos/kratos/contrib/log/logrus/v2
go 1.16
require (
github.com/go-kratos/kratos/v2 v2.5.1
github.com/go-kratos/kratos/v2 v2.5.2
github.com/sirupsen/logrus v1.8.1
)

@ -3,7 +3,7 @@ module github.com/go-kratos/kratos/contrib/log/tencent/v2
go 1.16
require (
github.com/go-kratos/kratos/v2 v2.5.1
github.com/go-kratos/kratos/v2 v2.5.2
github.com/tencentcloud/tencentcloud-cls-sdk-go v1.0.2
google.golang.org/protobuf v1.28.0
)

@ -14,8 +14,8 @@ import (
type Logger interface {
log.Logger
GetProducer() *cls.AsyncProducerClient
GetProducer() *cls.AsyncProducerClient
Close() error
}
@ -66,25 +66,20 @@ func WithAccessSecret(as string) Option {
type Option func(cls *options)
func (log *tencentLog) Close() error {
err := log.producer.Close(5000)
return err
return log.producer.Close(5000)
}
func (log *tencentLog) Log(level log.Level, keyvals ...interface{}) error {
buf := level.String()
levelTitle := "level"
contents := make([]*cls.Log_Content, 0)
contents := make([]*cls.Log_Content, 0, len(keyvals)/2+1)
contents = append(contents, &cls.Log_Content{
Key: &levelTitle,
Value: &buf,
Key: newString(level.Key()),
Value: newString(level.String()),
})
for i := 0; i < len(keyvals); i += 2 {
key := toString(keyvals[i])
value := toString(keyvals[i+1])
contents = append(contents, &cls.Log_Content{
Key: &key,
Value: &value,
Key: newString(toString(keyvals[i])),
Value: newString(toString(keyvals[i+1])),
})
}
@ -92,8 +87,7 @@ func (log *tencentLog) Log(level log.Level, keyvals ...interface{}) error {
Time: proto.Int64(time.Now().Unix()),
Contents: contents,
}
err := log.producer.SendLog(log.opts.topicID, logInst, nil)
return err
return log.producer.SendLog(log.opts.topicID, logInst, nil)
}
func NewLogger(options ...Option) (Logger, error) {
@ -115,6 +109,10 @@ func NewLogger(options ...Option) (Logger, error) {
}, nil
}
func newString(s string) *string {
return &s
}
// toString convert any type to string
func toString(v interface{}) string {
var key string
@ -125,23 +123,23 @@ func toString(v interface{}) string {
case float64:
key = strconv.FormatFloat(v, 'f', -1, 64)
case float32:
key = strconv.FormatFloat(float64(v), 'f', -1, 64)
key = strconv.FormatFloat(float64(v), 'f', -1, 32)
case int:
key = strconv.Itoa(v)
case uint:
key = strconv.Itoa(int(v))
key = strconv.FormatUint(uint64(v), 10)
case int8:
key = strconv.Itoa(int(v))
case uint8:
key = strconv.Itoa(int(v))
key = strconv.FormatUint(uint64(v), 10)
case int16:
key = strconv.Itoa(int(v))
case uint16:
key = strconv.Itoa(int(v))
key = strconv.FormatUint(uint64(v), 10)
case int32:
key = strconv.Itoa(int(v))
case uint32:
key = strconv.Itoa(int(v))
key = strconv.FormatUint(uint64(v), 10)
case int64:
key = strconv.FormatInt(v, 10)
case uint64:

@ -1,6 +1,8 @@
package tencent
import (
"math"
"reflect"
"testing"
"github.com/go-kratos/kratos/v2/log"
@ -101,3 +103,46 @@ func TestLog(t *testing.T) {
t.Errorf("Log() returns error:%v", err)
}
}
func TestNewString(t *testing.T) {
ptr := newString("")
if kind := reflect.TypeOf(ptr).Kind(); kind != reflect.Ptr {
t.Errorf("want type: %v, got type: %v", reflect.Ptr, kind)
}
}
func TestToString(t *testing.T) {
tests := []struct {
name string
in interface{}
out string
}{
{"float64", 6.66, "6.66"},
{"max float64", math.MaxFloat64, "179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"}, //nolint:lll
{"float32", float32(6.66), "6.66"},
{"max float32", float32(math.MaxFloat32), "340282350000000000000000000000000000000"},
{"int", math.MaxInt64, "9223372036854775807"},
{"uint", uint(math.MaxUint64), "18446744073709551615"},
{"int8", int8(math.MaxInt8), "127"},
{"uint8", uint8(math.MaxUint8), "255"},
{"int16", int16(math.MaxInt16), "32767"},
{"uint16", uint16(math.MaxUint16), "65535"},
{"int32", int32(math.MaxInt32), "2147483647"},
{"uint32", uint32(math.MaxUint32), "4294967295"},
{"int64", int64(math.MaxInt64), "9223372036854775807"},
{"uint64", uint64(math.MaxUint64), "18446744073709551615"},
{"string", "abc", "abc"},
{"bool", false, "false"},
{"[]byte", []byte("abc"), "abc"},
{"struct", struct{ Name string }{}, `{"Name":""}`},
{"nil", nil, ""},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
out := toString(test.in)
if test.out != out {
t.Fatalf("want: %s, got: %s", test.out, out)
}
})
}
}

@ -3,7 +3,7 @@ module github.com/go-kratos/kratos/contrib/log/zap/v2
go 1.16
require (
github.com/go-kratos/kratos/v2 v2.5.1
github.com/go-kratos/kratos/v2 v2.5.2
go.uber.org/zap v1.23.0
)

@ -4,8 +4,11 @@ go 1.16
require (
github.com/DataDog/datadog-go v4.8.3+incompatible
github.com/go-kratos/kratos/v2 v2.5.2
)
require (
github.com/Microsoft/go-winio v0.5.2 // indirect
github.com/go-kratos/kratos/v2 v2.5.1
)
replace github.com/go-kratos/kratos/v2 => ../../../

@ -3,8 +3,8 @@ module github.com/go-kratos/kratos/contrib/metrics/prometheus/v2
go 1.16
require (
github.com/go-kratos/kratos/v2 v2.5.1
github.com/prometheus/client_golang v1.12.2
github.com/go-kratos/kratos/v2 v2.5.2
github.com/prometheus/client_golang v1.13.1
github.com/prometheus/common v0.37.0
)

@ -129,8 +129,9 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@ -186,8 +187,8 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34=
github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_golang v1.13.1 h1:3gMjIY2+/hzmqhtUC/aQNYldJA6DtH3CgQvwS+02K1c=
github.com/prometheus/client_golang v1.13.1/go.mod h1:vTeo+zgvILHsnnj/39Ou/1fPN5nJFOEMgftOUOmlvYQ=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@ -203,8 +204,9 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/shirou/gopsutil/v3 v3.21.8/go.mod h1:YWp/H8Qs5fVmf17v7JNZzA0mPJ+mS2e9JdiUF9LlKzQ=
@ -319,6 +321,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -364,8 +367,9 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -422,7 +426,6 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
@ -506,8 +509,9 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

@ -3,11 +3,11 @@ module github.com/go-kratos/kratos/contrib/opensergo/v2
go 1.17
require (
github.com/go-kratos/kratos/v2 v2.5.1
github.com/go-kratos/kratos/v2 v2.5.2
github.com/opensergo/opensergo-go v0.0.0-20220331070310-e5b01fee4d1c
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2
google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd
google.golang.org/grpc v1.46.2
google.golang.org/grpc v1.50.1
google.golang.org/protobuf v1.28.1
)

@ -153,8 +153,9 @@ google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTp
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.46.2 h1:u+MLGgVf7vRdjEYZ8wDFhAVNmhkbJ5hmrA1LMWK1CAQ=
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=

@ -3,6 +3,7 @@ package opensergo
import (
"encoding/json"
"net"
"net/http"
"net/url"
"os"
"strconv"
@ -186,15 +187,15 @@ func listDescriptors() (services []*v1.ServiceDescriptor, types []*v1.TypeDescri
func HTTPPatternInfo(pattern interface{}) (method string, path string) {
switch p := pattern.(type) {
case *annotations.HttpRule_Get:
return "GET", p.Get
return http.MethodGet, p.Get
case *annotations.HttpRule_Post:
return "POST", p.Post
return http.MethodPost, p.Post
case *annotations.HttpRule_Delete:
return "DELETE", p.Delete
return http.MethodDelete, p.Delete
case *annotations.HttpRule_Patch:
return "PATCH", p.Patch
return http.MethodPatch, p.Patch
case *annotations.HttpRule_Put:
return "PUT", p.Put
return http.MethodPut, p.Put
case *annotations.HttpRule_Custom:
return p.Custom.Kind, p.Custom.Path
default:

@ -2,6 +2,7 @@ package opensergo
import (
"net"
"net/http"
"os"
"path/filepath"
"reflect"
@ -195,7 +196,7 @@ func TestHTTPPatternInfo(t *testing.T) {
args: args{
pattern: &annotations.HttpRule_Get{Get: "/foo"},
},
wantMethod: "GET",
wantMethod: http.MethodGet,
wantPath: "/foo",
},
{
@ -203,7 +204,7 @@ func TestHTTPPatternInfo(t *testing.T) {
args: args{
pattern: &annotations.HttpRule_Post{Post: "/foo"},
},
wantMethod: "POST",
wantMethod: http.MethodPost,
wantPath: "/foo",
},
{
@ -211,7 +212,7 @@ func TestHTTPPatternInfo(t *testing.T) {
args: args{
pattern: &annotations.HttpRule_Put{Put: "/foo"},
},
wantMethod: "PUT",
wantMethod: http.MethodPut,
wantPath: "/foo",
},
{
@ -219,7 +220,7 @@ func TestHTTPPatternInfo(t *testing.T) {
args: args{
pattern: &annotations.HttpRule_Delete{Delete: "/foo"},
},
wantMethod: "DELETE",
wantMethod: http.MethodDelete,
wantPath: "/foo",
},
{
@ -227,7 +228,7 @@ func TestHTTPPatternInfo(t *testing.T) {
args: args{
pattern: &annotations.HttpRule_Patch{Patch: "/foo"},
},
wantMethod: "PATCH",
wantMethod: http.MethodPatch,
wantPath: "/foo",
},
{

@ -3,8 +3,8 @@ module github.com/go-kratos/kratos/contrib/registry/consul/v2
go 1.16
require (
github.com/go-kratos/kratos/v2 v2.5.1
github.com/hashicorp/consul/api v1.14.0
github.com/go-kratos/kratos/v2 v2.5.2
github.com/hashicorp/consul/api v1.15.3
)
replace github.com/go-kratos/kratos/v2 => ../../../

@ -91,10 +91,10 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/consul/api v1.14.0 h1:Y64GIJ8hYTu+tuGekwO4G4ardXoiCivX9wv1iP/kihk=
github.com/hashicorp/consul/api v1.14.0/go.mod h1:bcaw5CSZ7NE9qfOfKCI1xb7ZKjzu/MyvQkCLTfqLqxQ=
github.com/hashicorp/consul/sdk v0.10.0 h1:rGLEh2AWK4K0KCMvqWAz2EYxQqgciIfMagWZ0nVe5MI=
github.com/hashicorp/consul/sdk v0.10.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw=
github.com/hashicorp/consul/api v1.15.3 h1:WYONYL2rxTXtlekAqblR2SCdJsizMDIj/uXb5wNy9zU=
github.com/hashicorp/consul/api v1.15.3/go.mod h1:/g/qgcoBcEXALCNZgRRisyTW0nY86++L0KbeAMXYCeY=
github.com/hashicorp/consul/sdk v0.11.0 h1:HRzj8YSCln2yGgCumN5CL8lYlD3gBurnervJRJAZyC4=
github.com/hashicorp/consul/sdk v0.11.0/go.mod h1:yPkX5Q6CsxTFMjQQDJwzeNmUUF5NUGGbrDsv9wTb8cw=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=

@ -7,14 +7,14 @@ import (
"sync/atomic"
"time"
"github.com/go-kratos/kratos/v2/registry"
"github.com/hashicorp/consul/api"
"github.com/go-kratos/kratos/v2/registry"
)
var (
_ registry.Registrar = &Registry{}
_ registry.Discovery = &Registry{}
_ registry.Registrar = (*Registry)(nil)
_ registry.Discovery = (*Registry)(nil)
)
// Option is consul registry option.

@ -3,7 +3,7 @@ module github.com/go-kratos/kratos/contrib/registry/discovery/v2
go 1.16
require (
github.com/go-kratos/kratos/v2 v2.5.1
github.com/go-kratos/kratos/v2 v2.5.2
github.com/go-resty/resty/v2 v2.7.0
github.com/pkg/errors v0.9.1
)

@ -3,9 +3,9 @@ module github.com/go-kratos/kratos/contrib/registry/etcd/v2
go 1.16
require (
github.com/go-kratos/kratos/v2 v2.5.1
go.etcd.io/etcd/client/v3 v3.5.4
google.golang.org/grpc v1.46.2
github.com/go-kratos/kratos/v2 v2.5.2
go.etcd.io/etcd/client/v3 v3.5.5
google.golang.org/grpc v1.50.1
)
replace github.com/go-kratos/kratos/v2 => ../../../

@ -17,6 +17,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
@ -33,6 +34,7 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
@ -151,12 +153,12 @@ github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcy
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.etcd.io/etcd/api/v3 v3.5.4 h1:OHVyt3TopwtUQ2GKdd5wu3PmmipR4FTwCqoEjSyRdIc=
go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A=
go.etcd.io/etcd/client/pkg/v3 v3.5.4 h1:lrneYvz923dvC14R54XcA7FXoZ3mlGZAgmwhfm7HqOg=
go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v3 v3.5.4 h1:p83BUL3tAYS0OT/r0qglgc3M1JjhM0diV8DSWAhVXv4=
go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY=
go.etcd.io/etcd/api/v3 v3.5.5 h1:BX4JIbQ7hl7+jL+g+2j5UAr0o1bctCm6/Ct+ArBGkf0=
go.etcd.io/etcd/api/v3 v3.5.5/go.mod h1:KFtNaxGDw4Yx/BA4iPPwevUTAuqcsPxzyX8PHydchN8=
go.etcd.io/etcd/client/pkg/v3 v3.5.5 h1:9S0JUVvmrVl7wCF39iTQthdaaNIiAaQbmK75ogO6GU8=
go.etcd.io/etcd/client/pkg/v3 v3.5.5/go.mod h1:ggrwbk069qxpKPq8/FKkQ3Xq9y39kbFR4LnKszpRXeQ=
go.etcd.io/etcd/client/v3 v3.5.5 h1:q++2WTJbUgpQu4B6hCuT7VkdwaTP7Qz6Daak3WzbrlI=
go.etcd.io/etcd/client/v3 v3.5.5/go.mod h1:aApjR4WGlSumpnJ2kloS75h6aHUmAyaPLjHMxpc7E7c=
go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU=
go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU=
@ -267,9 +269,11 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.46.2 h1:u+MLGgVf7vRdjEYZ8wDFhAVNmhkbJ5hmrA1LMWK1CAQ=
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY=
google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=

@ -12,8 +12,8 @@ import (
)
var (
_ registry.Registrar = &Registry{}
_ registry.Discovery = &Registry{}
_ registry.Registrar = (*Registry)(nil)
_ registry.Discovery = (*Registry)(nil)
)
// Option is etcd registry option.

@ -16,7 +16,7 @@ import (
const (
statusUp = "UP"
statusDown = "DOWN"
statusOutOfServeice = "OUT_OF_SERVICE"
statusOutOfService = "OUT_OF_SERVICE"
heartbeatRetry = 3
maxIdleConns = 100
heartbeatTime = 10
@ -153,7 +153,7 @@ func NewClient(urls []string, opts ...ClientOption) *Client {
func (e *Client) FetchApps(ctx context.Context) []Application {
var m ApplicationsRootResponse
if err := e.do(ctx, "GET", []string{"apps"}, nil, &m); err != nil {
if err := e.do(ctx, http.MethodGet, []string{"apps"}, nil, &m); err != nil {
return nil
}
@ -161,7 +161,7 @@ func (e *Client) FetchApps(ctx context.Context) []Application {
}
func (e *Client) FetchAppInstances(ctx context.Context, appID string) (m Application, err error) {
err = e.do(ctx, "GET", []string{"apps", appID}, nil, &m)
err = e.do(ctx, http.MethodGet, []string{"apps", appID}, nil, &m)
return
}
@ -174,21 +174,21 @@ func (e *Client) FetchAppUpInstances(ctx context.Context, appID string) []Instan
}
func (e *Client) FetchAppInstance(ctx context.Context, appID string, instanceID string) (m Instance, err error) {
err = e.do(ctx, "GET", []string{"apps", appID, instanceID}, nil, &m)
err = e.do(ctx, http.MethodGet, []string{"apps", appID, instanceID}, nil, &m)
return
}
func (e *Client) FetchInstance(ctx context.Context, instanceID string) (m Instance, err error) {
err = e.do(ctx, "GET", []string{"instances", instanceID}, nil, &m)
err = e.do(ctx, http.MethodGet, []string{"instances", instanceID}, nil, &m)
return
}
func (e *Client) Out(ctx context.Context, appID, instanceID string) error {
return e.do(ctx, "PUT", []string{"apps", appID, instanceID, fmt.Sprintf("status?value=%s", statusOutOfServeice)}, nil, nil)
return e.do(ctx, http.MethodPut, []string{"apps", appID, instanceID, fmt.Sprintf("status?value=%s", statusOutOfService)}, nil, nil)
}
func (e *Client) Down(ctx context.Context, appID, instanceID string) error {
return e.do(ctx, "PUT", []string{"apps", appID, instanceID, fmt.Sprintf("status?value=%s", statusDown)}, nil, nil)
return e.do(ctx, http.MethodPut, []string{"apps", appID, instanceID, fmt.Sprintf("status?value=%s", statusDown)}, nil, nil)
}
func (e *Client) FetchAllUpInstances(ctx context.Context) []Instance {
@ -200,7 +200,7 @@ func (e *Client) Register(ctx context.Context, ep Endpoint) error {
}
func (e *Client) Deregister(ctx context.Context, appID, instanceID string) error {
if err := e.do(ctx, "DELETE", []string{"apps", appID, instanceID}, nil, nil); err != nil {
if err := e.do(ctx, http.MethodDelete, []string{"apps", appID, instanceID}, nil, nil); err != nil {
return err
}
go e.cancelHeartbeat(appID)
@ -239,7 +239,7 @@ func (e *Client) registerEndpoint(ctx context.Context, ep Endpoint) error {
if err != nil {
return err
}
return e.do(ctx, "POST", []string{"apps", ep.AppID}, bytes.NewReader(body), nil)
return e.do(ctx, http.MethodPost, []string{"apps", ep.AppID}, bytes.NewReader(body), nil)
}
func (e *Client) Heartbeat(ep Endpoint) {
@ -257,7 +257,7 @@ func (e *Client) Heartbeat(ep Endpoint) {
case <-e.keepalive[ep.AppID]:
return
case <-ticker.C:
if err := e.do(e.ctx, "PUT", []string{"apps", ep.AppID, ep.InstanceID}, nil, nil); err != nil {
if err := e.do(e.ctx, http.MethodPut, []string{"apps", ep.AppID, ep.InstanceID}, nil, nil); err != nil {
if retryCount++; retryCount > heartbeatRetry {
_ = e.registerEndpoint(e.ctx, ep)
retryCount = 0
@ -268,8 +268,8 @@ func (e *Client) Heartbeat(ep Endpoint) {
}
func (e *Client) cancelHeartbeat(appID string) {
defer e.lock.Unlock()
e.lock.Lock()
defer e.lock.Unlock()
if ch, ok := e.keepalive[appID]; ok {
ch <- struct{}{}
}
@ -307,39 +307,50 @@ func (e *Client) buildAPI(currentTimes int, params ...string) string {
return strings.Join(params, "/")
}
func (e *Client) do(ctx context.Context, method string, params []string, input io.Reader, output interface{}) error {
for i := 0; i < e.maxRetry; i++ {
request, err := http.NewRequest(method, e.buildAPI(i, params...), input)
func (e *Client) request(ctx context.Context, method string, params []string, input io.Reader, output interface{}, i int) (bool, error) {
request, err := http.NewRequestWithContext(ctx, method, e.buildAPI(i, params...), input)
if err != nil {
return err
return false, err
}
request = request.WithContext(ctx)
request.Header.Add("User-Agent", "go-eureka-client")
request.Header.Add("Accept", "application/json;charset=UTF-8")
request.Header.Add("Content-Type", "application/json;charset=UTF-8")
resp, err := e.client.Do(request)
if err != nil {
continue
return true, err
}
defer func() {
_, _ = io.Copy(io.Discard, resp.Body)
resp.Body.Close()
_ = resp.Body.Close()
}()
if output != nil && resp.StatusCode/100 == 2 {
data, err := io.ReadAll(resp.Body)
if err != nil {
return err
return false, err
}
if err = json.Unmarshal(data, output); err != nil {
return err
err = json.Unmarshal(data, output)
if err != nil {
return false, err
}
}
if resp.StatusCode >= http.StatusBadRequest {
return fmt.Errorf("response Error %d", resp.StatusCode)
return false, fmt.Errorf("response Error %d", resp.StatusCode)
}
return false, nil
}
func (e *Client) do(ctx context.Context, method string, params []string, input io.Reader, output interface{}) error {
for i := 0; i < e.maxRetry; i++ {
retry, err := e.request(ctx, method, params, input, output, i)
if retry {
continue
}
if err != nil {
return err
}
return nil
}
return fmt.Errorf("retry after %d times", e.maxRetry)

@ -11,8 +11,8 @@ import (
)
var (
_ registry.Registrar = &Registry{}
_ registry.Discovery = &Registry{}
_ registry.Registrar = (*Registry)(nil)
_ registry.Discovery = (*Registry)(nil)
)
type Option func(o *Registry)

@ -3,7 +3,7 @@ module github.com/go-kratos/kratos/contrib/registry/kubernetes/v2
go 1.16
require (
github.com/go-kratos/kratos/v2 v2.5.1
github.com/go-kratos/kratos/v2 v2.5.2
github.com/json-iterator/go v1.1.12
k8s.io/api v0.24.3
k8s.io/apimachinery v0.24.3

@ -3,7 +3,7 @@ module github.com/go-kratos/kratos/contrib/registry/nacos/v2
go 1.16
require (
github.com/go-kratos/kratos/v2 v2.5.1
github.com/go-kratos/kratos/v2 v2.5.2
github.com/nacos-group/nacos-sdk-go v1.0.9
)

@ -3,8 +3,8 @@ module github.com/go-kratos/kratos/contrib/registry/polaris/v2
go 1.16
require (
github.com/go-kratos/kratos/v2 v2.5.1
github.com/polarismesh/polaris-go v1.1.0
github.com/go-kratos/kratos/v2 v2.5.2
github.com/polarismesh/polaris-go v1.2.0
)
replace github.com/go-kratos/kratos/v2 => ../../../

@ -60,22 +60,21 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@ -213,8 +212,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/polarismesh/polaris-go v1.1.0 h1:nFvn3q3XaVFhzF7pBnIySrN0ZZBwvbbYXC5r2DpsQN0=
github.com/polarismesh/polaris-go v1.1.0/go.mod h1:tquawfjEKp1W3ffNJQSzhfditjjoZ7tvhOCElN7Efzs=
github.com/polarismesh/polaris-go v1.2.0 h1:GIWvUno4DB0PD3HC7bHmTCeG+a54neMrVvNPiRXJUtc=
github.com/polarismesh/polaris-go v1.2.0/go.mod h1:HsN0ierETIujHpmnnYJ3qkwQw4QGAECuHvBZTDaw1tI=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
@ -275,12 +274,12 @@ go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI=
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@ -349,8 +348,8 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf h1:R150MpwJIv1MpS0N/pc+NhTM8ajzvlmxlY5OYsrevXQ=
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -409,19 +408,24 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60=
golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -524,6 +528,7 @@ google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7Fc
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20220504150022-98cd25cafc72/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd h1:e0TwkXOdbnH/1x5rc5MZ/VYyiZ4v+RdVfrGMqEwT68I=
google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@ -540,7 +545,6 @@ google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.46.2 h1:u+MLGgVf7vRdjEYZ8wDFhAVNmhkbJ5hmrA1LMWK1CAQ=
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=

@ -3,7 +3,7 @@ module github.com/go-kratos/kratos/contrib/registry/zookeeper/v2
go 1.16
require (
github.com/go-kratos/kratos/v2 v2.5.1
github.com/go-kratos/kratos/v2 v2.5.2
github.com/go-zookeeper/zk v1.0.3
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29
)

@ -12,8 +12,8 @@ import (
)
var (
_ registry.Registrar = &Registry{}
_ registry.Discovery = &Registry{}
_ registry.Registrar = (*Registry)(nil)
_ registry.Discovery = (*Registry)(nil)
)
// Option is etcd registry option.

@ -4,10 +4,10 @@ import (
"net/url"
"reflect"
"github.com/go-kratos/kratos/v2/encoding"
"github.com/go-playground/form/v4"
"google.golang.org/protobuf/proto"
"github.com/go-kratos/kratos/v2/encoding"
)
const (
@ -70,7 +70,8 @@ func (c codec) Unmarshal(data []byte, v interface{}) error {
}
if m, ok := v.(proto.Message); ok {
return DecodeValues(m, vs)
} else if m, ok := reflect.Indirect(reflect.ValueOf(v)).Interface().(proto.Message); ok {
}
if m, ok := rv.Interface().(proto.Message); ok {
return DecodeValues(m, vs)
}

@ -26,14 +26,12 @@ type TestModel struct {
Name string `json:"name"`
}
const contentType = "x-www-form-urlencoded"
func TestFormCodecMarshal(t *testing.T) {
req := &LoginRequest{
Username: "kratos",
Password: "kratos_pwd",
}
content, err := encoding.GetCodec(contentType).Marshal(req)
content, err := encoding.GetCodec(Name).Marshal(req)
if err != nil {
t.Errorf("marshal error: %v", err)
}
@ -45,7 +43,7 @@ func TestFormCodecMarshal(t *testing.T) {
Username: "kratos",
Password: "",
}
content, err = encoding.GetCodec(contentType).Marshal(req)
content, err = encoding.GetCodec(Name).Marshal(req)
if err != nil {
t.Errorf("expect %v, got %v", nil, err)
}
@ -57,7 +55,7 @@ func TestFormCodecMarshal(t *testing.T) {
ID: 1,
Name: "kratos",
}
content, err = encoding.GetCodec(contentType).Marshal(m)
content, err = encoding.GetCodec(Name).Marshal(m)
t.Log(string(content))
if err != nil {
t.Errorf("expect %v, got %v", nil, err)
@ -72,13 +70,13 @@ func TestFormCodecUnmarshal(t *testing.T) {
Username: "kratos",
Password: "kratos_pwd",
}
content, err := encoding.GetCodec(contentType).Marshal(req)
content, err := encoding.GetCodec(Name).Marshal(req)
if err != nil {
t.Errorf("expect %v, got %v", nil, err)
}
bindReq := new(LoginRequest)
err = encoding.GetCodec(contentType).Unmarshal(content, bindReq)
err = encoding.GetCodec(Name).Unmarshal(content, bindReq)
if err != nil {
t.Errorf("expect %v, got %v", nil, err)
}
@ -119,7 +117,7 @@ func TestProtoEncodeDecode(t *testing.T) {
String_: &wrapperspb.StringValue{Value: "go-kratos"},
Bytes: &wrapperspb.BytesValue{Value: []byte("123")},
}
content, err := encoding.GetCodec(contentType).Marshal(in)
content, err := encoding.GetCodec(Name).Marshal(in)
if err != nil {
t.Errorf("expect %v, got %v", nil, err)
}
@ -130,7 +128,7 @@ func TestProtoEncodeDecode(t *testing.T) {
t.Errorf("rawpath is not equal to %v", string(content))
}
in2 := &complex.Complex{}
err = encoding.GetCodec(contentType).Unmarshal(content, in2)
err = encoding.GetCodec(Name).Unmarshal(content, in2)
if err != nil {
t.Errorf("expect %v, got %v", nil, err)
}
@ -163,7 +161,7 @@ func TestProtoEncodeDecode(t *testing.T) {
func TestDecodeStructPb(t *testing.T) {
req := new(ectest.StructPb)
query := `data={"name":"kratos"}&data_list={"name1": "kratos"}&data_list={"name2": "go-kratos"}`
if err := encoding.GetCodec(contentType).Unmarshal([]byte(query), req); err != nil {
if err := encoding.GetCodec(Name).Unmarshal([]byte(query), req); err != nil {
t.Errorf("expect %v, got %v", nil, err)
}
if !reflect.DeepEqual("kratos", req.Data.GetFields()["name"].GetStringValue()) {
@ -186,7 +184,7 @@ func TestDecodeBytesValuePb(t *testing.T) {
val := base64.URLEncoding.EncodeToString([]byte(url))
content := "bytes=" + val
in2 := &complex.Complex{}
if err := encoding.GetCodec(contentType).Unmarshal([]byte(content), in2); err != nil {
if err := encoding.GetCodec(Name).Unmarshal([]byte(content), in2); err != nil {
t.Errorf("expect %v, got %v", nil, err)
}
if !reflect.DeepEqual(url, string(in2.Bytes.Value)) {

@ -10,13 +10,12 @@ import (
"time"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/fieldmaskpb"
"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/timestamppb"
"google.golang.org/protobuf/types/known/wrapperspb"
)
@ -122,15 +121,13 @@ func populateRepeatedField(fd protoreflect.FieldDescriptor, list protoreflect.Li
}
func populateMapField(fd protoreflect.FieldDescriptor, mp protoreflect.Map, fieldPath []string, values []string) error {
flen := len(fieldPath)
vlen := len(values)
// post sub key.
nkey := flen - 1
nkey := len(fieldPath) - 1
key, err := parseField(fd.MapKey(), fieldPath[nkey])
if err != nil {
return fmt.Errorf("parsing map key %q: %w", fd.FullName().Name(), err)
}
vkey := vlen - 1
vkey := len(values) - 1
value, err := parseField(fd.MapValue(), values[vkey])
if err != nil {
return fmt.Errorf("parsing map value %q: %w", fd.FullName().Name(), err)

@ -0,0 +1,217 @@
package form
import (
"fmt"
"net/url"
"reflect"
"strconv"
"testing"
"google.golang.org/protobuf/reflect/protoreflect"
"github.com/go-kratos/kratos/v2/internal/testdata/complex"
)
func TestDecodeValues(t *testing.T) {
form, err := url.ParseQuery("a=19&age=18&b=true&bool=false&byte=MTIz&bytes=MTIz&count=3&d=22.22&double=12.33&duration=" +
"2m0.000000022s&field=1%2C2&float=12.34&id=2233&int32=32&int64=64&numberOne=2233&price=11.23&sex=woman&simples=3344&" +
"simples=5566&string=go-kratos&timestamp=1970-01-01T00%3A00%3A20.000000002Z&uint32=32&uint64=64&very_simple.component=5566")
if err != nil {
t.Fatal(err)
}
comp := &complex.Complex{}
err = DecodeValues(comp, form)
if err != nil {
t.Fatal(err)
}
if comp.Id != int64(2233) {
t.Errorf("want %v, got %v", int64(2233), comp.Id)
}
if comp.NoOne != "2233" {
t.Errorf("want %v, got %v", "2233", comp.NoOne)
}
if comp.Simple == nil {
t.Fatalf("want %v, got %v", nil, comp.Simple)
}
if comp.Simple.Component != "5566" {
t.Errorf("want %v, got %v", "5566", comp.Simple.Component)
}
if len(comp.Simples) != 2 {
t.Fatalf("want %v, got %v", 2, len(comp.Simples))
}
if comp.Simples[0] != "3344" {
t.Errorf("want %v, got %v", "3344", comp.Simples[0])
}
if comp.Simples[1] != "5566" {
t.Errorf("want %v, got %v", "5566", comp.Simples[1])
}
}
func TestGetFieldDescriptor(t *testing.T) {
comp := &complex.Complex{}
field := getFieldDescriptor(comp.ProtoReflect(), "id")
if field.Kind() != protoreflect.Int64Kind {
t.Errorf("want: %d, got: %d", protoreflect.Int64Kind, field.Kind())
}
field = getFieldDescriptor(comp.ProtoReflect(), "simples")
if field.Kind() != protoreflect.StringKind {
t.Errorf("want: %d, got: %d", protoreflect.StringKind, field.Kind())
}
}
func TestPopulateRepeatedField(t *testing.T) {
query, err := url.ParseQuery("simples=3344&simples=5566")
if err != nil {
t.Fatal(err)
}
comp := &complex.Complex{}
field := getFieldDescriptor(comp.ProtoReflect(), "simples")
err = populateRepeatedField(field, comp.ProtoReflect().Mutable(field).List(), query["simples"])
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual([]string{"3344", "5566"}, comp.GetSimples()) {
t.Errorf("want: %v, got: %v", []string{"3344", "5566"}, comp.GetSimples())
}
}
func TestPopulateMapField(t *testing.T) {
query, err := url.ParseQuery("map%5Bkratos%5D=https://go-kratos.dev/")
if err != nil {
t.Fatal(err)
}
comp := &complex.Complex{}
field := getFieldDescriptor(comp.ProtoReflect(), "map")
// Fill the comp map field with the url query values
err = populateMapField(field, comp.ProtoReflect().Mutable(field).Map(), []string{"kratos"}, query["map[kratos]"])
if err != nil {
t.Fatal(err)
}
// Get the comp map field value
if query["map[kratos]"][0] != comp.Map["kratos"] {
t.Errorf("want: %s, got: %s", query["map[kratos]"], comp.Map["kratos"])
}
}
func TestParseField(t *testing.T) {
tests := []struct {
name string
fieldName string
protoReflectKind protoreflect.Kind
value string
targetProtoReflectValue protoreflect.Value
targetErr error
}{
{
name: "BoolKind",
fieldName: "b",
protoReflectKind: protoreflect.BoolKind,
value: "true",
targetProtoReflectValue: protoreflect.ValueOfBool(true),
targetErr: nil,
},
{
name: "BoolKind",
fieldName: "b",
protoReflectKind: protoreflect.BoolKind,
value: "a",
targetProtoReflectValue: protoreflect.Value{},
targetErr: &strconv.NumError{Func: "ParseBool", Num: "a", Err: strconv.ErrSyntax},
},
{
name: "EnumKind",
fieldName: "sex",
protoReflectKind: protoreflect.EnumKind,
value: "1",
targetProtoReflectValue: protoreflect.ValueOfEnum(1),
targetErr: nil,
},
{
name: "EnumKind",
fieldName: "sex",
protoReflectKind: protoreflect.EnumKind,
value: "2",
targetProtoReflectValue: protoreflect.Value{},
targetErr: fmt.Errorf("%q is not a valid value", "2"),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
comp := &complex.Complex{}
field := getFieldDescriptor(comp.ProtoReflect(), test.fieldName)
if test.protoReflectKind != field.Kind() {
t.Fatalf("want: %d, got: %d", test.protoReflectKind, field.Kind())
}
val, err := parseField(field, test.value)
if !reflect.DeepEqual(test.targetErr, err) {
t.Fatalf("want: %s, got: %s", test.targetErr, err)
}
if !reflect.DeepEqual(test.targetProtoReflectValue, val) {
t.Errorf("want: %s, got: %s", test.targetProtoReflectValue, val)
}
})
}
}
func TestJsonSnakeCase(t *testing.T) {
tests := []struct {
camelCase string
snakeCase string
}{
{
"userId", "user_id",
},
{
"user", "user",
},
{
"userIdAndUsername", "user_id_and_username",
},
{
"", "",
},
}
for _, test := range tests {
t.Run(test.camelCase, func(t *testing.T) {
snake := jsonSnakeCase(test.camelCase)
if snake != test.snakeCase {
t.Errorf("want: %s, got: %s", test.snakeCase, snake)
}
})
}
}
func TestIsASCIIUpper(t *testing.T) {
tests := []struct {
b byte
upper bool
}{
{
'A', true,
},
{
'a', false,
},
{
',', false,
},
{
'1', false,
},
{
' ', false,
},
}
for _, test := range tests {
t.Run(string(test.b), func(t *testing.T) {
upper := isASCIIUpper(test.b)
if test.upper != upper {
t.Errorf("'%s' is not ascii upper", string(test.b))
}
})
}
}

@ -64,20 +64,18 @@ func (f *Filter) Log(level Level, keyvals ...interface{}) error {
if level < f.level {
return nil
}
// fkv is used to provide a slice to contains both logger.prefix and keyvals for filter
var fkv []interface{}
// prefixkv contains the slice of arguments defined as prefixes during the log initialization
var prefixkv []interface{}
l, ok := f.logger.(*logger)
if ok && len(l.prefix) > 0 {
fkv = make([]interface{}, 0, len(l.prefix)+len(keyvals))
fkv = append(fkv, l.prefix...)
fkv = append(fkv, keyvals...)
prefixkv = make([]interface{}, 0, len(l.prefix))
prefixkv = append(prefixkv, l.prefix...)
}
if !ok {
fkv = keyvals
}
if f.filter != nil && f.filter(level, fkv...) {
if f.filter != nil && (f.filter(level, prefixkv...) || f.filter(level, keyvals...)) {
return nil
}
if len(f.key) > 0 || len(f.value) > 0 {
for i := 0; i < len(keyvals); i += 2 {
v := i + 1

@ -102,13 +102,19 @@ func TestFilterFuncWitchLoggerPrefix(t *testing.T) {
want: "",
},
{
// Filtered value
logger: NewFilter(With(NewStdLogger(buf), "caller", "caller"), FilterFunc(testFilterFuncWithLoggerPrefix)),
want: "INFO caller=caller msg=msg\n",
want: "INFO caller=caller msg=msg filtered=***\n",
},
{
// NO prefix
logger: NewFilter(With(NewStdLogger(buf)), FilterFunc(testFilterFuncWithLoggerPrefix)),
want: "INFO msg=msg filtered=***\n",
},
}
for _, tt := range tests {
err := tt.logger.Log(LevelInfo, "msg", "msg")
err := tt.logger.Log(LevelInfo, "msg", "msg", "filtered", "true")
if err != nil {
t.Fatal("err should be nil")
}
@ -128,6 +134,9 @@ func testFilterFuncWithLoggerPrefix(level Level, keyvals ...interface{}) bool {
if keyvals[i] == "prefix" {
return true
}
if keyvals[i] == "filtered" {
keyvals[i+1] = fuzzyStr
}
}
return false
}

@ -21,6 +21,10 @@ const (
LevelFatal
)
func (l Level) Key() string {
return LevelKey
}
func (l Level) String() string {
switch l {
case LevelDebug:

@ -2,6 +2,12 @@ package log
import "testing"
func TestLevel_Key(t *testing.T) {
if LevelInfo.Key() != LevelKey {
t.Errorf("want: %s, got: %s", LevelKey, LevelInfo.Key())
}
}
func TestLevel_String(t *testing.T) {
tests := []struct {
name string

@ -254,7 +254,7 @@ func TestServer(t *testing.T) {
}
if test.exceptErr == nil {
if testToken == nil {
t.Errorf("except testToken not nil, but got nil")
t.Fatal("except testToken not nil, but got nil")
}
_, ok := testToken.(jwt.MapClaims)
if !ok {
@ -493,3 +493,26 @@ func TestClientMissKey(t *testing.T) {
}
})
}
func TestNewContextAndFromContext(t *testing.T) {
tests := []struct {
name string
claims jwt.MapClaims
}{
{"val not nil", jwt.MapClaims{"name": "kratos"}},
{"val nil", nil},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
ctx := NewContext(context.Background(), test.claims)
claims, ok := FromContext(ctx)
if !ok {
t.Fatal("ctx not found authKey{}")
}
if !reflect.DeepEqual(test.claims, claims) {
t.Errorf(`want: %s, got: %v`, test.claims, claims)
}
})
}
}

@ -111,7 +111,7 @@ func (d *dummyStringer) String() string {
return "my value"
}
func Test_extractArgs(t *testing.T) {
func TestExtractArgs(t *testing.T) {
if extractArgs(&dummyStringer{field: ""}) != "my value" {
t.Errorf(`The stringified dummyStringer structure must be equal to "my value", %v given`, extractArgs(&dummyStringer{field: ""}))
}
@ -120,3 +120,30 @@ func Test_extractArgs(t *testing.T) {
t.Errorf(`The stringified dummy structure must be equal to "&{field:value}", %v given`, extractArgs(&dummy{field: "value"}))
}
}
func TestExtractError(t *testing.T) {
tests := []struct {
name string
err error
wantLevel log.Level
wantErrStr string
}{
{
"no error", nil, log.LevelInfo, "",
},
{
"error", errors.New("test error"), log.LevelError, "test error",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
level, errStr := extractError(test.err)
if level != test.wantLevel {
t.Errorf("want: %d, got: %d", test.wantLevel, level)
}
if errStr != test.wantErrStr {
t.Errorf("want: %s, got: %s", test.wantErrStr, errStr)
}
})
}
}

@ -51,7 +51,11 @@ func Server(opts ...Option) middleware.Middleware {
}
return func(handler middleware.Handler) middleware.Handler {
return func(ctx context.Context, req interface{}) (reply interface{}, err error) {
if tr, ok := transport.FromServerContext(ctx); ok {
tr, ok := transport.FromServerContext(ctx)
if !ok {
return handler(ctx, req)
}
md := options.md.Clone()
header := tr.RequestHeader()
for _, k := range header.Keys() {
@ -60,7 +64,6 @@ func Server(opts ...Option) middleware.Middleware {
}
}
ctx = metadata.NewServerContext(ctx, md)
}
return handler(ctx, req)
}
}
@ -76,7 +79,11 @@ func Client(opts ...Option) middleware.Middleware {
}
return func(handler middleware.Handler) middleware.Handler {
return func(ctx context.Context, req interface{}) (reply interface{}, err error) {
if tr, ok := transport.FromClientContext(ctx); ok {
tr, ok := transport.FromClientContext(ctx)
if !ok {
return handler(ctx, req)
}
header := tr.RequestHeader()
// x-md-local-
for k, v := range options.md {
@ -95,7 +102,6 @@ func Client(opts ...Option) middleware.Middleware {
}
}
}
}
return handler(ctx, req)
}
}

@ -4,6 +4,7 @@ import (
"context"
"errors"
"net/http"
"reflect"
"testing"
"github.com/go-kratos/kratos/v2/metadata"
@ -33,15 +34,18 @@ func (tr *testTransport) Operation() string { return "" }
func (tr *testTransport) RequestHeader() transport.Header { return tr.header }
func (tr *testTransport) ReplyHeader() transport.Header { return tr.header }
func TestSever(t *testing.T) {
var (
var (
globalKey = "x-md-global-key"
globalValue = "global-value"
localKey = "x-md-local-key"
localValue = "local-value"
customKey = "x-md-local-custom"
customValue = "custom-value"
constKey = "x-md-local-const"
constValue = "x-md-local-const"
)
)
func TestSever(t *testing.T) {
hs := func(ctx context.Context, in interface{}) (interface{}, error) {
md, ok := metadata.FromServerContext(ctx)
if !ok {
@ -75,16 +79,6 @@ func TestSever(t *testing.T) {
}
func TestClient(t *testing.T) {
var (
globalKey = "x-md-global-key"
globalValue = "global-value"
localKey = "x-md-local-key"
localValue = "local-value"
customKey = "x-md-local-custom"
customValue = "custom-value"
constKey = "x-md-local-const"
constValue = "x-md-local-const"
)
hs := func(ctx context.Context, in interface{}) (interface{}, error) {
tr, ok := transport.FromClientContext(ctx)
if !ok {
@ -127,13 +121,52 @@ func TestClient(t *testing.T) {
}
}
func Test_WithPropagatedPrefix(t *testing.T) {
o := &options{
func TestWithConstants(t *testing.T) {
md := metadata.Metadata{
constKey: constValue,
}
options := &options{
md: metadata.Metadata{
"override": "override",
},
}
WithConstants(md)(options)
if !reflect.DeepEqual(md, options.md) {
t.Errorf("want: %v, got: %v", md, options.md)
}
}
func TestOptions_WithPropagatedPrefix(t *testing.T) {
options := &options{
prefix: []string{"override"},
}
WithPropagatedPrefix("something", "another")(o)
prefixes := []string{"something", "another"}
if len(o.prefix) != 2 {
WithPropagatedPrefix(prefixes...)(options)
if !reflect.DeepEqual(prefixes, options.prefix) {
t.Error("The prefix must be overridden.")
}
}
func TestOptions_hasPrefix(t *testing.T) {
tests := []struct {
name string
options *options
key string
exists bool
}{
{"exists key upper", &options{prefix: []string{"prefix"}}, "PREFIX_true", true},
{"exists key lower", &options{prefix: []string{"prefix"}}, "prefix_true", true},
{"not exists key upper", &options{prefix: []string{"prefix"}}, "false_PREFIX", false},
{"not exists key lower", &options{prefix: []string{"prefix"}}, "false_prefix", false},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
exists := test.options.hasPrefix(test.key)
if test.exists != exists {
t.Errorf("key: '%sr', not exists prefixs: %v", test.key, test.options.prefix)
}
})
}
}

@ -30,6 +30,12 @@ type options struct {
registrarTimeout time.Duration
stopTimeout time.Duration
servers []transport.Server
// Before and After funcs
beforeStart []func(context.Context) error
beforeStop []func(context.Context) error
afterStart []func(context.Context) error
afterStop []func(context.Context) error
}
// ID with service id.
@ -91,3 +97,33 @@ func RegistrarTimeout(t time.Duration) Option {
func StopTimeout(t time.Duration) Option {
return func(o *options) { o.stopTimeout = t }
}
// Before and Afters
// BeforeStart run funcs before app starts
func BeforeStart(fn func(context.Context) error) Option {
return func(o *options) {
o.beforeStart = append(o.beforeStart, fn)
}
}
// BeforeStop run funcs before app stops
func BeforeStop(fn func(context.Context) error) Option {
return func(o *options) {
o.beforeStop = append(o.beforeStop, fn)
}
}
// AfterStart run funcs after app starts
func AfterStart(fn func(context.Context) error) Option {
return func(o *options) {
o.afterStart = append(o.afterStart, fn)
}
}
// AfterStop run funcs after app stops
func AfterStop(fn func(context.Context) error) Option {
return func(o *options) {
o.afterStop = append(o.afterStop, fn)
}
}

@ -152,3 +152,39 @@ func TestStopTimeout(t *testing.T) {
t.Fatal("o.stopTimeout is not equal to v")
}
}
func TestBeforeStart(t *testing.T) {
o := &options{}
v := func(_ context.Context) error {
t.Log("BeforeStart...")
return nil
}
BeforeStart(v)(o)
}
func TestBeforeStop(t *testing.T) {
o := &options{}
v := func(_ context.Context) error {
t.Log("BeforeStop...")
return nil
}
BeforeStop(v)(o)
}
func TestAfterStart(t *testing.T) {
o := &options{}
v := func(_ context.Context) error {
t.Log("AfterStart...")
return nil
}
AfterStart(v)(o)
}
func TestAfterStop(t *testing.T) {
o := &options{}
v := func(_ context.Context) error {
t.Log("AfterStop...")
return nil
}
AfterStop(v)(o)
}

@ -1,13 +1,21 @@
package selector
var globalSelector Builder
var globalSelector = &wrapSelector{}
var _ Builder = (*wrapSelector)(nil)
// wrapSelector wrapped Selector, help override global Selector implementation.
type wrapSelector struct{ Builder }
// GlobalSelector returns global selector builder.
func GlobalSelector() Builder {
if globalSelector.Builder != nil {
return globalSelector
}
return nil
}
// SetGlobalSelector set global selector builder.
func SetGlobalSelector(builder Builder) {
globalSelector = builder
globalSelector.Builder = builder
}

@ -4,6 +4,7 @@ import (
"container/list"
"context"
"math"
"net"
"sync"
"sync/atomic"
"time"
@ -158,8 +159,9 @@ func (n *Node) Pick() selector.DoneFunc {
if n.errHandler != nil && n.errHandler(di.Err) {
success = 0
}
var netErr net.Error
if errors.Is(context.DeadlineExceeded, di.Err) || errors.Is(context.Canceled, di.Err) ||
errors.IsServiceUnavailable(di.Err) || errors.IsGatewayTimeout(di.Err) {
errors.IsServiceUnavailable(di.Err) || errors.IsGatewayTimeout(di.Err) || errors.As(di.Err, &netErr) {
success = 0
}
}

@ -2,6 +2,7 @@ package ewma
import (
"context"
"net"
"reflect"
"testing"
"time"
@ -100,11 +101,15 @@ func TestDirectErrorHandler(t *testing.T) {
Endpoints: []string{"http://127.0.0.1:9090"},
Metadata: map[string]string{"weight": "10"},
}))
errs := []error{
context.DeadlineExceeded,
context.Canceled,
net.ErrClosed,
}
for i := 0; i < 5; i++ {
var err error
if i != 0 {
err = context.DeadlineExceeded
err = errs[i%len(errs)]
}
done := wn.Pick()
if done == nil {

@ -70,7 +70,7 @@ func TestWrr3(t *testing.T) {
t.Errorf("count1(%v) >= int64(4500),", count1)
}
if count2 <= int64(1500) {
t.Errorf("count2(%v) <= int64(1500)", count1)
t.Errorf("count2(%v) <= int64(1500)", count2)
}
if count2 >= int64(4500) {
t.Errorf("count2(%v) >= int64(4500),", count2)

@ -1,13 +1,13 @@
package grpc
import (
"github.com/go-kratos/kratos/v2/registry"
"github.com/go-kratos/kratos/v2/selector"
"github.com/go-kratos/kratos/v2/transport"
"google.golang.org/grpc/balancer"
"google.golang.org/grpc/balancer/base"
"google.golang.org/grpc/metadata"
"github.com/go-kratos/kratos/v2/registry"
"github.com/go-kratos/kratos/v2/selector"
"github.com/go-kratos/kratos/v2/transport"
)
const (
@ -15,8 +15,8 @@ const (
)
var (
_ base.PickerBuilder = &balancerBuilder{}
_ balancer.Picker = &balancerPicker{}
_ base.PickerBuilder = (*balancerBuilder)(nil)
_ balancer.Picker = (*balancerPicker)(nil)
)
func init() {

@ -96,7 +96,7 @@ func TestBindForm(t *testing.T) {
{
name: "error not nil",
args: args{
req: &http.Request{Method: "POST"},
req: &http.Request{Method: http.MethodPost},
target: &p1,
},
wantErr: true,
@ -106,7 +106,7 @@ func TestBindForm(t *testing.T) {
name: "error is nil",
args: args{
req: &http.Request{
Method: "POST",
Method: http.MethodPost,
Header: http.Header{"Content-Type": {"application/x-www-form-urlencoded; param=value"}},
Body: io.NopCloser(strings.NewReader("name=kratos&url=https://go-kratos.dev/")),
},
@ -119,7 +119,7 @@ func TestBindForm(t *testing.T) {
name: "error BadRequest",
args: args{
req: &http.Request{
Method: "POST",
Method: http.MethodPost,
Header: http.Header{"Content-Type": {"application/x-www-form-urlencoded; param=value"}},
Body: io.NopCloser(strings.NewReader("age=a")),
},

@ -9,6 +9,7 @@ import (
"fmt"
"io"
"log"
"net/http"
nethttp "net/http"
"reflect"
"strconv"
@ -348,18 +349,18 @@ func TestNewClient(t *testing.T) {
t.Error(err)
}
err = client.Invoke(context.Background(), "POST", "/go", map[string]string{"name": "kratos"}, nil, EmptyCallOption{}, &mockCallOption{})
err = client.Invoke(context.Background(), http.MethodPost, "/go", map[string]string{"name": "kratos"}, nil, EmptyCallOption{}, &mockCallOption{})
if err == nil {
t.Error("err should not be equal to nil")
}
err = client.Invoke(context.Background(), "POST", "/go", map[string]string{"name": "kratos"}, nil, EmptyCallOption{}, &mockCallOption{needErr: true})
err = client.Invoke(context.Background(), http.MethodPost, "/go", map[string]string{"name": "kratos"}, nil, EmptyCallOption{}, &mockCallOption{needErr: true})
if err == nil {
t.Error("err should be equal to callOption err")
}
client.opts.encoder = func(ctx context.Context, contentType string, in interface{}) (body []byte, err error) {
return nil, errors.New("mock test encoder error")
}
err = client.Invoke(context.Background(), "POST", "/go", map[string]string{"name": "kratos"}, nil, EmptyCallOption{})
err = client.Invoke(context.Background(), http.MethodPost, "/go", map[string]string{"name": "kratos"}, nil, EmptyCallOption{})
if err == nil {
t.Error("err should be equal to encoder error")
}

@ -30,7 +30,7 @@ func TestContextHeader(t *testing.T) {
func TestContextForm(t *testing.T) {
w := wrapper{
router: testRouter,
req: &http.Request{Header: map[string][]string{"name": {"kratos"}}, Method: "POST"},
req: &http.Request{Header: map[string][]string{"name": {"kratos"}}, Method: http.MethodPost},
res: nil,
w: responseWriter{},
}
@ -54,7 +54,7 @@ func TestContextForm(t *testing.T) {
func TestContextQuery(t *testing.T) {
w := wrapper{
router: testRouter,
req: &http.Request{URL: &url.URL{Scheme: "https", Host: "github.com", Path: "go-kratos/kratos", RawQuery: "page=1"}, Method: "POST"},
req: &http.Request{URL: &url.URL{Scheme: "https", Host: "github.com", Path: "go-kratos/kratos", RawQuery: "page=1"}, Method: http.MethodPost},
res: nil,
w: responseWriter{},
}
@ -65,7 +65,7 @@ func TestContextQuery(t *testing.T) {
}
func TestContextRequest(t *testing.T) {
req := &http.Request{Method: "POST"}
req := &http.Request{Method: http.MethodPost}
w := wrapper{
router: testRouter,
req: req,
@ -82,7 +82,7 @@ func TestContextResponse(t *testing.T) {
res := httptest.NewRecorder()
w := wrapper{
router: &Router{srv: &Server{enc: DefaultResponseEncoder}},
req: &http.Request{Method: "POST"},
req: &http.Request{Method: http.MethodPost},
res: res,
w: responseWriter{200, res},
}
@ -173,7 +173,7 @@ func TestContextResponseReturn(t *testing.T) {
func TestContextCtx(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
req := &http.Request{Method: "POST"}
req := &http.Request{Method: http.MethodPost}
req = req.WithContext(ctx)
w := wrapper{
router: testRouter,

@ -1,6 +1,7 @@
package http
import (
"net/http"
"net/http/httptest"
"testing"
)
@ -10,7 +11,7 @@ func TestRedirect(t *testing.T) {
redirectURL = "/redirect"
redirectCode = 302
)
r := httptest.NewRequest("POST", "/test", nil)
r := httptest.NewRequest(http.MethodPost, "/test", nil)
w := httptest.NewRecorder()
_ = DefaultResponseEncoder(w, r, NewRedirect(redirectURL, redirectCode))

@ -136,7 +136,7 @@ func testRoute(t *testing.T, srv *Server) {
t.Fatalf("got %s want bar", u.Name)
}
// PUT
req, _ := http.NewRequest("PUT", base+"/users", strings.NewReader(`{"name":"bar"}`))
req, _ := http.NewRequest(http.MethodPut, base+"/users", strings.NewReader(`{"name":"bar"}`))
req.Header.Set("Content-Type", appJSONStr)
resp, err = http.DefaultClient.Do(req)
if err != nil {
@ -157,7 +157,7 @@ func testRoute(t *testing.T, srv *Server) {
t.Fatalf("got %s want bar", u.Name)
}
// OPTIONS
req, _ = http.NewRequest("OPTIONS", base+"/users", nil)
req, _ = http.NewRequest(http.MethodOptions, base+"/users", nil)
resp, err = http.DefaultClient.Do(req)
if err != nil {
t.Fatal(err)
@ -166,7 +166,7 @@ func testRoute(t *testing.T, srv *Server) {
if resp.StatusCode != 200 {
t.Fatalf("code: %d", resp.StatusCode)
}
if resp.Header.Get("Access-Control-Allow-Methods") != "OPTIONS" {
if resp.Header.Get("Access-Control-Allow-Methods") != http.MethodOptions {
t.Fatal("cors failed")
}
}

@ -128,6 +128,13 @@ func Listener(lis net.Listener) ServerOption {
}
}
// PathPrefix with mux's PathPrefix, router will replaced by a subrouter that start with prefix.
func PathPrefix(prefix string) ServerOption {
return func(s *Server) {
s.router = s.router.PathPrefix(prefix).Subrouter()
}
}
// Server is an HTTP server wrapper.
type Server struct {
*http.Server
@ -162,11 +169,12 @@ func NewServer(opts ...ServerOption) *Server {
enc: DefaultResponseEncoder,
ene: DefaultErrorEncoder,
strictSlash: true,
router: mux.NewRouter(),
}
for _, o := range opts {
o(srv)
}
srv.router = mux.NewRouter().StrictSlash(srv.strictSlash)
srv.router.StrictSlash(srv.strictSlash)
srv.router.NotFoundHandler = http.DefaultServeMux
srv.router.MethodNotAllowedHandler = http.DefaultServeMux
srv.router.Use(srv.filter())

@ -118,8 +118,8 @@ func testAccept(t *testing.T, srv *Server) {
path string
contentType string
}{
{"GET", "/errors/cause", "application/json"},
{"GET", "/errors/cause", "application/proto"},
{http.MethodGet, "/errors/cause", "application/json"},
{http.MethodGet, "/errors/cause", "application/proto"},
}
e, err := srv.Endpoint()
if err != nil {
@ -155,7 +155,7 @@ func testHeader(t *testing.T, srv *Server) {
t.Errorf("expected nil got %v", err)
}
reqURL := fmt.Sprintf(e.String() + "/index")
req, err := http.NewRequest("GET", reqURL, nil)
req, err := http.NewRequest(http.MethodGet, reqURL, nil)
if err != nil {
t.Errorf("expected nil got %v", err)
}
@ -173,21 +173,21 @@ func testClient(t *testing.T, srv *Server) {
path string
code int
}{
{"GET", "/index", http.StatusOK},
{"PUT", "/index", http.StatusOK},
{"POST", "/index", http.StatusOK},
{"PATCH", "/index", http.StatusOK},
{"DELETE", "/index", http.StatusOK},
{http.MethodGet, "/index", http.StatusOK},
{http.MethodPut, "/index", http.StatusOK},
{http.MethodPost, "/index", http.StatusOK},
{http.MethodPatch, "/index", http.StatusOK},
{http.MethodDelete, "/index", http.StatusOK},
{"GET", "/index/1", http.StatusOK},
{"PUT", "/index/1", http.StatusOK},
{"POST", "/index/1", http.StatusOK},
{"PATCH", "/index/1", http.StatusOK},
{"DELETE", "/index/1", http.StatusOK},
{http.MethodGet, "/index/1", http.StatusOK},
{http.MethodPut, "/index/1", http.StatusOK},
{http.MethodPost, "/index/1", http.StatusOK},
{http.MethodPatch, "/index/1", http.StatusOK},
{http.MethodDelete, "/index/1", http.StatusOK},
{"GET", "/index/notfound", http.StatusNotFound},
{"GET", "/errors/cause", http.StatusBadRequest},
{"GET", "/test/prefix/123111", http.StatusOK},
{http.MethodGet, "/index/notfound", http.StatusNotFound},
{http.MethodGet, "/errors/cause", http.StatusBadRequest},
{http.MethodGet, "/test/prefix/123111", http.StatusOK},
}
e, err := srv.Endpoint()
if err != nil {
@ -310,7 +310,7 @@ func BenchmarkServer(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
var res testData
err := client.Invoke(context.Background(), "POST", "/index", nil, &res)
err := client.Invoke(context.Background(), http.MethodPost, "/index", nil, &res)
if err != nil {
b.Errorf("expected nil got %v", err)
}

@ -1,4 +1,4 @@
package kratos
// Release is the current kratos version.
const Release = "v2.5.1"
const Release = "v2.5.2"

Loading…
Cancel
Save