shao 1 dag geleden
bovenliggende
commit
f25bd2fa6c
11 gewijzigde bestanden met toevoegingen van 153 en 85 verwijderingen
  1. 0 0
      api/v1/dcmtk.go
  2. 24 0
      api/v1/study.go
  3. 87 0
      logger/grpc.go
  4. 3 3
      logger/logger.go
  5. 1 0
      router/router.go
  6. 1 1
      rpc_idl
  7. 5 7
      service/pb_dcmtk_client.go
  8. 5 28
      service/pb_protocol_client.go
  9. 8 12
      service/pb_resource_client.go
  10. 15 33
      service/pb_study_client.go
  11. 4 1
      service/user.go

+ 0 - 0
api/v1/dicom.go → api/v1/dcmtk.go


+ 24 - 0
api/v1/study.go

@@ -96,6 +96,30 @@ func CopyImage(c *gin.Context) {
 	common.HttpSuccess(c, res)
 }
 
+func SortImage(c *gin.Context) {
+	request := pb.SortRequest{}
+	reqBytes, err := c.GetRawData()
+	if err != nil {
+		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to read request body"})
+		return
+	}
+	unmarshaler := protojson.UnmarshalOptions{
+		AllowPartial:   true, // 允许部分解析,即使缺少必需字段
+		DiscardUnknown: true, // 丢弃 JSON 中 Protobuf 消息未定义的字段
+	}
+	err = unmarshaler.Unmarshal(reqBytes, &request)
+	if err != nil {
+		c.JSON(http.StatusBadRequest, gin.H{"error": fmt.Sprintf("Failed to unmarshal JSON to Protobuf: %v", err)})
+		return
+	}
+	res, err := service.StudyClient.SortImage(common.GC2GM(c), &request)
+	if err != nil {
+		common.HttpErr(c, err)
+		return
+	}
+	common.HttpSuccess(c, res)
+}
+
 func DeleteImage(c *gin.Context) {
 	id := c.Param("id")
 	res, err := service.StudyClient.DeleteImage(common.GC2GM(c), &id)

+ 87 - 0
logger/grpc.go

@@ -0,0 +1,87 @@
+package logger
+
+import (
+	"context"
+	"log/slog"
+	"time"
+)
+
+import (
+	"google.golang.org/grpc"
+	"google.golang.org/grpc/codes"
+	"google.golang.org/grpc/status"
+)
+
+func GRPCLoggerClientInterceptor(logger *slog.Logger) grpc.UnaryClientInterceptor {
+	return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
+		start := time.Now()
+		logger.Info("request",
+			slog.String("method", method),
+			slog.Any("payload", req),
+		)
+
+		err := invoker(ctx, method, req, reply, cc, opts...)
+
+		duration := time.Since(start)
+		if err != nil {
+			logger.Error("response",
+				slog.String("method", method),
+				slog.Duration("duration", duration),
+				slog.String("error", err.Error()),
+			)
+		} else {
+			logger.Info("response",
+				slog.String("method", method),
+				slog.Duration("duration", duration),
+				slog.Any("reply", reply),
+			)
+		}
+
+		return err
+	}
+}
+
+func GRPCLoggerServerInterceptor(logger *slog.Logger) grpc.UnaryServerInterceptor {
+	return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
+		start := time.Now()
+		method := info.FullMethod
+
+		// 在请求处理前记录
+		logger.Info("request",
+			slog.String("method", method),
+			slog.Any("payload", req),
+		)
+
+		// 调用实际的服务方法
+		resp, err = handler(ctx, req)
+
+		// 在请求处理后记录
+		duration := time.Since(start)
+		statusCode := codes.OK // 默认成功
+		if err != nil {
+			s, ok := status.FromError(err)
+			if ok {
+				statusCode = s.Code() // 从 gRPC 错误中获取状态码
+			} else {
+				statusCode = codes.Unknown // 非 gRPC 错误则视为未知
+			}
+		}
+
+		if err != nil {
+			logger.Error("response",
+				slog.String("method", method),
+				slog.Duration("duration", duration),
+				slog.String("status_code", statusCode.String()),
+				slog.String("error", err.Error()),
+			)
+		} else {
+			logger.Info("response",
+				slog.String("method", method),
+				slog.Duration("duration", duration),
+				slog.Any("reply", resp),
+			)
+		}
+
+		return resp, err
+	}
+}

+ 3 - 3
logger/logger.go

@@ -53,12 +53,12 @@ func SetupLogger(persisted bool) {
 
 	if persisted {
 		if common.LoggerConfig.Stdout {
-			logger = slog.New(slog.NewTextHandler(io.MultiWriter(lumberJackLogger, os.Stdout), opts))
+			logger = slog.New(slog.NewJSONHandler(io.MultiWriter(lumberJackLogger, os.Stdout), opts))
 		} else {
-			logger = slog.New(slog.NewTextHandler(lumberJackLogger, opts))
+			logger = slog.New(slog.NewJSONHandler(lumberJackLogger, opts))
 		}
 	} else {
-		logger = slog.New(slog.NewTextHandler(os.Stdout, opts))
+		logger = slog.New(slog.NewJSONHandler(os.Stdout, opts))
 	}
 	slog.SetDefault(logger)
 	//todo 输出到robot

+ 1 - 0
router/router.go

@@ -50,6 +50,7 @@ func InitRouter() *gin.Engine {
 		{
 			imageV1.POST("", apiv1.CreateImage)
 			imageV1.POST("copy", apiv1.CopyImage)
+			imageV1.POST("sort", apiv1.SortImage)
 			imageV1.DELETE(":id", apiv1.DeleteImage)
 		}
 		dicomV1 := authV1.Group("/dicom")

+ 1 - 1
rpc_idl

@@ -1 +1 @@
-Subproject commit f03bec09473b0c4a31385f0d1383e0a9fc4390c1
+Subproject commit 8ad07de374e1e88412d857c445c5c6a115aeab1a

+ 5 - 7
service/pb_dcmtk_client.go

@@ -13,6 +13,7 @@ import (
 
 import (
 	"auth-server/common"
+	"auth-server/logger"
 	pb "auth-server/rpc_idl/dr_dcmtk_pb"
 )
 
@@ -28,7 +29,10 @@ type Dcmtk struct {
 }
 
 func (s *Dcmtk) Setup() {
-	conn, err := grpc.NewClient(common.ServerConfig.Dcmtk, grpc.WithTransportCredentials(insecure.NewCredentials()))
+	conn, err := grpc.NewClient(common.ServerConfig.Dcmtk,
+		grpc.WithTransportCredentials(insecure.NewCredentials()),
+		grpc.WithUnaryInterceptor(logger.GRPCLoggerClientInterceptor(logger.WithGroup("grpc_c[dcmtk]"))),
+	)
 	if err != nil {
 		slog.Error("NewClient failed:", err)
 		panic(err)
@@ -40,12 +44,10 @@ func (s *Dcmtk) Setup() {
 }
 
 func (s *Dcmtk) GetSoftwareInfo() *pb.SoftwareInfoReply {
-	slog.Info("[rpc]SoftwareInfo...")
 	ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
 	defer cancel()
 	r, err := s.basicClient.SoftwareInfo(ctx, &emptypb.Empty{})
 	if err != nil {
-		slog.Error("[rpc]SoftwareInfo failed", "err", err)
 		return &pb.SoftwareInfoReply{
 			Module:  "",
 			Desc:    "",
@@ -57,7 +59,6 @@ func (s *Dcmtk) GetSoftwareInfo() *pb.SoftwareInfoReply {
 }
 
 func (s *Dcmtk) GenerateUniqueIdentifier(ctx context.Context, flag string, number int32) (*pb.UidReply, error) {
-	slog.Info("[rpc]GenerateUniqueIdentifier...")
 	SiteUidRoot := "1.2.276.0.1000000.5"
 	uidRoot := SiteUidRoot
 	switch flag {
@@ -77,8 +78,5 @@ func (s *Dcmtk) GenerateUniqueIdentifier(ctx context.Context, flag string, numbe
 		UidRoot: uidRoot,
 		Number:  number,
 	})
-	if err != nil {
-		slog.Error("[rpc]GenerateUniqueIdentifier failed", "err", err)
-	}
 	return r, err
 }

+ 5 - 28
service/pb_protocol_client.go

@@ -13,6 +13,7 @@ import (
 
 import (
 	"auth-server/common"
+	"auth-server/logger"
 	pb "auth-server/rpc_idl/dr_protocol_pb"
 )
 
@@ -29,7 +30,10 @@ type Protocol struct {
 }
 
 func (s *Protocol) Setup() {
-	conn, err := grpc.NewClient(common.ServerConfig.Protocol, grpc.WithTransportCredentials(insecure.NewCredentials()))
+	conn, err := grpc.NewClient(common.ServerConfig.Protocol,
+		grpc.WithTransportCredentials(insecure.NewCredentials()),
+		grpc.WithUnaryInterceptor(logger.GRPCLoggerClientInterceptor(logger.WithGroup("grpc_c[protocol]"))),
+	)
 	if err != nil {
 		slog.Error("NewClient failed", "err", err)
 		panic(err)
@@ -42,12 +46,10 @@ func (s *Protocol) Setup() {
 }
 
 func (s *Protocol) GetSoftwareInfo() *pb.SoftwareInfoReply {
-	slog.Info("[rpc]SoftwareInfo...")
 	ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
 	defer cancel()
 	r, err := s.basicClient.SoftwareInfo(ctx, &emptypb.Empty{})
 	if err != nil {
-		slog.Error("[rpc]SoftwareInfo failed", "err", err)
 		return &pb.SoftwareInfoReply{
 			Module:  "",
 			Desc:    "",
@@ -59,77 +61,52 @@ func (s *Protocol) GetSoftwareInfo() *pb.SoftwareInfoReply {
 }
 
 func (s *Protocol) GetPatientTypeList(ctx context.Context, isEnabled *bool) (*pb.PatientTypeReply, error) {
-	slog.Info("[rpc]GetPatientTypeList...")
 	r, err := s.protocolClient.GetPatientTypeList(ctx, &pb.PatientTypeRequest{
 		IsEnabled: isEnabled,
 	})
-	if err != nil {
-		slog.Error("[rpc]GetPatientType failed", "err", err)
-	}
-	slog.Info("[rpc]GetPatientTypeList result", "rows", len(r.PatientTypeList))
 	return r, err
 }
 
 func (s *Protocol) GetBodyPartList(ctx context.Context, patientType *string, modality *string, isEnabled *bool) (*pb.BodyPartReply, error) {
-	slog.Info("[rpc]GetBodyPartList...")
 	r, err := s.protocolClient.GetBodyPartList(ctx, &pb.BodyPartRequest{
 		PatientType: patientType,
 		Modality:    modality,
 		IsEnabled:   isEnabled,
 	})
-	if err != nil {
-		slog.Error("[rpc]GetBodyPartList failed", "err", err)
-	}
 	return r, err
 }
 
 func (s *Protocol) GetProcedureList(ctx context.Context, patientType *string, bodyPart *string, isEnabled *bool) (*pb.ProcedureReply, error) {
-	slog.Info("[rpc]GetProcedureList...")
 	r, err := s.protocolClient.GetProcedureList(ctx, &pb.ProcedureRequest{
 		PatientType: patientType,
 		BodyPartId:  bodyPart,
 		IsEnabled:   isEnabled,
 	})
-	if err != nil {
-		slog.Error("[rpc]GetProcedureList failed", "err", err)
-	}
 	return r, err
 }
 
 func (s *Protocol) GetViewList(ctx context.Context, patientType *string, bodyPart *string, procedureID *string, isEnabled *bool) (*pb.ViewReply, error) {
-	slog.Info("[rpc]GetViewList...")
 	r, err := s.protocolClient.GetViewList(ctx, &pb.ViewRequest{
 		PatientType: patientType,
 		BodyPartId:  bodyPart,
 		ProcedureId: procedureID,
 		IsEnabled:   isEnabled,
 	})
-	if err != nil {
-		slog.Error("[rpc]GetViewList failed", "err", err)
-	}
 	return r, err
 }
 
 func (s *Protocol) GetView(ctx context.Context, id *string) (*pb.View, error) {
-	slog.Info("[rpc]GetView...")
 	r, err := s.protocolClient.GetView(ctx, &pb.IDRequest{
 		InstanceId: id,
 	})
-	if err != nil {
-		slog.Error("[rpc]GetViewList failed", "err", err)
-	}
 	return r, err
 }
 
 func (s *Protocol) GetApr(ctx context.Context, viewID *string, aprID *string, isEnabled *bool) (*pb.AprReply, error) {
-	slog.Info("[rpc]GetApr...")
 	r, err := s.aprClient.GetApr(ctx, &pb.AprRequest{
 		ViewId:    viewID,
 		AprId:     aprID,
 		IsEnabled: isEnabled,
 	})
-	if err != nil {
-		slog.Error("[rpc]GetApr failed", "err", err)
-	}
 	return r, err
 }

+ 8 - 12
service/pb_resource_client.go

@@ -2,7 +2,6 @@ package service
 
 import (
 	"context"
-	"errors"
 	"log/slog"
 	"time"
 )
@@ -14,6 +13,7 @@ import (
 
 import (
 	"auth-server/common"
+	"auth-server/logger"
 	pb "auth-server/rpc_idl/dr_resource_pb"
 )
 
@@ -29,7 +29,10 @@ type Resource struct {
 }
 
 func (s *Resource) Setup() {
-	conn, err := grpc.NewClient(common.ServerConfig.Resource, grpc.WithTransportCredentials(insecure.NewCredentials()))
+	conn, err := grpc.NewClient(common.ServerConfig.Resource,
+		grpc.WithTransportCredentials(insecure.NewCredentials()),
+		grpc.WithUnaryInterceptor(logger.GRPCLoggerClientInterceptor(logger.WithGroup("grpc_c[resource]"))),
+	)
 	if err != nil {
 		slog.Error("NewClient failed:", err)
 		panic(err)
@@ -41,12 +44,10 @@ func (s *Resource) Setup() {
 }
 
 func (s *Resource) GetSoftwareInfo() *pb.SoftwareInfoReply {
-	slog.Info("[rpc]SoftwareInfo...")
 	ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
 	defer cancel()
 	r, err := s.basicClient.SoftwareInfo(ctx, &emptypb.Empty{})
 	if err != nil {
-		slog.Error("[rpc]SoftwareInfo failed", "err", err)
 		return &pb.SoftwareInfoReply{
 			Module:  "",
 			Desc:    "",
@@ -59,30 +60,25 @@ func (s *Resource) GetSoftwareInfo() *pb.SoftwareInfoReply {
 
 func (s *Resource) GetOptions(ctx context.Context, group, flag *string) (*pb.OptionReply, error) {
 	if group == nil {
-		return nil, errors.New("group is nil")
+		return nil, common.MissingParam.SetParam("Name", "group")
 	}
 	if flag == nil {
-		return nil, errors.New("flag is nil")
+		return nil, common.MissingParam.SetParam("Name", "group")
 	}
 	r, err := s.configClient.GetOptions(ctx, &pb.OptionRequest{
 		Group: *group,
 		Flag:  *flag,
 	})
-	if err != nil {
-		slog.Error("[rpc]GetOptions failed", "err", err)
-	}
-	slog.Info("[rpc]GetOptions result", "rows", len(r.Option))
 	return r, err
 }
 
 func (s *Resource) GetConfigOptionList(ctx context.Context, flag string, enable bool) ([]*pb.ConfigOption, error) {
-	slog.Info("[rpc]GetConfigOptionList...")
 	r, err := s.configClient.ConfigOptionList(ctx, &pb.ConfigOptionListRequest{
 		Flag:      flag,
 		IsEnabled: enable,
 	})
 	if err != nil {
-		slog.Error("[rpc]GetConfigOptionList failed", "err", err)
+		return nil, err
 	}
 	return r.GetConfigOption(), err
 }

+ 15 - 33
service/pb_study_client.go

@@ -13,6 +13,7 @@ import (
 
 import (
 	"auth-server/common"
+	"auth-server/logger"
 	pb "auth-server/rpc_idl/dr_study_pb"
 )
 
@@ -28,7 +29,10 @@ type Study struct {
 }
 
 func (s *Study) Setup() {
-	conn, err := grpc.NewClient(common.ServerConfig.Study, grpc.WithTransportCredentials(insecure.NewCredentials()))
+	conn, err := grpc.NewClient(common.ServerConfig.Study,
+		grpc.WithTransportCredentials(insecure.NewCredentials()),
+		grpc.WithUnaryInterceptor(logger.GRPCLoggerClientInterceptor(logger.WithGroup("grpc_c[study]"))),
+	)
 	if err != nil {
 		slog.Error("NewClient failed:", err)
 		panic(err)
@@ -40,12 +44,10 @@ func (s *Study) Setup() {
 }
 
 func (s *Study) GetSoftwareInfo() *pb.SoftwareInfoReply {
-	slog.Info("[rpc]SoftwareInfo...")
 	ctx, cancel := context.WithTimeout(context.Background(), 200*time.Millisecond)
 	defer cancel()
 	r, err := s.basicClient.SoftwareInfo(ctx, &emptypb.Empty{})
 	if err != nil {
-		slog.Error("[rpc]SoftwareInfo failed", "err", err)
 		return &pb.SoftwareInfoReply{
 			Module:  "",
 			Desc:    "",
@@ -57,55 +59,35 @@ func (s *Study) GetSoftwareInfo() *pb.SoftwareInfoReply {
 }
 
 func (s *Study) CreateStudy(ctx context.Context, in *pb.StudyRequest) (*pb.StudyReply, error) {
-	slog.Info("[rpc]CreateStudy...")
 	r, err := s.studyClient.CreateStudy(ctx, in)
-	if err != nil {
-		slog.Error("[rpc]CreateStudy failed", "err", err)
-		return r, err
-	}
-	return r, nil
+	return r, err
 }
 
 func (s *Study) GetStudy(ctx context.Context, id *string) (*pb.StudyReply, error) {
-	slog.Info("[rpc]GetStudy...")
 	r, err := s.studyClient.GetStudy(ctx, &pb.IDRequest{
 		InstanceId: id,
 	})
-	if err != nil {
-		slog.Error("[rpc]GetStudy failed", "err", err)
-		return r, err
-	}
-	return r, nil
+	return r, err
 }
 
 func (s *Study) CreateImage(ctx context.Context, in *pb.CreateImageRequest) (*pb.CreateImageReply, error) {
-	slog.Info("[rpc]CreateImage...")
 	r, err := s.studyClient.CreateImage(ctx, in)
-	if err != nil {
-		slog.Error("[rpc]CreateImage failed", "err", err)
-		return r, err
-	}
-	return r, nil
+	return r, err
 }
 
 func (s *Study) CopyImage(ctx context.Context, in *pb.IDRequest) (*pb.CreateImageReply, error) {
-	slog.Info("[rpc]CopyImage...")
 	r, err := s.studyClient.CopyImage(ctx, in)
-	if err != nil {
-		slog.Error("[rpc]CopyImage failed", "err", err)
-		return r, err
-	}
-	return r, nil
+	return r, err
+}
+
+func (s *Study) SortImage(ctx context.Context, in *pb.SortRequest) (*emptypb.Empty, error) {
+	r, err := s.studyClient.SortImage(ctx, in)
+	return r, err
 }
 
 func (s *Study) DeleteImage(ctx context.Context, id *string) (*emptypb.Empty, error) {
-	slog.Info("[rpc]DeleteImage...")
 	r, err := s.studyClient.DeleteImage(ctx, &pb.IDRequest{
 		InstanceId: id,
 	})
-	if err != nil {
-		slog.Error("[rpc]DeleteImage failed", "err", err)
-		return r, err
-	}
-	return r, nil
+	return r, err
 }

+ 4 - 1
service/user.go

@@ -1,10 +1,13 @@
 package service
 
+import (
+	"time"
+)
+
 import (
 	"auth-server/common"
 	"auth-server/dto"
 	"auth-server/models"
-	"time"
 )
 
 func Login(username string, password string) (*dto.UserInfoResp, error) {