mirror of
https://github.com/usememos/memos.git
synced 2025-02-12 01:10:38 +01:00
chore: update logger
This commit is contained in:
parent
12f4d3a10d
commit
dfa78cac49
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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()
|
|
||||||
}
|
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.")
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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 {
|
||||||
|
44
server/route/api/v2/logger_interceptor.go
Normal file
44
server/route/api/v2/logger_interceptor.go
Normal 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))
|
||||||
|
}
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user