Compare commits

..

54 Commits

Author SHA1 Message Date
Kevin Wan
6a8638fc85 chore: refine rpc template in goctl (#1129) 2021-10-12 22:13:14 +08:00
Mikael
837a9ffa03 go-zero/core/hash/hash_test.go 增加测试 TestMd5Hex (#1128) 2021-10-12 21:57:07 +08:00
chenquan
d28cfe5f20 Add opts ...grpc.CallOption in grpc client (#1122)
* Add `opts ...grpc.CallOption` in grpc client

* Update format

* Update format

* Add import package

* Update format
2021-10-12 21:52:50 +08:00
chenquan
022c100dc9 Add request method in http log (#1120)
* Add request method in http log

* Update log format
2021-10-12 21:50:30 +08:00
Kevin Wan
426b09c356 update goctl version to 1.2.2 (#1125) 2021-10-12 14:00:35 +08:00
Kevin Wan
40dc21e4cf add cncf landscape (#1123) 2021-10-11 15:31:29 +08:00
Kevin Wan
9b114e3251 test: add more tests (#1119) 2021-10-08 17:31:37 +08:00
Kevin Wan
4c6234f108 add more tests (#1115)
* add more tests

* fix lint errors
2021-10-04 21:08:44 +08:00
Kevin Wan
3cdfcb05f1 add more tests (#1114) 2021-10-04 20:02:25 +08:00
Kevin Wan
9f5bfa0088 add more tests (#1113) 2021-10-04 14:14:25 +08:00
Kevin Wan
2d42c8fa00 test: add more tests (#1112) 2021-10-03 21:30:48 +08:00
Kevin Wan
10e7922597 feat: opentelemetry integration, removed self designed tracing (#1111)
* feat: opentelemetry integration, removed self designed tracing

* feat: support zipkin on opentelemetry integration

* feat: support zipkin on opentelemetry integration, enable it in conf

* style: format code

* fix: support logx without exporter configured

* fix: check return values

* refactor: simplify code

* refactor: simplify opentelemetry integration

* ci: fix staticcheck errors
2021-10-03 20:53:50 +08:00
Kevin Wan
6e34b55ba7 docs: update roadmap (#1110) 2021-10-02 18:16:59 +08:00
Kevin Wan
ed15ca04f4 fix: opentelemetry traceid not correct (#1108) 2021-10-01 22:44:37 +08:00
小小小下
295ec27e1b feat: reflection grpc service (#1107)
* feat: reflection grpc service

* feat: reflection grpc service
2021-10-01 22:02:04 +08:00
Kevin Wan
d1e702e8a3 test: add more tests (#1106)
* style: format code

* test: add more tests

* fix: staticcheck errors
2021-10-01 10:03:56 +08:00
chenquan
d1bfb5ef61 Fix the resources variable not reset after the resource manager is closed (#1105)
* Fix the resource variable not reset after the resource manager is closed

* Format code
2021-09-30 16:55:36 +08:00
Kevin Wan
e43357164c chore: replace redis.NewRedis with redis.New (#1103) 2021-09-29 23:01:10 +08:00
Kevin Wan
cd21c9fa74 chore: mark redis.NewRedis as Deprecated, use redis.New instead. (#1100)
* chore: mark redis.NewRedis as Deprecated

* chore: mark redis.NewRedis as Deprecated
2021-09-29 22:07:05 +08:00
Kevin Wan
cdd2fcbbc9 update grpc package (#1099) 2021-09-29 19:30:06 +08:00
理工男
8d2db09d45 Update Makefile (#1098) 2021-09-29 18:04:08 +08:00
Kevin Wan
65905b914d ci: add reviewdog (#1096) 2021-09-29 13:09:20 +08:00
z-micro
80e3407be1 fix bug: generating dart code error (#1090) 2021-09-28 09:01:27 +08:00
Kevin Wan
657d27213a docs: update roadmap (#1094) 2021-09-26 17:41:19 +08:00
Kevin Wan
8ac18a9422 docs: update roadmap (#1093) 2021-09-26 17:38:49 +08:00
Kevin Wan
d3ae9cfd49 ci: accurate error reporting on lint check (#1089) 2021-09-25 23:25:40 +08:00
Kevin Wan
d7f42161fd update zero-doc links in readme (#1088) 2021-09-24 11:31:00 +08:00
Kevin Wan
e03229cabe docs: change organization from tal-tech to zeromicro in readme (#1087) 2021-09-23 20:24:46 +08:00
Kevin Wan
8403ed16ae ci: add Lint check on commits (#1086)
* ci: add Lint check on commits

* ci: fix Lint script error

* test: fix go vet errors

* test: fix go vet errors, remove gofumpt to check go vet

* test: fix go vet errors, try gofumpt

* test: fix go vet errors, try gofumpt, round 1

* test: fix go vet errors, try gofumpt, round 2

* ci: fix Lint errors
2021-09-23 19:57:05 +08:00
Kevin Wan
d87d203c3b Revert "chore: run unit test with go 1.14 (#1084)" (#1085)
This reverts commit 3ae6a882a7.
2021-09-23 15:34:10 +08:00
Kevin Wan
3ae6a882a7 chore: run unit test with go 1.14 (#1084) 2021-09-23 15:30:40 +08:00
Amor
41c980f00c update goctl api (#1052)
* update goctl api

* add LoadTemplate

* update new api template

* update
2021-09-23 14:31:11 +08:00
shenbaise9527
f34d81ca2c chore: when run goctl-rpc, the order of proto message aliases should be (#1078)
fixed

Co-authored-by: steven <steven.zhou@1quant.com>
2021-09-23 14:24:21 +08:00
NevS
004ee488a6 fix AtomicError panic when Set nil (#1049) (#1050) 2021-09-23 14:23:02 +08:00
Kevin Wan
2e12cd2c99 coding style (#1083) 2021-09-23 11:19:57 +08:00
neosu
2695c30886 we can use otel.ErrorHandlerFunc instead of custom struct when we update OpenTelemetry to 1.0.0 (#1081) 2021-09-23 10:42:45 +08:00
Kevin Wan
c74fb988e0 update go.mod (#1079) 2021-09-22 21:54:54 +08:00
anqiansong
e8a340c1c0 Create a symbol link file named protoc-gen-goctl from goctl (#1076) 2021-09-21 23:13:31 +08:00
Kevin Wan
06e114e5a3 update OpenTelemetry to 1.0.0 (#1075) 2021-09-21 23:11:36 +08:00
Kevin Wan
74ad681a66 update issue templates (#1074) 2021-09-21 14:13:28 +08:00
Kevin Wan
e7bbc09093 Update issue templates 2021-09-21 13:58:21 +08:00
Kevin Wan
1eb1450c43 downgrade golang-jwt to support go 1.14 (#1073) 2021-09-21 13:42:45 +08:00
anqiansong
9a724fe907 Add MustTempDir (#1069) 2021-09-21 10:13:43 +08:00
Kevin Wan
30e49f2939 fix jwt security issue by using golang-jwt package (#1066) 2021-09-19 22:33:35 +08:00
Kevin Wan
a5407479a6 upgrade grpc version & replace github.com/golang/protobuf/protoc-gen-go with google.golang.org/protobuf (#1065) 2021-09-19 21:37:55 +08:00
anqiansong
7fb5bab26b fix #1058 (#1064) 2021-09-19 08:53:41 +08:00
Kevin Wan
27249e021f add repo moving notice (#1062) 2021-09-18 22:24:45 +08:00
Kevin Wan
d809795fec add go-zero users (#1061) 2021-09-18 22:01:15 +08:00
Kevin Wan
c9db9588b7 chore: fix comment issues (#1056) 2021-09-17 17:11:03 +08:00
Kevin Wan
872c50b71a chore: make comment accurate (#1055) 2021-09-17 11:11:42 +08:00
Kevin Wan
7c83155e4f mention cncf landscape (#1054) 2021-09-17 10:44:42 +08:00
Kevin Wan
358d86b8ae add go-zero users (#1051) 2021-09-16 15:06:42 +08:00
Kevin Wan
f4bb9f5635 fix test error on ubuntu (#1048) 2021-09-15 13:31:20 +08:00
Jerry Liang
5c6a3132eb fix typo parse.go error message (#1041) 2021-09-14 10:26:44 +08:00
143 changed files with 2104 additions and 1915 deletions

40
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,40 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior, if applicable:
1. The code is
```go
```
2. The error is
```
```
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Environments (please complete the following information):**
- OS: [e.g. Linux]
- go-zero version [e.g. 1.2.1]
- goctl version [e.g. 1.2.1, optional]
**More description**
Add any other context about the problem here.

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

10
.github/ISSUE_TEMPLATE/question.md vendored Normal file
View File

@@ -0,0 +1,10 @@
---
name: Question
about: Ask a question on using go-zero or goctl
title: ''
labels: ''
assignees: ''
---

View File

@@ -25,6 +25,12 @@ jobs:
run: |
go get -v -t -d ./...
- name: Lint
run: |
go vet -stdmethods=false $(go list ./...)
go install mvdan.cc/gofumpt@latest
test -z "$(gofumpt -s -l -extra .)" || echo "Please run 'gofumpt -l -w -extra .'"
- name: Test
run: go test -race -coverprofile=coverage.txt -covermode=atomic ./...

19
.github/workflows/reviewdog.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
name: reviewdog
on: [pull_request]
jobs:
staticcheck:
name: runner / staticcheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: reviewdog/action-staticcheck@v1
with:
github_token: ${{ secrets.github_token }}
# Change reviewdog reporter if you need [github-pr-check,github-check,github-pr-review].
reporter: github-pr-review
# Report all results.
filter_mode: nofilter
# Exit with 1 when it find at least one finding.
fail_on_error: true
# Set staticcheck flags
staticcheck_flags: -checks=inherit,-SA1019,-SA1029,-SA5008

3
.gitignore vendored
View File

@@ -15,9 +15,6 @@
**/.DS_Store
**/logs
# ignore adhoc test code
**/adhoc
# gitlab ci
.cache

View File

@@ -5,17 +5,18 @@ Community and contributor involvement is vital for successfully implementing all
We hope that the items listed below will inspire further engagement from the community to keep go-zero progressing and shipping exciting and valuable features.
## 2021 Q2
- Support TLS in redis connections
- Support service discovery through K8S watch api
- Log full sql statements for easier sql problem solving
- [x] Support service discovery through K8S client api
- [x] Log full sql statements for easier sql problem solving
## 2021 Q3
- Support `goctl mock` command to start a mocking server with given `.api` file
- Adapt builtin tracing mechanism to opentracing solutions
- Support `goctl model pg` to support PostgreSQL code generation
- [x] Support `goctl model pg` to support PostgreSQL code generation
- [ ] Support `goctl mock` command to start a mocking server with given `.api` file
- [ ] Adapt builtin tracing mechanism to opentracing solutions
## 2021 Q4
- Support `goctl doctor` command to report potential issues for given service
- Support `context` in redis related methods for timeout and tracing
- Support `context` in sql related methods for timeout and tracing
- Support `context` in mongodb related methods for timeout and tracing
- [ ] Add `httpx.Client` with governance, like circuit breaker etc.
- [ ] Support `goctl doctor` command to report potential issues for given service
- [ ] Support `context` in redis related methods for timeout and tracing
- [ ] Support `context` in sql related methods for timeout and tracing
- [ ] Support `context` in mongodb related methods for timeout and tracing
- [ ] Support TLS in redis connections

View File

@@ -6,9 +6,10 @@ package internal
import (
context "context"
reflect "reflect"
gomock "github.com/golang/mock/gomock"
connectivity "google.golang.org/grpc/connectivity"
reflect "reflect"
)
// MocketcdConn is a mock of etcdConn interface

View File

@@ -5,8 +5,9 @@
package internal
import (
gomock "github.com/golang/mock/gomock"
reflect "reflect"
gomock "github.com/golang/mock/gomock"
)
// MockUpdateListener is a mock of UpdateListener interface

View File

@@ -9,7 +9,9 @@ type AtomicError struct {
// Set sets the error.
func (ae *AtomicError) Set(err error) {
ae.err.Store(err)
if err != nil {
ae.err.Store(err)
}
}
// Load returns the error.

View File

@@ -17,6 +17,15 @@ func TestAtomicError(t *testing.T) {
assert.Equal(t, errDummy, err.Load())
}
func TestAtomicErrorSetNil(t *testing.T) {
var (
errNil error
err AtomicError
)
err.Set(errNil)
assert.Equal(t, errNil, err.Load())
}
func TestAtomicErrorNil(t *testing.T) {
var err AtomicError
assert.Nil(t, err.Load())

View File

@@ -1,3 +1,4 @@
//go:build linux || darwin
// +build linux darwin
package fs

View File

@@ -395,16 +395,16 @@ func assetEqual(t *testing.T, except, data interface{}) {
func TestStream_AnyMach(t *testing.T) {
assetEqual(t, false, Just(1, 2, 3).AnyMach(func(item interface{}) bool {
return 4 == item.(int)
return item.(int) == 4
}))
assetEqual(t, false, Just(1, 2, 3).AnyMach(func(item interface{}) bool {
return 0 == item.(int)
return item.(int) == 0
}))
assetEqual(t, true, Just(1, 2, 3).AnyMach(func(item interface{}) bool {
return 2 == item.(int)
return item.(int) == 2
}))
assetEqual(t, true, Just(1, 2, 3).AnyMach(func(item interface{}) bool {
return 2 == item.(int)
return item.(int) == 2
}))
}

View File

@@ -20,6 +20,11 @@ func TestMd5(t *testing.T) {
assert.Equal(t, md5Digest, actual)
}
func TestMd5Hex(t *testing.T) {
actual := Md5Hex([]byte(text))
assert.Equal(t, md5Digest, actual)
}
func BenchmarkHashFnv(b *testing.B) {
for i := 0; i < b.N; i++ {
h := fnv.New32()

View File

@@ -24,7 +24,7 @@ func TestTokenLimit_Rescue(t *testing.T) {
rate = 5
burst = 10
)
l := NewTokenLimiter(rate, burst, redis.NewRedis(s.Addr(), redis.NodeType), "tokenlimit")
l := NewTokenLimiter(rate, burst, redis.New(s.Addr()), "tokenlimit")
s.Close()
var allowed int

View File

@@ -47,7 +47,6 @@ type (
done chan lang.PlaceholderType
rule RotateRule
compress bool
keepDays int
// can't use threading.RoutineGroup because of cycle import
waitGroup sync.WaitGroup
closeOnce sync.Once

View File

@@ -3,6 +3,7 @@ package logx
import (
"os"
"path/filepath"
"syscall"
"testing"
"time"
@@ -97,7 +98,13 @@ func TestRotateLoggerRotate(t *testing.T) {
}()
}
err = logger.rotate()
assert.Nil(t, err)
switch v := err.(type) {
case *os.LinkError:
// avoid rename error on docker container
assert.Equal(t, syscall.EXDEV, v.Err)
default:
assert.Nil(t, err)
}
}
func TestRotateLoggerWrite(t *testing.T) {

View File

@@ -7,7 +7,6 @@ import (
"time"
"github.com/tal-tech/go-zero/core/timex"
"github.com/tal-tech/go-zero/core/trace/tracespec"
"go.opentelemetry.io/otel/trace"
)
@@ -94,29 +93,19 @@ func WithContext(ctx context.Context) Logger {
}
func spanIdFromContext(ctx context.Context) string {
span := trace.SpanFromContext(ctx)
if span.IsRecording() {
return span.SpanContext().SpanID().String()
spanCtx := trace.SpanContextFromContext(ctx)
if spanCtx.HasSpanID() {
return spanCtx.SpanID().String()
}
t, ok := ctx.Value(tracespec.TracingKey).(tracespec.Trace)
if !ok {
return ""
}
return t.SpanId()
return ""
}
func traceIdFromContext(ctx context.Context) string {
span := trace.SpanFromContext(ctx)
if span.IsRecording() {
return span.SpanContext().SpanID().String()
spanCtx := trace.SpanContextFromContext(ctx)
if spanCtx.HasTraceID() {
return spanCtx.TraceID().String()
}
t, ok := ctx.Value(tracespec.TracingKey).(tracespec.Trace)
if !ok {
return ""
}
return t.TraceId()
return ""
}

View File

@@ -9,71 +9,90 @@ import (
"time"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/trace/tracespec"
"go.opentelemetry.io/otel"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
)
const (
mockTraceID = "mock-trace-id"
mockSpanID = "mock-span-id"
traceKey = "trace"
spanKey = "span"
)
var mock tracespec.Trace = new(mockTrace)
func TestTraceLog(t *testing.T) {
var buf mockWriter
atomic.StoreUint32(&initialized, 1)
ctx := context.WithValue(context.Background(), tracespec.TracingKey, mock)
otp := otel.GetTracerProvider()
tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))
otel.SetTracerProvider(tp)
defer otel.SetTracerProvider(otp)
ctx, _ := tp.Tracer("foo").Start(context.Background(), "bar")
WithContext(ctx).(*traceLogger).write(&buf, levelInfo, testlog)
assert.True(t, strings.Contains(buf.String(), mockTraceID))
assert.True(t, strings.Contains(buf.String(), mockSpanID))
assert.True(t, strings.Contains(buf.String(), traceKey))
assert.True(t, strings.Contains(buf.String(), spanKey))
}
func TestTraceError(t *testing.T) {
var buf mockWriter
atomic.StoreUint32(&initialized, 1)
errorLog = newLogWriter(log.New(&buf, "", flags))
ctx := context.WithValue(context.Background(), tracespec.TracingKey, mock)
otp := otel.GetTracerProvider()
tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))
otel.SetTracerProvider(tp)
defer otel.SetTracerProvider(otp)
ctx, _ := tp.Tracer("foo").Start(context.Background(), "bar")
l := WithContext(ctx).(*traceLogger)
SetLevel(InfoLevel)
l.WithDuration(time.Second).Error(testlog)
assert.True(t, strings.Contains(buf.String(), mockTraceID))
assert.True(t, strings.Contains(buf.String(), mockSpanID))
assert.True(t, strings.Contains(buf.String(), traceKey))
assert.True(t, strings.Contains(buf.String(), spanKey))
buf.Reset()
l.WithDuration(time.Second).Errorf(testlog)
assert.True(t, strings.Contains(buf.String(), mockTraceID))
assert.True(t, strings.Contains(buf.String(), mockSpanID))
assert.True(t, strings.Contains(buf.String(), traceKey))
assert.True(t, strings.Contains(buf.String(), spanKey))
}
func TestTraceInfo(t *testing.T) {
var buf mockWriter
atomic.StoreUint32(&initialized, 1)
infoLog = newLogWriter(log.New(&buf, "", flags))
ctx := context.WithValue(context.Background(), tracespec.TracingKey, mock)
otp := otel.GetTracerProvider()
tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))
otel.SetTracerProvider(tp)
defer otel.SetTracerProvider(otp)
ctx, _ := tp.Tracer("foo").Start(context.Background(), "bar")
l := WithContext(ctx).(*traceLogger)
SetLevel(InfoLevel)
l.WithDuration(time.Second).Info(testlog)
assert.True(t, strings.Contains(buf.String(), mockTraceID))
assert.True(t, strings.Contains(buf.String(), mockSpanID))
assert.True(t, strings.Contains(buf.String(), traceKey))
assert.True(t, strings.Contains(buf.String(), spanKey))
buf.Reset()
l.WithDuration(time.Second).Infof(testlog)
assert.True(t, strings.Contains(buf.String(), mockTraceID))
assert.True(t, strings.Contains(buf.String(), mockSpanID))
assert.True(t, strings.Contains(buf.String(), traceKey))
assert.True(t, strings.Contains(buf.String(), spanKey))
}
func TestTraceSlow(t *testing.T) {
var buf mockWriter
atomic.StoreUint32(&initialized, 1)
slowLog = newLogWriter(log.New(&buf, "", flags))
ctx := context.WithValue(context.Background(), tracespec.TracingKey, mock)
otp := otel.GetTracerProvider()
tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))
otel.SetTracerProvider(tp)
defer otel.SetTracerProvider(otp)
ctx, _ := tp.Tracer("foo").Start(context.Background(), "bar")
l := WithContext(ctx).(*traceLogger)
SetLevel(InfoLevel)
l.WithDuration(time.Second).Slow(testlog)
assert.True(t, strings.Contains(buf.String(), mockTraceID))
assert.True(t, strings.Contains(buf.String(), mockSpanID))
assert.True(t, strings.Contains(buf.String(), traceKey))
assert.True(t, strings.Contains(buf.String(), spanKey))
buf.Reset()
l.WithDuration(time.Second).Slowf(testlog)
assert.True(t, strings.Contains(buf.String(), mockTraceID))
assert.True(t, strings.Contains(buf.String(), mockSpanID))
assert.True(t, strings.Contains(buf.String(), traceKey))
assert.True(t, strings.Contains(buf.String(), spanKey))
}
func TestTraceWithoutContext(t *testing.T) {
@@ -83,34 +102,10 @@ func TestTraceWithoutContext(t *testing.T) {
l := WithContext(context.Background()).(*traceLogger)
SetLevel(InfoLevel)
l.WithDuration(time.Second).Info(testlog)
assert.False(t, strings.Contains(buf.String(), mockTraceID))
assert.False(t, strings.Contains(buf.String(), mockSpanID))
assert.False(t, strings.Contains(buf.String(), traceKey))
assert.False(t, strings.Contains(buf.String(), spanKey))
buf.Reset()
l.WithDuration(time.Second).Infof(testlog)
assert.False(t, strings.Contains(buf.String(), mockTraceID))
assert.False(t, strings.Contains(buf.String(), mockSpanID))
}
type mockTrace struct{}
func (t mockTrace) TraceId() string {
return mockTraceID
}
func (t mockTrace) SpanId() string {
return mockSpanID
}
func (t mockTrace) Finish() {
}
func (t mockTrace) Fork(ctx context.Context, serviceName, operationName string) (context.Context, tracespec.Trace) {
return nil, nil
}
func (t mockTrace) Follow(ctx context.Context, serviceName, operationName string) (context.Context, tracespec.Trace) {
return nil, nil
}
func (t mockTrace) Visit(fn func(key, val string) bool) {
assert.False(t, strings.Contains(buf.String(), traceKey))
assert.False(t, strings.Contains(buf.String(), spanKey))
}

View File

@@ -1,3 +1,4 @@
//go:build linux || darwin
// +build linux darwin
package proc

View File

@@ -1,3 +1,4 @@
//go:build debug
// +build debug
package search

View File

@@ -7,6 +7,7 @@ import (
"github.com/tal-tech/go-zero/core/logx"
"github.com/tal-tech/go-zero/core/prometheus"
"github.com/tal-tech/go-zero/core/stat"
"github.com/tal-tech/go-zero/core/trace"
)
const (
@@ -29,8 +30,7 @@ type ServiceConf struct {
Mode string `json:",default=pro,options=dev|test|rt|pre|pro"`
MetricsUrl string `json:",optional"`
Prometheus prometheus.Config `json:",optional"`
// TODO: enable it in v1.2.1
// Telemetry opentelemetry.Config `json:",optional"`
Telemetry trace.Config `json:",optional"`
}
// MustSetUp sets up the service, exits on error.
@@ -52,11 +52,10 @@ func (sc ServiceConf) SetUp() error {
sc.initMode()
prometheus.StartAgent(sc.Prometheus)
// TODO: enable it in v1.2.1
// if len(sc.Telemetry.Name) == 0 {
// sc.Telemetry.Name = sc.Name
// }
// opentelemetry.StartAgent(sc.Telemetry)
if len(sc.Telemetry.Name) == 0 {
sc.Telemetry.Name = sc.Name
}
trace.StartAgent(sc.Telemetry)
if len(sc.MetricsUrl) > 0 {
stat.SetReportWriter(stat.NewRemoteWriter(sc.MetricsUrl))

View File

@@ -1,3 +1,4 @@
//go:build linux
// +build linux
package stat

View File

@@ -1,3 +1,4 @@
//go:build linux
// +build linux
package stat

View File

@@ -7,7 +7,9 @@ import (
)
func TestRefreshCpu(t *testing.T) {
assert.True(t, RefreshCpu() >= 0)
assert.NotPanics(t, func() {
RefreshCpu()
})
}
func BenchmarkRefreshCpu(b *testing.B) {

View File

@@ -1,3 +1,4 @@
//go:build !linux
// +build !linux
package internal

View File

@@ -73,7 +73,7 @@ func TestCacheNode_InvalidCache(t *testing.T) {
defer s.Close()
cn := cacheNode{
rds: redis.NewRedis(s.Addr(), redis.NodeType),
rds: redis.New(s.Addr()),
r: rand.New(rand.NewSource(time.Now().UnixNano())),
lock: new(sync.Mutex),
unstableExpiry: mathx.NewUnstable(expiryDeviation),

View File

@@ -5,9 +5,10 @@
package internal
import (
reflect "reflect"
mgo "github.com/globalsign/mgo"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
// MockMgoCollection is a mock of MgoCollection interface

View File

@@ -5,9 +5,10 @@
package mongo
import (
reflect "reflect"
bson "github.com/globalsign/mgo/bson"
gomock "github.com/golang/mock/gomock"
reflect "reflect"
)
// MockIter is a mock of Iter interface

View File

@@ -120,7 +120,7 @@ func TestStatCacheFails(t *testing.T) {
log.SetOutput(ioutil.Discard)
defer log.SetOutput(os.Stdout)
r := redis.NewRedis("localhost:59999", redis.NodeType)
r := redis.New("localhost:59999")
cach := cache.NewNode(r, sharedCalls, stats, mgo.ErrNotFound)
c := newCollection(dummyConn{}, cach)

View File

@@ -90,6 +90,7 @@ func New(addr string, opts ...Option) *Redis {
return r
}
// Deprecated: use New instead, will be removed in v2.
// NewRedis returns a Redis.
func NewRedis(redisAddr, redisType string, redisPass ...string) *Redis {
var opts []Option

View File

@@ -963,7 +963,7 @@ func TestRedis_Pipelined(t *testing.T) {
func TestRedisString(t *testing.T) {
runOnRedis(t, func(client *Redis) {
client.Ping()
_, err := getRedis(NewRedis(client.Addr, ClusterType))
_, err := getRedis(New(client.Addr, Cluster()))
assert.Nil(t, err)
assert.Equal(t, client.Addr, client.String())
assert.NotNil(t, New(client.Addr, badType()).Ping())
@@ -1075,7 +1075,7 @@ func TestRedisGeo(t *testing.T) {
func TestRedis_WithPass(t *testing.T) {
runOnRedis(t, func(client *Redis) {
err := NewRedis(client.Addr, NodeType, "any").Ping()
err := New(client.Addr, WithPass("any")).Ping()
assert.NotNil(t, err)
})
}
@@ -1095,7 +1095,7 @@ func runOnRedis(t *testing.T, fn func(client *Redis)) {
client.Close()
}
}()
fn(NewRedis(s.Addr(), NodeType))
fn(New(s.Addr()))
}
func runOnRedisTLS(t *testing.T, fn func(client *Redis)) {

View File

@@ -10,10 +10,10 @@ import (
func TestBlockingNode(t *testing.T) {
r, err := miniredis.Run()
assert.Nil(t, err)
node, err := CreateBlockingNode(NewRedis(r.Addr(), NodeType))
node, err := CreateBlockingNode(New(r.Addr()))
assert.Nil(t, err)
node.Close()
node, err = CreateBlockingNode(NewRedis(r.Addr(), ClusterType))
node, err = CreateBlockingNode(New(r.Addr(), Cluster()))
assert.Nil(t, err)
node.Close()
}

View File

@@ -15,7 +15,7 @@ func CreateRedis() (r *redis.Redis, clean func(), err error) {
return nil, nil, err
}
return redis.NewRedis(mr.Addr(), redis.NodeType), func() {
return redis.New(mr.Addr()), func() {
ch := make(chan lang.PlaceholderType)
go func() {
mr.Close()

View File

@@ -286,7 +286,7 @@ func TestStatCacheFails(t *testing.T) {
log.SetOutput(ioutil.Discard)
defer log.SetOutput(os.Stdout)
r := redis.NewRedis("localhost:59999", redis.NodeType)
r := redis.New("localhost:59999")
c := NewNodeConn(dummySqlConn{}, r, cache.WithExpiry(time.Second*10))
for i := 0; i < 20; i++ {
@@ -485,7 +485,7 @@ func TestCachedConnExecDropCache(t *testing.T) {
value = "any"
)
var conn trackedConn
c := NewNodeConn(&conn, redis.NewRedis(r.Addr(), redis.NodeType), cache.WithExpiry(time.Second*30))
c := NewNodeConn(&conn, redis.New(r.Addr()), cache.WithExpiry(time.Second*30))
assert.Nil(t, c.SetCache(key, value))
_, err = c.Exec(func(conn sqlx.SqlConn) (result sql.Result, e error) {
return conn.Exec("delete from user_table where id='kevin'")
@@ -503,7 +503,7 @@ func TestCachedConnExecDropCache(t *testing.T) {
func TestCachedConnExecDropCacheFailed(t *testing.T) {
const key = "user"
var conn trackedConn
r := redis.NewRedis("anyredis:8888", redis.NodeType)
r := redis.New("anyredis:8888")
c := NewNodeConn(&conn, r, cache.WithExpiry(time.Second*10))
_, err := c.Exec(func(conn sqlx.SqlConn) (result sql.Result, e error) {
return conn.Exec("delete from user_table where id='kevin'")

View File

@@ -19,10 +19,8 @@ func TestDoneChanDone(t *testing.T) {
waitGroup.Add(1)
go func() {
select {
case <-doneChan.Done():
waitGroup.Done()
}
<-doneChan.Done()
waitGroup.Done()
}()
for i := 0; i < 5; i++ {

View File

@@ -17,10 +17,11 @@ func TestPoolGet(t *testing.T) {
ch := make(chan lang.PlaceholderType)
for i := 0; i < limit; i++ {
var fail AtomicBool
go func() {
v := stack.Get()
if v.(int) != 1 {
t.Fatal("unmatch value")
fail.Set(true)
}
ch <- lang.Placeholder
}()
@@ -30,6 +31,10 @@ func TestPoolGet(t *testing.T) {
case <-time.After(time.Second):
t.Fail()
}
if fail.True() {
t.Fatal("unmatch value")
}
}
}

View File

@@ -23,6 +23,7 @@ func NewResourceManager() *ResourceManager {
}
// Close closes the manager.
// Don't use the ResourceManager after Close() called.
func (manager *ResourceManager) Close() error {
manager.lock.Lock()
defer manager.lock.Unlock()
@@ -34,6 +35,9 @@ func (manager *ResourceManager) Close() error {
}
}
// release resources to avoid using it later
manager.resources = nil
return be.Err()
}

View File

@@ -44,3 +44,31 @@ func TestResourceManager_GetResourceError(t *testing.T) {
assert.NotNil(t, err)
}
}
func TestResourceManager_Close(t *testing.T) {
manager := NewResourceManager()
for i := 0; i < 10; i++ {
_, err := manager.GetResource("key", func() (io.Closer, error) {
return nil, errors.New("fail")
})
assert.NotNil(t, err)
}
if assert.NoError(t, manager.Close()) {
assert.Equal(t, 0, len(manager.resources))
}
}
func TestResourceManager_UseAfterClose(t *testing.T) {
manager := NewResourceManager()
_, err := manager.GetResource("key", func() (io.Closer, error) {
return nil, errors.New("fail")
})
assert.NotNil(t, err)
if assert.NoError(t, manager.Close()) {
_, err = manager.GetResource("key", func() (io.Closer, error) {
return nil, errors.New("fail")
})
assert.NotNil(t, err)
}
}

View File

@@ -1,11 +1,14 @@
package syncx
import (
"runtime"
"sync"
"sync/atomic"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/lang"
)
func TestTryLock(t *testing.T) {
@@ -30,8 +33,6 @@ func TestSpinLockRace(t *testing.T) {
var wait sync.WaitGroup
wait.Add(1)
go func() {
lock.Lock()
lock.Unlock()
wait.Done()
}()
time.Sleep(time.Millisecond * 100)
@@ -39,3 +40,31 @@ func TestSpinLockRace(t *testing.T) {
wait.Wait()
assert.True(t, lock.TryLock())
}
func TestSpinLock_TryLock(t *testing.T) {
var lock SpinLock
var count int32
var wait sync.WaitGroup
wait.Add(2)
sig := make(chan lang.PlaceholderType)
go func() {
lock.TryLock()
sig <- lang.Placeholder
atomic.AddInt32(&count, 1)
runtime.Gosched()
lock.Unlock()
wait.Done()
}()
go func() {
<-sig
lock.Lock()
atomic.AddInt32(&count, 1)
lock.Unlock()
wait.Done()
}()
wait.Wait()
assert.Equal(t, int32(2), atomic.LoadInt32(&count))
}

69
core/trace/agent.go Normal file
View File

@@ -0,0 +1,69 @@
package trace
import (
"fmt"
"sync"
"github.com/tal-tech/go-zero/core/logx"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/exporters/zipkin"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
)
const (
kindJaeger = "jaeger"
kindZipkin = "zipkin"
)
var once sync.Once
// StartAgent starts a opentelemetry agent.
func StartAgent(c Config) {
once.Do(func() {
startAgent(c)
})
}
func createExporter(c Config) (sdktrace.SpanExporter, error) {
// Just support jaeger now, more for later
switch c.Batcher {
case kindJaeger:
return jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(c.Endpoint)))
case kindZipkin:
return zipkin.New(c.Endpoint)
default:
return nil, fmt.Errorf("unknown exporter: %s", c.Batcher)
}
}
func startAgent(c Config) {
opts := []sdktrace.TracerProviderOption{
// Set the sampling rate based on the parent span to 100%
sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.TraceIDRatioBased(c.Sampler))),
// Record information about this application in an Resource.
sdktrace.WithResource(resource.NewSchemaless(semconv.ServiceNameKey.String(c.Name))),
}
if len(c.Endpoint) > 0 {
exp, err := createExporter(c)
if err != nil {
logx.Error(err)
return
}
// Always be sure to batch in production.
opts = append(opts, sdktrace.WithBatcher(exp))
}
tp := sdktrace.NewTracerProvider(opts...)
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
propagation.TraceContext{}, propagation.Baggage{}))
otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) {
logx.Errorf("[otel] error: %v", err)
}))
}

View File

@@ -1,4 +1,4 @@
package opentelemetry
package trace
import (
"go.opentelemetry.io/otel/attribute"

View File

@@ -1,43 +0,0 @@
package trace
import (
"errors"
"net/http"
"strings"
)
// ErrInvalidCarrier indicates an error that the carrier is invalid.
var ErrInvalidCarrier = errors.New("invalid carrier")
type (
// Carrier interface wraps the Get and Set method.
Carrier interface {
Get(key string) string
Set(key, value string)
}
httpCarrier http.Header
// grpc metadata takes keys as case insensitive
grpcCarrier map[string][]string
)
func (h httpCarrier) Get(key string) string {
return http.Header(h).Get(key)
}
func (h httpCarrier) Set(key, val string) {
http.Header(h).Set(key, val)
}
func (g grpcCarrier) Get(key string) string {
if vals, ok := g[strings.ToLower(key)]; ok && len(vals) > 0 {
return vals[0]
}
return ""
}
func (g grpcCarrier) Set(key, val string) {
key = strings.ToLower(key)
g[key] = append(g[key], val)
}

View File

@@ -1,58 +0,0 @@
package trace
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/stringx"
)
func TestHttpCarrier(t *testing.T) {
tests := []map[string]string{
{},
{
"first": "a",
"second": "b",
},
}
for _, test := range tests {
t.Run(stringx.RandId(), func(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
carrier := httpCarrier(req.Header)
for k, v := range test {
carrier.Set(k, v)
}
for k, v := range test {
assert.Equal(t, v, carrier.Get(k))
}
assert.Equal(t, "", carrier.Get("none"))
})
}
}
func TestGrpcCarrier(t *testing.T) {
tests := []map[string]string{
{},
{
"first": "a",
"second": "b",
},
}
for _, test := range tests {
t.Run(stringx.RandId(), func(t *testing.T) {
m := make(map[string][]string)
carrier := grpcCarrier(m)
for k, v := range test {
carrier.Set(k, v)
}
for k, v := range test {
assert.Equal(t, v, carrier.Get(k))
}
assert.Equal(t, "", carrier.Get("none"))
})
}
}

View File

@@ -1,4 +1,4 @@
package opentelemetry
package trace
// TraceName represents the tracing name.
const TraceName = "go-zero"
@@ -8,5 +8,5 @@ type Config struct {
Name string `json:",optional"`
Endpoint string `json:",optional"`
Sampler float64 `json:",default=1.0"`
Batcher string `json:",default=jaeger"`
Batcher string `json:",default=jaeger,options=jaeger|zipkin"`
}

View File

@@ -1,8 +0,0 @@
package trace
const (
// TraceIdKey is the trace id header.
TraceIdKey = "X-Trace-ID"
spanIdKey = "X-Span-ID"
)

View File

@@ -1,4 +1,4 @@
package opentelemetry
package trace
import (
"context"

View File

@@ -1,33 +0,0 @@
package trace
import (
"context"
"github.com/tal-tech/go-zero/core/trace/tracespec"
)
var emptyNoopSpan = noopSpan{}
type noopSpan struct{}
func (s noopSpan) Finish() {
}
func (s noopSpan) Follow(ctx context.Context, serviceName, operationName string) (context.Context, tracespec.Trace) {
return ctx, emptyNoopSpan
}
func (s noopSpan) Fork(ctx context.Context, serviceName, operationName string) (context.Context, tracespec.Trace) {
return ctx, emptyNoopSpan
}
func (s noopSpan) SpanId() string {
return ""
}
func (s noopSpan) TraceId() string {
return ""
}
func (s noopSpan) Visit(fn func(key, val string) bool) {
}

View File

@@ -1,32 +0,0 @@
package trace
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
)
func TestNoopSpan_Fork(t *testing.T) {
ctx, span := emptyNoopSpan.Fork(context.Background(), "", "")
assert.Equal(t, emptyNoopSpan, span)
assert.Equal(t, context.Background(), ctx)
}
func TestNoopSpan_Follow(t *testing.T) {
ctx, span := emptyNoopSpan.Follow(context.Background(), "", "")
assert.Equal(t, emptyNoopSpan, span)
assert.Equal(t, context.Background(), ctx)
}
func TestNoopSpan(t *testing.T) {
emptyNoopSpan.Visit(func(key, val string) bool {
assert.Fail(t, "should not go here")
return true
})
ctx, span := emptyNoopSpan.Follow(context.Background(), "", "")
assert.Equal(t, context.Background(), ctx)
assert.Equal(t, "", span.TraceId())
assert.Equal(t, "", span.SpanId())
}

View File

@@ -1,68 +0,0 @@
package opentelemetry
import (
"sync"
"github.com/tal-tech/go-zero/core/logx"
"github.com/tal-tech/go-zero/core/syncx"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
)
var (
once sync.Once
enabled syncx.AtomicBool
)
// Enabled returns if opentelemetry is enabled.
func Enabled() bool {
return enabled.True()
}
// StartAgent starts a opentelemetry agent.
func StartAgent(c Config) {
once.Do(func() {
if len(c.Endpoint) == 0 {
return
}
// Just support jaeger now
if c.Batcher != "jaeger" {
return
}
exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(c.Endpoint)))
if err != nil {
logx.Error(err)
return
}
tp := sdktrace.NewTracerProvider(
// Set the sampling rate based on the parent span to 100%
sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.TraceIDRatioBased(c.Sampler))),
// Always be sure to batch in production.
sdktrace.WithBatcher(exp),
// Record information about this application in an Resource.
sdktrace.WithResource(resource.NewSchemaless(semconv.ServiceNameKey.String(c.Name))),
)
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
otel.SetErrorHandler(otelErrHandler{})
enabled.Set(true)
})
}
// errHandler handing otel errors.
type otelErrHandler struct{}
var _ otel.ErrorHandler = otelErrHandler{}
func (o otelErrHandler) Handle(err error) {
logx.Errorf("[otel] error: %v", err)
}

View File

@@ -1,121 +0,0 @@
package opentelemetry
import (
"context"
"io"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)
const (
receiveEndEvent streamEventType = iota
errorEvent
)
type (
streamEventType int
streamEvent struct {
Type streamEventType
Err error
}
clientStream struct {
grpc.ClientStream
Finished chan error
desc *grpc.StreamDesc
events chan streamEvent
eventsDone chan struct{}
receivedMessageID int
sentMessageID int
}
)
func (w *clientStream) RecvMsg(m interface{}) error {
err := w.ClientStream.RecvMsg(m)
if err == nil && !w.desc.ServerStreams {
w.sendStreamEvent(receiveEndEvent, nil)
} else if err == io.EOF {
w.sendStreamEvent(receiveEndEvent, nil)
} else if err != nil {
w.sendStreamEvent(errorEvent, err)
} else {
w.receivedMessageID++
MessageReceived.Event(w.Context(), w.receivedMessageID, m)
}
return err
}
func (w *clientStream) SendMsg(m interface{}) error {
err := w.ClientStream.SendMsg(m)
w.sentMessageID++
MessageSent.Event(w.Context(), w.sentMessageID, m)
if err != nil {
w.sendStreamEvent(errorEvent, err)
}
return err
}
func (w *clientStream) Header() (metadata.MD, error) {
md, err := w.ClientStream.Header()
if err != nil {
w.sendStreamEvent(errorEvent, err)
}
return md, err
}
func (w *clientStream) CloseSend() error {
err := w.ClientStream.CloseSend()
if err != nil {
w.sendStreamEvent(errorEvent, err)
}
return err
}
func (w *clientStream) sendStreamEvent(eventType streamEventType, err error) {
select {
case <-w.eventsDone:
case w.events <- streamEvent{Type: eventType, Err: err}:
}
}
// WrapClientStream wraps s with given ctx and desc.
func WrapClientStream(ctx context.Context, s grpc.ClientStream, desc *grpc.StreamDesc) *clientStream {
events := make(chan streamEvent)
eventsDone := make(chan struct{})
finished := make(chan error)
go func() {
defer close(eventsDone)
for {
select {
case event := <-events:
switch event.Type {
case receiveEndEvent:
finished <- nil
return
case errorEvent:
finished <- event.Err
return
}
case <-ctx.Done():
finished <- ctx.Err()
return
}
}
}()
return &clientStream{
ClientStream: s,
desc: desc,
events: events,
eventsDone: eventsDone,
Finished: finished,
}
}

View File

@@ -1,47 +0,0 @@
package opentelemetry
import (
"context"
"google.golang.org/grpc"
)
// serverStream wraps around the embedded grpc.ServerStream, and intercepts the RecvMsg and
// SendMsg method call.
type serverStream struct {
grpc.ServerStream
ctx context.Context
receivedMessageID int
sentMessageID int
}
func (w *serverStream) Context() context.Context {
return w.ctx
}
func (w *serverStream) RecvMsg(m interface{}) error {
err := w.ServerStream.RecvMsg(m)
if err == nil {
w.receivedMessageID++
MessageReceived.Event(w.Context(), w.receivedMessageID, m)
}
return err
}
func (w *serverStream) SendMsg(m interface{}) error {
err := w.ServerStream.SendMsg(m)
w.sentMessageID++
MessageSent.Event(w.Context(), w.sentMessageID, m)
return err
}
// WrapServerStream wraps the given grpc.ServerStream with the given context.
func WrapServerStream(ctx context.Context, ss grpc.ServerStream) *serverStream {
return &serverStream{
ServerStream: ss,
ctx: ctx,
}
}

View File

@@ -1,90 +0,0 @@
package trace
import (
"net/http"
"google.golang.org/grpc/metadata"
)
const (
// HttpFormat means http carrier format.
HttpFormat = iota
// GrpcFormat means grpc carrier format.
GrpcFormat
)
var (
emptyHttpPropagator httpPropagator
emptyGrpcPropagator grpcPropagator
)
type (
// Propagator interface wraps the Extract and Inject methods.
Propagator interface {
Extract(carrier interface{}) (Carrier, error)
Inject(carrier interface{}) (Carrier, error)
}
httpPropagator struct{}
grpcPropagator struct{}
)
func (h httpPropagator) Extract(carrier interface{}) (Carrier, error) {
if c, ok := carrier.(http.Header); ok {
return httpCarrier(c), nil
}
return nil, ErrInvalidCarrier
}
func (h httpPropagator) Inject(carrier interface{}) (Carrier, error) {
if c, ok := carrier.(http.Header); ok {
return httpCarrier(c), nil
}
return nil, ErrInvalidCarrier
}
func (g grpcPropagator) Extract(carrier interface{}) (Carrier, error) {
if c, ok := carrier.(metadata.MD); ok {
return grpcCarrier(c), nil
}
return nil, ErrInvalidCarrier
}
func (g grpcPropagator) Inject(carrier interface{}) (Carrier, error) {
if c, ok := carrier.(metadata.MD); ok {
return grpcCarrier(c), nil
}
return nil, ErrInvalidCarrier
}
// Extract extracts tracing information from carrier with given format.
func Extract(format, carrier interface{}) (Carrier, error) {
switch v := format.(type) {
case int:
if v == HttpFormat {
return emptyHttpPropagator.Extract(carrier)
} else if v == GrpcFormat {
return emptyGrpcPropagator.Extract(carrier)
}
}
return nil, ErrInvalidCarrier
}
// Inject injects tracing information into carrier with given format.
func Inject(format, carrier interface{}) (Carrier, error) {
switch v := format.(type) {
case int:
if v == HttpFormat {
return emptyHttpPropagator.Inject(carrier)
} else if v == GrpcFormat {
return emptyGrpcPropagator.Inject(carrier)
}
}
return nil, ErrInvalidCarrier
}

View File

@@ -1,68 +0,0 @@
package trace
import (
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"google.golang.org/grpc/metadata"
)
func TestHttpPropagator_Extract(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
req.Header.Set(TraceIdKey, "trace")
req.Header.Set(spanIdKey, "span")
carrier, err := Extract(HttpFormat, req.Header)
assert.Nil(t, err)
assert.Equal(t, "trace", carrier.Get(TraceIdKey))
assert.Equal(t, "span", carrier.Get(spanIdKey))
_, err = Extract(HttpFormat, req)
assert.Equal(t, ErrInvalidCarrier, err)
}
func TestHttpPropagator_Inject(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
req.Header.Set(TraceIdKey, "trace")
req.Header.Set(spanIdKey, "span")
carrier, err := Inject(HttpFormat, req.Header)
assert.Nil(t, err)
assert.Equal(t, "trace", carrier.Get(TraceIdKey))
assert.Equal(t, "span", carrier.Get(spanIdKey))
_, err = Inject(HttpFormat, req)
assert.Equal(t, ErrInvalidCarrier, err)
}
func TestGrpcPropagator_Extract(t *testing.T) {
md := metadata.New(map[string]string{
TraceIdKey: "trace",
spanIdKey: "span",
})
carrier, err := Extract(GrpcFormat, md)
assert.Nil(t, err)
assert.Equal(t, "trace", carrier.Get(TraceIdKey))
assert.Equal(t, "span", carrier.Get(spanIdKey))
_, err = Extract(GrpcFormat, 1)
assert.Equal(t, ErrInvalidCarrier, err)
_, err = Extract(nil, 1)
assert.Equal(t, ErrInvalidCarrier, err)
}
func TestGrpcPropagator_Inject(t *testing.T) {
md := metadata.New(map[string]string{
TraceIdKey: "trace",
spanIdKey: "span",
})
carrier, err := Inject(GrpcFormat, md)
assert.Nil(t, err)
assert.Equal(t, "trace", carrier.Get(TraceIdKey))
assert.Equal(t, "span", carrier.Get(spanIdKey))
_, err = Inject(GrpcFormat, 1)
assert.Equal(t, ErrInvalidCarrier, err)
_, err = Inject(nil, 1)
assert.Equal(t, ErrInvalidCarrier, err)
}

View File

@@ -1,150 +0,0 @@
package trace
import (
"context"
"fmt"
"strconv"
"strings"
"time"
"github.com/tal-tech/go-zero/core/stringx"
"github.com/tal-tech/go-zero/core/timex"
"github.com/tal-tech/go-zero/core/trace/tracespec"
)
const (
initSpanId = "0"
clientFlag = "client"
serverFlag = "server"
spanSepRune = '.'
)
var spanSep = string([]byte{spanSepRune})
// A Span is a calling span that connects caller and callee.
type Span struct {
ctx spanContext
serviceName string
operationName string
startTime time.Time
flag string
children int
}
func newServerSpan(carrier Carrier, serviceName, operationName string) tracespec.Trace {
traceId := stringx.TakeWithPriority(func() string {
if carrier != nil {
return carrier.Get(TraceIdKey)
}
return ""
}, stringx.RandId)
spanId := stringx.TakeWithPriority(func() string {
if carrier != nil {
return carrier.Get(spanIdKey)
}
return ""
}, func() string {
return initSpanId
})
return &Span{
ctx: spanContext{
traceId: traceId,
spanId: spanId,
},
serviceName: serviceName,
operationName: operationName,
startTime: timex.Time(),
flag: serverFlag,
}
}
// Finish finishes the calling span.
func (s *Span) Finish() {
}
// Follow follows the tracing service and operation names in context.
func (s *Span) Follow(ctx context.Context, serviceName, operationName string) (context.Context, tracespec.Trace) {
span := &Span{
ctx: spanContext{
traceId: s.ctx.traceId,
spanId: s.followSpanId(),
},
serviceName: serviceName,
operationName: operationName,
startTime: timex.Time(),
flag: s.flag,
}
return context.WithValue(ctx, tracespec.TracingKey, span), span
}
// Fork forks the tracing service and operation names in context.
func (s *Span) Fork(ctx context.Context, serviceName, operationName string) (context.Context, tracespec.Trace) {
span := &Span{
ctx: spanContext{
traceId: s.ctx.traceId,
spanId: s.forkSpanId(),
},
serviceName: serviceName,
operationName: operationName,
startTime: timex.Time(),
flag: clientFlag,
}
return context.WithValue(ctx, tracespec.TracingKey, span), span
}
// SpanId returns the span id.
func (s *Span) SpanId() string {
return s.ctx.SpanId()
}
// TraceId returns the trace id.
func (s *Span) TraceId() string {
return s.ctx.TraceId()
}
// Visit visits the span using fn.
func (s *Span) Visit(fn func(key, val string) bool) {
s.ctx.Visit(fn)
}
func (s *Span) forkSpanId() string {
s.children++
return fmt.Sprintf("%s.%d", s.ctx.spanId, s.children)
}
func (s *Span) followSpanId() string {
fields := strings.FieldsFunc(s.ctx.spanId, func(r rune) bool {
return r == spanSepRune
})
if len(fields) == 0 {
return s.ctx.spanId
}
last := fields[len(fields)-1]
val, err := strconv.Atoi(last)
if err != nil {
return s.ctx.spanId
}
last = strconv.Itoa(val + 1)
fields[len(fields)-1] = last
return strings.Join(fields, spanSep)
}
// StartClientSpan starts the client span with given context, service and operation names.
func StartClientSpan(ctx context.Context, serviceName, operationName string) (context.Context, tracespec.Trace) {
if span, ok := ctx.Value(tracespec.TracingKey).(*Span); ok {
return span.Fork(ctx, serviceName, operationName)
}
return ctx, emptyNoopSpan
}
// StartServerSpan starts the server span with given context, carrier, service and operation names.
func StartServerSpan(ctx context.Context, carrier Carrier, serviceName, operationName string) (
context.Context, tracespec.Trace) {
span := newServerSpan(carrier, serviceName, operationName)
return context.WithValue(ctx, tracespec.TracingKey, span), span
}

View File

@@ -1,139 +0,0 @@
package trace
import (
"context"
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/stringx"
"github.com/tal-tech/go-zero/core/trace/tracespec"
"google.golang.org/grpc/metadata"
)
func TestClientSpan(t *testing.T) {
span := newServerSpan(nil, "service", "operation")
ctx := context.WithValue(context.Background(), tracespec.TracingKey, span)
ctx, span = StartClientSpan(ctx, "entrance", "operation")
defer span.Finish()
assert.Equal(t, span, ctx.Value(tracespec.TracingKey))
const serviceName = "authorization"
const operationName = "verification"
ctx, childSpan := span.Fork(ctx, serviceName, operationName)
defer childSpan.Finish()
assert.Equal(t, childSpan, ctx.Value(tracespec.TracingKey))
assert.Equal(t, getSpan(span).TraceId(), getSpan(childSpan).TraceId())
assert.Equal(t, "0.1.1", getSpan(childSpan).SpanId())
assert.Equal(t, serviceName, childSpan.(*Span).serviceName)
assert.Equal(t, operationName, childSpan.(*Span).operationName)
assert.Equal(t, clientFlag, childSpan.(*Span).flag)
}
func TestClientSpan_WithoutTrace(t *testing.T) {
ctx, span := StartClientSpan(context.Background(), "entrance", "operation")
defer span.Finish()
assert.Equal(t, emptyNoopSpan, span)
assert.Equal(t, context.Background(), ctx)
}
func TestServerSpan(t *testing.T) {
ctx, span := StartServerSpan(context.Background(), nil, "service", "operation")
defer span.Finish()
assert.Equal(t, span, ctx.Value(tracespec.TracingKey))
const serviceName = "authorization"
const operationName = "verification"
ctx, childSpan := span.Fork(ctx, serviceName, operationName)
defer childSpan.Finish()
assert.Equal(t, childSpan, ctx.Value(tracespec.TracingKey))
assert.Equal(t, getSpan(span).TraceId(), getSpan(childSpan).TraceId())
assert.Equal(t, "0.1", getSpan(childSpan).SpanId())
assert.Equal(t, serviceName, childSpan.(*Span).serviceName)
assert.Equal(t, operationName, childSpan.(*Span).operationName)
assert.Equal(t, clientFlag, childSpan.(*Span).flag)
}
func TestServerSpan_WithCarrier(t *testing.T) {
md := metadata.New(map[string]string{
TraceIdKey: "a",
spanIdKey: "0.1",
})
ctx, span := StartServerSpan(context.Background(), grpcCarrier(md), "service", "operation")
defer span.Finish()
assert.Equal(t, span, ctx.Value(tracespec.TracingKey))
const serviceName = "authorization"
const operationName = "verification"
ctx, childSpan := span.Fork(ctx, serviceName, operationName)
defer childSpan.Finish()
assert.Equal(t, childSpan, ctx.Value(tracespec.TracingKey))
assert.Equal(t, getSpan(span).TraceId(), getSpan(childSpan).TraceId())
assert.Equal(t, "0.1.1", getSpan(childSpan).SpanId())
assert.Equal(t, serviceName, childSpan.(*Span).serviceName)
assert.Equal(t, operationName, childSpan.(*Span).operationName)
assert.Equal(t, clientFlag, childSpan.(*Span).flag)
}
func TestSpan_Follow(t *testing.T) {
tests := []struct {
span string
expectSpan string
}{
{
"0.1",
"0.2",
},
{
"0",
"1",
},
{
"a",
"a",
},
}
for _, test := range tests {
t.Run(stringx.RandId(), func(t *testing.T) {
md := metadata.New(map[string]string{
TraceIdKey: "a",
spanIdKey: test.span,
})
ctx, span := StartServerSpan(context.Background(), grpcCarrier(md),
"service", "operation")
defer span.Finish()
assert.Equal(t, span, ctx.Value(tracespec.TracingKey))
const serviceName = "authorization"
const operationName = "verification"
ctx, childSpan := span.Follow(ctx, serviceName, operationName)
defer childSpan.Finish()
assert.Equal(t, childSpan, ctx.Value(tracespec.TracingKey))
assert.Equal(t, getSpan(span).TraceId(), getSpan(childSpan).TraceId())
assert.Equal(t, test.expectSpan, getSpan(childSpan).SpanId())
assert.Equal(t, serviceName, childSpan.(*Span).serviceName)
assert.Equal(t, operationName, childSpan.(*Span).operationName)
assert.Equal(t, span.(*Span).flag, childSpan.(*Span).flag)
})
}
}
func TestSpan_Visit(t *testing.T) {
var run bool
span := newServerSpan(nil, "service", "operation")
span.Visit(func(key, val string) bool {
assert.True(t, len(key) > 0)
assert.True(t, len(val) > 0)
run = true
return true
})
assert.True(t, run)
}
func getSpan(span tracespec.Trace) tracespec.Trace {
return span.(*Span)
}

View File

@@ -1,19 +0,0 @@
package trace
type spanContext struct {
traceId string
spanId string
}
func (sc spanContext) TraceId() string {
return sc.traceId
}
func (sc spanContext) SpanId() string {
return sc.spanId
}
func (sc spanContext) Visit(fn func(key, val string) bool) {
fn(TraceIdKey, sc.traceId)
fn(spanIdKey, sc.spanId)
}

View File

@@ -1,4 +1,4 @@
package opentelemetry
package trace
import (
"context"

View File

@@ -1,4 +1,4 @@
package opentelemetry
package trace
import (
"context"

View File

@@ -1,12 +0,0 @@
package tracespec
// TracingKey is tracing key for context
var TracingKey = contextKey("X-Trace")
// contextKey a type for context key
type contextKey string
// String returns a context will reveal a fair amount of information about it.
func (c contextKey) String() string {
return "trace/tracespec context key " + string(c)
}

View File

@@ -1,8 +0,0 @@
package tracespec
// SpanContext interface that represents a span context.
type SpanContext interface {
TraceId() string
SpanId() string
Visit(fn func(key, val string) bool)
}

View File

@@ -1,11 +0,0 @@
package tracespec
import "context"
// Trace interface represents a tracing.
type Trace interface {
SpanContext
Finish()
Fork(ctx context.Context, serviceName, operationName string) (context.Context, Trace)
Follow(ctx context.Context, serviceName, operationName string) (context.Context, Trace)
}

View File

@@ -1,4 +1,4 @@
package opentelemetry
package trace
import (
"context"

View File

@@ -1,4 +1,4 @@
package opentelemetry
package trace
import (
"testing"

8
core/trace/vars.go Normal file
View File

@@ -0,0 +1,8 @@
package trace
import "net/http"
// TraceIdKey is the trace id header.
// https://www.w3.org/TR/trace-context/#trace-id
// May change it to trace-id afterwards.
var TraceIdKey = http.CanonicalHeaderKey("x-trace-id")

22
go.mod
View File

@@ -7,7 +7,6 @@ require (
github.com/DATA-DOG/go-sqlmock v1.4.1
github.com/alicebob/miniredis/v2 v2.14.1
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/emicklei/proto v1.9.0
github.com/fatih/color v1.9.0 // indirect
github.com/fatih/structtag v1.2.0
@@ -16,8 +15,8 @@ require (
github.com/go-redis/redis v6.15.7+incompatible
github.com/go-sql-driver/mysql v1.5.0
github.com/go-xorm/builder v0.3.4
github.com/golang-jwt/jwt v3.2.1+incompatible
github.com/golang/mock v1.4.3
github.com/golang/protobuf v1.5.2
github.com/google/uuid v1.1.2
github.com/iancoleman/strcase v0.1.2
github.com/justinas/alice v1.2.0
@@ -33,18 +32,21 @@ require (
github.com/urfave/cli v1.22.5
github.com/zeromicro/antlr v0.0.1
github.com/zeromicro/ddl-parser v0.0.0-20210712021150-63520aca7348
github.com/zeromicro/protobuf v0.0.0-20210921042113-636cd51f0c35
go.etcd.io/etcd/api/v3 v3.5.0
go.etcd.io/etcd/client/v3 v3.5.0
go.opentelemetry.io/otel v1.0.0-RC2
go.opentelemetry.io/otel/exporters/jaeger v1.0.0-RC2
go.opentelemetry.io/otel/sdk v1.0.0-RC2
go.opentelemetry.io/otel/trace v1.0.0-RC2
go.opentelemetry.io/otel v1.0.1
go.opentelemetry.io/otel/exporters/jaeger v1.0.1
go.opentelemetry.io/otel/exporters/zipkin v1.0.1
go.opentelemetry.io/otel/sdk v1.0.1
go.opentelemetry.io/otel/trace v1.0.1
go.uber.org/automaxprocs v1.3.0
golang.org/x/net v0.0.0-20210716203947-853a461950ff
golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55 // indirect
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b // indirect
golang.org/x/sys v0.0.0-20211002104244-808efd93c36d // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f // indirect
google.golang.org/grpc v1.39.0
google.golang.org/genproto v0.0.0-20210928142010-c7af6a1a74c9 // indirect
google.golang.org/grpc v1.41.0
google.golang.org/protobuf v1.27.1
gopkg.in/cheggaaa/pb.v1 v1.0.28
gopkg.in/h2non/gock.v1 v1.0.15

67
go.sum
View File

@@ -37,8 +37,11 @@ github.com/ClickHouse/clickhouse-go v1.4.3/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHg
github.com/DATA-DOG/go-sqlmock v1.4.1 h1:ThlnYciV1iM/V0OSF/dtkqWb6xo5qITT1TJBG1MRDJM=
github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
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=
@@ -59,6 +62,8 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/bkaradzic/go-lz4 v1.0.0 h1:RXc4wYsyz985CkXXeX04y4VnZFGG8Rd43pRaHsOXAKk=
github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
@@ -70,6 +75,7 @@ github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h
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/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
@@ -80,11 +86,13 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr
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/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/proto v1.9.0 h1:l0QiNT6Qs7Yj0Mb4X6dnWBQer4ebei2BFcgQLbGqUDc=
@@ -95,6 +103,7 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
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.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
@@ -144,6 +153,8 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c=
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -172,6 +183,7 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -201,6 +213,8 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I=
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
@@ -275,12 +289,17 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/openzipkin/zipkin-go v0.2.5 h1:UwtQQx2pyPIgWYHRg+epgdx1/HnBQTgN3/oIYEJTQzU=
github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4 v2.5.1+incompatible h1:Yq0up0149Hh5Ekhm/91lgkZuD1ZDnXNM26bycpTzYBM=
github.com/pierrec/lz4 v2.5.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
@@ -288,6 +307,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
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/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@@ -309,6 +329,7 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
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/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -318,12 +339,14 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
@@ -346,6 +369,8 @@ github.com/zeromicro/antlr v0.0.1 h1:CQpIn/dc0pUjgGQ81y98s/NGOm2Hfru2NNio2I9mQgk
github.com/zeromicro/antlr v0.0.1/go.mod h1:nfpjEwFR6Q4xGDJMcZnCL9tEfQRgszMwu3rDz2Z+p5M=
github.com/zeromicro/ddl-parser v0.0.0-20210712021150-63520aca7348 h1:OhxL9tn28gDeJVzreIUiE5oVxZCjL3tBJ0XBNw8p5R8=
github.com/zeromicro/ddl-parser v0.0.0-20210712021150-63520aca7348/go.mod h1:ISU/8NuPyEpl9pa17Py9TBPetMjtsiHrb9f5XGiYbo8=
github.com/zeromicro/protobuf v0.0.0-20210921042113-636cd51f0c35 h1:LKLiozf78evAX4+82AHw/rG7TvefD7TJII7XB7Oip7o=
github.com/zeromicro/protobuf v0.0.0-20210921042113-636cd51f0c35/go.mod h1:CJvyESptK/6uU5003fPJQ9Hmubl3vRuGqaLgzUU0R7Y=
go.etcd.io/etcd/api/v3 v3.5.0 h1:GsV3S+OfZEOCNXdtNkBSR7kgLobAa/SO6tCxRa0GAYw=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.0 h1:2aQv6F436YnN7I4VbI8PPYrBhu+SmrTaADcf8Mi/6PU=
@@ -356,14 +381,16 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opentelemetry.io/otel v1.0.0-RC2 h1:SHhxSjB+omnGZPgGlKe+QMp3MyazcOHdQ8qwo89oKbg=
go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM=
go.opentelemetry.io/otel/exporters/jaeger v1.0.0-RC2 h1:RF0nWsIDpDBe+s06lkLxUw9CWQUAhO6hBSxxB7dz45s=
go.opentelemetry.io/otel/exporters/jaeger v1.0.0-RC2/go.mod h1:sZZqN3Vb0iT+NE6mZ1S7sNyH3t4PFk6ElK5TLGFBZ7E=
go.opentelemetry.io/otel/sdk v1.0.0-RC2 h1:ROuteeSCBaZNjiT9JcFzZepmInDvLktR28Y6qKo8bCs=
go.opentelemetry.io/otel/sdk v1.0.0-RC2/go.mod h1:fgwHyiDn4e5k40TD9VX243rOxXR+jzsWBZYA2P5jpEw=
go.opentelemetry.io/otel/trace v1.0.0-RC2 h1:dunAP0qDULMIT82atj34m5RgvsIK6LcsXf1c/MsYg1w=
go.opentelemetry.io/otel/trace v1.0.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4=
go.opentelemetry.io/otel v1.0.1 h1:4XKyXmfqJLOQ7feyV5DB6gsBFZ0ltB8vLtp6pj4JIcc=
go.opentelemetry.io/otel v1.0.1/go.mod h1:OPEOD4jIT2SlZPMmwT6FqZz2C0ZNdQqiWcoK6M0SNFU=
go.opentelemetry.io/otel/exporters/jaeger v1.0.1 h1:fg9udWIWWJMAT+Gq2ATFd/DFy3OZvKEZy9VK2amxvkw=
go.opentelemetry.io/otel/exporters/jaeger v1.0.1/go.mod h1:85Ym3qknJdIdfRzYS9Ofy9NeLi9gKPFzFDBEHCKpfXI=
go.opentelemetry.io/otel/exporters/zipkin v1.0.1 h1:Li6OvM1Po5qrP+HnXlZa+FyLkMun7JG4R0vTAch12qs=
go.opentelemetry.io/otel/exporters/zipkin v1.0.1/go.mod h1:KXb2W6IVINSd/rKugSARqP3TsByxngvea3B1vm5ju74=
go.opentelemetry.io/otel/sdk v1.0.1 h1:wXxFEWGo7XfXupPwVJvTBOaPBC9FEg0wB8hMNrKk+cA=
go.opentelemetry.io/otel/sdk v1.0.1/go.mod h1:HrdXne+BiwsOHYYkBE5ysIcv2bvdZstxzmCQhxTcZkI=
go.opentelemetry.io/otel/trace v1.0.1 h1:StTeIH6Q3G4r0Fiw34LTokUFESZgIDUr0qIJ7mKmAfw=
go.opentelemetry.io/otel/trace v1.0.1/go.mod h1:5g4i4fKLaX2BQpSBsxw8YYcgKpMMSW3x7ZTuYBr3sUk=
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=
@@ -441,8 +468,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-20201110031124-69a78807bb2b/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-20210716203947-853a461950ff h1:j2EK/QoxYNBsXI4R7fQkkRUk8y6wnOBI+6hgPdP/6Ds=
golang.org/x/net v0.0.0-20210716203947-853a461950ff/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b h1:eB48h3HiRycXNy8E0Gf5e0hv7YT6Kt14L/D73G1fuwo=
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
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=
@@ -500,8 +527,8 @@ 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-20210820121016-41cdb8703e55 h1:rw6UNGRMfarCepjI8qOepea/SXwIBVfTKjztZ5gBbq4=
golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211002104244-808efd93c36d h1:SABT8Vei3iTiu+Gy8KOzpSNz+W1EQ5YBCRtiEETxF+0=
golang.org/x/sys v0.0.0-20211002104244-808efd93c36d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
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=
@@ -510,8 +537,9 @@ 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.4/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=
@@ -552,7 +580,6 @@ golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjs
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
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=
@@ -595,8 +622,8 @@ google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f h1:YORWxaStkWBnWgELOHTmDrqNlFXuVGEbhwbB5iK94bQ=
google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210928142010-c7af6a1a74c9 h1:XTH066D35LyHehRwlYhoK3qA+Hcgvg5xREG4kFQEW1Y=
google.golang.org/genproto v0.0.0-20210928142010-c7af6a1a74c9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -605,11 +632,13 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.30.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.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.39.0 h1:Klz8I9kdtkIN6EpHHUOMLCYhTn/2WAe5a0s1hcBkdTI=
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E=
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
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=

View File

@@ -4,16 +4,18 @@
[English](readme.md) | 简体中文
[![Go](https://github.com/tal-tech/go-zero/workflows/Go/badge.svg?branch=master)](https://github.com/tal-tech/go-zero/actions)
[![Go Report Card](https://goreportcard.com/badge/github.com/tal-tech/go-zero)](https://goreportcard.com/report/github.com/tal-tech/go-zero)
[![Go](https://github.com/zeromicro/go-zero/workflows/Go/badge.svg?branch=master)](https://github.com/zeromicro/go-zero/actions)
[![Go Report Card](https://goreportcard.com/badge/github.com/zeromicro/go-zero)](https://goreportcard.com/report/github.com/zeromicro/go-zero)
[![goproxy](https://goproxy.cn/stats/github.com/tal-tech/go-zero/badges/download-count.svg)](https://goproxy.cn/stats/github.com/tal-tech/go-zero/badges/download-count.svg)
[![codecov](https://codecov.io/gh/tal-tech/go-zero/branch/master/graph/badge.svg)](https://codecov.io/gh/tal-tech/go-zero)
[![Release](https://img.shields.io/github/v/release/tal-tech/go-zero.svg?style=flat-square)](https://github.com/tal-tech/go-zero)
[![codecov](https://codecov.io/gh/zeromicro/go-zero/branch/master/graph/badge.svg)](https://codecov.io/gh/zeromicro/go-zero)
[![Release](https://img.shields.io/github/v/release/zeromicro/go-zero.svg?style=flat-square)](https://github.com/zeromicro/go-zero)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
**注意为了满足开源基金会要求go-zero 从好未来tal-tech组织下迁移至中立的 GitHub 组织zeromicro**
## 0. go-zero 介绍
go-zero 是一个集成了各种工程实践的 web 和 rpc 框架。通过弹性设计保障了大并发服务端的稳定性,经受了充分的实战检验。
go-zero(收录于 CNCF 云原生技术全景图:[https://landscape.cncf.io/?selected=go-zero](https://landscape.cncf.io/?selected=go-zero)是一个集成了各种工程实践的 web 和 rpc 框架。通过弹性设计保障了大并发服务端的稳定性,经受了充分的实战检验。
go-zero 包含极简的 API 定义和生成工具 goctl可以根据定义的 api 文件一键生成 Go, iOS, Android, Kotlin, Dart, TypeScript, JavaScript 代码,并可直接运行。
@@ -26,7 +28,7 @@ go-zero 包含极简的 API 定义和生成工具 goctl可以根据定义的
* 自动校验客户端请求参数合法性
* 大量微服务治理和并发工具包
![架构图](https://raw.githubusercontent.com/tal-tech/zero-doc/main/doc/images/architecture.png)
![架构图](https://raw.githubusercontent.com/zeromicro/zero-doc/main/doc/images/architecture.png)
## 1. go-zero 框架背景
@@ -76,7 +78,7 @@ go-zero 是一个集成了各种工程实践的包含 web 和 rpc 框架,有
如下图,我们从多个层面保障了整体服务的高可用:
![弹性设计](https://raw.githubusercontent.com/tal-tech/zero-doc/main/doc/images/resilience.jpg)
![弹性设计](https://raw.githubusercontent.com/zeromicro/zero-doc/main/doc/images/resilience.jpg)
觉得不错的话,别忘 **star** 👏
@@ -92,9 +94,9 @@ GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/tal-tech/
0. 完整示例请查看
[快速构建高并发微服务](https://github.com/tal-tech/zero-doc/blob/main/doc/shorturl.md)
[快速构建高并发微服务](https://github.com/zeromicro/zero-doc/blob/main/doc/shorturl.md)
[快速构建高并发微服务 - 多 RPC 版](https://github.com/tal-tech/zero-doc/blob/main/docs/zero/bookstore.md)
[快速构建高并发微服务 - 多 RPC 版](https://github.com/zeromicro/zero-doc/blob/main/docs/zero/bookstore.md)
1. 安装 goctl 工具
@@ -139,7 +141,7 @@ GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/tal-tech/
编写业务代码:
* api 文件定义了服务对外 HTTP 接口,可参考 [api 规范](https://github.com/tal-tech/zero-doc/blob/main/doc/goctl.md)
* api 文件定义了服务对外 HTTP 接口,可参考 [api 规范](https://github.com/zeromicro/zero-doc/blob/main/doc/goctl.md)
* 可以在 `servicecontext.go` 里面传递依赖给 logic比如 mysql, redis 等
* 在 api 定义的 `get/post/put/delete` 等请求对应的 logic 里增加业务处理逻辑
@@ -153,7 +155,7 @@ GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/tal-tech/
## 6. Benchmark
![benchmark](https://raw.githubusercontent.com/tal-tech/zero-doc/main/doc/images/benchmark.png)
![benchmark](https://raw.githubusercontent.com/zeromicro/zero-doc/main/doc/images/benchmark.png)
[测试代码见这里](https://github.com/smallnest/go-web-framework-benchmark)
@@ -165,9 +167,9 @@ GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/tal-tech/
* awesome 系列(更多文章见『微服务实践』公众号)
* [快速构建高并发微服务](https://github.com/tal-tech/zero-doc/blob/main/doc/shorturl.md)
* [快速构建高并发微服务 - 多 RPC 版](https://github.com/tal-tech/zero-doc/blob/main/docs/zero/bookstore.md)
* [goctl 使用帮助](https://github.com/tal-tech/zero-doc/blob/main/doc/goctl.md)
* [快速构建高并发微服务](https://github.com/zeromicro/zero-doc/blob/main/doc/shorturl.md)
* [快速构建高并发微服务 - 多 RPC 版](https://github.com/zeromicro/zero-doc/blob/main/docs/zero/bookstore.md)
* [goctl 使用帮助](https://github.com/zeromicro/zero-doc/blob/main/doc/goctl.md)
* [Examples](https://github.com/zeromicro/zero-examples)
* 精选 `goctl` 插件
@@ -222,16 +224,27 @@ go-zero 已被许多公司用于生产部署,接入场景如在线教育、电
>38. 北京小鸦科技有限公司
>39. 深圳无边界技术有限公司
>40. 马鞍山百助网络科技有限公司
>41. 上海阿莫尔科技有限公司
>42. 发明者量化
如果贵公司也已使用 go-zero欢迎在 [登记地址](https://github.com/tal-tech/go-zero/issues/602) 登记,仅仅为了推广,不做其它用途。
如果贵公司也已使用 go-zero欢迎在 [登记地址](https://github.com/zeromicro/go-zero/issues/602) 登记,仅仅为了推广,不做其它用途。
## 9. 微信公众号
## 9. CNCF 云原生技术全景图
<p float="left">
<img src="https://landscape.cncf.io/images/left-logo.svg" width="150"/>&nbsp;&nbsp;&nbsp;
<img src="https://landscape.cncf.io/images/right-logo.svg" width="200"/>
</p>
go-zero 收录在 [CNCF Cloud Native 云原生技术全景图](https://landscape.cncf.io/?selected=go-zero)。
## 10. 微信公众号
`go-zero` 相关文章和视频都会在 `微服务实践` 公众号整理呈现,欢迎扫码关注 👏
<img src="https://raw.githubusercontent.com/tal-tech/zero-doc/main/doc/images/wechat-micro.jpg" alt="wechat" width="300" />
<img src="https://raw.githubusercontent.com/zeromicro/zero-doc/main/doc/images/wechat-micro.jpg" alt="wechat" width="300" />
## 10. 微信交流群
## 11. 微信交流群
如果文档中未能覆盖的任何疑问,欢迎您在群里提出,我们会尽快答复。
@@ -241,4 +254,4 @@ go-zero 已被许多公司用于生产部署,接入场景如在线教育、电
加群之前有劳点一下 ***star***,一个小小的 ***star*** 是作者们回答海量问题的动力!🤝
<img src="https://raw.githubusercontent.com/tal-tech/zero-doc/main/doc/images/wechat.jpg" alt="wechat" width="300" />
<img src="https://raw.githubusercontent.com/zeromicro/zero-doc/main/doc/images/wechat.jpg" alt="wechat" width="300" />

View File

@@ -1,18 +1,20 @@
<img align="right" width="150px" src="https://raw.githubusercontent.com/tal-tech/zero-doc/main/doc/images/go-zero.png">
<img align="right" width="150px" src="https://raw.githubusercontent.com/zeromicro/zero-doc/main/doc/images/go-zero.png">
# go-zero
English | [简体中文](readme-cn.md)
[![Go](https://github.com/tal-tech/go-zero/workflows/Go/badge.svg?branch=master)](https://github.com/tal-tech/go-zero/actions)
[![codecov](https://codecov.io/gh/tal-tech/go-zero/branch/master/graph/badge.svg)](https://codecov.io/gh/tal-tech/go-zero)
[![Go Report Card](https://goreportcard.com/badge/github.com/tal-tech/go-zero)](https://goreportcard.com/report/github.com/tal-tech/go-zero)
[![Release](https://img.shields.io/github/v/release/tal-tech/go-zero.svg?style=flat-square)](https://github.com/tal-tech/go-zero)
[![Go](https://github.com/zeromicro/go-zero/workflows/Go/badge.svg?branch=master)](https://github.com/zeromicro/go-zero/actions)
[![codecov](https://codecov.io/gh/zeromicro/go-zero/branch/master/graph/badge.svg)](https://codecov.io/gh/zeromicro/go-zero)
[![Go Report Card](https://goreportcard.com/badge/github.com/zeromicro/go-zero)](https://goreportcard.com/report/github.com/zeromicro/go-zero)
[![Release](https://img.shields.io/github/v/release/zeromicro/go-zero.svg?style=flat-square)](https://github.com/zeromicro/go-zero)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
**Note: To meet the requirements of Open Source Foundation, we moved go-zero from tal-tech to zeromicro (a neutral GitHub organization).**
## 0. what is go-zero
go-zero is a web and rpc framework with lots of builtin engineering practices. Its born to ensure the stability of the busy services with resilience design, and has been serving sites with tens of millions users for years.
go-zero (listed in CNCF Landscape: [https://landscape.cncf.io/?selected=go-zero](https://landscape.cncf.io/?selected=go-zero)) is a web and rpc framework with lots of builtin engineering practices. Its born to ensure the stability of the busy services with resilience design, and has been serving sites with tens of millions users for years.
go-zero contains simple API description syntax and code generation tool called `goctl`. You can generate Go, iOS, Android, Kotlin, Dart, TypeScript, JavaScript from .api files with `goctl`.
@@ -25,7 +27,7 @@ Advantages of go-zero:
* auto validate the request parameters from clients
* plenty of builtin microservice management and concurrent toolkits
<img src="https://raw.githubusercontent.com/tal-tech/zero-doc/main/doc/images/architecture-en.png" alt="Architecture" width="1500" />
<img src="https://raw.githubusercontent.com/zeromicro/zero-doc/main/doc/images/architecture-en.png" alt="Architecture" width="1500" />
## 1. Backgrounds of go-zero
@@ -76,7 +78,7 @@ go-zero is a web and rpc framework that integrates lots of engineering practices
As below, go-zero protects the system with couple layers and mechanisms:
![Resilience](https://raw.githubusercontent.com/tal-tech/zero-doc/main/doc/images/resilience-en.png)
![Resilience](https://raw.githubusercontent.com/zeromicro/zero-doc/main/doc/images/resilience-en.png)
## 4. Future development plans of go-zero
@@ -95,9 +97,9 @@ go get -u github.com/tal-tech/go-zero
0. full examples can be checked out from below:
[Rapid development of microservice systems](https://github.com/tal-tech/zero-doc/blob/main/doc/shorturl-en.md)
[Rapid development of microservice systems](https://github.com/zeromicro/zero-doc/blob/main/doc/shorturl-en.md)
[Rapid development of microservice systems - multiple RPCs](https://github.com/tal-tech/zero-doc/blob/main/docs/zero/bookstore-en.md)
[Rapid development of microservice systems - multiple RPCs](https://github.com/zeromicro/zero-doc/blob/main/docs/zero/bookstore-en.md)
1. install goctl
@@ -206,21 +208,30 @@ go get -u github.com/tal-tech/go-zero
## 7. Benchmark
![benchmark](https://raw.githubusercontent.com/tal-tech/zero-doc/main/doc/images/benchmark.png)
![benchmark](https://raw.githubusercontent.com/zeromicro/zero-doc/main/doc/images/benchmark.png)
[Checkout the test code](https://github.com/smallnest/go-web-framework-benchmark)
## 8. Documents (adding)
* [Documents](https://go-zero.dev/en/)
* [Rapid development of microservice systems](https://github.com/tal-tech/zero-doc/blob/main/doc/shorturl-en.md)
* [Rapid development of microservice systems - multiple RPCs](https://github.com/tal-tech/zero-doc/blob/main/docs/zero/bookstore-en.md)
* [Rapid development of microservice systems](https://github.com/zeromicro/zero-doc/blob/main/doc/shorturl-en.md)
* [Rapid development of microservice systems - multiple RPCs](https://github.com/zeromicro/zero-doc/blob/main/docs/zero/bookstore-en.md)
* [Examples](https://github.com/zeromicro/zero-examples)
## 9. Chat group
Join the chat via https://join.slack.com/t/go-zero/shared_invite/zt-ulzixfgi-NAkZjq856TewLY2KQSxHCw
## 10. Cloud Native Landscape
<p float="left">
<img src="https://landscape.cncf.io/images/left-logo.svg" width="150"/>&nbsp;&nbsp;&nbsp;
<img src="https://landscape.cncf.io/images/right-logo.svg" width="200"/>
</p>
go-zero enlisted in the [CNCF Cloud Native Landscape](https://landscape.cncf.io/?selected=go-zero).
## Give a Star! ⭐
If you like or are using this project to learn or start your solution, please give it a star. Thanks!

View File

@@ -107,8 +107,7 @@ func (s *engine) bindFeaturedRoutes(router httpx.Router, fr featuredRoutes, metr
func (s *engine) bindRoute(fr featuredRoutes, router httpx.Router, metrics *stat.Metrics,
route Route, verifier func(chain alice.Chain) alice.Chain) error {
chain := alice.New(
handler.TracingHandler,
handler.OtelHandler(route.Path),
handler.TracingHandler(s.conf.Name, route.Path),
s.getLogHandler(),
handler.PrometheusHandler(route.Path),
handler.MaxConns(s.conf.MaxConns),

View File

@@ -8,7 +8,7 @@ import (
"net/http"
"net/http/httputil"
"github.com/dgrijalva/jwt-go"
"github.com/golang-jwt/jwt"
"github.com/tal-tech/go-zero/core/logx"
"github.com/tal-tech/go-zero/rest/token"
)

View File

@@ -8,7 +8,7 @@ import (
"testing"
"time"
"github.com/dgrijalva/jwt-go"
"github.com/golang-jwt/jwt"
"github.com/stretchr/testify/assert"
)
@@ -16,7 +16,8 @@ func TestAuthHandlerFailed(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
handler := Authorize("B63F477D-BBA3-4E52-96D3-C0034C27694A", WithUnauthorizedCallback(
func(w http.ResponseWriter, r *http.Request, err error) {
w.Header().Set("X-Test", "test")
assert.NotNil(t, err)
w.Header().Set("X-Test", err.Error())
w.WriteHeader(http.StatusUnauthorized)
_, err = w.Write([]byte("content"))
assert.Nil(t, err)

View File

@@ -275,8 +275,7 @@ func TestContentSecurityHandler_UnsignedCallback_WrongTime(t *testing.T) {
})
handler := contentSecurityHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {}))
var reader io.Reader
reader = strings.NewReader("hello")
reader := strings.NewReader("hello")
setting := requestSettings{
method: http.MethodPost,
url: "http://localhost/a/b?c=d&e=f",

View File

@@ -152,11 +152,12 @@ func dumpRequest(r *http.Request) string {
func logBrief(r *http.Request, code int, timer *utils.ElapsedTimer, logs *internal.LogCollector) {
var buf bytes.Buffer
duration := timer.Duration()
buf.WriteString(fmt.Sprintf("%d - %s - %s - %s - %s",
code, r.RequestURI, httpx.GetRemoteAddr(r), r.UserAgent(), timex.ReprOfDuration(duration)))
logger := logx.WithContext(r.Context())
buf.WriteString(fmt.Sprintf("[HTTP] %s - %d - %s - %s - %s - %s",
r.Method, code, r.RequestURI, httpx.GetRemoteAddr(r), r.UserAgent(), timex.ReprOfDuration(duration)))
if duration > slowThreshold {
logx.WithContext(r.Context()).Slowf("[HTTP] %d - %s - %s - %s - slowcall(%s)",
code, r.RequestURI, httpx.GetRemoteAddr(r), r.UserAgent(), timex.ReprOfDuration(duration))
logger.Slowf("[HTTP] %s - %d - %s - %s - %s - slowcall(%s)",
r.Method, code, r.RequestURI, httpx.GetRemoteAddr(r), r.UserAgent(), timex.ReprOfDuration(duration))
}
ok := isOkResponse(code)
@@ -177,9 +178,9 @@ func logBrief(r *http.Request, code int, timer *utils.ElapsedTimer, logs *intern
}
if ok {
logx.WithContext(r.Context()).Info(buf.String())
logger.Info(buf.String())
} else {
logx.WithContext(r.Context()).Error(buf.String())
logger.Error(buf.String())
}
}
@@ -187,11 +188,12 @@ func logDetails(r *http.Request, response *detailLoggedResponseWriter, timer *ut
logs *internal.LogCollector) {
var buf bytes.Buffer
duration := timer.Duration()
buf.WriteString(fmt.Sprintf("%d - %s - %s\n=> %s\n",
response.writer.code, r.RemoteAddr, timex.ReprOfDuration(duration), dumpRequest(r)))
logger := logx.WithContext(r.Context())
buf.WriteString(fmt.Sprintf("[HTTP] %s - %d - %s - %s\n=> %s\n",
r.Method, response.writer.code, r.RemoteAddr, timex.ReprOfDuration(duration), dumpRequest(r)))
if duration > slowThreshold {
logx.WithContext(r.Context()).Slowf("[HTTP] %d - %s - slowcall(%s)\n=> %s\n",
response.writer.code, r.RemoteAddr, timex.ReprOfDuration(duration), dumpRequest(r))
logger.Slowf("[HTTP] %s - %d - %s - slowcall(%s)\n=> %s\n",
r.Method, response.writer.code, r.RemoteAddr, timex.ReprOfDuration(duration), dumpRequest(r))
}
body := logs.Flush()
@@ -204,7 +206,7 @@ func logDetails(r *http.Request, response *detailLoggedResponseWriter, timer *ut
buf.WriteString(fmt.Sprintf("<= %s", respBuf))
}
logx.WithContext(r.Context()).Info(buf.String())
logger.Info(buf.String())
}
func isOkResponse(code int) bool {

View File

@@ -1,36 +0,0 @@
package handler
import (
"net/http"
"github.com/tal-tech/go-zero/core/trace/opentelemetry"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/propagation"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
oteltrace "go.opentelemetry.io/otel/trace"
)
// OtelHandler return a middleware that process the opentelemetry.
func OtelHandler(path string) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
if !opentelemetry.Enabled() {
return next
}
propagator := otel.GetTextMapPropagator()
tracer := otel.GetTracerProvider().Tracer(opentelemetry.TraceName)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := propagator.Extract(r.Context(), propagation.HeaderCarrier(r.Header))
spanCtx, span := tracer.Start(
ctx,
path,
oteltrace.WithSpanKind(oteltrace.SpanKindServer),
oteltrace.WithAttributes(semconv.HTTPServerAttributesFromHTTPRequest("", path, r)...),
)
defer span.End()
next.ServeHTTP(w, r.WithContext(spanCtx))
})
}
}

View File

@@ -1,48 +0,0 @@
package handler
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/trace/opentelemetry"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/trace"
)
func TestOtelHandler(t *testing.T) {
opentelemetry.StartAgent(opentelemetry.Config{
Name: "go-zero-test",
Endpoint: "http://localhost:14268/api/traces",
Batcher: "jaeger",
Sampler: 1.0,
})
ts := httptest.NewServer(
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := otel.GetTextMapPropagator().Extract(r.Context(), propagation.HeaderCarrier(r.Header))
spanCtx := trace.SpanContextFromContext(ctx)
assert.Equal(t, true, spanCtx.IsValid())
}),
)
defer ts.Close()
client := ts.Client()
err := func(ctx context.Context) error {
ctx, span := otel.Tracer("httptrace/client").Start(ctx, "test")
defer span.End()
req, _ := http.NewRequest("GET", ts.URL, nil)
otel.GetTextMapPropagator().Inject(ctx, propagation.HeaderCarrier(req.Header))
res, err := client.Do(req)
assert.Equal(t, err, nil)
_ = res.Body.Close()
return nil
}(context.Background())
assert.Equal(t, err, nil)
}

View File

@@ -3,26 +3,37 @@ package handler
import (
"net/http"
"github.com/tal-tech/go-zero/core/logx"
"github.com/tal-tech/go-zero/core/sysx"
"github.com/tal-tech/go-zero/core/trace"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/propagation"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
oteltrace "go.opentelemetry.io/otel/trace"
)
// TracingHandler returns a middleware that traces the request.
func TracingHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
carrier, err := trace.Extract(trace.HttpFormat, r.Header)
// ErrInvalidCarrier means no trace id was set in http header
if err != nil && err != trace.ErrInvalidCarrier {
logx.Error(err)
}
// TracingHandler return a middleware that process the opentelemetry.
func TracingHandler(serviceName, path string) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
propagator := otel.GetTextMapPropagator()
tracer := otel.GetTracerProvider().Tracer(trace.TraceName)
ctx, span := trace.StartServerSpan(r.Context(), carrier, sysx.Hostname(), r.RequestURI)
defer span.Finish()
r = r.WithContext(ctx)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := propagator.Extract(r.Context(), propagation.HeaderCarrier(r.Header))
spanCtx, span := tracer.Start(
ctx,
path,
oteltrace.WithSpanKind(oteltrace.SpanKindServer),
oteltrace.WithAttributes(semconv.HTTPServerAttributesFromHTTPRequest(
serviceName, path, r)...),
)
defer span.End()
// conveniently tracking error messages
w.Header().Set(trace.TraceIdKey, span.TraceId())
next.ServeHTTP(w, r)
})
// convenient for tracking error messages
sc := span.SpanContext()
if sc.HasTraceID() {
w.Header().Set(trace.TraceIdKey, sc.TraceID().String())
}
next.ServeHTTP(w, r.WithContext(spanCtx))
})
}
}

View File

@@ -1,31 +1,48 @@
package handler
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/stringx"
"github.com/tal-tech/go-zero/core/trace"
"github.com/tal-tech/go-zero/core/trace/tracespec"
ztrace "github.com/tal-tech/go-zero/core/trace"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/trace"
)
func TestTracingHandler(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, "http://localhost", nil)
func TestOtelHandler(t *testing.T) {
ztrace.StartAgent(ztrace.Config{
Name: "go-zero-test",
Endpoint: "http://localhost:14268/api/traces",
Batcher: "jaeger",
Sampler: 1.0,
})
traceId := stringx.RandId()
req.Header.Set(trace.TraceIdKey, traceId)
ts := httptest.NewServer(
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := otel.GetTextMapPropagator().Extract(r.Context(), propagation.HeaderCarrier(r.Header))
spanCtx := trace.SpanContextFromContext(ctx)
assert.Equal(t, true, spanCtx.IsValid())
}),
)
defer ts.Close()
handler := TracingHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
span, ok := r.Context().Value(tracespec.TracingKey).(tracespec.Trace)
assert.True(t, ok)
assert.Equal(t, traceId, span.TraceId())
}))
client := ts.Client()
err := func(ctx context.Context) error {
ctx, span := otel.Tracer("httptrace/client").Start(ctx, "test")
defer span.End()
resp := httptest.NewRecorder()
handler.ServeHTTP(resp, req)
req, _ := http.NewRequest("GET", ts.URL, nil)
otel.GetTextMapPropagator().Inject(ctx, propagation.HeaderCarrier(req.Header))
assert.Equal(t, http.StatusOK, resp.Code)
assert.Equal(t, traceId, resp.Header().Get(trace.TraceIdKey))
res, err := client.Do(req)
assert.Equal(t, err, nil)
_ = res.Body.Close()
return nil
}(context.Background())
assert.Equal(t, err, nil)
}

View File

@@ -6,8 +6,8 @@ import (
"sync/atomic"
"time"
"github.com/dgrijalva/jwt-go"
"github.com/dgrijalva/jwt-go/request"
"github.com/golang-jwt/jwt"
"github.com/golang-jwt/jwt/request"
"github.com/tal-tech/go-zero/core/timex"
)

View File

@@ -6,7 +6,7 @@ import (
"testing"
"time"
"github.com/dgrijalva/jwt-go"
"github.com/golang-jwt/jwt"
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/core/timex"
)

View File

@@ -1,15 +0,0 @@
# 2020-01-08
## features ![](https://img.shields.io/static/v1?label=&message=new&color=red)
* reactor api parse by g4
* add syntax lexer for api
* support java-style documentation comments
* support parsing doc and comment
* support import group
> original: [api grammar document](./api/parser/readme.md)
# 2020-01-08
* add change log

View File

@@ -1,14 +1,12 @@
version := $(shell /bin/date "+%Y-%m-%d %H:%M")
build:
go build -ldflags="-s -w" -ldflags="-X 'main.BuildTime=$(version)'" goctl.go
go build -ldflags="-s -w" goctl.go
$(if $(shell command -v upx), upx goctl)
mac:
GOOS=darwin go build -ldflags="-s -w" -ldflags="-X 'main.BuildTime=$(version)'" -o goctl-darwin goctl.go
GOOS=darwin go build -ldflags="-s -w" -o goctl-darwin goctl.go
$(if $(shell command -v upx), upx goctl-darwin)
win:
GOOS=windows go build -ldflags="-s -w" -ldflags="-X 'main.BuildTime=$(version)'" -o goctl.exe goctl.go
GOOS=windows go build -ldflags="-s -w" -o goctl.exe goctl.go
$(if $(shell command -v upx), upx goctl.exe)
linux:
GOOS=linux go build -ldflags="-s -w" -ldflags="-X 'main.BuildTime=$(version)'" -o goctl-linux goctl.go
GOOS=linux go build -ldflags="-s -w" -o goctl-linux goctl.go
$(if $(shell command -v upx), upx goctl-linux)

View File

@@ -12,19 +12,19 @@ const dataTemplate = `// --{{with .Info}}{{.Title}}{{end}}--
class {{.Name}}{
{{range .Members}}
/// {{.Comment}}
final {{.Type}} {{lowCamelCase .Name}};
final {{.Type.Name}} {{lowCamelCase .Name}};
{{end}}
{{.Name}}({ {{range .Members}}
this.{{lowCamelCase .Name}},{{end}}
});
factory {{.Name}}.fromJson(Map<String,dynamic> m) {
return {{.Name}}({{range .Members}}
{{lowCamelCase .Name}}: {{if isDirectType .Type}}m['{{tagGet .Tag "json"}}']{{else if isClassListType .Type}}(m['{{tagGet .Tag "json"}}'] as List<dynamic>).map((i) => {{getCoreType .Type}}.fromJson(i)){{else}}{{.Type}}.fromJson(m['{{tagGet .Tag "json"}}']){{end}},{{end}}
{{lowCamelCase .Name}}: {{if isDirectType .Type.Name}}m['{{tagGet .Tag "json"}}']{{else if isClassListType .Type.Name}}(m['{{tagGet .Tag "json"}}'] as List<dynamic>).map((i) => {{getCoreType .Type.Name}}.fromJson(i)){{else}}{{.Type.Name}}.fromJson(m['{{tagGet .Tag "json"}}']){{end}},{{end}}
);
}
Map<String,dynamic> toJson() {
return { {{range .Members}}
'{{tagGet .Tag "json"}}': {{if isDirectType .Type}}{{lowCamelCase .Name}}{{else if isClassListType .Type}}{{lowCamelCase .Name}}.map((i) => i.toJson()){{else}}{{lowCamelCase .Name}}.toJson(){{end}},{{end}}
'{{tagGet .Tag "json"}}': {{if isDirectType .Type.Name}}{{lowCamelCase .Name}}{{else if isClassListType .Type.Name}}{{lowCamelCase .Name}}.map((i) => i.toJson()){{else}}{{lowCamelCase .Name}}.toJson(){{end}},{{end}}
};
}
}
@@ -55,6 +55,11 @@ func genData(dir string, api *spec.ApiSpec) error {
return err
}
err = convertDataType(api)
if err != nil {
return err
}
return t.Execute(file, api)
}
@@ -73,3 +78,25 @@ func genTokens(dir string) error {
_, err = tokensFile.WriteString(tokensFileContent)
return err
}
func convertDataType(api *spec.ApiSpec) error {
types := api.Types
if len(types) == 0 {
return nil
}
for _, ty := range types {
defineStruct, ok := ty.(spec.DefineStruct)
if ok {
for index, member := range defineStruct.Members {
tp, err := specTypeToDart(member.Type)
if err != nil {
return err
}
defineStruct.Members[index].Type = buildSpecType(member.Type, tp)
}
}
}
return nil
}

View File

@@ -1,6 +1,8 @@
package dartgen
import (
"errors"
"fmt"
"os"
"strings"
@@ -82,3 +84,91 @@ func fileExists(path string) bool {
_, err := os.Stat(path)
return !os.IsNotExist(err)
}
func buildSpecType(tp spec.Type, name string) spec.Type {
switch v := tp.(type) {
case spec.PrimitiveType:
return spec.PrimitiveType{RawName: name}
case spec.MapType:
return spec.MapType{RawName: name, Key: v.Key, Value: v.Value}
case spec.ArrayType:
return spec.ArrayType{RawName: name, Value: v.Value}
case spec.InterfaceType:
return spec.InterfaceType{RawName: name}
case spec.PointerType:
return spec.PointerType{RawName: name, Type: v.Type}
}
return tp
}
func specTypeToDart(tp spec.Type) (string, error) {
switch v := tp.(type) {
case spec.DefineStruct:
return tp.Name(), nil
case spec.PrimitiveType:
r, ok := primitiveType(tp.Name())
if !ok {
return "", errors.New("unsupported primitive type " + tp.Name())
}
return r, nil
case spec.MapType:
valueType, err := specTypeToDart(v.Value)
if err != nil {
return "", err
}
return fmt.Sprintf("Map<String, %s>", valueType), nil
case spec.ArrayType:
if tp.Name() == "[]byte" {
return "List<int>", nil
}
valueType, err := specTypeToDart(v.Value)
if err != nil {
return "", err
}
s := getBaseType(valueType)
if len(s) == 0 {
return s, errors.New("unsupported primitive type " + tp.Name())
}
return s, nil
case spec.InterfaceType:
return "Object", nil
case spec.PointerType:
return specTypeToDart(v.Type)
}
return "", errors.New("unsupported primitive type " + tp.Name())
}
func getBaseType(valueType string) string {
switch valueType {
case "int":
return "List<int>"
case "double":
return "List<double>"
case "boolean":
return "List<bool>"
case "String":
return "List<String>"
default:
return ""
}
}
func primitiveType(tp string) (string, bool) {
switch tp {
case "string":
return "String", true
case "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "rune":
return "int", true
case "float32", "float64":
return "double", true
case "bool":
return "bool", true
}
return "", false
}

View File

@@ -197,9 +197,8 @@ func getRoutes(api *spec.ApiSpec) ([]group, error) {
}
middleware := g.GetAnnotation("middleware")
if len(middleware) > 0 {
for _, item := range strings.Split(middleware, ",") {
groupedRoutes.middlewares = append(groupedRoutes.middlewares, item)
}
groupedRoutes.middlewares = append(groupedRoutes.middlewares,
strings.Split(middleware, ",")...)
}
routes = append(routes, groupedRoutes)
}

View File

@@ -39,12 +39,6 @@ func genServiceContext(dir, rootPkg string, cfg *config.Config, api *spec.ApiSpe
return err
}
authNames := getAuths(api)
var auths []string
for _, item := range authNames {
auths = append(auths, fmt.Sprintf("%s config.AuthConfig", item))
}
var middlewareStr string
var middlewareAssignment string
middlewares := getMiddleware(api)

View File

@@ -70,7 +70,20 @@ func getParentPackage(dir string) (string, error) {
return "", err
}
return filepath.ToSlash(filepath.Join(projectCtx.Path, strings.TrimPrefix(projectCtx.WorkDir, projectCtx.Dir))), nil
// fix https://github.com/zeromicro/go-zero/issues/1058
wd := projectCtx.WorkDir
d := projectCtx.Dir
same, err := ctlutil.SameFile(wd, d)
if err != nil {
return "", err
}
trim := strings.TrimPrefix(projectCtx.WorkDir, projectCtx.Dir)
if same {
trim = strings.TrimPrefix(strings.ToLower(projectCtx.WorkDir), strings.ToLower(projectCtx.Dir))
}
return filepath.ToSlash(filepath.Join(projectCtx.Path, trim)), nil
}
func writeProperty(writer io.Writer, name, tag, comment string, tp spec.Type, indent int) error {

View File

@@ -28,11 +28,7 @@ func JavaCommand(c *cli.Context) error {
return err
}
packetName := api.Service.Name
if strings.HasSuffix(packetName, "-api") {
packetName = packetName[:len(packetName)-4]
}
packetName := strings.TrimSuffix(api.Service.Name, "-api")
logx.Must(util.MkdirIfNotExist(dir))
logx.Must(genPacket(dir, packetName, api))
logx.Must(genComponents(dir, packetName, api))

View File

@@ -204,10 +204,7 @@ func processUri(route spec.Route) string {
}
}
}
result := builder.String()
if strings.HasSuffix(result, " + \"") {
result = result[:len(result)-4]
}
result := strings.TrimSuffix(builder.String(), " + \"")
if strings.HasPrefix(result, "/") {
result = strings.TrimPrefix(result, "/")
result = "\"" + result

View File

@@ -59,7 +59,18 @@ func CreateServiceCommand(c *cli.Context) error {
}
defer fp.Close()
t := template.Must(template.New("template").Parse(apiTemplate))
home := c.String("home")
if len(home) > 0 {
util.RegisterGoctlHome(home)
}
text, err := util.LoadTemplate(category, apiTemplateFile, apiTemplate)
if err != nil {
return err
}
t := template.Must(template.New("template").Parse(text))
if err := t.Execute(fp, map[string]string{
"name": dirName,
"handler": strings.Title(dirName),

View File

@@ -0,0 +1,51 @@
package new
import (
"fmt"
"github.com/tal-tech/go-zero/tools/goctl/util"
"github.com/urfave/cli"
)
const (
category = "newapi"
apiTemplateFile = "newtemplate.tpl"
)
var templates = map[string]string{
apiTemplateFile: apiTemplate,
}
// Category returns the category of the api files.
func Category() string {
return category
}
// Clean cleans the generated deployment files.
func Clean() error {
return util.Clean(category)
}
// GenTemplates generates api template files.
func GenTemplates(_ *cli.Context) error {
return util.InitTemplates(category, templates)
}
// RevertTemplate reverts the given template file to the default value.
func RevertTemplate(name string) error {
content, ok := templates[name]
if !ok {
return fmt.Errorf("%s: no such file name", name)
}
return util.CreateTemplate(category, name, content)
}
// Update updates the template files to the templates built in current goctl.
func Update() error {
err := Clean()
if err != nil {
return err
}
return util.InitTemplates(category, templates)
}

View File

@@ -5,7 +5,6 @@ import (
"sort"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api"
"github.com/tal-tech/go-zero/tools/goctl/api/util"
)
type (
@@ -155,8 +154,6 @@ func (v *ApiVisitor) VisitTypeStruct(ctx *api.TypeStructContext) interface{} {
var st TypeStruct
st.Name = v.newExprWithToken(ctx.GetStructName())
if util.UnExport(ctx.GetStructName().GetText()) {
}
if ctx.GetStructToken() != nil {
structExpr := v.newExprWithToken(ctx.GetStructToken())
structTokenText := ctx.GetStructToken().GetText()

View File

@@ -1087,7 +1087,6 @@ func (p *ApiParserParser) ImportBlock() (localctx IImportBlockContext) {
}
p.SetState(105)
p.GetErrorHandler().Sync(p)
_la = p.GetTokenStream().LA(1)
for ok := true; ok; ok = _la == ApiParserParserSTRING {
{
@@ -1447,7 +1446,6 @@ func (p *ApiParserParser) InfoSpec() (localctx IInfoSpecContext) {
}
p.SetState(120)
p.GetErrorHandler().Sync(p)
_la = p.GetTokenStream().LA(1)
for ok := true; ok; ok = _la == ApiParserParserID {
{
@@ -4102,7 +4100,6 @@ func (p *ApiParserParser) AtServer() (localctx IAtServerContext) {
}
p.SetState(245)
p.GetErrorHandler().Sync(p)
_la = p.GetTokenStream().LA(1)
for ok := true; ok; ok = _la == ApiParserParserID {
{
@@ -4627,7 +4624,6 @@ func (p *ApiParserParser) AtDoc() (localctx IAtDocContext) {
case ApiParserParserID:
p.SetState(277)
p.GetErrorHandler().Sync(p)
_la = p.GetTokenStream().LA(1)
for ok := true; ok; ok = _la == ApiParserParserID {
{
@@ -5461,7 +5457,6 @@ func (p *ApiParserParser) ServiceName() (localctx IServiceNameContext) {
p.EnterOuterAlt(localctx, 1)
p.SetState(322)
p.GetErrorHandler().Sync(p)
_la = p.GetTokenStream().LA(1)
for ok := true; ok; ok = _la == ApiParserParserID {
{
@@ -5575,7 +5570,6 @@ func (p *ApiParserParser) Path() (localctx IPathContext) {
p.EnterOuterAlt(localctx, 1)
p.SetState(341)
p.GetErrorHandler().Sync(p)
_la = p.GetTokenStream().LA(1)
for ok := true; ok; ok = _la == ApiParserParserT__10 || _la == ApiParserParserT__11 {
p.SetState(341)

View File

@@ -9,6 +9,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/ast"
"github.com/tal-tech/go-zero/tools/goctl/util"
)
var (
@@ -118,7 +119,7 @@ func TestApiParser(t *testing.T) {
})
t.Run("nestedImport", func(t *testing.T) {
file := filepath.Join(t.TempDir(), "foo.api")
file := filepath.Join(util.MustTempDir(), "foo.api")
err := ioutil.WriteFile(file, []byte(nestedAPIImport), os.ModePerm)
if err != nil {
return
@@ -148,7 +149,7 @@ func TestApiParser(t *testing.T) {
})
t.Run("ambiguousSyntax", func(t *testing.T) {
file := filepath.Join(t.TempDir(), "foo.api")
file := filepath.Join(util.MustTempDir(), "foo.api")
err := ioutil.WriteFile(file, []byte(ambiguousSyntax), os.ModePerm)
if err != nil {
return
@@ -162,7 +163,7 @@ func TestApiParser(t *testing.T) {
})
t.Run("ambiguousSyntax", func(t *testing.T) {
file := filepath.Join(t.TempDir(), "foo.api")
file := filepath.Join(util.MustTempDir(), "foo.api")
err := ioutil.WriteFile(file, []byte(ambiguousSyntax), os.ModePerm)
if err != nil {
return
@@ -176,7 +177,7 @@ func TestApiParser(t *testing.T) {
})
t.Run("ambiguousService", func(t *testing.T) {
file := filepath.Join(t.TempDir(), "foo.api")
file := filepath.Join(util.MustTempDir(), "foo.api")
err := ioutil.WriteFile(file, []byte(ambiguousService), os.ModePerm)
if err != nil {
return
@@ -206,7 +207,7 @@ func TestApiParser(t *testing.T) {
`)
assert.Error(t, err)
file := filepath.Join(t.TempDir(), "foo.api")
file := filepath.Join(util.MustTempDir(), "foo.api")
err = ioutil.WriteFile(file, []byte(duplicateHandler), os.ModePerm)
if err != nil {
return
@@ -235,7 +236,7 @@ func TestApiParser(t *testing.T) {
`)
assert.Error(t, err)
file := filepath.Join(t.TempDir(), "foo.api")
file := filepath.Join(util.MustTempDir(), "foo.api")
err = ioutil.WriteFile(file, []byte(duplicateRoute), os.ModePerm)
if err != nil {
return
@@ -259,7 +260,7 @@ func TestApiParser(t *testing.T) {
`)
assert.Error(t, err)
file := filepath.Join(t.TempDir(), "foo.api")
file := filepath.Join(util.MustTempDir(), "foo.api")
err = ioutil.WriteFile(file, []byte(duplicateType), os.ModePerm)
if err != nil {
return

View File

@@ -276,7 +276,7 @@ func (p parser) fillService() error {
name := item.ServiceApi.Name.Text()
if len(p.spec.Service.Name) > 0 && p.spec.Service.Name != name {
return fmt.Errorf("mulit service name defined %s and %s", name, p.spec.Service.Name)
return fmt.Errorf("multiple service names defined %s and %s", name, p.spec.Service.Name)
}
p.spec.Service.Name = name
}

View File

@@ -11,7 +11,6 @@ import (
"github.com/logrusorgru/aurora"
"github.com/tal-tech/go-zero/tools/goctl/util"
ctlutil "github.com/tal-tech/go-zero/tools/goctl/util"
"github.com/urfave/cli"
)
@@ -128,7 +127,7 @@ func generateDockerfile(goFile string, port int, args ...string) error {
}
defer out.Close()
text, err := ctlutil.LoadTemplate(category, dockerTemplateFile, dockerTemplate)
text, err := util.LoadTemplate(category, dockerTemplateFile, dockerTemplate)
if err != nil {
return err
}

View File

@@ -3,7 +3,9 @@ package main
import (
"fmt"
"os"
"path/filepath"
"runtime"
"syscall"
"github.com/logrusorgru/aurora"
"github.com/tal-tech/go-zero/core/load"
@@ -29,7 +31,10 @@ import (
rpc "github.com/tal-tech/go-zero/tools/goctl/rpc/cli"
"github.com/tal-tech/go-zero/tools/goctl/tpl"
"github.com/tal-tech/go-zero/tools/goctl/upgrade"
"github.com/tal-tech/go-zero/tools/goctl/util/console"
"github.com/tal-tech/go-zero/tools/goctl/util/env"
"github.com/urfave/cli"
pluginCtl "github.com/zeromicro/protobuf/protoc-gen-go"
)
var commands = []cli.Command{
@@ -57,6 +62,12 @@ var commands = []cli.Command{
Name: "new",
Usage: "fast create api service",
Action: new.CreateServiceCommand,
Flags: []cli.Flag{
cli.StringFlag{
Name: "home",
Usage: "the goctl home path of the template",
},
},
},
{
Name: "format",
@@ -637,6 +648,13 @@ func main() {
load.Disable()
stat.DisableLog()
args := os.Args
pluginName := filepath.Base(args[0])
if pluginName == protocGenGoctl {
pluginCtl.Generate()
return
}
app := cli.NewApp()
app.Usage = "a cli tool to generate code"
app.Version = fmt.Sprintf("%s %s/%s", version.BuildVersion, runtime.GOOS, runtime.GOARCH)
@@ -646,3 +664,33 @@ func main() {
fmt.Println(aurora.Red(errorx.Wrap(err).Error()))
}
}
func init() {
err := linkProtocGenGoctl()
if err != nil {
console.Error("%+v", err)
}
}
const protocGenGoctl = "protoc-gen-goctl"
func linkProtocGenGoctl() error {
path, err := env.LookPath("goctl")
if err != nil {
return err
}
dir := filepath.Dir(path)
ext := filepath.Ext(path)
target := filepath.Join(dir, protocGenGoctl)
if len(ext) > 0 {
target = target + ext
}
err = syscall.Unlink(target)
if err != nil && !os.IsNotExist(err) {
return err
}
return os.Symlink(path, target)
}

View File

@@ -6,7 +6,7 @@ import (
)
// BuildVersion is the version of goctl.
const BuildVersion = "1.2.1"
const BuildVersion = "1.2.2"
// GetGoctlVersion returns BuildVersion
func GetGoctlVersion() string {
@@ -48,7 +48,7 @@ func convertVersion(version string) (versionNumber float64, tag string) {
}
return '_'
}, splits[0])
numberStr = strings.ReplaceAll(numberStr, "_", "")
numberStr = strings.Replace(numberStr, "_", "", -1)
versionNumber, _ = json.Number(numberStr).Float64()
return
}

View File

@@ -7,6 +7,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/tools/goctl/config"
"github.com/tal-tech/go-zero/tools/goctl/util"
)
var testTypes = `
@@ -18,7 +19,7 @@ func TestDo(t *testing.T) {
cfg, err := config.NewConfig(config.DefaultFormat)
assert.Nil(t, err)
tempDir := t.TempDir()
tempDir := util.MustTempDir()
typesfile := filepath.Join(tempDir, "types.go")
err = ioutil.WriteFile(typesfile, []byte(testTypes), 0o666)
assert.Nil(t, err)

View File

@@ -105,13 +105,13 @@ func RawFieldNames(in interface{}, postgresSql ...bool) []string {
fi := typ.Field(i)
if tagv := fi.Tag.Get(dbTag); tagv != "" {
if pg {
out = append(out, fmt.Sprintf("%s", tagv))
out = append(out, tagv)
} else {
out = append(out, fmt.Sprintf("`%s`", tagv))
}
} else {
if pg {
out = append(out, fmt.Sprintf("%s", fi.Name))
out = append(out, fi.Name)
} else {
out = append(out, fmt.Sprintf("`%s`", fi.Name))
}

Some files were not shown because too many files have changed in this diff Show More