Skip to content

Commit

Permalink
Provide APIs to users (#104)
Browse files Browse the repository at this point in the history
  • Loading branch information
Alipebt authored Oct 17, 2023
1 parent 907c044 commit 52d96af
Show file tree
Hide file tree
Showing 47 changed files with 1,529 additions and 9 deletions.
1 change: 1 addition & 0 deletions .github/workflows/plugin-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ jobs:
- mux
- grpc
- irisv12
- trace-activation
steps:
- uses: actions/checkout@v2
with:
Expand Down
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ Release Notes.
0.3.0
------------------
#### Features
* Support manual tracing APIs for users.

#### Plugins
* Support [mux](https://github.com/gorilla/mux) HTTP server framework.
* Support [grpc](https://github.com/grpc/grpc-go) server and client framework.
* Support [iris](https://github.com/kataras/iris) framework.

#### Documentation
* Add `Tracing APIs` document into `Manual APIs`.

#### Bug Fixes

Expand Down
124 changes: 124 additions & 0 deletions docs/en/advanced-features/manual-apis/toolkit-trace.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Tracing APIs

## Add trace Toolkit

toolkit/trace provides the APIs to enhance the trace context, such as createLocalSpan, createExitSpan, createEntrySpan, log, tag, prepareForAsync and asyncFinish.
Add the toolkit dependency to your project.

```go
import "github.com/apache/skywalking-go/toolkit/trace"
```

## Use Native Tracing

### Context Carrier

The context carrier is used to pass the context between the difference application.

When creating an Entry Span, you need to obtain the context carrier from the request. When creating an Exit Span, you need to write the context carrier into the target RPC request.

```go
type ExtractorRef func(headerKey string) (string, error)

type InjectorRef func(headerKey, headerValue string) error
```

### Create Span

Use `trace.CreateEntrySpan()` API to create entry span, and then use `SpanRef` to contain the reference of created span in agent kernel.

- The first parameter is operation name of span
- the second parameter is `InjectorRef`.

```go
spanRef, err := trace.CreateEntrySpan("operationName", InjectorRef)
```

Use `trace.CreateLocalSpan()` API to create local span

- the only parameter is the operation name of span.

```go
spanRef, err := trace.CreateLocalSpan("operationName")
```

Use `trace.CreateExitSpan()` API to create exit span.

- the first parameter is the operation name of span
- the second parameter is the remote peer which means the peer address of exit operation.
- the third parameter is the `ExtractorRef`

```go
spanRef, err := trace.CreateExitSpan("operationName", "peer", ExtractorRef)
```

Use `trace.StopSpan()` API to stop current span

```go
trace.StopSpan()
```

### Add Span’s Tag and Log

Use `trace.SetLog` to record log in span.

Use `trace.SetTag` to add tag to span, the parameters of tag are two String which are key and value respectively.

```go
trace.SetLog(...string)

trace.SetTag("key","value")
```

### Async Prepare/Finish

Use `trace.PrepareAsync()` to make current span still alive until `trace.AsyncFinish()` called.

### Capture/Continue Context Snapshot

1. Use `trace.CaptureContext()` to get tthe segment info and store it in `ContextSnapshotRef`.
2. Propagate the snapshot context to any other goroutine.
3. Use `trace.ContinueContext(snapshotRef)` to load the snapshotRef in the target goroutine.

## Reading Context

All following APIs provide **readonly** features for the tracing context from tracing system. The values are only available when the current thread is traced.

- Use `trace.GetTraceID()` API to get traceID.

```go
traceID := trace.GetTraceID()
```

- Use `trace.GetSegmentID` API to get segmentID.

```go
segmentID := trace.GetSegmentID()
```

- Use `trace.GetSpanID()` API to get spanID.

```go
spanID := trace.GetSpanID()
```

## Trace Correlation Context

Trace correlation context APIs provide a way to put custom data in tracing context. All the data in the context will be propagated with the in-wire process automatically.

Use `trace.SetCorrelation()` API to set custom data in tracing context.

```go
trace.SetCorrelation("key","value")
```

- Max element count in the correlation context is 3
- Max value length of each element is 128

CorrelationContext will remove the key when the value is empty.

Use `trace.GetCorrelation` API to get custom data.

```go
value := trace.GetCorrealtion("key")
```
4 changes: 4 additions & 0 deletions docs/menu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ catalog:
path: /en/agent/plugin-configurations
- name: Transport Layer Security (TLS)
path: /en/advanced-features/grpc-tls
- name: Manual APIs
catalog:
- name: Tracing APIs
path: /en/advanced-features/manual-apis/toolkit-trace.md
- name: Plugins
catalog:
- name: Supported Libraries
Expand Down
3 changes: 3 additions & 0 deletions go.work
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use (
./plugins/mux
./plugins/grpc
./plugins/irisv12
./plugins/trace-activation

./test/benchmark-codebase/consumer
./test/benchmark-codebase/provider
Expand All @@ -41,10 +42,12 @@ use (
./test/plugins/scenarios/mux
./test/plugins/scenarios/grpc
./test/plugins/scenarios/irisv12
./test/plugins/scenarios/trace-activation

./test/plugins/scenarios/plugin_exclusion
./test/plugins/scenarios/runtime_metrics

./tools/go-agent

./toolkit
)
3 changes: 3 additions & 0 deletions plugins/core/operator/tracing.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,7 @@ type TracingOperator interface {
CaptureContext() interface{}
ContinueContext(interface{})
CleanContext()

GetCorrelationContextValue(key string) string
SetCorrelationContextValue(key, val string)
}
2 changes: 2 additions & 0 deletions plugins/core/reporter/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ type SegmentContext interface {
GetSpanID() int32
GetParentSpanID() int32
GetParentSegmentID() string
GetCorrelationContextValue(key string) string
SetCorrelationContextValue(key, value string)
}

// SpanContext defines propagation specification of SkyWalking
Expand Down
11 changes: 11 additions & 0 deletions plugins/core/span_tracing.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,17 @@ func (c *SegmentContext) GetParentSegmentID() string {
return c.ParentSegmentID
}

func (c *SegmentContext) GetCorrelationContextValue(key string) string {
return c.CorrelationContext[key]
}

func (c *SegmentContext) SetCorrelationContextValue(key, value string) {
c.CorrelationContext[key] = value
if value == "" {
delete(c.CorrelationContext, key)
}
}

type SegmentSpan interface {
TracingSpan
GetSegmentContext() SegmentContext
Expand Down
11 changes: 6 additions & 5 deletions plugins/core/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ type Tracer struct {
ServiceEntity *reporter.Entity
Reporter reporter.Reporter
// 0 not init 1 init
initFlag int32
Sampler Sampler
Log *LogWrapper
// correlation *CorrelationConfig // temporarily disable, because haven't been implemented yet
initFlag int32
Sampler Sampler
Log *LogWrapper
correlation *CorrelationConfig
cdsWatchers []reporter.AgentConfigChangeWatcher
// for plugin tools
tools *TracerTools
Expand All @@ -55,7 +55,7 @@ type Tracer struct {
}

func (t *Tracer) Init(entity *reporter.Entity, rep reporter.Reporter, samp Sampler, logger operator.LogOperator,
meterCollectSecond int) error {
meterCollectSecond int, correlation *CorrelationConfig) error {
t.ServiceEntity = entity
t.Reporter = rep
t.Sampler = samp
Expand All @@ -65,6 +65,7 @@ func (t *Tracer) Init(entity *reporter.Entity, rep reporter.Reporter, samp Sampl
t.Reporter.Boot(entity, t.cdsWatchers)
t.initFlag = 1
t.initMetricsCollect(meterCollectSecond)
t.correlation = correlation
// notify the tracer been init success
if len(GetInitNotify()) > 0 {
for _, fun := range GetInitNotify() {
Expand Down
41 changes: 41 additions & 0 deletions plugins/core/tracing.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,47 @@ func (t *Tracer) CleanContext() {
SetGLS(nil)
}

func (t *Tracer) GetCorrelationContextValue(key string) string {
span := t.ActiveSpan()
if span == nil {
return ""
}
switch reportedSpan := span.(type) {
case *SegmentSpanImpl:
return reportedSpan.Context().GetCorrelationContextValue(key)
case *RootSegmentSpan:
return reportedSpan.Context().GetCorrelationContextValue(key)
default:
return ""
}
}

func (t *Tracer) SetCorrelationContextValue(key, value string) {
span := t.ActiveSpan()
if span == nil {
return
}
switch reportedSpan := span.(type) {
case *SegmentSpanImpl:
if len(value) > t.correlation.MaxValueSize {
return
}
if len(reportedSpan.GetSegmentContext().CorrelationContext) >= t.correlation.MaxKeyCount {
return
}
reportedSpan.Context().SetCorrelationContextValue(key, value)
case *RootSegmentSpan:
if len(value) > t.correlation.MaxValueSize {
return
}
if len(reportedSpan.GetSegmentContext().CorrelationContext) >= t.correlation.MaxKeyCount {
return
}
reportedSpan.Context().SetCorrelationContextValue(key, value)
default:
}
}

type ContextSnapshot struct {
activeSpan TracingSpan
runtime *RuntimeContext
Expand Down
17 changes: 17 additions & 0 deletions plugins/core/tracing/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,23 @@ func copyOptsAsInterface(opts []SpanOption) []interface{} {
return optsVal
}

// GetCorrelationContextValue returns the value of the key in the correlation context.
func GetCorrelationContextValue(key string) string {
op := operator.GetOperator()
if op == nil {
return ""
}
return op.Tracing().(operator.TracingOperator).GetCorrelationContextValue(key)
}

// SetRuntimeContextValue sets the value of the key in the correlation context.
func SetCorrelationContextValue(key, val string) {
op := operator.GetOperator()
if op != nil {
op.Tracing().(operator.TracingOperator).SetCorrelationContextValue(key, val)
}
}

type extractorWrapperImpl struct {
extractor Extractor
}
Expand Down
39 changes: 39 additions & 0 deletions plugins/trace-activation/add_log_intercepter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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 traceactivation

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

type AddLogInterceptor struct {
}

func (h *AddLogInterceptor) BeforeInvoke(invocation operator.Invocation) error {
span := tracing.ActiveSpan()
if span != nil {
logs := invocation.Args()[0].([]string)
span.Log(logs...)
}
return nil
}

func (h *AddLogInterceptor) AfterInvoke(invocation operator.Invocation, result ...interface{}) error {
return nil
}
38 changes: 38 additions & 0 deletions plugins/trace-activation/async_finish_intercepter.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 traceactivation

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

type AsyncFinishInterceptor struct {
}

func (h *AsyncFinishInterceptor) BeforeInvoke(invocation operator.Invocation) error {
return nil
}

func (h *AsyncFinishInterceptor) AfterInvoke(invocation operator.Invocation, result ...interface{}) error {
span := tracing.ActiveSpan()
if span != nil {
span.AsyncFinish()
}
return nil
}
Loading

0 comments on commit 52d96af

Please sign in to comment.