pkg/rules/gomicro/gomicro_service_otel_instrumenter.go (115 lines of code) (raw):
// Copyright (c) 2025 Alibaba Group Holding Ltd.
//
// Licensed 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 gomicro
import (
"github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/inst-api-semconv/instrumenter/http"
"github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/inst-api-semconv/instrumenter/net"
"github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/inst-api/instrumenter"
"github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/inst-api/utils"
"github.com/alibaba/opentelemetry-go-auto-instrumentation/pkg/inst-api/version"
"go-micro.dev/v5/metadata"
"go.opentelemetry.io/otel/sdk/instrumentation"
)
type goMicroHttpClientAttrsGetter struct {
}
func (n goMicroHttpClientAttrsGetter) GetRequestMethod(request goMicroRequest) string {
switch request.reqType {
case CallRequest:
return request.request.Method()
case StreamRequest:
return request.request.Method()
case MessageRequest:
return "pub"
}
return ""
}
func (n goMicroHttpClientAttrsGetter) GetHttpRequestHeader(request goMicroRequest, name string) []string {
all := make([]string, 0)
md, ok := metadata.FromContext(request.ctx)
if ok {
value, ok := md.Get(name)
if ok {
all = append(all, string(value))
}
}
return all
}
func (n goMicroHttpClientAttrsGetter) GetHttpResponseStatusCode(request goMicroRequest, response goMicroResponse, err error) int {
if response.err != nil {
return 500
}
return 200
}
func (n goMicroHttpClientAttrsGetter) GetHttpResponseHeader(request goMicroRequest, response goMicroResponse, name string) []string {
all := make([]string, 0)
md, ok := metadata.FromContext(response.ctx)
if ok {
value, ok := md.Get(name)
if ok {
all = append(all, string(value))
}
}
return all
}
func (n goMicroHttpClientAttrsGetter) GetErrorType(request goMicroRequest, response goMicroResponse, err error) string {
return ""
}
func (n goMicroHttpClientAttrsGetter) GetNetworkType(request goMicroRequest, response goMicroResponse) string {
return "ipv4"
}
func (n goMicroHttpClientAttrsGetter) GetNetworkTransport(request goMicroRequest, response goMicroResponse) string {
return "tcp"
}
func (n goMicroHttpClientAttrsGetter) GetNetworkProtocolName(request goMicroRequest, response goMicroResponse) string {
return "http"
}
func (n goMicroHttpClientAttrsGetter) GetNetworkProtocolVersion(request goMicroRequest, response goMicroResponse) string {
return ""
}
func (n goMicroHttpClientAttrsGetter) GetNetworkLocalInetAddress(request goMicroRequest, response goMicroResponse) string {
return ""
}
func (n goMicroHttpClientAttrsGetter) GetNetworkLocalPort(request goMicroRequest, response goMicroResponse) int {
return 0
}
func (n goMicroHttpClientAttrsGetter) GetNetworkPeerInetAddress(request goMicroRequest, response goMicroResponse) string {
if request.reqType == MessageRequest {
return request.msg.Topic()
}
return request.request.Service()
}
func (n goMicroHttpClientAttrsGetter) GetNetworkPeerPort(request goMicroRequest, response goMicroResponse) int {
return 0
}
func (n goMicroHttpClientAttrsGetter) GetUrlFull(request goMicroRequest) string {
if request.reqType == MessageRequest {
return request.msg.Topic()
}
return request.request.Endpoint()
}
func (n goMicroHttpClientAttrsGetter) GetServerPort(request goMicroRequest) int {
return 0
}
func (h goMicroHttpClientAttrsGetter) GetServerAddress(request goMicroRequest) string {
switch request.reqType {
case CallRequest:
return request.request.Service()
case StreamRequest:
return request.request.Service()
case MessageRequest:
return request.msg.Topic()
}
return ""
}
func BuildGoMicroClientInstrumenter() *instrumenter.PropagatingToDownstreamInstrumenter[goMicroRequest, goMicroResponse] {
builder := instrumenter.Builder[goMicroRequest, goMicroResponse]{}
clientGetter := goMicroHttpClientAttrsGetter{}
commonExtractor := http.HttpCommonAttrsExtractor[goMicroRequest, goMicroResponse, goMicroHttpClientAttrsGetter, goMicroHttpClientAttrsGetter]{HttpGetter: clientGetter, NetGetter: clientGetter}
networkExtractor := net.NetworkAttrsExtractor[goMicroRequest, goMicroResponse, goMicroHttpClientAttrsGetter]{Getter: clientGetter}
return builder.Init().SetSpanStatusExtractor(http.HttpClientSpanStatusExtractor[goMicroRequest, goMicroResponse]{Getter: clientGetter}).SetSpanNameExtractor(&http.HttpClientSpanNameExtractor[goMicroRequest, goMicroResponse]{Getter: clientGetter}).
SetSpanKindExtractor(&instrumenter.AlwaysClientExtractor[goMicroRequest]{}).
AddOperationListeners(http.HttpClientMetrics("gomicro.client")).
SetInstrumentationScope(instrumentation.Scope{
Name: utils.GOMICRO_CLIENT_SCOPE_NAME,
Version: version.Tag,
}).
AddAttributesExtractor(&http.HttpClientAttrsExtractor[goMicroRequest, goMicroResponse, goMicroHttpClientAttrsGetter, goMicroHttpClientAttrsGetter]{Base: commonExtractor, NetworkExtractor: networkExtractor}).BuildPropagatingToDownstreamInstrumenter(nil, nil)
}