Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/HubQin/dubbo-go
Browse files Browse the repository at this point in the history
  • Loading branch information
HubQin committed Aug 29, 2023
2 parents 5d9dfdb + 25d3813 commit 2a59627
Show file tree
Hide file tree
Showing 25 changed files with 977 additions and 369 deletions.
17 changes: 4 additions & 13 deletions filter/otel/trace/version.go → common/constant/otel.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,9 @@
* limitations under the License.
*/

package trace
package constant

import (
"dubbo.apache.org/dubbo-go/v3/common/constant"
const (
OtelPackageName = "go.opentelemetry.io/otel"
OtelPackageVersion = "v1.10.0"
)

// Version is the current release version of the dubbogo instrumentation.
func Version() string {
return constant.Version
}

// SemVersion is the semantic version to be supplied to tracer/meter creation.
func SemVersion() string {
return "semver:" + Version()
}
58 changes: 58 additions & 0 deletions common/extension/otel_trace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Licensed to the 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.
* The 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 extension

import (
"context"
)

import (
"dubbo.apache.org/dubbo-go/v3/otel/trace"
)

import (
"github.com/dubbogo/gost/log/logger"
)

var traceExporterMap = make(map[string]func(config *trace.ExporterConfig) (trace.Exporter, error), 4)

func SetTraceExporter(name string, createFunc func(config *trace.ExporterConfig) (trace.Exporter, error)) {
traceExporterMap[name] = createFunc
}

func GetTraceExporter(name string, config *trace.ExporterConfig) (trace.Exporter, error) {
createFunc, ok := traceExporterMap[name]
if !ok {
panic("Cannot find the trace provider with name " + name)
}
return createFunc(config)
}

func GetTraceShutdownCallback() func() {
return func() {
for name, createFunc := range traceExporterMap {
if exporter, err := createFunc(nil); err == nil {
if err := exporter.GetTracerProvider().Shutdown(context.Background()); err != nil {
logger.Errorf("Graceful shutdown --- Failed to shutdown trace provider %s, error: %s", name, err.Error())
} else {
logger.Infof("Graceful shutdown --- Tracer provider of %s", name)
}
}
}
}
}
3 changes: 3 additions & 0 deletions common/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,9 @@ func NewURL(urlString string, opts ...Option) (*URL, error) {
for _, opt := range opts {
opt(&s)
}
if s.params.Get(constant.RegistryGroupKey) != "" {
s.PrimitiveURL = strings.Join([]string{s.PrimitiveURL, s.params.Get(constant.RegistryGroupKey)}, constant.PathSeparator)
}
return &s, nil
}

Expand Down
115 changes: 115 additions & 0 deletions config/otel_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Licensed to the 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.
* The 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 config

import (
"github.com/creasty/defaults"
"github.com/dubbogo/gost/log/logger"
"github.com/pkg/errors"
"go.opentelemetry.io/otel"
)

import (
"dubbo.apache.org/dubbo-go/v3/common/extension"
"dubbo.apache.org/dubbo-go/v3/otel/trace"
)

type OtelConfig struct {
TraceConfig *OtelTraceConfig `yaml:"trace" json:"trace,omitempty" property:"trace"`
}

type OtelTraceConfig struct {
Enable *bool `default:"false" yaml:"enable" json:"enable,omitempty" property:"enable"`
Exporter string `default:"stdout" yaml:"exporter" json:"exporter,omitempty" property:"exporter"` // stdout, jaeger, zipkin, otlp-http, otlp-grpc
Endpoint string `default:"" yaml:"endpoint" json:"endpoint,omitempty" property:"endpoint"`
Propagator string `default:"w3c" yaml:"propagator" json:"propagator,omitempty" property:"propagator"` // one of w3c(standard), b3(for zipkin),
SampleMode string `default:"ratio" yaml:"sample-mode" json:"sample-mode,omitempty" property:"sample-mode"` // one of always, never, ratio
SampleRatio float64 `default:"0.5" yaml:"sample-ratio" json:"sample-ratio,omitempty" property:"sample-ratio"` // [0.0, 1.0]
}

func (oc *OtelConfig) Init(appConfig *ApplicationConfig) error {
if oc == nil {
return errors.New("otel config is nil")
}
if err := defaults.Set(oc); err != nil {
return err
}
if err := verify(oc); err != nil {
return err
}
if *oc.TraceConfig.Enable {
extension.AddCustomShutdownCallback(extension.GetTraceShutdownCallback())
return oc.TraceConfig.init(appConfig)
}

return nil
}

func (c *OtelTraceConfig) init(appConfig *ApplicationConfig) error {
exporter, err := extension.GetTraceExporter(c.Exporter, c.toTraceProviderConfig(appConfig))
if err != nil {
return err
}
otel.SetTracerProvider(exporter.GetTracerProvider())
otel.SetTextMapPropagator(exporter.GetPropagator())

// print trace exporter configuration
if c.Exporter == "stdout" {
logger.Infof("enable %s trace provider with propagator: %s", c.Exporter, c.Propagator)
} else {
logger.Infof("enable %s trace provider with endpoint: %s, propagator: %s", c.Exporter, c.Endpoint, c.Propagator)
}
logger.Infof("sample mode: %s", c.SampleMode)
if c.SampleMode == "ratio" {
logger.Infof("sample ratio: %.2f", c.SampleRatio)
}

return nil
}

func (c *OtelTraceConfig) toTraceProviderConfig(a *ApplicationConfig) *trace.ExporterConfig {
tpc := &trace.ExporterConfig{
Exporter: c.Exporter,
Endpoint: c.Endpoint,
SampleMode: c.SampleMode,
SampleRatio: c.SampleRatio,
Propagator: c.Propagator,
ServiceNamespace: a.Organization,
ServiceName: a.Name,
ServiceVersion: a.Version,
}
return tpc
}

type OtelConfigBuilder struct {
otelConfig *OtelConfig
}

func NewOtelConfigBuilder() *OtelConfigBuilder {
return &OtelConfigBuilder{
otelConfig: &OtelConfig{
TraceConfig: &OtelTraceConfig{},
},
}
}

func (ocb *OtelConfigBuilder) Build() *OtelConfig {
return ocb.otelConfig
}

// TODO: dynamic config
46 changes: 11 additions & 35 deletions filter/otel/trace/version_test.go → config/otel_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,49 +15,25 @@
* limitations under the License.
*/

package trace
package config

import (
"testing"
)

import (
"dubbo.apache.org/dubbo-go/v3/common/constant"
"github.com/stretchr/testify/assert"
)

type filed struct {
name string
want string
}
func TestNewOtelConfigBuilder(t *testing.T) {
config := NewOtelConfigBuilder().Build()
assert.NotNil(t, config)
assert.NotNil(t, config.TraceConfig)

func TestSemVersion(t *testing.T) {
tests := []filed{
{
name: "test",
want: "semver:" + constant.Version,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := SemVersion(); got != tt.want {
t.Errorf("SemVersion() = %v, want %v", got, tt.want)
}
})
}
}
ac := NewApplicationConfigBuilder().Build()
err := config.Init(ac)
assert.NoError(t, err)

func TestVersion(t *testing.T) {
tests := []filed{
{
name: "test",
want: constant.Version,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Version(); got != tt.want {
t.Errorf("Version() = %v, want %v", got, tt.want)
}
})
}
tpc := config.TraceConfig.toTraceProviderConfig(ac)
assert.NotNil(t, tpc)
}
3 changes: 3 additions & 0 deletions config/registry_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ func TestLoadRegistries(t *testing.T) {
urls := loadRegistries(target, regs, common.CONSUMER)
t.Logf("loadRegistries() = urls:%v", urls)
assert.Equal(t, "127.0.0.2:2181,128.0.0.1:2181", urls[0].Location)
assert.Equal(t, "service-discovery-registry://127.0.0.2:2181,128.0.0.1:2181/shanghai_idc", urls[0].PrimitiveURL)
}

func TestLoadRegistries1(t *testing.T) {
Expand All @@ -64,6 +65,7 @@ func TestLoadRegistries1(t *testing.T) {
urls := loadRegistries(target, regs, common.CONSUMER)
t.Logf("loadRegistries() = urls:%v", urls)
assert.Equal(t, "127.0.0.2:2181", urls[0].Location)
assert.Equal(t, "service-discovery-registry://127.0.0.2:2181/shanghai_idc", urls[0].PrimitiveURL)
}

func TestRegistryTypeAll(t *testing.T) {
Expand All @@ -77,6 +79,7 @@ func TestRegistryTypeAll(t *testing.T) {
}
urls := loadRegistries(target, regs, common.PROVIDER)
assert.Equal(t, 2, len(urls))
assert.Equal(t, "service-discovery-registry://127.0.0.2:2181", urls[0].PrimitiveURL)
}

func TestTranslateRegistryAddress(t *testing.T) {
Expand Down
10 changes: 10 additions & 0 deletions config/root_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ type RootConfig struct {
MetadataReport *MetadataReportConfig `yaml:"metadata-report" json:"metadata-report,omitempty" property:"metadata-report"`
Provider *ProviderConfig `yaml:"provider" json:"provider" property:"provider"`
Consumer *ConsumerConfig `yaml:"consumer" json:"consumer" property:"consumer"`
Otel *OtelConfig `yaml:"otel" json:"otel,omitempty" property:"otel"`
Metric *MetricConfig `yaml:"metrics" json:"metrics,omitempty" property:"metrics"`
Tracing map[string]*TracingConfig `yaml:"tracing" json:"tracing,omitempty" property:"tracing"`
Logger *LoggerConfig `yaml:"logger" json:"logger,omitempty" property:"logger"`
Expand Down Expand Up @@ -178,6 +179,9 @@ func (rc *RootConfig) Init() error {
if err := rc.MetadataReport.Init(rc); err != nil {
return err
}
if err := rc.Otel.Init(rc.Application); err != nil {
return err
}
if err := rc.Metric.Init(); err != nil {
return err
}
Expand Down Expand Up @@ -227,6 +231,7 @@ func newEmptyRootConfig() *RootConfig {
Tracing: make(map[string]*TracingConfig),
Provider: NewProviderConfigBuilder().Build(),
Consumer: NewConsumerConfigBuilder().Build(),
Otel: NewOtelConfigBuilder().Build(),
Metric: NewMetricConfigBuilder().Build(),
Logger: NewLoggerConfigBuilder().Build(),
Custom: NewCustomConfigBuilder().Build(),
Expand Down Expand Up @@ -284,6 +289,11 @@ func (rb *RootConfigBuilder) SetConsumer(consumer *ConsumerConfig) *RootConfigBu
return rb
}

func (rb *RootConfigBuilder) SetOtel(otel *OtelConfig) *RootConfigBuilder {
rb.rootConfig.Otel = otel
return rb
}

func (rb *RootConfigBuilder) SetMetric(metric *MetricConfig) *RootConfigBuilder {
rb.rootConfig.Metric = metric
return rb
Expand Down
2 changes: 1 addition & 1 deletion filter/otel/trace/attachment.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ func Inject(ctx context.Context, metadata map[string]interface{}, propagators pr
})
}

// Extract returns the correlation context and span context that
// Extract returns the baggage and span context that
// another service encoded in the dubbo metadata object with Inject.
// This function is meant to be used on incoming requests.
func Extract(ctx context.Context, metadata map[string]interface{}, propagators propagation.TextMapPropagator) (baggage.Baggage, trace.SpanContext) {
Expand Down
13 changes: 5 additions & 8 deletions filter/otel/trace/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,8 @@ import (
"dubbo.apache.org/dubbo-go/v3/protocol"
)

const (
instrumentationName = "dubbo.apache.org/dubbo-go/v3/oteldubbo"
)

func init() {
// TODO: use single filter to simplify filter field in configuration
extension.SetFilter(constant.OTELServerTraceKey, func() filter.Filter {
return &otelServerFilter{
Propagators: otel.GetTextMapPropagator(),
Expand Down Expand Up @@ -71,8 +68,8 @@ func (f *otelServerFilter) Invoke(ctx context.Context, invoker protocol.Invoker,
ctx = baggage.ContextWithBaggage(ctx, bags)

tracer := f.TracerProvider.Tracer(
instrumentationName,
trace.WithInstrumentationVersion(SemVersion()),
constant.OtelPackageName,
trace.WithInstrumentationVersion(constant.OtelPackageVersion),
)

ctx, span := tracer.Start(
Expand Down Expand Up @@ -108,8 +105,8 @@ func (f *otelClientFilter) OnResponse(ctx context.Context, result protocol.Resul

func (f *otelClientFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
tracer := f.TracerProvider.Tracer(
instrumentationName,
trace.WithInstrumentationVersion(SemVersion()),
constant.OtelPackageName,
trace.WithInstrumentationVersion(constant.OtelPackageVersion),
)

var span trace.Span
Expand Down
Loading

0 comments on commit 2a59627

Please sign in to comment.