feat(架构): 完善基础架构设计
This commit is contained in:
189
internal/shared/tracing/service_wrapper.go
Normal file
189
internal/shared/tracing/service_wrapper.go
Normal file
@@ -0,0 +1,189 @@
|
||||
package tracing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"tyapi-server/internal/domains/user/dto"
|
||||
"tyapi-server/internal/domains/user/entities"
|
||||
"tyapi-server/internal/shared/interfaces"
|
||||
)
|
||||
|
||||
// ServiceWrapper 服务包装器,提供自动追踪能力
|
||||
type ServiceWrapper struct {
|
||||
tracer *Tracer
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
// NewServiceWrapper 创建服务包装器
|
||||
func NewServiceWrapper(tracer *Tracer, logger *zap.Logger) *ServiceWrapper {
|
||||
return &ServiceWrapper{
|
||||
tracer: tracer,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
// TraceServiceCall 追踪服务调用的通用方法
|
||||
func (w *ServiceWrapper) TraceServiceCall(
|
||||
ctx context.Context,
|
||||
serviceName, methodName string,
|
||||
fn func(context.Context) error,
|
||||
) error {
|
||||
// 创建span名称
|
||||
spanName := fmt.Sprintf("%s.%s", serviceName, methodName)
|
||||
|
||||
// 开始追踪
|
||||
ctx, span := w.tracer.StartSpan(ctx, spanName)
|
||||
defer span.End()
|
||||
|
||||
// 添加基础属性
|
||||
w.tracer.AddSpanAttributes(span,
|
||||
attribute.String("service.name", serviceName),
|
||||
attribute.String("service.method", methodName),
|
||||
attribute.String("service.type", "business"),
|
||||
)
|
||||
|
||||
// 记录开始时间
|
||||
startTime := time.Now()
|
||||
|
||||
// 执行原始方法
|
||||
err := fn(ctx)
|
||||
|
||||
// 计算执行时间
|
||||
duration := time.Since(startTime)
|
||||
w.tracer.AddSpanAttributes(span,
|
||||
attribute.Int64("service.duration_ms", duration.Milliseconds()),
|
||||
)
|
||||
|
||||
// 标记慢方法
|
||||
if duration > 100*time.Millisecond {
|
||||
w.tracer.AddSpanAttributes(span,
|
||||
attribute.Bool("service.slow_method", true),
|
||||
)
|
||||
w.logger.Warn("慢方法检测",
|
||||
zap.String("service", serviceName),
|
||||
zap.String("method", methodName),
|
||||
zap.Duration("duration", duration),
|
||||
zap.String("trace_id", w.tracer.GetTraceID(ctx)),
|
||||
)
|
||||
}
|
||||
|
||||
// 处理错误
|
||||
if err != nil {
|
||||
w.tracer.SetSpanError(span, err)
|
||||
w.logger.Error("服务方法执行失败",
|
||||
zap.String("service", serviceName),
|
||||
zap.String("method", methodName),
|
||||
zap.Error(err),
|
||||
zap.String("trace_id", w.tracer.GetTraceID(ctx)),
|
||||
)
|
||||
} else {
|
||||
w.tracer.SetSpanSuccess(span)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// TracedUserService 自动追踪的用户服务包装器
|
||||
type TracedUserService struct {
|
||||
service interfaces.UserService
|
||||
wrapper *ServiceWrapper
|
||||
}
|
||||
|
||||
// NewTracedUserService 创建带追踪的用户服务
|
||||
func NewTracedUserService(service interfaces.UserService, wrapper *ServiceWrapper) interfaces.UserService {
|
||||
return &TracedUserService{
|
||||
service: service,
|
||||
wrapper: wrapper,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *TracedUserService) Name() string {
|
||||
return "user-service"
|
||||
}
|
||||
|
||||
func (t *TracedUserService) Initialize(ctx context.Context) error {
|
||||
return t.wrapper.TraceServiceCall(ctx, "user", "initialize", t.service.Initialize)
|
||||
}
|
||||
|
||||
func (t *TracedUserService) HealthCheck(ctx context.Context) error {
|
||||
return t.service.HealthCheck(ctx) // 不追踪健康检查
|
||||
}
|
||||
|
||||
func (t *TracedUserService) Shutdown(ctx context.Context) error {
|
||||
return t.wrapper.TraceServiceCall(ctx, "user", "shutdown", t.service.Shutdown)
|
||||
}
|
||||
|
||||
func (t *TracedUserService) Register(ctx context.Context, req *dto.RegisterRequest) (*entities.User, error) {
|
||||
var result *entities.User
|
||||
var err error
|
||||
|
||||
traceErr := t.wrapper.TraceServiceCall(ctx, "user", "register", func(ctx context.Context) error {
|
||||
result, err = t.service.Register(ctx, req)
|
||||
return err
|
||||
})
|
||||
|
||||
if traceErr != nil {
|
||||
return nil, traceErr
|
||||
}
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (t *TracedUserService) LoginWithPassword(ctx context.Context, req *dto.LoginWithPasswordRequest) (*entities.User, error) {
|
||||
var result *entities.User
|
||||
var err error
|
||||
|
||||
traceErr := t.wrapper.TraceServiceCall(ctx, "user", "login_password", func(ctx context.Context) error {
|
||||
result, err = t.service.LoginWithPassword(ctx, req)
|
||||
return err
|
||||
})
|
||||
|
||||
if traceErr != nil {
|
||||
return nil, traceErr
|
||||
}
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (t *TracedUserService) LoginWithSMS(ctx context.Context, req *dto.LoginWithSMSRequest) (*entities.User, error) {
|
||||
var result *entities.User
|
||||
var err error
|
||||
|
||||
traceErr := t.wrapper.TraceServiceCall(ctx, "user", "login_sms", func(ctx context.Context) error {
|
||||
result, err = t.service.LoginWithSMS(ctx, req)
|
||||
return err
|
||||
})
|
||||
|
||||
if traceErr != nil {
|
||||
return nil, traceErr
|
||||
}
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (t *TracedUserService) ChangePassword(ctx context.Context, userID string, req *dto.ChangePasswordRequest) error {
|
||||
return t.wrapper.TraceServiceCall(ctx, "user", "change_password", func(ctx context.Context) error {
|
||||
return t.service.ChangePassword(ctx, userID, req)
|
||||
})
|
||||
}
|
||||
|
||||
func (t *TracedUserService) GetByID(ctx context.Context, id string) (*entities.User, error) {
|
||||
var result *entities.User
|
||||
var err error
|
||||
|
||||
traceErr := t.wrapper.TraceServiceCall(ctx, "user", "get_by_id", func(ctx context.Context) error {
|
||||
result, err = t.service.GetByID(ctx, id)
|
||||
return err
|
||||
})
|
||||
|
||||
if traceErr != nil {
|
||||
return nil, traceErr
|
||||
}
|
||||
|
||||
return result, err
|
||||
}
|
||||
Reference in New Issue
Block a user