mirror of
https://github.com/zeromicro/go-zero.git
synced 2026-05-11 08:50:00 +08:00
Compare commits
54 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a8638fc85 | ||
|
|
837a9ffa03 | ||
|
|
d28cfe5f20 | ||
|
|
022c100dc9 | ||
|
|
426b09c356 | ||
|
|
40dc21e4cf | ||
|
|
9b114e3251 | ||
|
|
4c6234f108 | ||
|
|
3cdfcb05f1 | ||
|
|
9f5bfa0088 | ||
|
|
2d42c8fa00 | ||
|
|
10e7922597 | ||
|
|
6e34b55ba7 | ||
|
|
ed15ca04f4 | ||
|
|
295ec27e1b | ||
|
|
d1e702e8a3 | ||
|
|
d1bfb5ef61 | ||
|
|
e43357164c | ||
|
|
cd21c9fa74 | ||
|
|
cdd2fcbbc9 | ||
|
|
8d2db09d45 | ||
|
|
65905b914d | ||
|
|
80e3407be1 | ||
|
|
657d27213a | ||
|
|
8ac18a9422 | ||
|
|
d3ae9cfd49 | ||
|
|
d7f42161fd | ||
|
|
e03229cabe | ||
|
|
8403ed16ae | ||
|
|
d87d203c3b | ||
|
|
3ae6a882a7 | ||
|
|
41c980f00c | ||
|
|
f34d81ca2c | ||
|
|
004ee488a6 | ||
|
|
2e12cd2c99 | ||
|
|
2695c30886 | ||
|
|
c74fb988e0 | ||
|
|
e8a340c1c0 | ||
|
|
06e114e5a3 | ||
|
|
74ad681a66 | ||
|
|
e7bbc09093 | ||
|
|
1eb1450c43 | ||
|
|
9a724fe907 | ||
|
|
30e49f2939 | ||
|
|
a5407479a6 | ||
|
|
7fb5bab26b | ||
|
|
27249e021f | ||
|
|
d809795fec | ||
|
|
c9db9588b7 | ||
|
|
872c50b71a | ||
|
|
7c83155e4f | ||
|
|
358d86b8ae | ||
|
|
f4bb9f5635 | ||
|
|
5c6a3132eb |
40
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
40
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal 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.
|
||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal 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
10
.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
---
|
||||
name: Question
|
||||
about: Ask a question on using go-zero or goctl
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
|
||||
6
.github/workflows/go.yml
vendored
6
.github/workflows/go.yml
vendored
@@ -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
19
.github/workflows/reviewdog.yml
vendored
Normal 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
3
.gitignore
vendored
@@ -15,9 +15,6 @@
|
||||
**/.DS_Store
|
||||
**/logs
|
||||
|
||||
# ignore adhoc test code
|
||||
**/adhoc
|
||||
|
||||
# gitlab ci
|
||||
.cache
|
||||
|
||||
|
||||
21
ROADMAP.md
21
ROADMAP.md
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build linux || darwin
|
||||
// +build linux darwin
|
||||
|
||||
package fs
|
||||
|
||||
@@ -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
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 ""
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build linux || darwin
|
||||
// +build linux darwin
|
||||
|
||||
package proc
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build debug
|
||||
// +build debug
|
||||
|
||||
package search
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package stat
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package stat
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package internal
|
||||
|
||||
2
core/stores/cache/cachenode_test.go
vendored
2
core/stores/cache/cachenode_test.go
vendored
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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'")
|
||||
|
||||
@@ -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++ {
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
69
core/trace/agent.go
Normal 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)
|
||||
}))
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package opentelemetry
|
||||
package trace
|
||||
|
||||
import (
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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"))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -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"`
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package trace
|
||||
|
||||
const (
|
||||
// TraceIdKey is the trace id header.
|
||||
TraceIdKey = "X-Trace-ID"
|
||||
|
||||
spanIdKey = "X-Span-ID"
|
||||
)
|
||||
@@ -1,4 +1,4 @@
|
||||
package opentelemetry
|
||||
package trace
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -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) {
|
||||
}
|
||||
@@ -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())
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package opentelemetry
|
||||
package trace
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -1,4 +1,4 @@
|
||||
package opentelemetry
|
||||
package trace
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package opentelemetry
|
||||
package trace
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -1,4 +1,4 @@
|
||||
package opentelemetry
|
||||
package trace
|
||||
|
||||
import (
|
||||
"testing"
|
||||
8
core/trace/vars.go
Normal file
8
core/trace/vars.go
Normal 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
22
go.mod
@@ -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
67
go.sum
@@ -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=
|
||||
|
||||
51
readme-cn.md
51
readme-cn.md
@@ -4,16 +4,18 @@
|
||||
|
||||
[English](readme.md) | 简体中文
|
||||
|
||||
[](https://github.com/tal-tech/go-zero/actions)
|
||||
[](https://goreportcard.com/report/github.com/tal-tech/go-zero)
|
||||
[](https://github.com/zeromicro/go-zero/actions)
|
||||
[](https://goreportcard.com/report/github.com/zeromicro/go-zero)
|
||||
[](https://goproxy.cn/stats/github.com/tal-tech/go-zero/badges/download-count.svg)
|
||||
[](https://codecov.io/gh/tal-tech/go-zero)
|
||||
[](https://github.com/tal-tech/go-zero)
|
||||
[](https://codecov.io/gh/zeromicro/go-zero)
|
||||
[](https://github.com/zeromicro/go-zero)
|
||||
[](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,可以根据定义的
|
||||
* 自动校验客户端请求参数合法性
|
||||
* 大量微服务治理和并发工具包
|
||||
|
||||

|
||||

|
||||
|
||||
## 1. go-zero 框架背景
|
||||
|
||||
@@ -76,7 +78,7 @@ go-zero 是一个集成了各种工程实践的包含 web 和 rpc 框架,有
|
||||
|
||||
如下图,我们从多个层面保障了整体服务的高可用:
|
||||
|
||||

|
||||

|
||||
|
||||
觉得不错的话,别忘 **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
|
||||
|
||||

|
||||

|
||||
|
||||
[测试代码见这里](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"/>
|
||||
<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" />
|
||||
|
||||
37
readme.md
37
readme.md
@@ -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)
|
||||
|
||||
[](https://github.com/tal-tech/go-zero/actions)
|
||||
[](https://codecov.io/gh/tal-tech/go-zero)
|
||||
[](https://goreportcard.com/report/github.com/tal-tech/go-zero)
|
||||
[](https://github.com/tal-tech/go-zero)
|
||||
[](https://github.com/zeromicro/go-zero/actions)
|
||||
[](https://codecov.io/gh/zeromicro/go-zero)
|
||||
[](https://goreportcard.com/report/github.com/zeromicro/go-zero)
|
||||
[](https://github.com/zeromicro/go-zero)
|
||||
[](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. It’s 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. It’s 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:
|
||||
|
||||

|
||||

|
||||
|
||||
## 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
|
||||
|
||||

|
||||

|
||||
|
||||
[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"/>
|
||||
<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!
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
# 2020-01-08
|
||||
|
||||
## features 
|
||||
|
||||
* 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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
51
tools/goctl/api/new/template.go
Normal file
51
tools/goctl/api/new/template.go
Normal 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)
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user