Skip to content

Commit d7f0680

Browse files
authored
Support go-micro framework with v4 version (#46)
1 parent 19471c4 commit d7f0680

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+2988
-139
lines changed

.github/workflows/plugin-tests.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ jobs:
6262
- go-restfulv3
6363
- gorm
6464
- kratosv2
65+
- microv4
6566
- plugin_exclusion
6667
steps:
6768
- uses: actions/checkout@v2

agent/core/compile.go

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
_ "sync"
3535
_ "sync/atomic"
3636
_ "time"
37+
_ "unsafe"
3738

3839
//go:nolint
3940
_ "github.com/apache/skywalking-go/agent/core/operator"

docs/en/agent/support-plugins.md

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* RPC Frameworks
1010
* `dubbo`: [Dubbo](https://github.com/apache/dubbo-go)
1111
* `kratosv2`: [Kratos](github.com/go-kratos/kratos)
12+
* `microv4`: [Go-Micro](https://github.com/go-micro/go-micro)
1213
* Database Client
1314
* `gorm`: [GORM](https://github.com/go-gorm/gorm)
1415
* [MySQL Driver](https://github.com/go-gorm/mysql)

docs/en/development-and-contribution/development-guide.md

+20
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,26 @@ Following the previous API define, you should following these steps to use the a
387387
4. Once the above steps are all set, call `span.AsyncFinish()` in any goroutine.
388388
5. When the `span.AsyncFinish()` is complete for all spans, the all spans would be finished and report to the backend.
389389

390+
#### Tracing Context Operation
391+
392+
In the Go Agent, Trace Context would continue cross goroutines automatically by default.
393+
However, in some cases, goroutine would be context sharing due to be scheduled by the pool mechanism. Consider these advanced APIs to manipulate context and switch the current context.
394+
395+
```go
396+
// CaptureContext capture current tracing context in the current goroutine.
397+
func CaptureContext() ContextSnapshot
398+
399+
// ContinueContext continue the tracing context in the current goroutine.
400+
func ContinueContext(ctx ContextSnapshot)
401+
402+
// CleanContext clean the tracing context in the current goroutine.
403+
func CleanContext()
404+
```
405+
406+
Typically, use APIs as following to control or switch the context:
407+
1. Use `tracing.CaptureContext()` to get the ContextSnapshot object.
408+
2. Propagate the snapshot context to any other goroutine in your plugin.
409+
3. Use `tracing.ContinueContext(snapshot)` to continue the snapshot context in the target goroutine.
390410

391411
## Import Plugin
392412

go.work

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use (
1111
./plugins/go-restfulv3
1212
./plugins/gorm
1313
./plugins/kratosv2
14+
./plugins/microv4
1415

1516
./test/benchmark-codebase/consumer
1617
./test/benchmark-codebase/provider
@@ -24,6 +25,7 @@ use (
2425
./test/plugins/scenarios/go-restfulv3
2526
./test/plugins/scenarios/gorm
2627
./test/plugins/scenarios/kratosv2
28+
./test/plugins/scenarios/microv4
2729

2830
./test/plugins/scenarios/plugin_exclusion
2931

go.work.sum

+856-10
Large diffs are not rendered by default.

plugins/core/go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ require (
1616
github.com/golang/protobuf v1.5.3 // indirect
1717
github.com/kr/pretty v0.3.0 // indirect
1818
github.com/pmezard/go-difflib v1.0.0 // indirect
19-
github.com/rogpeppe/go-internal v1.9.0 // indirect
19+
github.com/rogpeppe/go-internal v1.10.0 // indirect
2020
golang.org/x/mod v0.9.0 // indirect
2121
golang.org/x/net v0.10.0 // indirect
2222
golang.org/x/sys v0.8.0 // indirect

plugins/core/go.sum

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
6868
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
6969
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
7070
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
71-
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
71+
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
7272
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
7373
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
7474
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=

plugins/core/operator/common.go

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ var GetOperator = func() Operator { return nil }
2222
type Operator interface {
2323
Tracing() interface{} // to TracingOperator
2424
Logger() interface{} // to LogOperator
25+
Tools() interface{} // to ToolsOperator
2526
DebugStack() []byte // Getting the stack of the current goroutine, for getting details when plugin broken.
2627
Entity() interface{} // Get the entity of the service
2728
}

plugins/core/operator/tools.go

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Licensed to Apache Software Foundation (ASF) under one or more contributor
2+
// license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright
4+
// ownership. Apache Software Foundation (ASF) licenses this file to you under
5+
// the Apache License, Version 2.0 (the "License"); you may
6+
// not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package operator
19+
20+
type ToolsOperator interface {
21+
ReflectGetValue(instance interface{}, filters []interface{}) interface{}
22+
}

plugins/core/operator/tracing.go

+4
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,8 @@ type TracingOperator interface {
2525

2626
GetRuntimeContextValue(key string) interface{}
2727
SetRuntimeContextValue(key string, value interface{})
28+
29+
CaptureContext() interface{}
30+
ContinueContext(interface{})
31+
CleanContext()
2832
}

plugins/core/span_default.go

-1
Original file line numberDiff line numberDiff line change
@@ -190,5 +190,4 @@ func (ds *DefaultSpan) AsyncFinish() {
190190
panic("already finished async")
191191
}
192192
ds.AsyncModeFinished = true
193-
ds.AsyncOpLocker = nil
194193
}

plugins/core/span_tracing.go

+12-12
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,9 @@ func (s *SegmentSpanImpl) End() {
101101
return
102102
}
103103
s.DefaultSpan.End(true)
104-
s.end0()
104+
if !s.DefaultSpan.InAsyncMode {
105+
s.end0()
106+
}
105107
}
106108

107109
func (s *SegmentSpanImpl) AsyncFinish() {
@@ -111,11 +113,9 @@ func (s *SegmentSpanImpl) AsyncFinish() {
111113
}
112114

113115
func (s *SegmentSpanImpl) end0() {
114-
if !s.DefaultSpan.InAsyncMode || s.DefaultSpan.AsyncModeFinished {
115-
go func() {
116-
s.SegmentContext.collect <- s
117-
}()
118-
}
116+
go func() {
117+
s.SegmentContext.collect <- s
118+
}()
119119
}
120120
func (s *SegmentSpanImpl) GetDefaultSpan() *DefaultSpan {
121121
return &s.DefaultSpan
@@ -232,7 +232,9 @@ func (rs *RootSegmentSpan) End() {
232232
return
233233
}
234234
rs.DefaultSpan.End(true)
235-
rs.end0()
235+
if !rs.InAsyncMode {
236+
rs.end0()
237+
}
236238
}
237239

238240
func (rs *RootSegmentSpan) AsyncFinish() {
@@ -242,11 +244,9 @@ func (rs *RootSegmentSpan) AsyncFinish() {
242244
}
243245

244246
func (rs *RootSegmentSpan) end0() {
245-
if !rs.InAsyncMode || rs.AsyncModeFinished {
246-
go func() {
247-
rs.doneCh <- atomic.SwapInt32(rs.SegmentContext.refNum, -1)
248-
}()
249-
}
247+
go func() {
248+
rs.doneCh <- atomic.SwapInt32(rs.SegmentContext.refNum, -1)
249+
}()
250250
}
251251

252252
func (rs *RootSegmentSpan) createRootSegmentContext(ctx *TracingContext, _ SegmentSpan) (err error) {

plugins/core/tools/reflect.go

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Licensed to Apache Software Foundation (ASF) under one or more contributor
2+
// license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright
4+
// ownership. Apache Software Foundation (ASF) licenses this file to you under
5+
// the Apache License, Version 2.0 (the "License"); you may
6+
// not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package tools
19+
20+
import "github.com/apache/skywalking-go/plugins/core/operator"
21+
22+
type ReflectFieldFilter interface {
23+
Apply(interface{})
24+
}
25+
26+
// GetInstanceValueByType using reflect to get the first value of instance by type
27+
func GetInstanceValueByType(instance interface{}, filters ...ReflectFieldFilter) interface{} {
28+
if instance == nil || len(filters) == 0 {
29+
return nil
30+
}
31+
op := operator.GetOperator()
32+
if op == nil {
33+
return nil
34+
}
35+
fs := make([]interface{}, len(filters))
36+
for i, f := range filters {
37+
fs[i] = f
38+
}
39+
return op.Tools().(operator.ToolsOperator).ReflectGetValue(instance, fs)
40+
}
41+
42+
func WithFieldName(name string) ReflectFieldFilter {
43+
return buildFieldFilterOption(func(s ReflectFieldFilterSetter) {
44+
s.SetName(name)
45+
})
46+
}
47+
48+
func WithInterfaceType(typeVal interface{}) ReflectFieldFilter {
49+
return buildFieldFilterOption(func(s ReflectFieldFilterSetter) {
50+
s.SetInterfaceType(typeVal)
51+
})
52+
}
53+
54+
func WithType(typeVal interface{}) ReflectFieldFilter {
55+
return buildFieldFilterOption(func(s ReflectFieldFilterSetter) {
56+
s.SetType(typeVal)
57+
})
58+
}

plugins/core/tools/reflect_bridge.go

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Licensed to Apache Software Foundation (ASF) under one or more contributor
2+
// license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright
4+
// ownership. Apache Software Foundation (ASF) licenses this file to you under
5+
// the Apache License, Version 2.0 (the "License"); you may
6+
// not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
package tools
19+
20+
type ReflectFieldFilterSetter interface {
21+
SetName(string)
22+
SetInterfaceType(interface{})
23+
SetType(interface{})
24+
}
25+
26+
type fieldFilterImpl struct {
27+
exe func(s ReflectFieldFilterSetter)
28+
}
29+
30+
func (s *fieldFilterImpl) Apply(span interface{}) {
31+
if setter, ok := span.(ReflectFieldFilterSetter); ok {
32+
s.exe(setter)
33+
}
34+
}
35+
36+
func buildFieldFilterOption(e func(s ReflectFieldFilterSetter)) ReflectFieldFilter {
37+
return &fieldFilterImpl{exe: e}
38+
}

plugins/core/tracer.go

+7
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ type Tracer struct {
4444
Log *LogWrapper
4545
// correlation *CorrelationConfig // temporarily disable, because haven't been implemented yet
4646
cdsWatchers []reporter.AgentConfigChangeWatcher
47+
// for plugin tools
48+
tools *TracerTools
4749
}
4850

4951
func (t *Tracer) Init(entity *reporter.Entity, rep reporter.Reporter, samp Sampler, logger operator.LogOperator) error {
@@ -62,6 +64,10 @@ func (t *Tracer) Entity() interface{} {
6264
return t.ServiceEntity
6365
}
6466

67+
func (t *Tracer) Tools() interface{} {
68+
return t.tools
69+
}
70+
6571
func NewEntity(service, instanceEnvName string) *reporter.Entity {
6672
instanceName := os.Getenv(instanceEnvName)
6773
if instanceName == "" {
@@ -88,6 +94,7 @@ func newTracer() *Tracer {
8894
Sampler: NewConstSampler(false),
8995
Log: &LogWrapper{newDefaultLogger()},
9096
cdsWatchers: make([]reporter.AgentConfigChangeWatcher, 0),
97+
tools: NewTracerTools(),
9198
}
9299
}
93100

0 commit comments

Comments
 (0)