go使用opentelemetry+jaeger---gin+gprc

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;
}

protoc -I . --go_out=plugins=grpc:.\grpc_proto .\grpc_proto\hello.proto

posted @ 2024-06-18 16:14  朝阳1  阅读(245)  评论(0)    收藏  举报