chore: update logger

This commit is contained in:
Steven 2024-02-29 23:54:43 +08:00
parent 12f4d3a10d
commit dfa78cac49
14 changed files with 87 additions and 146 deletions

View File

@ -3,6 +3,7 @@ package main
import ( import (
"context" "context"
"fmt" "fmt"
"log/slog"
"net/http" "net/http"
"os" "os"
"os/signal" "os/signal"
@ -10,10 +11,8 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"go.uber.org/zap"
"github.com/usememos/memos/internal/jobs" "github.com/usememos/memos/internal/jobs"
"github.com/usememos/memos/internal/log"
"github.com/usememos/memos/server" "github.com/usememos/memos/server"
_profile "github.com/usememos/memos/server/profile" _profile "github.com/usememos/memos/server/profile"
"github.com/usememos/memos/store" "github.com/usememos/memos/store"
@ -49,26 +48,26 @@ var (
dbDriver, err := db.NewDBDriver(profile) dbDriver, err := db.NewDBDriver(profile)
if err != nil { if err != nil {
cancel() cancel()
log.Error("failed to create db driver", zap.Error(err)) slog.Error("failed to create db driver", err)
return return
} }
if err := dbDriver.Migrate(ctx); err != nil { if err := dbDriver.Migrate(ctx); err != nil {
cancel() cancel()
log.Error("failed to migrate db", zap.Error(err)) slog.Error("failed to migrate database", err)
return return
} }
storeInstance := store.New(dbDriver, profile) storeInstance := store.New(dbDriver, profile)
if err := storeInstance.MigrateManually(ctx); err != nil { if err := storeInstance.MigrateManually(ctx); err != nil {
cancel() cancel()
log.Error("failed to migrate manually", zap.Error(err)) slog.Error("failed to migrate manually", err)
return return
} }
s, err := server.NewServer(ctx, profile, storeInstance) s, err := server.NewServer(ctx, profile, storeInstance)
if err != nil { if err != nil {
cancel() cancel()
log.Error("failed to create server", zap.Error(err)) slog.Error("failed to create server", err)
return return
} }
@ -78,8 +77,7 @@ var (
// which is taken as the graceful shutdown signal for many systems, eg., Kubernetes, Gunicorn. // which is taken as the graceful shutdown signal for many systems, eg., Kubernetes, Gunicorn.
signal.Notify(c, os.Interrupt, syscall.SIGTERM) signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() { go func() {
sig := <-c <-c
log.Info(fmt.Sprintf("%s received.\n", sig.String()))
s.Shutdown(ctx) s.Shutdown(ctx)
cancel() cancel()
}() }()
@ -91,7 +89,7 @@ var (
if err := s.Start(ctx); err != nil { if err := s.Start(ctx); err != nil {
if err != http.ErrServerClosed { if err != http.ErrServerClosed {
log.Error("failed to start server", zap.Error(err)) slog.Error("failed to start server", err)
cancel() cancel()
} }
} }
@ -103,7 +101,6 @@ var (
) )
func Execute() error { func Execute() error {
defer log.Sync()
return rootCmd.Execute() return rootCmd.Execute()
} }

View File

@ -3,13 +3,12 @@ package jobs
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"log/slog"
"strings" "strings"
"time" "time"
"github.com/pkg/errors" "github.com/pkg/errors"
"go.uber.org/zap"
"github.com/usememos/memos/internal/log"
"github.com/usememos/memos/plugin/storage/s3" "github.com/usememos/memos/plugin/storage/s3"
apiv1 "github.com/usememos/memos/server/route/api/v1" apiv1 "github.com/usememos/memos/server/route/api/v1"
"github.com/usememos/memos/store" "github.com/usememos/memos/store"
@ -19,11 +18,10 @@ import (
// It uses S3 client to generate presigned URLs and updates the corresponding resources in the store. // It uses S3 client to generate presigned URLs and updates the corresponding resources in the store.
func RunPreSignLinks(ctx context.Context, dataStore *store.Store) { func RunPreSignLinks(ctx context.Context, dataStore *store.Store) {
for { for {
started := time.Now()
if err := signExternalLinks(ctx, dataStore); err != nil { if err := signExternalLinks(ctx, dataStore); err != nil {
log.Warn("failed sign external links", zap.Error(err)) slog.Error("failed to pre-sign links", err)
} else { } else {
log.Info("links pre-signed", zap.Duration("duration", time.Since(started))) slog.Debug("pre-signed links")
} }
select { select {
case <-time.After(s3.LinkLifetime / 2): case <-time.After(s3.LinkLifetime / 2):
@ -69,7 +67,7 @@ func signExternalLinks(ctx context.Context, dataStore *store.Store) error {
} }
newLink, err := objectStore.PreSignLink(ctx, res.ExternalLink) newLink, err := objectStore.PreSignLink(ctx, res.ExternalLink)
if err != nil { if err != nil {
log.Warn("failed pre-sign link", zap.Int32("resource", res.ID), zap.String("link", res.ExternalLink), zap.Error(err)) slog.Error("failed to pre-sign link", err)
continue // do not fail - we may want update left over links too continue // do not fail - we may want update left over links too
} }
now := time.Now().Unix() now := time.Now().Unix()

View File

@ -1,66 +0,0 @@
package log
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var (
// `gl` is the global logger.
// Other packages should use public methods such as Info/Error to do the logging.
// For other types of logging, e.g. logging to a separate file, they should use their own loggers.
gl *zap.Logger
gLevel zap.AtomicLevel
)
// Initializes the global console logger.
func init() {
gLevel = zap.NewAtomicLevelAt(zap.InfoLevel)
gl, _ = zap.Config{
Level: gLevel,
Development: true,
// Use "console" to print readable stacktrace.
Encoding: "console",
EncoderConfig: zap.NewDevelopmentEncoderConfig(),
OutputPaths: []string{"stderr"},
ErrorOutputPaths: []string{"stderr"},
}.Build(
// Skip one caller stack to locate the correct caller.
zap.AddCallerSkip(1),
)
}
// SetLevel wraps the zap Level's SetLevel method.
func SetLevel(level zapcore.Level) {
gLevel.SetLevel(level)
}
// EnabledLevel wraps the zap Level's Enabled method.
func EnabledLevel(level zapcore.Level) bool {
return gLevel.Enabled(level)
}
// Debug wraps the zap Logger's Debug method.
func Debug(msg string, fields ...zap.Field) {
gl.Debug(msg, fields...)
}
// Info wraps the zap Logger's Info method.
func Info(msg string, fields ...zap.Field) {
gl.Info(msg, fields...)
}
// Warn wraps the zap Logger's Warn method.
func Warn(msg string, fields ...zap.Field) {
gl.Warn(msg, fields...)
}
// Error wraps the zap Logger's Error method.
func Error(msg string, fields ...zap.Field) {
gl.Error(msg, fields...)
}
// Sync wraps the zap Logger's Sync method.
func Sync() {
_ = gl.Sync()
}

View File

@ -1,11 +1,8 @@
package telegram package telegram
import ( import (
"log/slog"
"path/filepath" "path/filepath"
"go.uber.org/zap"
"github.com/usememos/memos/internal/log"
) )
type Attachment struct { type Attachment struct {
@ -29,9 +26,7 @@ func (b Attachment) GetMimeType() string {
mime, ok := mimeTypes[filepath.Ext(b.FileName)] mime, ok := mimeTypes[filepath.Ext(b.FileName)]
if !ok { if !ok {
// Handle unknown file extension slog.Warn("Unknown file extension", slog.String("file", b.FileName))
log.Warn("Unknown file type for ", zap.String("filename", b.FileName))
return "application/octet-stream" return "application/octet-stream"
} }

View File

@ -3,13 +3,9 @@ package telegram
import ( import (
"context" "context"
"errors" "errors"
"fmt" "log/slog"
"strings" "strings"
"time" "time"
"go.uber.org/zap"
"github.com/usememos/memos/internal/log"
) )
type Handler interface { type Handler interface {
@ -41,7 +37,6 @@ func (b *Bot) Start(ctx context.Context) {
continue continue
} }
if err != nil { if err != nil {
log.Warn("fail to telegram.GetUpdates", zap.Error(err))
time.Sleep(errRetryWait) time.Sleep(errRetryWait)
continue continue
} }
@ -56,7 +51,7 @@ func (b *Bot) Start(ctx context.Context) {
if update.CallbackQuery != nil { if update.CallbackQuery != nil {
err := b.handler.CallbackQueryHandle(ctx, b, *update.CallbackQuery) err := b.handler.CallbackQueryHandle(ctx, b, *update.CallbackQuery)
if err != nil { if err != nil {
log.Error("fail to handle CallbackQuery", zap.Error(err)) slog.Error("fail to handle callback query", err)
} }
continue continue
@ -70,7 +65,7 @@ func (b *Bot) Start(ctx context.Context) {
if !message.IsSupported() { if !message.IsSupported() {
_, err := b.SendReplyMessage(ctx, message.Chat.ID, message.MessageID, "Supported messages: animation, audio, text, document, photo, video, video note, voice, other messages with caption") _, err := b.SendReplyMessage(ctx, message.Chat.ID, message.MessageID, "Supported messages: animation, audio, text, document, photo, video, video note, voice, other messages with caption")
if err != nil { if err != nil {
log.Error(fmt.Sprintf("fail to telegram.SendReplyMessage for messageID=%d", message.MessageID), zap.Error(err)) slog.Error("fail to send reply message", err)
} }
continue continue
} }
@ -88,12 +83,12 @@ func (b *Bot) Start(ctx context.Context) {
err = b.handleSingleMessages(ctx, singleMessages) err = b.handleSingleMessages(ctx, singleMessages)
if err != nil { if err != nil {
log.Error("fail to handle singleMessage", zap.Error(err)) slog.Error("fail to handle plain text message", err)
} }
err = b.handleGroupMessages(ctx, groupMessages) err = b.handleGroupMessages(ctx, groupMessages)
if err != nil { if err != nil {
log.Error("fail to handle plain text message", zap.Error(err)) slog.Error("fail to handle media group message", err)
} }
} }
} }

View File

@ -2,15 +2,14 @@ package v1
import ( import (
"fmt" "fmt"
"log/slog"
"net/http" "net/http"
"strings" "strings"
"github.com/golang-jwt/jwt/v5" "github.com/golang-jwt/jwt/v5"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/pkg/errors" "github.com/pkg/errors"
"go.uber.org/zap"
"github.com/usememos/memos/internal/log"
"github.com/usememos/memos/internal/util" "github.com/usememos/memos/internal/util"
storepb "github.com/usememos/memos/proto/gen/store" storepb "github.com/usememos/memos/proto/gen/store"
"github.com/usememos/memos/server/route/api/auth" "github.com/usememos/memos/server/route/api/auth"
@ -83,7 +82,7 @@ func JWTMiddleware(server *APIV1Service, next echo.HandlerFunc, secret string) e
if err != nil { if err != nil {
err = removeAccessTokenAndCookies(c, server.Store, userID, accessToken) err = removeAccessTokenAndCookies(c, server.Store, userID, accessToken)
if err != nil { if err != nil {
log.Error("fail to remove AccessToken and Cookies", zap.Error(err)) slog.Warn("fail to remove AccessToken and Cookies", err)
} }
return echo.NewHTTPError(http.StatusUnauthorized, "Invalid or expired access token") return echo.NewHTTPError(http.StatusUnauthorized, "Invalid or expired access token")
} }
@ -95,7 +94,7 @@ func JWTMiddleware(server *APIV1Service, next echo.HandlerFunc, secret string) e
if !validateAccessToken(accessToken, accessTokens) { if !validateAccessToken(accessToken, accessTokens) {
err = removeAccessTokenAndCookies(c, server.Store, userID, accessToken) err = removeAccessTokenAndCookies(c, server.Store, userID, accessToken)
if err != nil { if err != nil {
log.Error("fail to remove AccessToken and Cookies", zap.Error(err)) slog.Warn("fail to remove AccessToken and Cookies", err)
} }
return echo.NewHTTPError(http.StatusUnauthorized, "Invalid access token.") return echo.NewHTTPError(http.StatusUnauthorized, "Invalid access token.")
} }

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"log/slog"
"net/http" "net/http"
"strconv" "strconv"
"time" "time"
@ -11,9 +12,7 @@ import (
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/lithammer/shortuuid/v4" "github.com/lithammer/shortuuid/v4"
"github.com/pkg/errors" "github.com/pkg/errors"
"go.uber.org/zap"
"github.com/usememos/memos/internal/log"
"github.com/usememos/memos/internal/util" "github.com/usememos/memos/internal/util"
"github.com/usememos/memos/plugin/webhook" "github.com/usememos/memos/plugin/webhook"
storepb "github.com/usememos/memos/proto/gen/store" storepb "github.com/usememos/memos/proto/gen/store"
@ -390,7 +389,6 @@ func (s *APIV1Service) CreateMemo(c echo.Context) error {
for _, userSetting := range userSettings { for _, userSetting := range userSettings {
tgUserID, err := strconv.ParseInt(userSetting.GetTelegramUserId(), 10, 64) tgUserID, err := strconv.ParseInt(userSetting.GetTelegramUserId(), 10, 64)
if err != nil { if err != nil {
log.Error("failed to parse Telegram UserID", zap.Error(err))
continue continue
} }
@ -398,14 +396,13 @@ func (s *APIV1Service) CreateMemo(c echo.Context) error {
content := memoResponse.CreatorName + " Says:\n\n" + memoResponse.Content content := memoResponse.CreatorName + " Says:\n\n" + memoResponse.Content
_, err = s.telegramBot.SendMessage(ctx, tgUserID, content) _, err = s.telegramBot.SendMessage(ctx, tgUserID, content)
if err != nil { if err != nil {
log.Error("Failed to send Telegram notification", zap.Error(err))
continue continue
} }
} }
} }
// Try to dispatch webhook when memo is created. // Try to dispatch webhook when memo is created.
if err := s.DispatchMemoCreatedWebhook(ctx, memoResponse); err != nil { if err := s.DispatchMemoCreatedWebhook(ctx, memoResponse); err != nil {
log.Warn("Failed to dispatch memo created webhook", zap.Error(err)) slog.Warn("Failed to dispatch memo created webhook", err)
} }
return c.JSON(http.StatusOK, memoResponse) return c.JSON(http.StatusOK, memoResponse)
@ -627,7 +624,7 @@ func (s *APIV1Service) DeleteMemo(c echo.Context) error {
if memoMessage, err := s.convertMemoFromStore(ctx, memo); err == nil { if memoMessage, err := s.convertMemoFromStore(ctx, memo); err == nil {
// Try to dispatch webhook when memo is deleted. // Try to dispatch webhook when memo is deleted.
if err := s.DispatchMemoDeletedWebhook(ctx, memoMessage); err != nil { if err := s.DispatchMemoDeletedWebhook(ctx, memoMessage); err != nil {
log.Warn("Failed to dispatch memo deleted webhook", zap.Error(err)) slog.Warn("Failed to dispatch memo deleted webhook", err)
} }
} }
@ -821,7 +818,7 @@ func (s *APIV1Service) UpdateMemo(c echo.Context) error {
} }
// Try to dispatch webhook when memo is updated. // Try to dispatch webhook when memo is updated.
if err := s.DispatchMemoUpdatedWebhook(ctx, memoResponse); err != nil { if err := s.DispatchMemoUpdatedWebhook(ctx, memoResponse); err != nil {
log.Warn("Failed to dispatch memo updated webhook", zap.Error(err)) slog.Error("Failed to dispatch memo updated webhook", err)
} }
return c.JSON(http.StatusOK, memoResponse) return c.JSON(http.StatusOK, memoResponse)

View File

@ -17,9 +17,7 @@ import (
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/lithammer/shortuuid/v4" "github.com/lithammer/shortuuid/v4"
"github.com/pkg/errors" "github.com/pkg/errors"
"go.uber.org/zap"
"github.com/usememos/memos/internal/log"
"github.com/usememos/memos/internal/util" "github.com/usememos/memos/internal/util"
"github.com/usememos/memos/plugin/storage/s3" "github.com/usememos/memos/plugin/storage/s3"
"github.com/usememos/memos/store" "github.com/usememos/memos/store"
@ -192,7 +190,6 @@ func (s *APIV1Service) UploadResource(c echo.Context) error {
if settingMaxUploadSizeMiB, err := strconv.Atoi(maxUploadSetting.Value); err == nil { if settingMaxUploadSizeMiB, err := strconv.Atoi(maxUploadSetting.Value); err == nil {
settingMaxUploadSizeBytes = settingMaxUploadSizeMiB * MebiByte settingMaxUploadSizeBytes = settingMaxUploadSizeMiB * MebiByte
} else { } else {
log.Warn("Failed to parse max upload size", zap.Error(err))
settingMaxUploadSizeBytes = 0 settingMaxUploadSizeBytes = 0
} }
} else { } else {

View File

@ -0,0 +1,44 @@
package v2
import (
"context"
"log/slog"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type LoggerInterceptor struct {
}
func NewLoggerInterceptor() *LoggerInterceptor {
return &LoggerInterceptor{}
}
func (in *LoggerInterceptor) LoggerInterceptor(ctx context.Context, request any, serverInfo *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
resp, err := handler(ctx, request)
in.loggerInterceptorDo(ctx, serverInfo.FullMethod, err)
return resp, err
}
func (*LoggerInterceptor) loggerInterceptorDo(ctx context.Context, fullMethod string, err error) {
st := status.Convert(err)
var logLevel slog.Level
var logMsg string
switch st.Code() {
case codes.OK:
logLevel = slog.LevelInfo
logMsg = "OK"
case codes.Unauthenticated, codes.OutOfRange, codes.PermissionDenied, codes.NotFound:
logLevel = slog.LevelInfo
logMsg = "client error"
case codes.Internal, codes.Unknown, codes.DataLoss, codes.Unavailable, codes.DeadlineExceeded:
logLevel = slog.LevelError
logMsg = "server error"
default:
logLevel = slog.LevelError
logMsg = "unknown error"
}
slog.LogAttrs(ctx, logLevel, logMsg, slog.String("method", fullMethod))
}

View File

@ -6,18 +6,17 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"log/slog"
"time" "time"
"github.com/google/cel-go/cel" "github.com/google/cel-go/cel"
"github.com/lithammer/shortuuid/v4" "github.com/lithammer/shortuuid/v4"
"github.com/pkg/errors" "github.com/pkg/errors"
"go.uber.org/zap"
expr "google.golang.org/genproto/googleapis/api/expr/v1alpha1" expr "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"
"google.golang.org/grpc/status" "google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb" "google.golang.org/protobuf/types/known/timestamppb"
"github.com/usememos/memos/internal/log"
"github.com/usememos/memos/internal/util" "github.com/usememos/memos/internal/util"
"github.com/usememos/memos/plugin/webhook" "github.com/usememos/memos/plugin/webhook"
apiv2pb "github.com/usememos/memos/proto/gen/api/v2" apiv2pb "github.com/usememos/memos/proto/gen/api/v2"
@ -70,7 +69,7 @@ func (s *APIV2Service) CreateMemo(ctx context.Context, request *apiv2pb.CreateMe
} }
// Try to dispatch webhook when memo is created. // Try to dispatch webhook when memo is created.
if err := s.DispatchMemoCreatedWebhook(ctx, memoMessage); err != nil { if err := s.DispatchMemoCreatedWebhook(ctx, memoMessage); err != nil {
log.Warn("Failed to dispatch memo created webhook", zap.Error(err)) slog.Warn("Failed to dispatch memo created webhook", err)
} }
response := &apiv2pb.CreateMemoResponse{ response := &apiv2pb.CreateMemoResponse{
@ -280,7 +279,7 @@ func (s *APIV2Service) UpdateMemo(ctx context.Context, request *apiv2pb.UpdateMe
} }
// Try to dispatch webhook when memo is updated. // Try to dispatch webhook when memo is updated.
if err := s.DispatchMemoUpdatedWebhook(ctx, memoMessage); err != nil { if err := s.DispatchMemoUpdatedWebhook(ctx, memoMessage); err != nil {
log.Warn("Failed to dispatch memo updated webhook", zap.Error(err)) slog.Warn("Failed to dispatch memo updated webhook", err)
} }
return &apiv2pb.UpdateMemoResponse{ return &apiv2pb.UpdateMemoResponse{
@ -307,7 +306,7 @@ func (s *APIV2Service) DeleteMemo(ctx context.Context, request *apiv2pb.DeleteMe
if memoMessage, err := s.convertMemoFromStore(ctx, memo); err == nil { if memoMessage, err := s.convertMemoFromStore(ctx, memo); err == nil {
// Try to dispatch webhook when memo is deleted. // Try to dispatch webhook when memo is deleted.
if err := s.DispatchMemoDeletedWebhook(ctx, memoMessage); err != nil { if err := s.DispatchMemoDeletedWebhook(ctx, memoMessage); err != nil {
log.Warn("Failed to dispatch memo deleted webhook", zap.Error(err)) slog.Warn("Failed to dispatch memo deleted webhook", err)
} }
} }

View File

@ -3,18 +3,17 @@ package v2
import ( import (
"context" "context"
"fmt" "fmt"
"log/slog"
"net" "net"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/improbable-eng/grpc-web/go/grpcweb" "github.com/improbable-eng/grpc-web/go/grpcweb"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/pkg/errors" "github.com/pkg/errors"
"go.uber.org/zap"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/reflection" "google.golang.org/grpc/reflection"
"github.com/usememos/memos/internal/log"
apiv2pb "github.com/usememos/memos/proto/gen/api/v2" apiv2pb "github.com/usememos/memos/proto/gen/api/v2"
"github.com/usememos/memos/server/profile" "github.com/usememos/memos/server/profile"
"github.com/usememos/memos/store" "github.com/usememos/memos/store"
@ -45,6 +44,7 @@ func NewAPIV2Service(secret string, profile *profile.Profile, store *store.Store
authProvider := NewGRPCAuthInterceptor(store, secret) authProvider := NewGRPCAuthInterceptor(store, secret)
grpcServer := grpc.NewServer( grpcServer := grpc.NewServer(
grpc.ChainUnaryInterceptor( grpc.ChainUnaryInterceptor(
NewLoggerInterceptor().LoggerInterceptor,
authProvider.AuthenticationInterceptor, authProvider.AuthenticationInterceptor,
), ),
) )
@ -138,7 +138,7 @@ func (s *APIV2Service) RegisterGateway(ctx context.Context, e *echo.Echo) error
} }
go func() { go func() {
if err := s.grpcServer.Serve(listen); err != nil { if err := s.grpcServer.Serve(listen); err != nil {
log.Error("grpc server listen error", zap.Error(err)) slog.Error("failed to start gRPC server", err)
} }
}() }()

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"fmt" "fmt"
"io" "io"
"log/slog"
"net/http" "net/http"
"os" "os"
"path/filepath" "path/filepath"
@ -14,9 +15,7 @@ import (
"github.com/disintegration/imaging" "github.com/disintegration/imaging"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/pkg/errors" "github.com/pkg/errors"
"go.uber.org/zap"
"github.com/usememos/memos/internal/log"
"github.com/usememos/memos/internal/util" "github.com/usememos/memos/internal/util"
"github.com/usememos/memos/server/profile" "github.com/usememos/memos/server/profile"
"github.com/usememos/memos/store" "github.com/usememos/memos/store"
@ -99,7 +98,7 @@ func (s *ResourceService) streamResource(c echo.Context) error {
thumbnailPath := filepath.Join(s.Profile.Data, thumbnailImagePath, fmt.Sprintf("%d%s", resource.ID, ext)) thumbnailPath := filepath.Join(s.Profile.Data, thumbnailImagePath, fmt.Sprintf("%d%s", resource.ID, ext))
thumbnailBlob, err := getOrGenerateThumbnailImage(blob, thumbnailPath) thumbnailBlob, err := getOrGenerateThumbnailImage(blob, thumbnailPath)
if err != nil { if err != nil {
log.Warn(fmt.Sprintf("failed to get or generate local thumbnail with path %s", thumbnailPath), zap.Error(err)) slog.Warn("failed to get or generate thumbnail image", err)
} else { } else {
blob = thumbnailBlob blob = thumbnailBlob
} }

View File

@ -9,7 +9,6 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/usememos/memos/plugin/telegram" "github.com/usememos/memos/plugin/telegram"
@ -49,31 +48,15 @@ func NewServer(ctx context.Context, profile *profile.Profile, store *store.Store
telegramBot: telegram.NewBotWithHandler(integration.NewTelegramHandler(store)), telegramBot: telegram.NewBotWithHandler(integration.NewTelegramHandler(store)),
} }
e.Use(middleware.LoggerWithConfig(middleware.LoggerConfig{ // Register CORS middleware.
Format: `{"time":"${time_rfc3339}","latency":"${latency_human}",` +
`"method":"${method}","uri":"${uri}",` +
`"status":${status},"error":"${error}"}` + "\n",
}))
e.Use(CORSMiddleware()) e.Use(CORSMiddleware())
e.Use(middleware.TimeoutWithConfig(middleware.TimeoutConfig{
Skipper: grpcRequestSkipper,
Timeout: 30 * time.Second,
}))
serverID, err := s.getSystemServerID(ctx) serverID, err := s.getSystemServerID(ctx)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "failed to retrieve system server ID") return nil, errors.Wrap(err, "failed to retrieve system server ID")
} }
s.ID = serverID s.ID = serverID
// Only serve frontend when it's enabled.
if profile.Frontend {
frontendService := frontend.NewFrontendService(profile, store)
frontendService.Serve(ctx, e)
}
secret := "usememos" secret := "usememos"
if profile.Mode == "prod" { if profile.Mode == "prod" {
secret, err = s.getSystemSecretSessionName(ctx) secret, err = s.getSystemSecretSessionName(ctx)
@ -88,6 +71,12 @@ func NewServer(ctx context.Context, profile *profile.Profile, store *store.Store
return c.String(http.StatusOK, "Service ready.") return c.String(http.StatusOK, "Service ready.")
}) })
// Only serve frontend when it's enabled.
if profile.Frontend {
frontendService := frontend.NewFrontendService(profile, store)
frontendService.Serve(ctx, e)
}
// Register API v1 endpoints. // Register API v1 endpoints.
rootGroup := e.Group("") rootGroup := e.Group("")
apiV1Service := apiv1.NewAPIV1Service(s.Secret, profile, store, s.telegramBot) apiV1Service := apiv1.NewAPIV1Service(s.Secret, profile, store, s.telegramBot)

View File

@ -3,12 +3,11 @@ package mysql
import ( import (
"context" "context"
"database/sql" "database/sql"
"fmt" "log/slog"
"github.com/go-sql-driver/mysql" "github.com/go-sql-driver/mysql"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/usememos/memos/internal/log"
"github.com/usememos/memos/server/profile" "github.com/usememos/memos/server/profile"
"github.com/usememos/memos/store" "github.com/usememos/memos/store"
) )
@ -31,7 +30,6 @@ func NewDB(profile *profile.Profile) (store.Driver, error) {
driver := DB{profile: profile} driver := DB{profile: profile}
driver.config, err = mysql.ParseDSN(dsn) driver.config, err = mysql.ParseDSN(dsn)
if err != nil { if err != nil {
log.Error(fmt.Sprintf("DSN parse error: %s", dsn))
return nil, errors.New("Parse DSN eroor") return nil, errors.New("Parse DSN eroor")
} }
@ -87,7 +85,7 @@ func (d *DB) GetCurrentDBSize(ctx context.Context) (int64, error) {
" GROUP BY `table_schema`" " GROUP BY `table_schema`"
rows, err := d.db.QueryContext(ctx, query, d.config.DBName) rows, err := d.db.QueryContext(ctx, query, d.config.DBName)
if err != nil { if err != nil {
log.Error("Query db size error, make sure you have enough privilege") slog.Error("Query db size error, make sure you have enough privilege", err)
return 0, err return 0, err
} }
defer rows.Close() defer rows.Close()