Skip to content

Commit

Permalink
Support go-micro framework with v4 version (#46)
Browse files Browse the repository at this point in the history
  • Loading branch information
mrproliu authored May 31, 2023
1 parent 19471c4 commit d7f0680
Show file tree
Hide file tree
Showing 69 changed files with 2,988 additions and 139 deletions.
1 change: 1 addition & 0 deletions .github/workflows/plugin-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ jobs:
- go-restfulv3
- gorm
- kratosv2
- microv4
- plugin_exclusion
steps:
- uses: actions/checkout@v2
Expand Down
1 change: 1 addition & 0 deletions agent/core/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
_ "sync"
_ "sync/atomic"
_ "time"
_ "unsafe"

//go:nolint
_ "github.com/apache/skywalking-go/agent/core/operator"
Expand Down
1 change: 1 addition & 0 deletions docs/en/agent/support-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* RPC Frameworks
* `dubbo`: [Dubbo](https://github.com/apache/dubbo-go)
* `kratosv2`: [Kratos](github.com/go-kratos/kratos)
* `microv4`: [Go-Micro](https://github.com/go-micro/go-micro)
* Database Client
* `gorm`: [GORM](https://github.com/go-gorm/gorm)
* [MySQL Driver](https://github.com/go-gorm/mysql)
20 changes: 20 additions & 0 deletions docs/en/development-and-contribution/development-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,26 @@ Following the previous API define, you should following these steps to use the a
4. Once the above steps are all set, call `span.AsyncFinish()` in any goroutine.
5. When the `span.AsyncFinish()` is complete for all spans, the all spans would be finished and report to the backend.

#### Tracing Context Operation

In the Go Agent, Trace Context would continue cross goroutines automatically by default.
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.

```go
// CaptureContext capture current tracing context in the current goroutine.
func CaptureContext() ContextSnapshot

// ContinueContext continue the tracing context in the current goroutine.
func ContinueContext(ctx ContextSnapshot)

// CleanContext clean the tracing context in the current goroutine.
func CleanContext()
```

Typically, use APIs as following to control or switch the context:
1. Use `tracing.CaptureContext()` to get the ContextSnapshot object.
2. Propagate the snapshot context to any other goroutine in your plugin.
3. Use `tracing.ContinueContext(snapshot)` to continue the snapshot context in the target goroutine.

## Import Plugin

Expand Down
2 changes: 2 additions & 0 deletions go.work
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use (
./plugins/go-restfulv3
./plugins/gorm
./plugins/kratosv2
./plugins/microv4

./test/benchmark-codebase/consumer
./test/benchmark-codebase/provider
Expand All @@ -24,6 +25,7 @@ use (
./test/plugins/scenarios/go-restfulv3
./test/plugins/scenarios/gorm
./test/plugins/scenarios/kratosv2
./test/plugins/scenarios/microv4

./test/plugins/scenarios/plugin_exclusion

Expand Down
866 changes: 856 additions & 10 deletions go.work.sum

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion plugins/core/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ require (
github.com/golang/protobuf v1.5.3 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
golang.org/x/mod v0.9.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect
Expand Down
2 changes: 1 addition & 1 deletion plugins/core/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
Expand Down
1 change: 1 addition & 0 deletions plugins/core/operator/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ var GetOperator = func() Operator { return nil }
type Operator interface {
Tracing() interface{} // to TracingOperator
Logger() interface{} // to LogOperator
Tools() interface{} // to ToolsOperator
DebugStack() []byte // Getting the stack of the current goroutine, for getting details when plugin broken.
Entity() interface{} // Get the entity of the service
}
Expand Down
22 changes: 22 additions & 0 deletions plugins/core/operator/tools.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package operator

type ToolsOperator interface {
ReflectGetValue(instance interface{}, filters []interface{}) interface{}
}
4 changes: 4 additions & 0 deletions plugins/core/operator/tracing.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,8 @@ type TracingOperator interface {

GetRuntimeContextValue(key string) interface{}
SetRuntimeContextValue(key string, value interface{})

CaptureContext() interface{}
ContinueContext(interface{})
CleanContext()
}
1 change: 0 additions & 1 deletion plugins/core/span_default.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,5 +190,4 @@ func (ds *DefaultSpan) AsyncFinish() {
panic("already finished async")
}
ds.AsyncModeFinished = true
ds.AsyncOpLocker = nil
}
24 changes: 12 additions & 12 deletions plugins/core/span_tracing.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,9 @@ func (s *SegmentSpanImpl) End() {
return
}
s.DefaultSpan.End(true)
s.end0()
if !s.DefaultSpan.InAsyncMode {
s.end0()
}
}

func (s *SegmentSpanImpl) AsyncFinish() {
Expand All @@ -111,11 +113,9 @@ func (s *SegmentSpanImpl) AsyncFinish() {
}

func (s *SegmentSpanImpl) end0() {
if !s.DefaultSpan.InAsyncMode || s.DefaultSpan.AsyncModeFinished {
go func() {
s.SegmentContext.collect <- s
}()
}
go func() {
s.SegmentContext.collect <- s
}()
}
func (s *SegmentSpanImpl) GetDefaultSpan() *DefaultSpan {
return &s.DefaultSpan
Expand Down Expand Up @@ -232,7 +232,9 @@ func (rs *RootSegmentSpan) End() {
return
}
rs.DefaultSpan.End(true)
rs.end0()
if !rs.InAsyncMode {
rs.end0()
}
}

func (rs *RootSegmentSpan) AsyncFinish() {
Expand All @@ -242,11 +244,9 @@ func (rs *RootSegmentSpan) AsyncFinish() {
}

func (rs *RootSegmentSpan) end0() {
if !rs.InAsyncMode || rs.AsyncModeFinished {
go func() {
rs.doneCh <- atomic.SwapInt32(rs.SegmentContext.refNum, -1)
}()
}
go func() {
rs.doneCh <- atomic.SwapInt32(rs.SegmentContext.refNum, -1)
}()
}

func (rs *RootSegmentSpan) createRootSegmentContext(ctx *TracingContext, _ SegmentSpan) (err error) {
Expand Down
58 changes: 58 additions & 0 deletions plugins/core/tools/reflect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package tools

import "github.com/apache/skywalking-go/plugins/core/operator"

type ReflectFieldFilter interface {
Apply(interface{})
}

// GetInstanceValueByType using reflect to get the first value of instance by type
func GetInstanceValueByType(instance interface{}, filters ...ReflectFieldFilter) interface{} {
if instance == nil || len(filters) == 0 {
return nil
}
op := operator.GetOperator()
if op == nil {
return nil
}
fs := make([]interface{}, len(filters))
for i, f := range filters {
fs[i] = f
}
return op.Tools().(operator.ToolsOperator).ReflectGetValue(instance, fs)
}

func WithFieldName(name string) ReflectFieldFilter {
return buildFieldFilterOption(func(s ReflectFieldFilterSetter) {
s.SetName(name)
})
}

func WithInterfaceType(typeVal interface{}) ReflectFieldFilter {
return buildFieldFilterOption(func(s ReflectFieldFilterSetter) {
s.SetInterfaceType(typeVal)
})
}

func WithType(typeVal interface{}) ReflectFieldFilter {
return buildFieldFilterOption(func(s ReflectFieldFilterSetter) {
s.SetType(typeVal)
})
}
38 changes: 38 additions & 0 deletions plugins/core/tools/reflect_bridge.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Apache Software Foundation (ASF) licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package tools

type ReflectFieldFilterSetter interface {
SetName(string)
SetInterfaceType(interface{})
SetType(interface{})
}

type fieldFilterImpl struct {
exe func(s ReflectFieldFilterSetter)
}

func (s *fieldFilterImpl) Apply(span interface{}) {
if setter, ok := span.(ReflectFieldFilterSetter); ok {
s.exe(setter)
}
}

func buildFieldFilterOption(e func(s ReflectFieldFilterSetter)) ReflectFieldFilter {
return &fieldFilterImpl{exe: e}
}
7 changes: 7 additions & 0 deletions plugins/core/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ type Tracer struct {
Log *LogWrapper
// correlation *CorrelationConfig // temporarily disable, because haven't been implemented yet
cdsWatchers []reporter.AgentConfigChangeWatcher
// for plugin tools
tools *TracerTools
}

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

func (t *Tracer) Tools() interface{} {
return t.tools
}

func NewEntity(service, instanceEnvName string) *reporter.Entity {
instanceName := os.Getenv(instanceEnvName)
if instanceName == "" {
Expand All @@ -88,6 +94,7 @@ func newTracer() *Tracer {
Sampler: NewConstSampler(false),
Log: &LogWrapper{newDefaultLogger()},
cdsWatchers: make([]reporter.AgentConfigChangeWatcher, 0),
tools: NewTracerTools(),
}
}

Expand Down
Loading

0 comments on commit d7f0680

Please sign in to comment.