diff --git a/Makefile b/Makefile
index 68324c9..9f8be42 100644
--- a/Makefile
+++ b/Makefile
@@ -49,7 +49,7 @@ gen-swagger: install-swaggo
gen-proto: install-proto
protoc --go_out=. --go_opt=paths=source_relative \
--go-grpc_out=. --go-grpc_opt=paths=source_relative \
- proto/*.proto
+ proto/*.proto
# Targets for development
@@ -70,7 +70,7 @@ setup-dependencies: build get-front get-problem-packages
./bin/clean; \
else \
docker compose up -d postgres redis minio; \
- @echo "Wait 10 seconds for db setup"; \
+ echo "Wait 10 seconds for db setup"; \
sleep 10s; \
fi
./bin/init;
diff --git a/cmd/clean/main.go b/cmd/clean/main.go
index 8300fb9..d07c5da 100644
--- a/cmd/clean/main.go
+++ b/cmd/clean/main.go
@@ -2,6 +2,7 @@ package main
import (
"context"
+ "log/slog"
"github.com/minio/minio-go/v7"
judge_model "github.com/oj-lab/platform/models/judge"
@@ -11,14 +12,12 @@ import (
gorm_agent "github.com/oj-lab/platform/modules/agent/gorm"
minio_agent "github.com/oj-lab/platform/modules/agent/minio"
redis_agent "github.com/oj-lab/platform/modules/agent/redis"
-
- log_module "github.com/oj-lab/platform/modules/log"
)
func clearCasbin() {
enforcer := casbin_agent.GetDefaultCasbinEnforcer()
enforcer.ClearPolicy() // no err return
- log_module.AppLogger().Info("Clear Casbin success")
+ slog.Info("Clear Casbin success")
}
func removeMinioObjects() {
@@ -30,7 +29,7 @@ func removeMinioObjects() {
opts := minio.ListObjectsOptions{Recursive: true}
for object := range minioClient.ListObjects(context.Background(), minio_agent.GetBucketName(), opts) {
if object.Err != nil {
- log_module.AppLogger().WithError(object.Err).Error("Get object error")
+ slog.With("err", object.Err).Error("Get object error")
}
objectsCh <- object
}
@@ -38,10 +37,10 @@ func removeMinioObjects() {
errorCh := minioClient.RemoveObjects(context.Background(), minio_agent.GetBucketName(), objectsCh, minio.RemoveObjectsOptions{})
for e := range errorCh {
- log_module.AppLogger().WithError(e.Err).Error("Failed to remove " + e.ObjectName)
+ slog.With("err", e.Err).Error("Failed to remove " + e.ObjectName)
}
- log_module.AppLogger().Info("Remove Minio Objects success")
+ slog.Info("Remove Minio Objects success")
}
func clearRedis() {
@@ -49,10 +48,10 @@ func clearRedis() {
redis_agent := redis_agent.GetDefaultRedisClient()
err := redis_agent.FlushDB(ctx).Err()
if err != nil {
- log_module.AppLogger().WithError(err).Error("Failed to clear redis")
+ slog.With("err", err).Error("Failed to clear redis")
}
- log_module.AppLogger().Info("Clear Redis success")
+ slog.Info("Clear Redis success")
}
func clearDB() {
db := gorm_agent.GetDefaultDB()
@@ -73,7 +72,7 @@ func clearDB() {
panic("failed to drop tables")
}
- log_module.AppLogger().Info("Clear DB success")
+ slog.Info("Clear DB success")
}
func main() {
diff --git a/cmd/init/db.go b/cmd/init/db.go
index 3812002..9721157 100644
--- a/cmd/init/db.go
+++ b/cmd/init/db.go
@@ -2,19 +2,19 @@ package main
import (
"fmt"
+ "log/slog"
judge_model "github.com/oj-lab/platform/models/judge"
problem_model "github.com/oj-lab/platform/models/problem"
user_model "github.com/oj-lab/platform/models/user"
gorm_agent "github.com/oj-lab/platform/modules/agent/gorm"
- config_module "github.com/oj-lab/platform/modules/config"
- log_module "github.com/oj-lab/platform/modules/log"
+ core_module "github.com/oj-lab/platform/modules/core"
)
-const rootPasswordProp = "auth.root_password"
+const rootPasswordConfigKey = "auth.root_password"
func initDB() {
- rootPassword := config_module.AppConfig().GetString(rootPasswordProp)
+ rootPassword := core_module.Config.GetString(rootPasswordConfigKey)
db := gorm_agent.GetDefaultDB()
err := db.AutoMigrate(
&user_model.User{},
@@ -47,5 +47,5 @@ func initDB() {
panic(fmt.Sprintf("failed to create anonymous user: %v", err))
}
- log_module.AppLogger().Info("migrate tables ans users success")
+ slog.Info("migrate tables ans users success")
}
diff --git a/cmd/init/problem_package.go b/cmd/init/problem_package.go
index f0e2974..200fe79 100644
--- a/cmd/init/problem_package.go
+++ b/cmd/init/problem_package.go
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"io/fs"
+ "log/slog"
"os"
"path"
"path/filepath"
@@ -15,8 +16,7 @@ import (
problem_model "github.com/oj-lab/platform/models/problem"
gorm_agent "github.com/oj-lab/platform/modules/agent/gorm"
minio_agent "github.com/oj-lab/platform/modules/agent/minio"
- config_module "github.com/oj-lab/platform/modules/config"
- log_module "github.com/oj-lab/platform/modules/log"
+ core_module "github.com/oj-lab/platform/modules/core"
"gopkg.in/yaml.v2"
)
@@ -24,12 +24,12 @@ func loadProblemPackages(ctx context.Context) {
db := gorm_agent.GetDefaultDB()
minioClient := minio_agent.GetMinioClient()
- packagePath := path.Join(config_module.ProjectRoot(), "problem-packages/icpc")
+ packagePath := path.Join(core_module.ProjectRoot(), "problem-packages/icpc")
// Load Dirs under `packagePath`
problemPackageDirs, err := os.ReadDir(packagePath)
if err != nil {
- log_module.AppLogger().WithError(err).Error("Read package path failed")
+ slog.With("err", err).Error("Read package path failed")
panic(err)
}
for _, problemPackageDir := range problemPackageDirs {
@@ -51,7 +51,7 @@ func loadProblemPackages(ctx context.Context) {
problemPackagePath := path.Join(packagePath, problemPackageDir.Name())
err := filepath.Walk(problemPackagePath, func(path string, info fs.FileInfo, err error) error {
if err != nil {
- log_module.AppLogger().WithError(err).Error("Walk package path failed")
+ slog.With("err", err).Error("Walk package path failed")
return err
}
if info == nil {
@@ -61,33 +61,33 @@ func loadProblemPackages(ctx context.Context) {
return nil
}
relativePath := strings.Replace(path, packagePath, "", 1)
- log_module.AppLogger().
- WithField("relativePath", relativePath).
- WithField("Ext", filepath.Ext(relativePath)).
- WithField("Dir", filepath.Dir(relativePath)).
+ slog.
+ With("relativePath", relativePath).
+ With("Ext", filepath.Ext(relativePath)).
+ With("Dir", filepath.Dir(relativePath)).
Debug("Read file from package")
if filepath.Base(relativePath) == "problem.yaml" {
resultMap := make(map[string]interface{})
yamlFile, err := os.ReadFile(path)
if err != nil {
- log_module.AppLogger().WithError(err).Error("Read problem.yaml failed")
+ slog.With("err", err).Error("Read problem.yaml failed")
}
err = yaml.Unmarshal(yamlFile, &resultMap)
if err != nil {
- log_module.AppLogger().WithError(err).Error("Unmarshal problem.yaml failed")
+ slog.With("err", err).Error("Unmarshal problem.yaml failed")
}
- log_module.AppLogger().WithField("resultMap", reflect.TypeOf(resultMap["limits"])).Debug("Read problem.yaml")
+ slog.With("resultMap", reflect.TypeOf(resultMap["limits"])).Debug("Read problem.yaml")
if resultMap["name"] == nil {
- log_module.AppLogger().Error("Problem name is nil")
+ slog.Error("Problem name is nil")
return nil
}
title = resultMap["name"].(string)
if title == "" {
- log_module.AppLogger().Error("Problem title is empty")
+ slog.Error("Problem title is empty")
}
slug = strings.Split(relativePath, "/")[1]
- log_module.AppLogger().WithField("title", title).WithField("slug", slug).Debug("Read problem.yaml")
+ slog.With("title", title).With("slug", slug).Debug("Read problem.yaml")
if limits, ok := resultMap["limits"].(map[interface{}]interface{}); ok {
if memoryLimit, ok := limits["memory"].(int); ok {
limitDescription += fmt.Sprintf("
Memory Limit: %d MB\n", memoryLimit)
@@ -112,20 +112,20 @@ func loadProblemPackages(ctx context.Context) {
if filepath.Base(relativePath) == "problem.md" {
content, err := os.ReadFile(path)
if err != nil {
- log_module.AppLogger().WithError(err).Error("Read problem.md failed")
+ slog.With("err", err).Error("Read problem.md failed")
}
description = string(content)
- log_module.AppLogger().WithField("description", description).Debug("Read problem.md")
+ slog.With("description", description).Debug("Read problem.md")
}
if filepath.Base(relativePath) == ".timelimit" {
timeLimitStr, err := os.ReadFile(path)
if err != nil {
- log_module.AppLogger().WithError(err).Error("Read time limit file failed")
+ slog.With("err", err).Error("Read time limit file failed")
return nil
}
timeLimit, err := strconv.Atoi(strings.Trim(string(timeLimitStr), "\n"))
if err != nil {
- log_module.AppLogger().WithError(err).Error("Parse time limit failed")
+ slog.With("err", err).Error("Parse time limit failed")
return nil
}
limitDescription += fmt.Sprintf("Time Limit: %d s\n", timeLimit)
@@ -133,18 +133,18 @@ func loadProblemPackages(ctx context.Context) {
if filepath.Ext(relativePath) == ".in" && strings.HasSuffix(filepath.Dir(relativePath), "sample") {
ansPath := strings.Replace(path, ".in", ".ans", 1)
if _, err := os.Stat(ansPath); err != nil {
- log_module.AppLogger().WithField("path", ansPath).Error("Answer file not found")
+ slog.With("path", ansPath).Error("Answer file not found")
return nil
}
input, err := os.ReadFile(path)
if err != nil {
- log_module.AppLogger().WithError(err).Error("Read input file failed")
+ slog.With("err", err).Error("Read input file failed")
return nil
}
inputStr := strings.Trim(string(input), "\n")
output, err := os.ReadFile(ansPath)
if err != nil {
- log_module.AppLogger().WithError(err).Error("Read output file failed")
+ slog.With("err", err).Error("Read output file failed")
return nil
}
outputStr := strings.Trim(string(output), "\n")
@@ -159,7 +159,7 @@ func loadProblemPackages(ctx context.Context) {
path,
minio.PutObjectOptions{})
if err != nil {
- log_module.AppLogger().WithError(err).Error("Put object to minio failed")
+ slog.With("err", err).Error("Put object to minio failed")
}
return err
})
@@ -196,5 +196,5 @@ func loadProblemPackages(ctx context.Context) {
}
}
- log_module.AppLogger().Info("Problem loaded")
+ slog.Info("Problem loaded")
}
diff --git a/cmd/rpc_server/main.go b/cmd/rpc_server/main.go
index daf485d..3dae702 100644
--- a/cmd/rpc_server/main.go
+++ b/cmd/rpc_server/main.go
@@ -9,18 +9,18 @@ import (
"net"
"github.com/oj-lab/platform/cmd/rpc_server/impls"
- config_module "github.com/oj-lab/platform/modules/config"
+ core_module "github.com/oj-lab/platform/modules/core"
"github.com/oj-lab/platform/proto"
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)
const (
- portProp = "rpc-server.port"
+ portConfigKey = "rpc-server.port"
)
var (
- port = config_module.AppConfig().GetInt(portProp)
+ port = core_module.Config.GetInt(portConfigKey)
)
func main() {
diff --git a/cmd/web_server/handler/auth.go b/cmd/web_server/handler/auth.go
index a7b8b2a..a82a670 100644
--- a/cmd/web_server/handler/auth.go
+++ b/cmd/web_server/handler/auth.go
@@ -2,6 +2,7 @@ package handler
import (
"fmt"
+ "log/slog"
"net/http"
"time"
@@ -11,21 +12,20 @@ import (
user_model "github.com/oj-lab/platform/models/user"
gorm_agent "github.com/oj-lab/platform/modules/agent/gorm"
auth_module "github.com/oj-lab/platform/modules/auth"
- config_module "github.com/oj-lab/platform/modules/config"
- log_module "github.com/oj-lab/platform/modules/log"
+ core_module "github.com/oj-lab/platform/modules/core"
gin_utils "github.com/oj-lab/platform/modules/utils/gin"
user_service "github.com/oj-lab/platform/services/user"
)
const (
- emailBacklistProp = "auth.email_backlist"
- callbackURL = "/auth/github/callback"
+ emailBacklistConfigKey = "auth.email_backlist"
+ callbackURL = "/auth/github/callback"
)
var emailBacklist = map[string]bool{}
func init() {
- emailBacklistSlice := config_module.AppConfig().GetStringSlice(emailBacklistProp)
+ emailBacklistSlice := core_module.Config.GetStringSlice(emailBacklistConfigKey)
for _, email := range emailBacklistSlice {
emailBacklist[email] = true
}
@@ -52,7 +52,7 @@ func githubCallback(ginCtx *gin.Context) {
return
}
- log_module.AppLogger().WithField("tokenResponse", tokenResponse).Info("github callback")
+ slog.With("tokenResponse", tokenResponse).Info("github callback")
githubUser, err := auth_module.GetGithubUser(tokenResponse.AccessToken)
if err != nil {
gin_utils.NewInternalError(ginCtx, fmt.Sprintf("failed to get github user: %v", err))
diff --git a/cmd/web_server/handler/event.go b/cmd/web_server/handler/event.go
index 68e01fb..95c1da1 100644
--- a/cmd/web_server/handler/event.go
+++ b/cmd/web_server/handler/event.go
@@ -3,10 +3,10 @@ package handler
import (
"fmt"
"io"
+ "log/slog"
"time"
"github.com/gin-gonic/gin"
- log_module "github.com/oj-lab/platform/modules/log"
)
func SetupEventRouter(baseRoute *gin.RouterGroup) {
@@ -33,7 +33,7 @@ func Stream(ginCtx *gin.Context) {
ginCtx.Stream(func(w io.Writer) bool {
// With event type
message := fmt.Sprintf("event: %s\ndata: %s\n\n", "eventType", time.Now().String())
- log_module.AppLogger().Infof("Send message:\n%s", message)
+ slog.Info(fmt.Sprintf("Send message:\n%s", message))
fmt.Fprint(w, message)
time.Sleep(1 * time.Second)
counter++
diff --git a/cmd/web_server/handler/problem.go b/cmd/web_server/handler/problem.go
index 20e70e5..fd31a6d 100644
--- a/cmd/web_server/handler/problem.go
+++ b/cmd/web_server/handler/problem.go
@@ -232,8 +232,8 @@ func checkProblemSlug(ginCtx *gin.Context) {
// PostJudgeBody
//
// @Description The body of a judge request, containing the code and the language used for the judge.
-// @Property code (string) required "The source code of the judge" minlength(1)
-// @Property language (ProgrammingLanguage) required "The programming language used for the judge"
+// @ConfigKeyerty code (string) required "The source code of the judge" minlength(1)
+// @ConfigKeyerty language (ProgrammingLanguage) required "The programming language used for the judge"
type PostJudgeBody struct {
Code string `json:"code" binding:"required"`
Language judge_model.ProgrammingLanguage `json:"language" binding:"required"`
diff --git a/cmd/web_server/handler/swaggo.go b/cmd/web_server/handler/swaggo.go
index a987a44..21bf0d5 100644
--- a/cmd/web_server/handler/swaggo.go
+++ b/cmd/web_server/handler/swaggo.go
@@ -11,8 +11,8 @@ import (
)
const (
- servicePortProp = "service.port"
- serviceHostProp = "service.host"
+ servicePortConfigKey = "service.port"
+ serviceHostConfigKey = "service.host"
)
var (
@@ -24,8 +24,8 @@ func SetupSwaggoRouter(r *gin.RouterGroup) {
}
func init() {
- sevicePort := viper.GetUint(servicePortProp)
- seviceHost := viper.GetString(serviceHostProp)
+ sevicePort := viper.GetUint(servicePortConfigKey)
+ seviceHost := viper.GetString(serviceHostConfigKey)
swaggerHost = fmt.Sprintf("%s:%d", seviceHost, sevicePort)
println("Swagger host is set to: " + swaggerHost)
// programmatically set swagger info
diff --git a/cmd/web_server/main.go b/cmd/web_server/main.go
index 06ba44c..0e329b3 100644
--- a/cmd/web_server/main.go
+++ b/cmd/web_server/main.go
@@ -2,6 +2,7 @@ package main
import (
"fmt"
+ "log/slog"
"os"
"path/filepath"
"runtime"
@@ -9,34 +10,27 @@ import (
"github.com/gin-gonic/gin"
"github.com/oj-lab/platform/cmd/web_server/handler"
"github.com/oj-lab/platform/cmd/web_server/middleware"
+ sloggin "github.com/samber/slog-gin"
- config_module "github.com/oj-lab/platform/modules/config"
-
- log_module "github.com/oj-lab/platform/modules/log"
+ core_module "github.com/oj-lab/platform/modules/core"
)
const (
- serviceForceConsoleColorProp = "service.force_console_color"
- servicePortProp = "service.port"
- serviceModeProp = "service.mode"
- swaggerOnProp = "service.swagger_on"
- frontendDistProp = "service.frontend_dist"
+ servicePortConfigKey = "service.port"
+ swaggerOnConfigKey = "service.swagger_on"
+ frontendDistConfigKey = "service.frontend_dist"
)
var (
- serviceForceConsoleColor bool
- servicePort uint
- serviceMode string
- swaggerOn bool
- frontendDist string
+ servicePort uint
+ swaggerOn bool
+ frontendDist string
)
func init() {
- serviceForceConsoleColor = config_module.AppConfig().GetBool(serviceForceConsoleColorProp)
- servicePort = config_module.AppConfig().GetUint(servicePortProp)
- serviceMode = config_module.AppConfig().GetString(serviceModeProp)
- swaggerOn = config_module.AppConfig().GetBool(swaggerOnProp)
- frontendDist = config_module.AppConfig().GetString(frontendDistProp)
+ servicePort = core_module.Config.GetUint(servicePortConfigKey)
+ swaggerOn = core_module.Config.GetBool(swaggerOnConfigKey)
+ frontendDist = core_module.Config.GetString(frontendDistConfigKey)
}
func GetProjectDir() string {
@@ -47,20 +41,19 @@ func GetProjectDir() string {
}
func main() {
- if serviceForceConsoleColor {
- gin.ForceConsoleColor()
- }
- r := gin.Default()
+ gin.SetMode(gin.ReleaseMode)
+ r := gin.New()
+ r.Use(sloggin.New(slog.Default().With("module", "gin")))
+ r.Use(gin.Recovery())
r.Use(middleware.HandleError)
- gin.SetMode(serviceMode)
baseRouter := r.Group("/")
if frontendDist != "" {
// If dist folder is not empty, serve frontend
if _, err := os.Stat(frontendDist); os.IsNotExist(err) {
- log_module.AppLogger().Warn("Frontend dist is set but folder not found")
+ slog.Warn("Frontend dist is set but folder not found")
} else {
- log_module.AppLogger().Info("Serving frontend...")
+ slog.Info("Serving frontend...")
r.LoadHTMLFiles(frontendDist + "/index.html")
handler.SetupFrontendRoute(baseRouter, frontendDist)
r.NoRoute(handler.RenderHTML)
@@ -68,7 +61,7 @@ func main() {
}
if swaggerOn {
- log_module.AppLogger().Info("Serving swagger Doc...")
+ slog.Info("Serving swagger Doc...")
handler.SetupSwaggoRouter(baseRouter)
}
handler.SetupAuthRouter(baseRouter)
diff --git a/cmd/web_server/middleware/casbin.go b/cmd/web_server/middleware/casbin.go
index a2d72f8..608de97 100644
--- a/cmd/web_server/middleware/casbin.go
+++ b/cmd/web_server/middleware/casbin.go
@@ -1,9 +1,10 @@
package middleware
import (
+ "log/slog"
+
"github.com/gin-gonic/gin"
casbin_agent "github.com/oj-lab/platform/modules/agent/casbin"
- log_module "github.com/oj-lab/platform/modules/log"
gin_utils "github.com/oj-lab/platform/modules/utils/gin"
)
@@ -21,7 +22,7 @@ func BuildCasbinEnforceHandlerWithDomain(domain string) gin.HandlerFunc {
allow, err := enforcer.Enforce(casbin_agent.UserSubjectPrefix+ls.Key.Account, "_", domain, path, method)
if err != nil {
- log_module.AppLogger().Errorf("Failed to enforce: %v", err)
+ slog.With("err", err).Error("Failed to enforce")
gin_utils.NewInternalError(ginCtx, "Failed to enforce")
ginCtx.Abort()
return
diff --git a/cmd/web_server/middleware/error.go b/cmd/web_server/middleware/error.go
index bbee31c..77f0a44 100644
--- a/cmd/web_server/middleware/error.go
+++ b/cmd/web_server/middleware/error.go
@@ -2,10 +2,10 @@ package middleware
import (
"fmt"
+ "log/slog"
"net/http"
"github.com/gin-gonic/gin"
- log_module "github.com/oj-lab/platform/modules/log"
gin_utils "github.com/oj-lab/platform/modules/utils/gin"
)
@@ -27,7 +27,8 @@ func HandleError(ginCtx *gin.Context) {
errCount := len(ginCtx.Errors)
if errCount > 0 {
- log_module.AppLogger().Errorf("Last error from GIN middleware: %+v", ginCtx.Errors[errCount-1].Err)
+ slog.With("err", ginCtx.Errors[errCount-1].Err).
+ Error("Last error from GIN middleware")
err := GetServiceError(*ginCtx.Errors[errCount-1])
ginCtx.JSON(err.Code, gin.H{
"code": err.Code,
diff --git a/cmd/web_server/middleware/internal.go b/cmd/web_server/middleware/internal.go
index f6bbb35..57ea4b1 100644
--- a/cmd/web_server/middleware/internal.go
+++ b/cmd/web_server/middleware/internal.go
@@ -4,12 +4,12 @@ import (
"fmt"
"github.com/gin-gonic/gin"
- config_module "github.com/oj-lab/platform/modules/config"
+ core_module "github.com/oj-lab/platform/modules/core"
gin_utils "github.com/oj-lab/platform/modules/utils/gin"
)
const (
- internalTokenProp = "service.internal_token"
+ internalTokenConfigKey = "service.internal_token"
)
var (
@@ -17,7 +17,7 @@ var (
)
func init() {
- internalToken = config_module.AppConfig().GetString(internalTokenProp)
+ internalToken = core_module.Config.GetString(internalTokenConfigKey)
}
func HandleRequireInternalToken(ginCtx *gin.Context) {
diff --git a/config.toml b/config.toml
index 40da5d2..5d23bac 100644
--- a/config.toml
+++ b/config.toml
@@ -1,10 +1,8 @@
[log]
level = "debug"
-pretty_json = true
-time_on = true
-time_format = "2000-01-01 00:00:00"
+format = "text"
-[database]
+[gorm]
dsn = "user=postgres password=postgres host=localhost port=5432 dbname=oj_lab sslmode=disable TimeZone=Asia/Shanghai"
[redis]
diff --git a/go.mod b/go.mod
index f5d6948..59598fc 100644
--- a/go.mod
+++ b/go.mod
@@ -7,7 +7,6 @@ toolchain go1.23.1
require (
github.com/google/uuid v1.6.0
github.com/redis/go-redis/v9 v9.6.1
- github.com/sirupsen/logrus v1.9.3
github.com/spf13/viper v1.19.0
gorm.io/driver/postgres v1.5.9
gorm.io/gorm v1.25.12
@@ -39,6 +38,7 @@ require (
github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 // indirect
github.com/jackc/puddle/v2 v2.2.2 // indirect
github.com/lib/pq v1.10.9 // indirect
+ github.com/lmittmann/tint v1.0.7 // indirect
github.com/microsoft/go-mssqldb v1.7.2 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/paulmach/orb v0.11.1 // indirect
@@ -48,6 +48,7 @@ require (
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/sagikazarmark/locafero v0.6.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
+ github.com/samber/slog-gin v1.14.1 // indirect
github.com/segmentio/asm v1.2.0 // indirect
github.com/shopspring/decimal v1.4.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
@@ -55,7 +56,7 @@ require (
go.opentelemetry.io/otel/trace v1.30.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
- golang.org/x/sync v0.8.0 // indirect
+ golang.org/x/sync v0.10.0 // indirect
gorm.io/driver/mysql v1.5.7 // indirect
gorm.io/driver/sqlserver v1.5.3 // indirect
gorm.io/plugin/dbresolver v1.5.3 // indirect
@@ -129,9 +130,9 @@ require (
github.com/swaggo/files v1.0.1
github.com/swaggo/gin-swagger v1.6.0
github.com/ugorji/go/codec v1.2.12 // indirect
- golang.org/x/crypto v0.27.0 // indirect
+ golang.org/x/crypto v0.31.0 // indirect
golang.org/x/net v0.29.0 // indirect
- golang.org/x/sys v0.25.0 // indirect
- golang.org/x/text v0.18.0 // indirect
+ golang.org/x/sys v0.28.0 // indirect
+ golang.org/x/text v0.21.0 // indirect
google.golang.org/protobuf v1.34.2
)
diff --git a/go.sum b/go.sum
index d100468..71a1dc2 100644
--- a/go.sum
+++ b/go.sum
@@ -191,6 +191,8 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/lmittmann/tint v1.0.7 h1:D/0OqWZ0YOGZ6AyC+5Y2kD8PBEzBk6rFHVSfOqCkF9Y=
+github.com/lmittmann/tint v1.0.7/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
@@ -243,12 +245,12 @@ github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3
github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0=
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
+github.com/samber/slog-gin v1.14.1 h1:6DMAcy2gBFyyztrpYIvAcXZH1sA/j75iSSXuqhirLtg=
+github.com/samber/slog-gin v1.14.1/go.mod h1:yS2C+cX5tRnPX0MqDby7a3tRFsJuMk7hNwAunyfDxQk=
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
-github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
-github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
@@ -314,6 +316,8 @@ golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98y
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
+golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
+golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -347,6 +351,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
+golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -355,7 +361,6 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -364,6 +369,8 @@ golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
+golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
@@ -383,6 +390,8 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
+golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
+golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
diff --git a/modules/agent/casbin/enforcer.go b/modules/agent/casbin/enforcer.go
index 827155e..f4f011b 100644
--- a/modules/agent/casbin/enforcer.go
+++ b/modules/agent/casbin/enforcer.go
@@ -1,6 +1,7 @@
package casbin_agent
import (
+ "log/slog"
"strings"
"github.com/casbin/casbin/persist"
@@ -10,7 +11,6 @@ import (
rediswatcher "github.com/casbin/redis-watcher/v2"
gorm_agent "github.com/oj-lab/platform/modules/agent/gorm"
redis_agent "github.com/oj-lab/platform/modules/agent/redis"
- log_module "github.com/oj-lab/platform/modules/log"
)
var casbinEnforcer *casbin.SyncedCachedEnforcer
@@ -53,10 +53,10 @@ func GetDefaultCasbinEnforcer() *casbin.SyncedCachedEnforcer {
if err != nil {
panic(err)
}
- log_module.AppLogger().Info("Casbin enforcer watcher initialized")
+ slog.Info("Casbin enforcer watcher initialized")
}
casbinEnforcer.AddFunction("keyMatchGin", keyMatchGinFunc)
- log_module.AppLogger().Info("Casbin enforcer initialized")
+ slog.Info("Casbin enforcer initialized")
}
return casbinEnforcer
diff --git a/modules/agent/gorm/database.go b/modules/agent/gorm/database.go
index 8886589..3058abb 100644
--- a/modules/agent/gorm/database.go
+++ b/modules/agent/gorm/database.go
@@ -1,19 +1,24 @@
package gorm_agent
import (
- config_module "github.com/oj-lab/platform/modules/config"
+ "log/slog"
+
+ core_module "github.com/oj-lab/platform/modules/core"
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
-const dsnProp = "database.dsn"
+const (
+ dsnConfigKey = "gorm.dsn"
+ loggerIgnoreRunLogConfigKey = "gorm.logger.ignore_run_log"
+)
var db *gorm.DB
var dsn string
func init() {
- dsn = config_module.AppConfig().GetString(dsnProp)
+ dsn = core_module.Config.GetString(dsnConfigKey)
if dsn == "" {
panic("database dsn is not set")
}
@@ -23,10 +28,12 @@ func GetDefaultDB() *gorm.DB {
if db == nil {
var err error
db, err = gorm.Open(postgres.New(postgres.Config{
- DSN: dsn,
- PreferSimpleProtocol: true, // disables implicit prepared statement usage
+ DSN: dsn,
}), &gorm.Config{
- Logger: getLogger(),
+ Logger: NewSlogLogger(slog.Default().With("module", "gorm"),
+ slogLoggerConfig{
+ IngoreRunLog: core_module.Config.GetBool(loggerIgnoreRunLogConfigKey),
+ }),
})
if err != nil {
panic("failed to connect database")
diff --git a/modules/agent/gorm/logger.go b/modules/agent/gorm/logger.go
index 4b9e420..fbb9766 100644
--- a/modules/agent/gorm/logger.go
+++ b/modules/agent/gorm/logger.go
@@ -1,24 +1,96 @@
package gorm_agent
import (
- "log"
- "os"
+ "context"
+ "errors"
+ "fmt"
+ "log/slog"
"time"
+ "gorm.io/gorm"
"gorm.io/gorm/logger"
+ "gorm.io/gorm/utils"
)
-func getLogger() logger.Interface {
- logger := logger.New(
- log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
- logger.Config{
- SlowThreshold: time.Second, // Slow SQL threshold
- LogLevel: logger.Silent, // Log level
- IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound error for logger
- ParameterizedQueries: true, // Don't include params in the SQL log
- Colorful: false, // Disable color
- },
- )
-
- return logger
+type slogLogger struct {
+ logger *slog.Logger
+ config slogLoggerConfig
+}
+
+type slogLoggerConfig struct {
+ SlowThreshold time.Duration
+ IgnoreRecordNotFoundError bool
+ IngoreErrorLog bool
+ IgnoreSlowLog bool
+ IngoreRunLog bool
+}
+
+func NewSlogLogger(logger *slog.Logger, config slogLoggerConfig) slogLogger {
+ if config.SlowThreshold == 0 {
+ config.SlowThreshold = 100 * time.Millisecond
+ }
+ return slogLogger{
+ logger: logger,
+ config: config,
+ }
+}
+
+func (l slogLogger) LogMode(level logger.LogLevel) logger.Interface {
+ return l
+}
+
+func (l slogLogger) Info(ctx context.Context, msg string, data ...interface{}) {
+ l.logger.InfoContext(ctx, msg, data...)
+}
+
+func (l slogLogger) Warn(ctx context.Context, msg string, data ...interface{}) {
+ l.logger.WarnContext(ctx, msg, data...)
+}
+
+func (l slogLogger) Error(ctx context.Context, msg string, data ...interface{}) {
+ l.logger.ErrorContext(ctx, msg, data...)
+}
+
+func (l slogLogger) Debug(ctx context.Context, msg string, data ...interface{}) {
+ l.logger.DebugContext(ctx, msg, data...)
+}
+
+func (l slogLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {
+ elapsed := time.Since(begin)
+ switch {
+ case !l.config.IngoreErrorLog &&
+ err != nil && (!errors.Is(err, gorm.ErrRecordNotFound) || !l.config.IgnoreRecordNotFoundError):
+ sql, rows := fc()
+ errLog := "Error SQL"
+ if rows == -1 {
+ l.Error(ctx, errLog, "file", utils.FileWithLineNum(),
+ "elapsed", float64(elapsed.Nanoseconds())/1e6, "rows", "-", "sql", sql,
+ "err", err)
+ } else {
+ l.Error(ctx, errLog, "file", utils.FileWithLineNum(),
+ "elapsed", float64(elapsed.Nanoseconds())/1e6, "rows", rows, "sql", sql,
+ "err", err)
+ }
+ case !l.config.IgnoreSlowLog &&
+ elapsed > l.config.SlowThreshold && l.config.SlowThreshold != 0:
+ sql, rows := fc()
+ slowLog := fmt.Sprintf("Slow SQL >= %v", l.config.SlowThreshold)
+ if rows == -1 {
+ l.Warn(ctx, slowLog, "file", utils.FileWithLineNum(),
+ "elapsed", float64(elapsed.Nanoseconds())/1e6, "rows", "-", "sql", sql)
+ } else {
+ l.Warn(ctx, slowLog, "file", utils.FileWithLineNum(),
+ "elapsed", float64(elapsed.Nanoseconds())/1e6, "rows", rows, "sql", sql)
+ }
+ case !l.config.IngoreRunLog:
+ sql, rows := fc()
+ runLog := "Run SQL"
+ if rows == -1 {
+ l.Debug(ctx, runLog, "file", utils.FileWithLineNum(),
+ "elapsed", float64(elapsed.Nanoseconds())/1e6, "rows", "-", "sql", sql)
+ } else {
+ l.Debug(ctx, runLog, "file", utils.FileWithLineNum(),
+ "elapsed", float64(elapsed.Nanoseconds())/1e6, "rows", rows, "sql", sql)
+ }
+ }
}
diff --git a/modules/agent/minio/client.go b/modules/agent/minio/client.go
index 9627ad5..945fe48 100644
--- a/modules/agent/minio/client.go
+++ b/modules/agent/minio/client.go
@@ -2,20 +2,20 @@ package minio_agent
import (
"context"
+ "log/slog"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
- config_module "github.com/oj-lab/platform/modules/config"
- log_module "github.com/oj-lab/platform/modules/log"
+ core_module "github.com/oj-lab/platform/modules/core"
)
const (
- minioEndpointProp = "minio.endpoint"
- minioAccessKeyProp = "minio.access_key_id"
- minioSecretAccessKeyProp = "minio.secret_access_key"
- minioUseSSLProp = "minio.use_ssl"
- minioRegionProp = "minio.region"
- minioBucketNameProp = "minio.bucket_name"
+ minioEndpointConfigKey = "minio.endpoint"
+ minioAccessKeyConfigKey = "minio.access_key_id"
+ minioSecretAccessKeyConfigKey = "minio.secret_access_key"
+ minioUseSSLConfigKey = "minio.use_ssl"
+ minioRegionConfigKey = "minio.region"
+ minioBucketNameConfigKey = "minio.bucket_name"
)
var (
@@ -29,12 +29,12 @@ var (
)
func init() {
- endpoint = config_module.AppConfig().GetString(minioEndpointProp)
- accessKeyID = config_module.AppConfig().GetString(minioAccessKeyProp)
- secretAccessKey = config_module.AppConfig().GetString(minioSecretAccessKeyProp)
- useSSL = config_module.AppConfig().GetBool(minioUseSSLProp)
- region = config_module.AppConfig().GetString(minioRegionProp)
- bucketName = config_module.AppConfig().GetString(minioBucketNameProp)
+ endpoint = core_module.Config.GetString(minioEndpointConfigKey)
+ accessKeyID = core_module.Config.GetString(minioAccessKeyConfigKey)
+ secretAccessKey = core_module.Config.GetString(minioSecretAccessKeyConfigKey)
+ useSSL = core_module.Config.GetBool(minioUseSSLConfigKey)
+ region = core_module.Config.GetString(minioRegionConfigKey)
+ bucketName = core_module.Config.GetString(minioBucketNameConfigKey)
}
func GetBucketName() string {
@@ -56,16 +56,15 @@ func GetMinioClient() *minio.Client {
exists, err := minioClient.BucketExists(ctx, bucketName)
if err == nil && exists {
- log_module.AppLogger().WithField("bucket", bucketName).Info("Bucket already exists")
+ slog.With("bucket", bucketName).Info("Bucket already exists")
return minioClient
}
err = minioClient.MakeBucket(ctx, bucketName, minio.MakeBucketOptions{})
if err != nil {
- log_module.AppLogger().WithError(err).
- WithField("bucket", bucketName).Error("Failed to create bucket")
+ slog.With("err", err, "bucket", bucketName).Error("Failed to create bucket")
} else {
- log_module.AppLogger().WithField("bucket", bucketName).Info("Successfully created bucket")
+ slog.With("bucket", bucketName).Info("Successfully created bucket")
}
}
diff --git a/modules/agent/redis/client.go b/modules/agent/redis/client.go
index 9cb3142..2099fb9 100644
--- a/modules/agent/redis/client.go
+++ b/modules/agent/redis/client.go
@@ -1,12 +1,12 @@
package redis_agent
import (
- config_module "github.com/oj-lab/platform/modules/config"
+ core_module "github.com/oj-lab/platform/modules/core"
"github.com/redis/go-redis/v9"
)
const (
- redisHostsProp = "redis.hosts"
+ redisHostsConfigKey = "redis.hosts"
)
var (
@@ -14,7 +14,7 @@ var (
)
func init() {
- RedisHosts = config_module.AppConfig().GetStringSlice(redisHostsProp)
+ RedisHosts = core_module.Config.GetStringSlice(redisHostsConfigKey)
}
type RedisClientInterface interface {
diff --git a/modules/auth/github.go b/modules/auth/github.go
index fc1d0ad..d44f962 100644
--- a/modules/auth/github.go
+++ b/modules/auth/github.go
@@ -6,7 +6,7 @@ import (
"net/http"
"net/url"
- config_module "github.com/oj-lab/platform/modules/config"
+ core_module "github.com/oj-lab/platform/modules/core"
)
const (
@@ -14,9 +14,9 @@ const (
githubAccessTokenURL = "https://github.com/login/oauth/access_token"
githubApiUserURL = "https://api.github.com/user"
- serviceBaseURLProp = "service.base_url"
- githubClientIDProp = "auth.github_client_id"
- githubClientSecretProp = "auth.github_client_secret"
+ serviceBaseURLConfigKey = "service.base_url"
+ githubClientIDConfigKey = "auth.github_client_id"
+ githubClientSecretConfigKey = "auth.github_client_secret"
)
var (
@@ -27,9 +27,9 @@ var (
)
func init() {
- githubClientID = config_module.AppConfig().GetString(githubClientIDProp)
- githubClientSecret = config_module.AppConfig().GetString(githubClientSecretProp)
- serviceBaseURLStr := config_module.AppConfig().GetString(serviceBaseURLProp)
+ githubClientID = core_module.Config.GetString(githubClientIDConfigKey)
+ githubClientSecret = core_module.Config.GetString(githubClientSecretConfigKey)
+ serviceBaseURLStr := core_module.Config.GetString(serviceBaseURLConfigKey)
var err error
serviceBaseURL, err = url.Parse(serviceBaseURLStr)
if err != nil {
diff --git a/modules/auth/jwt.go b/modules/auth/jwt.go
index 19d70db..116219e 100644
--- a/modules/auth/jwt.go
+++ b/modules/auth/jwt.go
@@ -5,7 +5,7 @@ import (
"time"
"github.com/golang-jwt/jwt/v4"
- config_module "github.com/oj-lab/platform/modules/config"
+ core_module "github.com/oj-lab/platform/modules/core"
)
var (
@@ -14,8 +14,8 @@ var (
)
func init() {
- jwtSecret = config_module.AppConfig().GetString("jwt.secret")
- jwtDuration = config_module.AppConfig().GetDuration("jwt.duration")
+ jwtSecret = core_module.Config.GetString("jwt.secret")
+ jwtDuration = core_module.Config.GetDuration("jwt.duration")
}
type AuthToken struct {
diff --git a/modules/auth/login_session.go b/modules/auth/login_session.go
index 6ff81de..1b79ab6 100644
--- a/modules/auth/login_session.go
+++ b/modules/auth/login_session.go
@@ -6,7 +6,7 @@ import (
"time"
"github.com/google/uuid"
- config_module "github.com/oj-lab/platform/modules/config"
+ core_module "github.com/oj-lab/platform/modules/core"
)
const defaultLoginSessionDuration = time.Hour * 24 * 7
@@ -14,7 +14,7 @@ const defaultLoginSessionDuration = time.Hour * 24 * 7
var LoginSessionDuration time.Duration
func init() {
- LoginSessionDuration = config_module.AppConfig().GetDuration("service.login_session_duration")
+ LoginSessionDuration = core_module.Config.GetDuration("service.login_session_duration")
if LoginSessionDuration == 0 {
LoginSessionDuration = defaultLoginSessionDuration
}
diff --git a/modules/auth/redis.go b/modules/auth/redis.go
index 1b8545e..f738961 100644
--- a/modules/auth/redis.go
+++ b/modules/auth/redis.go
@@ -3,9 +3,9 @@ package auth_module
import (
"context"
"fmt"
+ "log/slog"
redis_agent "github.com/oj-lab/platform/modules/agent/redis"
- log_module "github.com/oj-lab/platform/modules/log"
"github.com/redis/go-redis/v9"
)
@@ -76,7 +76,8 @@ func UpdateLoginSessionByAccount(ctx context.Context, account string, data Login
// TODO: KeepTTL only works in redis v6+
err = redisClient.Set(ctx, redisKey, val, redis.KeepTTL).Err()
if err != nil {
- log_module.AppLogger().Errorf("failed to update login session: %v", err)
+ slog.With("err", err).
+ Error("failed to update login session")
}
}
diff --git a/modules/config/config.go b/modules/core/config.go
similarity index 66%
rename from modules/config/config.go
rename to modules/core/config.go
index 98bf870..4444965 100644
--- a/modules/config/config.go
+++ b/modules/core/config.go
@@ -1,4 +1,4 @@
-package config_module
+package core_module
import (
"fmt"
@@ -9,42 +9,13 @@ import (
"github.com/spf13/viper"
)
-const serviceEnvEnvKey = "OJ_LAB_SERVICE_ENV"
-
const defaultConfigName = "config"
const defaultOverrideConfigName = "override"
const defaultProjectRootName = "platform"
-type ServiceEnv string
-
-const (
- serviceEnvDev ServiceEnv = "development"
- serviceEnvPrd ServiceEnv = "production"
-)
+var Config *viper.Viper
-var serviceEnv ServiceEnv
var projectRoot string
-var appConfig *viper.Viper
-
-func (se ServiceEnv) isValid() bool {
- if se == serviceEnvDev || se == serviceEnvPrd {
- return true
- }
- return false
-}
-
-func IsDevEnv() bool {
- return serviceEnv == serviceEnvDev
-}
-
-func loadServiceEnv() {
- serviceEnv = serviceEnvDev
- env := os.Getenv(serviceEnvEnvKey)
- if ServiceEnv(env).isValid() {
- serviceEnv = ServiceEnv(env)
- }
- println("Env:", serviceEnv)
-}
func loadConfig() error {
viper.AddConfigPath(projectRoot)
@@ -64,14 +35,10 @@ func loadConfig() error {
viper.AutomaticEnv()
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
- appConfig = viper.GetViper()
+ Config = viper.GetViper()
return nil
}
-func AppConfig() *viper.Viper {
- return appConfig
-}
-
func loadProjectRoot() {
// Try to locate project root, then find the workdir
wd, err := os.Getwd()
@@ -95,7 +62,6 @@ func ProjectRoot() string {
}
func init() {
- loadServiceEnv()
loadProjectRoot()
if _, err := os.Stat(projectRoot); err != nil {
panic(fmt.Sprintf("Project root not found: %v", projectRoot))
@@ -104,4 +70,5 @@ func init() {
if err := loadConfig(); err != nil {
panic(fmt.Sprintf("Load config with error: %v", err))
}
+ setupLog()
}
diff --git a/modules/core/log.go b/modules/core/log.go
new file mode 100644
index 0000000..3796443
--- /dev/null
+++ b/modules/core/log.go
@@ -0,0 +1,49 @@
+package core_module
+
+import (
+ "log/slog"
+ "os"
+
+ "github.com/lmittmann/tint"
+)
+
+const (
+ logLevelConfigKey = "log.level"
+ logFormatConfigKey = "log.format"
+)
+
+var (
+ LogLevel slog.Level
+ LogFormat string
+)
+
+func StringToSlogLevel(
+ level string,
+) slog.Level {
+ switch level {
+ case "debug":
+ return slog.LevelDebug
+ case "info":
+ return slog.LevelInfo
+ case "warn":
+ return slog.LevelWarn
+ case "error":
+ return slog.LevelError
+ default:
+ return slog.LevelInfo
+ }
+}
+
+func setupLog() {
+ LogLevel = StringToSlogLevel(Config.GetString(logLevelConfigKey))
+ LogFormat = Config.GetString(logFormatConfigKey)
+
+ var handler slog.Handler
+ if LogFormat == "json" {
+ handler = slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: LogLevel})
+ slog.SetDefault(slog.New(handler))
+ } else {
+ handler = tint.NewHandler(os.Stdout, &tint.Options{Level: LogLevel})
+ slog.SetDefault(slog.New(handler))
+ }
+}
diff --git a/modules/log/init_test.go b/modules/log/init_test.go
deleted file mode 100644
index 4f42017..0000000
--- a/modules/log/init_test.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package log_module
-
-import (
- "testing"
-
- "github.com/spf13/viper"
-)
-
-func TestInit(T *testing.T) {
- logLevel := viper.GetString(logLevelProp)
- if logLevel != "debug" {
- T.Errorf("log level is not debug but %s", logLevel)
- }
-}
diff --git a/modules/log/log.go b/modules/log/log.go
deleted file mode 100644
index 1878005..0000000
--- a/modules/log/log.go
+++ /dev/null
@@ -1,56 +0,0 @@
-package log_module
-
-import (
- "os"
- "runtime"
- "strconv"
-
- config_module "github.com/oj-lab/platform/modules/config"
- "github.com/sirupsen/logrus"
-)
-
-const logLevelProp = "log.level"
-const logFormatProp = "log.format"
-const logPrettyJson = "log.pretty_json"
-const logTimeOn = "log.time_on"
-const logTimeFormat = "log.time_format"
-
-func AppLogger() *logrus.Entry {
- return logrus.WithFields(logrus.Fields{
- "caller": func() string {
- pc := make([]uintptr, 1)
- runtime.Callers(3, pc)
- f := runtime.FuncForPC(pc[0])
- name, line := f.FileLine(pc[0])
- return name + ":" + strconv.Itoa(line)
- }(),
- })
-}
-
-func setupLog() {
- logrus.SetOutput(os.Stdout)
-
- logrus.SetLevel(logrus.DebugLevel)
- format := config_module.AppConfig().GetString(logFormatProp)
- lvl := config_module.AppConfig().GetString(logLevelProp)
- prettyJson := config_module.AppConfig().GetBool(logPrettyJson)
- timeOn := config_module.AppConfig().GetBool(logTimeOn)
- timestampFormat := config_module.AppConfig().GetString(logTimeFormat)
-
- logLevel, err := logrus.ParseLevel(lvl)
- if err == nil {
- println("log level:", lvl)
- logrus.SetLevel(logLevel)
- }
- if format == "json" {
- logrus.SetFormatter(&logrus.JSONFormatter{
- TimestampFormat: timestampFormat,
- DisableTimestamp: !timeOn,
- PrettyPrint: prettyJson,
- })
- }
-}
-
-func init() {
- setupLog()
-}
diff --git a/override.example.toml b/override.example.toml
index 447b0d4..c0fc922 100644
--- a/override.example.toml
+++ b/override.example.toml
@@ -12,4 +12,7 @@ level = "info"
[service]
# When you need to work with the lastest frontend code,
# set the frontend_dist to the path of the frontend repository.
-frontend_dist = "../frontend/dist"
\ No newline at end of file
+frontend_dist = "../frontend/dist"
+
+[gorm]
+logger.ignore_run_log = true
\ No newline at end of file
diff --git a/services/judge/judge_cache.go b/services/judge/judge_cache.go
index ad82196..7670f1a 100644
--- a/services/judge/judge_cache.go
+++ b/services/judge/judge_cache.go
@@ -19,7 +19,7 @@ func UpsertJudgeCache(ctx context.Context, uid uuid.UUID, verdict judge_model.Ju
if err != nil {
return err
}
- // log_module.AppLogger().WithField("judge", judge).Debug("getjudge")
+ // slog.With("judge", judge).Debug("getjudge")
var problem *problem_model.Problem
problem, err = problem_model.GetProblem(db, judge.ProblemSlug)
if err != nil {
@@ -53,7 +53,7 @@ func UpsertJudgeCache(ctx context.Context, uid uuid.UUID, verdict judge_model.Ju
}
}
- // log_module.AppLogger().WithField("scoreCache", scoreCache).Debug("get scoreCache")
+ // slog.With("scoreCache", scoreCache).Debug("get scoreCache")
// previous no ac || current more early
// need to update
@@ -77,7 +77,7 @@ func UpsertJudgeCache(ctx context.Context, uid uuid.UUID, verdict judge_model.Ju
}
rankCache.TotalSubmissions += scoreCache.SubmissionCount - preSubmissionCount
problem.SubmitCount += scoreCache.SubmissionCount - preSubmissionCount
- // log_module.AppLogger().WithField("scoreCache", scoreCache).Debug("update scoreCache")
+ // slog.With("scoreCache", scoreCache).Debug("update scoreCache")
err = problem_model.UpdateProblem(db, *problem)
if err != nil {
diff --git a/services/user/user.go b/services/user/user.go
index 88b0744..5947e68 100644
--- a/services/user/user.go
+++ b/services/user/user.go
@@ -3,13 +3,13 @@ package user_service
import (
"context"
"fmt"
+ "log/slog"
judge_model "github.com/oj-lab/platform/models/judge"
user_model "github.com/oj-lab/platform/models/user"
casbin_agent "github.com/oj-lab/platform/modules/agent/casbin"
gorm_agent "github.com/oj-lab/platform/modules/agent/gorm"
auth_module "github.com/oj-lab/platform/modules/auth"
- log_module "github.com/oj-lab/platform/modules/log"
)
func CreateUser(ctx context.Context, request user_model.User) (*user_model.User, error) {
@@ -53,20 +53,20 @@ func DeleteUser(ctx context.Context, account string) error {
for _, judge := range judges {
err = judge_model.DeleteJudgeResultByJudgeUID(db, judge.UID)
if err != nil {
- log_module.AppLogger().WithField("judge", judge).Errorf("delete judge result failed: %v", err)
+ slog.With("judge", judge, "error", err).Error("delete judge result failed")
}
}
err = judge_model.DeleteJudgesByAccount(db, account)
if err != nil {
- log_module.AppLogger().WithField("account", account).Errorf("delete judges failed: %v", err)
+ slog.With("account", account, "error", err).Error("delete judges failed")
}
err = judge_model.DeleteJudgeRankCache(db, account)
if err != nil {
- log_module.AppLogger().WithField("account", account).Errorf("delete judge rank cache failed: %v", err)
+ slog.With("account", account, "error", err).Error("delete judge rank cache failed")
}
err = judge_model.DeleteJudgeScoreCacheByUserAccount(db, account)
if err != nil {
- log_module.AppLogger().WithField("account", account).Errorf("delete judge score cache failed: %v", err)
+ slog.With("account", account, "error", err).Error("delete judge score cache failed")
}
err = user_model.DeleteUser(db, account)
@@ -180,10 +180,7 @@ func CheckUserExist(ctx context.Context, account string) (bool, error) {
}
if count > 1 {
- log_module.AppLogger().
- WithField("account", account).
- WithField("count", count).
- Warn("user account is not unique")
+ slog.With("account", account, "count", count).Warn("user account is not unique")
}
return count > 0, nil