api-1
package main
import (
"context"
"fmt"
"github.com/gin-gonic/gin"
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
tracesdk "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
oteltrace "go.opentelemetry.io/otel/trace"
"log"
"net/http"
modahttp "github.com/webws/go-moda/transport/http"
)
const (
service = "api1"
environment = "dev"
id = 3
)
var tracer = otel.Tracer(service)
func tracerProvider() (*tracesdk.TracerProvider, error) {
// Create the Jaeger exporter
exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint("http://192.168.252.128:14268/api/traces")))
if err != nil {
return nil, err
}
tp := tracesdk.NewTracerProvider(
// Always be sure to batch in production.
tracesdk.WithSampler(tracesdk.AlwaysSample()),
tracesdk.WithBatcher(exp),
tracesdk.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName(service),
attribute.String("environment", environment),
attribute.Int64("ID", id),
),
),
)
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
return tp, nil
}
func main() {
tp, err := tracerProvider()
if err != nil {
log.Fatal(err)
}
defer func() {
if err := tp.Shutdown(context.Background()); err != nil {
log.Fatal(err)
}
}()
r := gin.New()
r.Use(otelgin.Middleware("gin-api1"))
loadRoutes(r)
fmt.Println("api1 start 8081")
r.Run(":8081")
}
func loadRoutes(r *gin.Engine) {
r.GET("/ping", pingFunc)
}
func pingFunc(c *gin.Context) {
tracerCtx, span := tracer.Start(c.Request.Context(), "pingFunc",
oteltrace.WithAttributes(attribute.String("key-pingFunc", "val-pingFunc")))
defer span.End()
callApi2(tracerCtx)
c.JSON(http.StatusOK, gin.H{
"message": "pong",
})
}
func callApi2(ctx context.Context) {
// tracer
fmt.Println("on callApi2")
tracerCtx, span := tracer.Start(ctx, "callApi2")
span.AddEvent("starting callApi2")
span.SetAttributes(attribute.Key("key_callApi2").String("value_callApi2"))
defer span.End()
// 打印TraceID SpanID
spanCtx := oteltrace.SpanContextFromContext(ctx)
fmt.Println(spanCtx.TraceID())
fmt.Println(spanCtx.SpanID())
// 调用api2
url := fmt.Sprintf("http://localhost:8082/ping")
defer span.End()
_, err := modahttp.CallAPI(tracerCtx, url, "GET", nil)
if err != nil {
fmt.Printf("call api2 error: %v", err)
span.SetStatus(codes.Error, err.Error())
}
}
api-2
package main
import (
"context"
"fmt"
"github.com/gin-gonic/gin"
"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
tracesdk "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
oteltrace "go.opentelemetry.io/otel/trace"
"go_otel/3gin_http/grpc/grpc_proto/hello_grpc"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"log"
"net/http"
)
const (
service = "api2"
environment = "dev"
id = 2
)
var tracer = otel.Tracer(service)
func tracerProvider() (*tracesdk.TracerProvider, error) {
// Create the Jaeger exporter
exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint("http://192.168.252.128:14268/api/traces")))
if err != nil {
return nil, err
}
tp := tracesdk.NewTracerProvider(
// Always be sure to batch in production.
tracesdk.WithSampler(tracesdk.AlwaysSample()),
tracesdk.WithBatcher(exp),
tracesdk.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName(service),
attribute.String("environment", environment),
attribute.Int64("ID", id),
),
),
)
// Register our TracerProvider as the global so any imported
// instrumentation in the future will default to using it.
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
return tp, nil
}
func main() {
tp, err := tracerProvider()
if err != nil {
log.Fatal(err)
}
// Cleanly shutdown and flush telemetry when the application exits.
defer func() {
if err := tp.Shutdown(context.Background()); err != nil {
log.Fatal(err)
}
}()
r := gin.New()
r.Use(otelgin.Middleware("gin-api2"))
loadRoutes(r)
fmt.Println("api2 start 8082")
r.Run(":8082")
}
func loadRoutes(r *gin.Engine) {
r.GET("/ping", pingFunc)
}
func pingFunc(c *gin.Context) {
fmt.Println("on pingFunc")
ctx, span := tracer.Start(c.Request.Context(), "pingFunc")
defer span.End()
callGrpc(ctx)
c.JSON(http.StatusOK, gin.H{
"message": "pong",
})
}
func callGrpc(ctx context.Context) {
fmt.Println("on callGrpc")
ctx, span := tracer.Start(ctx, "callGrpc")
defer span.End()
// 打印TraceID SpanID
spanCtx := oteltrace.SpanContextFromContext(ctx)
fmt.Println(spanCtx.TraceID())
fmt.Println(spanCtx.SpanID())
// 连接服务器
options := make([]grpc.DialOption, 0)
options = append(options, grpc.WithTransportCredentials(insecure.NewCredentials()),
grpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor()),
grpc.WithStreamInterceptor(otelgrpc.StreamClientInterceptor()))
conn, err := grpc.DialContext(ctx, "localhost:8083", options...)
if err != nil {
panic(err)
}
defer conn.Close()
// 初始化客户端
client := hello_grpc.NewHelloServiceClient(conn)
result, err := client.SayHello(ctx, &hello_grpc.HelloRequest{
Name: "client",
Message: "hello",
})
fmt.Println(result, err)
}
grpc-server
package main
import (
"context"
"fmt"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
tracesdk "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.17.0"
oteltrace "go.opentelemetry.io/otel/trace"
"go_otel/3gin_http/grpc/grpc_proto/hello_grpc"
"google.golang.org/grpc"
"google.golang.org/grpc/grpclog"
"log"
"net"
)
const (
service = "remote-grpc"
environment = "dev"
id = 3
)
var tracer = otel.Tracer(service)
// HelloServer 得有一个结构体,需要实现这个服务的全部方法,叫什么名字不重要
type HelloServer struct {
}
func (HelloServer) SayHello(ctx context.Context, request *hello_grpc.HelloRequest) (*hello_grpc.HelloResponse, error) {
fmt.Println("on grpc SayHello")
_, span := tracer.Start(ctx, "SayHello",
oteltrace.WithAttributes(attribute.String("key-pingFunc", "val-pingFunc")))
defer span.End()
spanCtx := oteltrace.SpanContextFromContext(ctx)
fmt.Println(spanCtx.SpanID())
fmt.Println(spanCtx.TraceID())
fmt.Println("入参:", request.Name, request.Message)
return &hello_grpc.HelloResponse{
Name: "server",
Message: "hello " + request.Name,
}, nil
}
func tracerProvider() (*tracesdk.TracerProvider, error) {
// Create the Jaeger exporter
exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint("http://10.128.175.196:14268/api/traces")))
if err != nil {
return nil, err
}
tp := tracesdk.NewTracerProvider(
// Always be sure to batch in production.
tracesdk.WithSampler(tracesdk.AlwaysSample()),
tracesdk.WithBatcher(exp),
tracesdk.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName(service),
attribute.String("environment", environment),
attribute.Int64("ID", id),
),
),
)
// Register our TracerProvider as the global so any imported
// instrumentation in the future will default to using it.
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{}))
return tp, nil
}
func main() {
tp, err := tracerProvider()
if err != nil {
log.Fatal(err)
}
// Cleanly shutdown and flush telemetry when the application exits.
defer func() {
if err := tp.Shutdown(context.Background()); err != nil {
log.Fatal(err)
}
}()
// grpc
fmt.Println("grpc start 8083")
listen, err := net.Listen("tcp", ":8083")
if err != nil {
grpclog.Fatalf("Failed to listen: %v", err)
}
// 创建一个gRPC服务器实例。
// 添加拦截器(grpc集成OpenTelemetry主要是调用(otelgrpc.UnaryServerInterceptor())
s := grpc.NewServer(grpc.UnaryInterceptor(otelgrpc.UnaryServerInterceptor()))
server := HelloServer{}
// 将server结构体注册为gRPC服务。
hello_grpc.RegisterHelloServiceServer(s, &server)
// 开始处理客户端请求。
err = s.Serve(listen)
}
hello.proto
syntax = "proto3"; // 指定proto版本
package hello_grpc; // 指定默认包名
// 指定golang包名
option go_package = "/hello_grpc";
//定义rpc服务
service HelloService {
// 定义函数
rpc SayHello (HelloRequest) returns (HelloResponse) {}
}
// HelloRequest 请求内容
message HelloRequest {
string name = 1;
string message = 2;
}
// HelloResponse 响应内容
message HelloResponse{
string name = 1;
string message = 2;
}