From 13f4589a18e97f4ee7b4a9487f5e39dae3c42f01 Mon Sep 17 00:00:00 2001 From: Yvan <8574526@qq,com> Date: Fri, 21 Aug 2026 00:28:09 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../internal/data/payment/payment_helpers.go | 2 +- app/system/internal/integration/README.md | 4 +- .../integration/payment/gopay_test.go | 2 +- .../internal/integration/payment/qq_test.go | 2 +- .../internal/integration/payment/result.go | 2 +- .../internal/integration/payment/vendor.go | 2 +- .../internal/transport/httpx/response.go | 33 +++---- app/system/internal/utils/configutil/json.go | 68 +------------ .../internal/utils/paymentutil/README.md | 5 - .../internal/utils/paymentutil/amount.go | 97 ------------------- .../internal/utils/paymentutil/amount_test.go | 25 ----- app/system/internal/utils/paymentutil/json.go | 66 ------------- .../internal/utils/paymentutil/json_test.go | 16 --- .../internal/utils/paymentutil/signing.go | 58 ----------- .../utils/paymentutil/signing_test.go | 12 --- .../internal/utils/paymentutil/status.go | 63 ------------ app/system/internal/utils/paymentutil/xml.go | 60 ------------ pkg/README.md | 9 +- pkg/logging/source.go | 6 +- pkg/logging/zap.go | 4 +- pkg/logging/zap_test.go | 2 +- 21 files changed, 32 insertions(+), 506 deletions(-) delete mode 100644 app/system/internal/utils/paymentutil/README.md delete mode 100644 app/system/internal/utils/paymentutil/amount.go delete mode 100644 app/system/internal/utils/paymentutil/amount_test.go delete mode 100644 app/system/internal/utils/paymentutil/json.go delete mode 100644 app/system/internal/utils/paymentutil/json_test.go delete mode 100644 app/system/internal/utils/paymentutil/signing.go delete mode 100644 app/system/internal/utils/paymentutil/signing_test.go delete mode 100644 app/system/internal/utils/paymentutil/status.go delete mode 100644 app/system/internal/utils/paymentutil/xml.go diff --git a/app/system/internal/data/payment/payment_helpers.go b/app/system/internal/data/payment/payment_helpers.go index 268076e..2d6f03c 100644 --- a/app/system/internal/data/payment/payment_helpers.go +++ b/app/system/internal/data/payment/payment_helpers.go @@ -1,6 +1,6 @@ package payment -import "kra/app/system/internal/utils/paymentutil" +import "kra/pkg/paymentkit" func text(values map[string]any, key string) string { value, _ := values[key].(string) diff --git a/app/system/internal/integration/README.md b/app/system/internal/integration/README.md index 5c7c546..840dc57 100644 --- a/app/system/internal/integration/README.md +++ b/app/system/internal/integration/README.md @@ -1,6 +1,6 @@ # Integrations -`internal/integration` contains adapters that talk to systems outside the +`app/system/internal/integration` contains adapters that talk to systems outside the application process. They may open sockets, create SDK clients, keep reloadable state, or translate provider-specific protocols into `biz` interfaces. @@ -16,5 +16,5 @@ lifecycles. Their constructors are exposed through `ProviderSet`; `cmd` binds the `cache.RedisProvider` implementation to the shared `data.Data` container. Stateless protocol helpers that do not own clients live in -`internal/utils/paymentutil`. They are intentionally small and dependency +`pkg/paymentkit`. They are intentionally small and dependency light, while provider adapters remain here. diff --git a/app/system/internal/integration/payment/gopay_test.go b/app/system/internal/integration/payment/gopay_test.go index 4500981..ff50cab 100644 --- a/app/system/internal/integration/payment/gopay_test.go +++ b/app/system/internal/integration/payment/gopay_test.go @@ -21,7 +21,7 @@ import ( "testing" "kra/app/system/internal/biz" - "kra/app/system/internal/utils/paymentutil" + "kra/pkg/paymentkit" gopayAlipay "github.com/go-pay/gopay/alipay" gopayDouyin "github.com/go-pay/gopay/douyin" diff --git a/app/system/internal/integration/payment/qq_test.go b/app/system/internal/integration/payment/qq_test.go index 65026c9..ea762a9 100644 --- a/app/system/internal/integration/payment/qq_test.go +++ b/app/system/internal/integration/payment/qq_test.go @@ -12,7 +12,7 @@ import ( "testing" "kra/app/system/internal/biz" - "kra/app/system/internal/utils/paymentutil" + "kra/pkg/paymentkit" "github.com/go-pay/gopay" gopayQQ "github.com/go-pay/gopay/qq" diff --git a/app/system/internal/integration/payment/result.go b/app/system/internal/integration/payment/result.go index a75e493..aedd127 100644 --- a/app/system/internal/integration/payment/result.go +++ b/app/system/internal/integration/payment/result.go @@ -8,7 +8,7 @@ import ( "strings" "kra/app/system/internal/biz" - "kra/app/system/internal/utils/paymentutil" + "kra/pkg/paymentkit" ) func callbackFields(callback *biz.PaymentCallback) map[string]string { diff --git a/app/system/internal/integration/payment/vendor.go b/app/system/internal/integration/payment/vendor.go index 9cc350e..ac0cd26 100644 --- a/app/system/internal/integration/payment/vendor.go +++ b/app/system/internal/integration/payment/vendor.go @@ -15,7 +15,7 @@ import ( "time" "kra/app/system/internal/biz" - "kra/app/system/internal/utils/paymentutil" + "kra/pkg/paymentkit" ) type vendorProfile string diff --git a/app/system/internal/transport/httpx/response.go b/app/system/internal/transport/httpx/response.go index 8003bd9..25598f2 100644 --- a/app/system/internal/transport/httpx/response.go +++ b/app/system/internal/transport/httpx/response.go @@ -1,40 +1,29 @@ package httpx import ( - "net/http" - "github.com/gin-gonic/gin" + shared "kra/pkg/httpx" ) const ( - CodeSuccess = 0 - CodeError = 7 - CodePasswordChangeRequired = 10001 + CodeSuccess = shared.CodeSuccess + CodeError = shared.CodeError + CodePasswordChangeRequired = shared.CodePasswordChangeRequired ) -type Response struct { - Code int `json:"code"` - Data any `json:"data"` - Msg string `json:"msg"` -} - -type PageResult struct { - List any `json:"list"` - Total int64 `json:"total"` - Page int `json:"page"` - PageSize int `json:"pageSize"` -} +type Response = shared.Response +type PageResult = shared.PageResult func Write(c *gin.Context, code int, data any, message string) { - c.JSON(http.StatusOK, Response{Code: code, Data: data, Msg: message}) + shared.Write(c, code, data, message) } -func OK(c *gin.Context) { Write(c, CodeSuccess, gin.H{}, "操作成功") } +func OK(c *gin.Context) { shared.OK(c) } -func OKWithData(c *gin.Context, data any) { Write(c, CodeSuccess, data, "成功") } +func OKWithData(c *gin.Context, data any) { shared.OKWithData(c, data) } -func Fail(c *gin.Context, message string) { Write(c, CodeError, gin.H{}, message) } +func Fail(c *gin.Context, message string) { shared.Fail(c, message) } func NoAuth(c *gin.Context, message string) { - c.AbortWithStatusJSON(http.StatusUnauthorized, Response{Code: CodeError, Data: nil, Msg: message}) + shared.NoAuth(c, message) } diff --git a/app/system/internal/utils/configutil/json.go b/app/system/internal/utils/configutil/json.go index 38bd3f7..8f3e980 100644 --- a/app/system/internal/utils/configutil/json.go +++ b/app/system/internal/utils/configutil/json.go @@ -2,7 +2,8 @@ package configutil import ( "encoding/json" - "strings" + + "kra/pkg/protoutil" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/proto" @@ -11,68 +12,5 @@ import ( // MergeProtoJSON applies a JSON object as a partial protobuf update while // retaining fields omitted by the caller. func MergeProtoJSON(target proto.Message, patch json.RawMessage, options protojson.UnmarshalOptions) error { - currentRaw, err := protojson.MarshalOptions{UseProtoNames: false}.Marshal(target) - if err != nil { - return err - } - var current map[string]any - if err = json.Unmarshal(currentRaw, ¤t); err != nil { - return err - } - var incoming map[string]any - if err = json.Unmarshal(patch, &incoming); err != nil { - return err - } - incoming = normalizeJSONKeys(incoming).(map[string]any) - mergeJSONObjects(current, incoming) - merged, err := json.Marshal(current) - if err != nil { - return err - } - return options.Unmarshal(merged, target) -} - -func normalizeJSONKeys(value any) any { - switch item := value.(type) { - case map[string]any: - result := make(map[string]any, len(item)) - for key, nested := range item { - result[snakeToLowerCamel(key)] = normalizeJSONKeys(nested) - } - return result - case []any: - result := make([]any, len(item)) - for index, nested := range item { - result[index] = normalizeJSONKeys(nested) - } - return result - default: - return value - } -} - -func snakeToLowerCamel(value string) string { - if !strings.Contains(value, "_") { - return value - } - parts := strings.Split(value, "_") - result := parts[0] - for _, part := range parts[1:] { - if part != "" { - result += strings.ToUpper(part[:1]) + part[1:] - } - } - return result -} - -func mergeJSONObjects(target, patch map[string]any) { - for key, value := range patch { - if incoming, ok := value.(map[string]any); ok { - if existing, exists := target[key].(map[string]any); exists { - mergeJSONObjects(existing, incoming) - continue - } - } - target[key] = value - } + return protoutil.MergeProtoJSON(target, patch, options) } diff --git a/app/system/internal/utils/paymentutil/README.md b/app/system/internal/utils/paymentutil/README.md deleted file mode 100644 index 8459592..0000000 --- a/app/system/internal/utils/paymentutil/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Payment Utilities - -Stateless payment protocol helpers live here: amount conversion, status -normalization, JSON/XML extraction, and request signing. Provider adapters and -their SDK clients remain under `internal/integration/payment`. diff --git a/app/system/internal/utils/paymentutil/amount.go b/app/system/internal/utils/paymentutil/amount.go deleted file mode 100644 index 180fe74..0000000 --- a/app/system/internal/utils/paymentutil/amount.go +++ /dev/null @@ -1,97 +0,0 @@ -package paymentutil - -import ( - "errors" - "fmt" - "strconv" - "strings" -) - -// ParseIntegerAmount parses an integer amount expressed in the smallest -// currency unit. Floating point is intentionally not involved. -func ParseIntegerAmount(value string) (int64, error) { - value = strings.TrimSpace(value) - if value == "" { - return 0, errors.New("支付金额为空") - } - return strconv.ParseInt(value, 10, 64) -} - -// ParseDecimalAmount converts a major-unit decimal string to an integer amount -// using a power-of-ten scale, without using floating point. -func ParseDecimalAmount(value string, scale int64) (int64, error) { - value = strings.TrimSpace(value) - if value == "" || scale <= 0 { - return 0, errors.New("支付金额或换算比例无效") - } - if strings.HasPrefix(value, "-") { - return 0, errors.New("支付金额不能为负数") - } - parts := strings.Split(value, ".") - if len(parts) > 2 || parts[0] == "" { - return 0, fmt.Errorf("支付金额格式错误: %s", value) - } - digits, err := scaleDigits(scale) - if err != nil { - return 0, err - } - whole, err := strconv.ParseInt(parts[0], 10, 64) - if err != nil { - return 0, err - } - fraction := "" - if len(parts) == 2 { - fraction = parts[1] - } - if len(fraction) > digits { - return 0, fmt.Errorf("支付金额精度超过 %d 位", digits) - } - fraction += strings.Repeat("0", digits-len(fraction)) - fractionValue := int64(0) - if fraction != "" { - fractionValue, err = strconv.ParseInt(fraction, 10, 64) - if err != nil { - return 0, err - } - } - if whole > (int64(^uint64(0)>>1)-fractionValue)/scale { - return 0, errors.New("支付金额超出范围") - } - return whole*scale + fractionValue, nil -} - -func FormatDecimalAmount(amount, scale int64) (string, error) { - if amount <= 0 || scale <= 0 { - return "", errors.New("支付金额或换算比例无效") - } - digits, err := scaleDigits(scale) - if err != nil { - return "", err - } - if digits == 0 { - return strconv.FormatInt(amount, 10), nil - } - return fmt.Sprintf("%d.%0*d", amount/scale, digits, amount%scale), nil -} - -func scaleDigits(scale int64) (int, error) { - digits := 0 - for n := scale; n > 1 && n%10 == 0; n /= 10 { - digits++ - } - if scale <= 0 || scale != pow10(digits) { - return 0, errors.New("支付金额换算比例必须是 10 的幂") - } - return digits, nil -} - -func pow10(digits int) int64 { - value := int64(1) - for i := 0; i < digits; i++ { - if value > (int64(^uint64(0)>>1))/10 { - return 0 - } - value *= 10 - } - return value -} diff --git a/app/system/internal/utils/paymentutil/amount_test.go b/app/system/internal/utils/paymentutil/amount_test.go deleted file mode 100644 index 1d82d33..0000000 --- a/app/system/internal/utils/paymentutil/amount_test.go +++ /dev/null @@ -1,25 +0,0 @@ -package paymentutil - -import "testing" - -func TestDecimalAmountUsesIntegerMath(t *testing.T) { - got, err := ParseDecimalAmount("12.34", 100) - if err != nil || got != 1234 { - t.Fatalf("ParseDecimalAmount = %d, %v", got, err) - } - formatted, err := FormatDecimalAmount(got, 100) - if err != nil || formatted != "12.34" { - t.Fatalf("FormatDecimalAmount = %q, %v", formatted, err) - } -} - -func TestDecimalAmountRejectsUnsafeInput(t *testing.T) { - for _, value := range []string{"-1.00", "1.001", "1.2.3"} { - if _, err := ParseDecimalAmount(value, 100); err == nil { - t.Fatalf("ParseDecimalAmount(%q) accepted unsafe input", value) - } - } - if _, err := ParseDecimalAmount("1", 3); err == nil { - t.Fatal("non power-of-ten scale accepted") - } -} diff --git a/app/system/internal/utils/paymentutil/json.go b/app/system/internal/utils/paymentutil/json.go deleted file mode 100644 index c31d6bc..0000000 --- a/app/system/internal/utils/paymentutil/json.go +++ /dev/null @@ -1,66 +0,0 @@ -package paymentutil - -import ( - "encoding/json" - "fmt" - "strings" -) - -func JSONObject(raw []byte) map[string]any { - var value any - if json.Unmarshal(raw, &value) != nil { - return nil - } - object, _ := value.(map[string]any) - return object -} - -func NestedString(value any, keys ...string) string { - found := nestedValue(value, keys...) - if found == nil { - return "" - } - return strings.TrimSpace(fmt.Sprint(found)) -} - -func StringAtPath(value any, path string) string { - found := ValueAtPath(value, path) - if found == nil { - return "" - } - return strings.TrimSpace(fmt.Sprint(found)) -} - -func ValueAtPath(value any, path string) any { - path = strings.TrimSpace(path) - if path == "" { - return nil - } - current := value - for _, part := range strings.Split(path, ".") { - object, ok := current.(map[string]any) - if !ok { - return nil - } - current = object[part] - } - return current -} - -func nestedValue(value any, keys ...string) any { - object, ok := value.(map[string]any) - if !ok { - return nil - } - for _, key := range keys { - if found, exists := object[key]; exists && found != nil && fmt.Sprint(found) != "" { - return found - } - } - for _, nestedKey := range []string{"data", "result", "order", "transaction", "response"} { - if found := nestedValue(object[nestedKey], keys...); found != nil { - return found - } - } - return nil -} diff --git a/app/system/internal/utils/paymentutil/json_test.go b/app/system/internal/utils/paymentutil/json_test.go deleted file mode 100644 index 34f46e2..0000000 --- a/app/system/internal/utils/paymentutil/json_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package paymentutil - -import "testing" - -func TestNestedAndPathValues(t *testing.T) { - object := JSONObject([]byte(`{"data":{"status":"SUCCESS","amount":100}}`)) - if got := NestedString(object, "status"); got != "SUCCESS" { - t.Fatalf("NestedString = %q", got) - } - if got := StringAtPath(object, "data.amount"); got != "100" { - t.Fatalf("StringAtPath = %q", got) - } - if got := StringAtPath(object, "data.missing"); got != "" { - t.Fatalf("missing path = %q", got) - } -} diff --git a/app/system/internal/utils/paymentutil/signing.go b/app/system/internal/utils/paymentutil/signing.go deleted file mode 100644 index 7ba4b15..0000000 --- a/app/system/internal/utils/paymentutil/signing.go +++ /dev/null @@ -1,58 +0,0 @@ -package paymentutil - -import ( - "crypto/hmac" - "crypto/md5" - "crypto/sha256" - "encoding/hex" - "fmt" - "net/url" - "sort" - "strings" -) - -func WechatV2Sign(values map[string]string, key, signType string) string { - keys := make([]string, 0, len(values)) - for k, v := range values { - if k != "sign" && v != "" { - keys = append(keys, k) - } - } - sort.Strings(keys) - parts := make([]string, 0, len(keys)) - for _, k := range keys { - parts = append(parts, k+"="+values[k]) - } - raw := strings.Join(parts, "&") + "&key=" + key - if strings.EqualFold(signType, "HMAC-SHA256") { - return HMACSHA256Hex([]byte(raw), key, true) - } - sum := md5.Sum([]byte(raw)) - return strings.ToUpper(hex.EncodeToString(sum[:])) -} - -func MD5Canonical(values map[string]any, secret string) string { - keys := make([]string, 0, len(values)) - for key, value := range values { - if key != "sign" && value != nil && fmt.Sprint(value) != "" { - keys = append(keys, key) - } - } - sort.Strings(keys) - query := url.Values{} - for _, key := range keys { - query.Set(key, fmt.Sprint(values[key])) - } - sum := md5.Sum([]byte(query.Encode() + "&key=" + secret)) - return strings.ToUpper(hex.EncodeToString(sum[:])) -} - -func HMACSHA256Hex(raw []byte, secret string, upper bool) string { - h := hmac.New(sha256.New, []byte(secret)) - _, _ = h.Write(raw) - result := hex.EncodeToString(h.Sum(nil)) - if upper { - return strings.ToUpper(result) - } - return result -} diff --git a/app/system/internal/utils/paymentutil/signing_test.go b/app/system/internal/utils/paymentutil/signing_test.go deleted file mode 100644 index a85e011..0000000 --- a/app/system/internal/utils/paymentutil/signing_test.go +++ /dev/null @@ -1,12 +0,0 @@ -package paymentutil - -import "testing" - -func TestWechatV2SignIsStableAndExcludesSign(t *testing.T) { - values := map[string]string{"b": "2", "a": "1", "sign": "old"} - first := WechatV2Sign(values, "secret", "MD5") - values["sign"] = "different" - if second := WechatV2Sign(values, "secret", "MD5"); first != second { - t.Fatalf("signature changed when sign field changed: %q != %q", first, second) - } -} diff --git a/app/system/internal/utils/paymentutil/status.go b/app/system/internal/utils/paymentutil/status.go deleted file mode 100644 index 12b6030..0000000 --- a/app/system/internal/utils/paymentutil/status.go +++ /dev/null @@ -1,63 +0,0 @@ -package paymentutil - -import ( - "fmt" - "strings" -) - -func NormalizeStatus(value, fallback string) string { - switch strings.ToUpper(strings.TrimSpace(value)) { - case "SUCCESS", "PAID", "TRADE_SUCCESS", "TRADE_FINISHED", "COMPLETED", "PAY_SUCCESS": - return "success" - case "WAIT_BUYER_PAY", "USERPAYING", "NOTPAY", "PROCESSING", "PENDING", "CREATED", "ACCEPT", "PAYING": - return "pending" - case "CLOSED", "TRADE_CLOSED", "CANCELLED", "CANCELED", "REVOKED", "REFUND", "REFUNDED", "FAILED", "FAIL", "PAYERROR": - return "failed" - default: - return fallback - } -} - -func ConfiguredInt64(values map[string]any, key string, fallback int64) int64 { - value, ok := values[key] - if !ok { - return fallback - } - parsed, err := ParseIntegerAmount(strings.TrimSpace(toString(value))) - if err != nil || parsed <= 0 { - return fallback - } - return parsed -} - -func ConfiguredValues(values map[string]any, key string) []string { - result := []string{} - for _, item := range strings.Split(toString(values[key]), ",") { - item = strings.ToUpper(strings.TrimSpace(item)) - if item != "" { - result = append(result, item) - } - } - return result -} - -func ContainsFold(values []string, value string) bool { - value = strings.ToUpper(strings.TrimSpace(value)) - for _, item := range values { - if item == value { - return true - } - } - return false -} - -func toString(value any) string { - if value == nil { - return "" - } - return strings.TrimSpace(strings.ReplaceAll(strings.TrimSpace(stringify(value)), "", "")) -} - -func stringify(value any) string { - return fmt.Sprint(value) -} diff --git a/app/system/internal/utils/paymentutil/xml.go b/app/system/internal/utils/paymentutil/xml.go deleted file mode 100644 index 6c46733..0000000 --- a/app/system/internal/utils/paymentutil/xml.go +++ /dev/null @@ -1,60 +0,0 @@ -package paymentutil - -import ( - "bytes" - "encoding/xml" - "io" - "sort" - "strings" -) - -type xmlValue struct { - XMLName xml.Name - Value string `xml:",chardata"` -} - -func XMLValues(raw []byte) (map[string]string, error) { - decoder := xml.NewDecoder(bytes.NewReader(raw)) - result := map[string]string{} - for { - token, err := decoder.Token() - if err == io.EOF { - return result, nil - } - if err != nil { - return nil, err - } - start, ok := token.(xml.StartElement) - if !ok || start.Name.Local == "xml" { - continue - } - var value xmlValue - if err = decoder.DecodeElement(&value, &start); err != nil { - return nil, err - } - if value.Value != "" { - result[start.Name.Local] = value.Value - } - } -} - -func XMLEncode(values map[string]string) []byte { - var b strings.Builder - b.WriteString("") - keys := make([]string, 0, len(values)) - for key := range values { - keys = append(keys, key) - } - sort.Strings(keys) - for _, key := range keys { - b.WriteString("<") - b.WriteString(key) - b.WriteString(">") - } - b.WriteString("") - return []byte(b.String()) -} diff --git a/pkg/README.md b/pkg/README.md index 986e4b3..dacc4ae 100644 --- a/pkg/README.md +++ b/pkg/README.md @@ -1,4 +1,4 @@ -# Platform +# Shared Packages 这里放跨业务模块的基础设施,不放具体业务表或业务用例。 @@ -7,7 +7,8 @@ - `database`:跨模块共享的 GORM 支持、分页和迁移执行器 - `module`:模块迁移、后台元数据和路由注册协议 - `task`:跨模块共享的进程内任务注册表和贡献协议 +- `logging`:跨 app 复用的结构化日志能力 +- `paymentkit`:支付金额、签名、状态和报文处理纯函数 -平台层只能提供机制,不能引用 `internal/modules/*`。数据库配置加载、系统集成配置 -和系统表仍由 system 模块负责;未来提炼公共连接管理时,也必须先形成不带系统 -业务语义的稳定接口,再移动到这里。 +`pkg` 只能提供机制和稳定协议,不能引用任何 `app/*/internal`。数据库配置加载、 +系统集成配置、系统表和 provider 生命周期仍由 `app/system` 负责。 diff --git a/pkg/logging/source.go b/pkg/logging/source.go index 0b8e17c..f37673b 100644 --- a/pkg/logging/source.go +++ b/pkg/logging/source.go @@ -50,9 +50,9 @@ func skipStackFile(filename string) bool { "/go/pkg/mod/", "/go.uber.org/", "/gorm.io/", - "/internal/logging/", - "/internal/server/middleware/", - "/internal/server/router/", + "/pkg/logging/", + "/internal/transport/middleware/", + "/internal/transport/router/", } { if strings.Contains(normalized, marker) { return true diff --git a/pkg/logging/zap.go b/pkg/logging/zap.go index 3bedc66..caffb1f 100644 --- a/pkg/logging/zap.go +++ b/pkg/logging/zap.go @@ -25,7 +25,7 @@ type Options struct { } // ErrorEntry is the storage-neutral representation of an Error-level log. -// Keeping it in internal/logging lets the log core report failures without taking a +// Keeping it in pkg/logging lets the log core report failures without taking a // dependency on the application service or persistence layers. type ErrorEntry struct { Form, Info, Level, RequestID, TraceID string @@ -264,7 +264,7 @@ func isGORMLoggerEntry(filename string, fields []zapcore.Field) bool { } normalized := strings.ReplaceAll(filename, "\\", "/") return strings.HasSuffix(normalized, "/gorm_logger_writer.go") || - strings.HasSuffix(normalized, "/internal/data/gorm_logger.go") + strings.HasSuffix(normalized, "/pkg/database/gormkit/logger.go") } func errorEntryFromZap(entry zapcore.Entry, fields []zapcore.Field) ErrorEntry { diff --git a/pkg/logging/zap_test.go b/pkg/logging/zap_test.go index 74cebf1..be393ba 100644 --- a/pkg/logging/zap_test.go +++ b/pkg/logging/zap_test.go @@ -105,7 +105,7 @@ func TestErrorSinkSkipsGORMBridge(t *testing.T) { base := zapcore.NewNopCore() core := &routedFileCore{base: base, encoder: zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), level: zapcore.ErrorLevel, root: root, state: &routedFileState{writers: map[string]*DailyWriter{}}, errorSink: state} defer core.Close() - for _, filename := range []string{"/tmp/gorm_logger_writer.go", "/workspace/internal/data/gorm_logger.go"} { + for _, filename := range []string{"/tmp/gorm_logger_writer.go", "/workspace/pkg/database/gormkit/logger.go"} { if err := core.Write(zapcore.Entry{Level: zapcore.ErrorLevel, Message: "database failed", Caller: zapcore.EntryCaller{Defined: true, File: filename, Line: 10}}, nil); err != nil { t.Fatal(err) }