Przeglądaj źródła

:recycle: 日志组件单独抽取项目 https://github.com/siyuan-note/siyuan/issues/5439

Liang Ding 3 lat temu
rodzic
commit
505b973c2d
70 zmienionych plików z 671 dodań i 942 usunięć
  1. 2 1
      kernel/api/block.go
  2. 2 1
      kernel/api/extension.go
  3. 10 9
      kernel/api/file.go
  4. 13 12
      kernel/api/import.go
  5. 2 1
      kernel/api/lute.go
  6. 5 4
      kernel/api/system.go
  7. 3 2
      kernel/api/transaction.go
  8. 4 3
      kernel/api/workspace.go
  9. 7 6
      kernel/bazaar/icon.go
  10. 7 6
      kernel/bazaar/package.go
  11. 7 6
      kernel/bazaar/template.go
  12. 7 6
      kernel/bazaar/theme.go
  13. 7 6
      kernel/bazaar/widget.go
  14. 2 1
      kernel/cache/asset.go
  15. 2 1
      kernel/cmd/cmd.go
  16. 13 12
      kernel/filesys/tree.go
  17. 1 0
      kernel/go.mod
  18. 2 0
      kernel/go.sum
  19. 27 26
      kernel/model/appearance.go
  20. 29 28
      kernel/model/assets.go
  21. 6 5
      kernel/model/assets_watcher.go
  22. 2 1
      kernel/model/backlink.go
  23. 2 1
      kernel/model/blockinfo.go
  24. 16 15
      kernel/model/box.go
  25. 26 25
      kernel/model/conf.go
  26. 7 6
      kernel/model/css.go
  27. 47 46
      kernel/model/export.go
  28. 41 40
      kernel/model/file.go
  29. 5 4
      kernel/model/format.go
  30. 2 2
      kernel/model/graph.go
  31. 28 27
      kernel/model/history.go
  32. 19 18
      kernel/model/import.go
  33. 10 9
      kernel/model/index.go
  34. 29 28
      kernel/model/liandi.go
  35. 3 2
      kernel/model/mount.go
  36. 2 1
      kernel/model/path.go
  37. 3 2
      kernel/model/process.go
  38. 14 13
      kernel/model/repository.go
  39. 2 1
      kernel/model/search.go
  40. 8 7
      kernel/model/session.go
  41. 9 8
      kernel/model/sync.go
  42. 3 2
      kernel/model/template.go
  43. 42 41
      kernel/model/transaction.go
  44. 4 4
      kernel/model/tree.go
  45. 2 1
      kernel/model/updater.go
  46. 2 1
      kernel/model/upload.go
  47. 2 1
      kernel/model/widget.go
  48. 17 16
      kernel/server/serve.go
  49. 5 4
      kernel/sql/aseet.go
  50. 27 26
      kernel/sql/block_query.go
  51. 23 23
      kernel/sql/block_ref_query.go
  52. 26 25
      kernel/sql/database.go
  53. 3 3
      kernel/sql/file_annotation_ref.go
  54. 9 8
      kernel/sql/queue.go
  55. 6 6
      kernel/sql/span.go
  56. 2 1
      kernel/sql/stat.go
  57. 4 3
      kernel/sql/upsert.go
  58. 12 11
      kernel/treenode/blocktree.go
  59. 2 2
      kernel/treenode/node.go
  60. 5 3
      kernel/util/crypt.go
  61. 5 4
      kernel/util/file.go
  62. 2 1
      kernel/util/font.go
  63. 0 340
      kernel/util/log.go
  64. 2 1
      kernel/util/path.go
  65. 5 2
      kernel/util/result.go
  66. 2 1
      kernel/util/rhy.go
  67. 5 4
      kernel/util/runtime.go
  68. 3 2
      kernel/util/web.go
  69. 15 13
      kernel/util/working.go
  70. 3 1
      kernel/util/working_mobile.go

+ 2 - 1
kernel/api/block.go

@@ -25,6 +25,7 @@ import (
 	"github.com/88250/lute/html"
 	"github.com/88250/lute/html"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
@@ -285,7 +286,7 @@ func getBlockInfo(c *gin.Context) {
 			break
 			break
 		}
 		}
 		if b, _ = model.GetBlock(parentID); nil == b {
 		if b, _ = model.GetBlock(parentID); nil == b {
-			util.LogErrorf("not found parent")
+			logging.LogErrorf("not found parent")
 			break
 			break
 		}
 		}
 	}
 	}

+ 2 - 1
kernel/api/extension.go

@@ -29,6 +29,7 @@ import (
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/ast"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
@@ -48,7 +49,7 @@ func extensionCopy(c *gin.Context) {
 	}
 	}
 
 
 	if err := os.MkdirAll(assets, 0755); nil != err {
 	if err := os.MkdirAll(assets, 0755); nil != err {
-		util.LogErrorf("create assets folder [%s] failed: %s", assets, err)
+		logging.LogErrorf("create assets folder [%s] failed: %s", assets, err)
 		ret.Msg = err.Error()
 		ret.Msg = err.Error()
 		return
 		return
 	}
 	}

+ 10 - 9
kernel/api/file.go

@@ -29,6 +29,7 @@ import (
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
@@ -49,12 +50,12 @@ func getFile(c *gin.Context) {
 		return
 		return
 	}
 	}
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("stat [%s] failed: %s", filePath, err)
+		logging.LogErrorf("stat [%s] failed: %s", filePath, err)
 		c.Status(500)
 		c.Status(500)
 		return
 		return
 	}
 	}
 	if info.IsDir() {
 	if info.IsDir() {
-		util.LogErrorf("file [%s] is a directory", filePath)
+		logging.LogErrorf("file [%s] is a directory", filePath)
 		c.Status(405)
 		c.Status(405)
 		return
 		return
 	}
 	}
@@ -78,28 +79,28 @@ func putFile(c *gin.Context) {
 	if isDir {
 	if isDir {
 		err = os.MkdirAll(filePath, 0755)
 		err = os.MkdirAll(filePath, 0755)
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("make a dir [%s] failed: %s", filePath, err)
+			logging.LogErrorf("make a dir [%s] failed: %s", filePath, err)
 		}
 		}
 	} else {
 	} else {
 		file, _ := c.FormFile("file")
 		file, _ := c.FormFile("file")
 		if nil == file {
 		if nil == file {
-			util.LogErrorf("form file is nil [path=%s]", filePath)
+			logging.LogErrorf("form file is nil [path=%s]", filePath)
 			c.Status(400)
 			c.Status(400)
 			return
 			return
 		}
 		}
 
 
 		dir := filepath.Dir(filePath)
 		dir := filepath.Dir(filePath)
 		if err = os.MkdirAll(dir, 0755); nil != err {
 		if err = os.MkdirAll(dir, 0755); nil != err {
-			util.LogErrorf("put a file [%s] make dir [%s] failed: %s", filePath, dir, err)
+			logging.LogErrorf("put a file [%s] make dir [%s] failed: %s", filePath, dir, err)
 		} else {
 		} else {
 			if filelock.IsLocked(filePath) {
 			if filelock.IsLocked(filePath) {
 				msg := fmt.Sprintf("file [%s] is locked", filePath)
 				msg := fmt.Sprintf("file [%s] is locked", filePath)
-				util.LogErrorf(msg)
+				logging.LogErrorf(msg)
 				err = errors.New(msg)
 				err = errors.New(msg)
 			} else {
 			} else {
 				err = writeFile(file, filePath)
 				err = writeFile(file, filePath)
 				if nil != err {
 				if nil != err {
-					util.LogErrorf("put a file [%s] failed: %s", filePath, err)
+					logging.LogErrorf("put a file [%s] failed: %s", filePath, err)
 				}
 				}
 			}
 			}
 		}
 		}
@@ -113,13 +114,13 @@ func putFile(c *gin.Context) {
 	modTimeStr := c.PostForm("modTime")
 	modTimeStr := c.PostForm("modTime")
 	modTimeInt, err := strconv.ParseInt(modTimeStr, 10, 64)
 	modTimeInt, err := strconv.ParseInt(modTimeStr, 10, 64)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("parse mod time [%s] failed: %s", modTimeStr, err)
+		logging.LogErrorf("parse mod time [%s] failed: %s", modTimeStr, err)
 		c.Status(500)
 		c.Status(500)
 		return
 		return
 	}
 	}
 	modTime := millisecond2Time(modTimeInt)
 	modTime := millisecond2Time(modTimeInt)
 	if err = os.Chtimes(filePath, modTime, modTime); nil != err {
 	if err = os.Chtimes(filePath, modTime, modTime); nil != err {
-		util.LogErrorf("change time failed: %s", err)
+		logging.LogErrorf("change time failed: %s", err)
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = err.Error()
 		ret.Msg = err.Error()
 		return
 		return

+ 13 - 12
kernel/api/import.go

@@ -24,6 +24,7 @@ import (
 
 
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
@@ -34,7 +35,7 @@ func importSY(c *gin.Context) {
 
 
 	form, err := c.MultipartForm()
 	form, err := c.MultipartForm()
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("parse import .sy.zip failed: %s", err)
+		logging.LogErrorf("parse import .sy.zip failed: %s", err)
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = err.Error()
 		ret.Msg = err.Error()
 		return
 		return
@@ -42,7 +43,7 @@ func importSY(c *gin.Context) {
 
 
 	files := form.File["file"]
 	files := form.File["file"]
 	if 1 > len(files) {
 	if 1 > len(files) {
-		util.LogErrorf("parse import .sy.zip failed: %s", err)
+		logging.LogErrorf("parse import .sy.zip failed: %s", err)
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = err.Error()
 		ret.Msg = err.Error()
 		return
 		return
@@ -50,7 +51,7 @@ func importSY(c *gin.Context) {
 	file := files[0]
 	file := files[0]
 	reader, err := file.Open()
 	reader, err := file.Open()
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read import .sy.zip failed: %s", err)
+		logging.LogErrorf("read import .sy.zip failed: %s", err)
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = err.Error()
 		ret.Msg = err.Error()
 		return
 		return
@@ -58,7 +59,7 @@ func importSY(c *gin.Context) {
 
 
 	importDir := filepath.Join(util.TempDir, "import")
 	importDir := filepath.Join(util.TempDir, "import")
 	if err = os.MkdirAll(importDir, 0755); nil != err {
 	if err = os.MkdirAll(importDir, 0755); nil != err {
-		util.LogErrorf("make import dir [%s] failed: %s", importDir, err)
+		logging.LogErrorf("make import dir [%s] failed: %s", importDir, err)
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = err.Error()
 		ret.Msg = err.Error()
 		return
 		return
@@ -67,13 +68,13 @@ func importSY(c *gin.Context) {
 	defer os.RemoveAll(writePath)
 	defer os.RemoveAll(writePath)
 	writer, err := os.OpenFile(writePath, os.O_RDWR|os.O_CREATE, 0644)
 	writer, err := os.OpenFile(writePath, os.O_RDWR|os.O_CREATE, 0644)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("open import .sy.zip [%s] failed: %s", writePath, err)
+		logging.LogErrorf("open import .sy.zip [%s] failed: %s", writePath, err)
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = err.Error()
 		ret.Msg = err.Error()
 		return
 		return
 	}
 	}
 	if _, err = io.Copy(writer, reader); nil != err {
 	if _, err = io.Copy(writer, reader); nil != err {
-		util.LogErrorf("write import .sy.zip failed: %s", err)
+		logging.LogErrorf("write import .sy.zip failed: %s", err)
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = err.Error()
 		ret.Msg = err.Error()
 		return
 		return
@@ -98,14 +99,14 @@ func importData(c *gin.Context) {
 
 
 	form, err := c.MultipartForm()
 	form, err := c.MultipartForm()
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("import data failed: %s", err)
+		logging.LogErrorf("import data failed: %s", err)
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = err.Error()
 		ret.Msg = err.Error()
 		return
 		return
 	}
 	}
 
 
 	if 1 > len(form.File["file"]) {
 	if 1 > len(form.File["file"]) {
-		util.LogErrorf("import data failed: %s", err)
+		logging.LogErrorf("import data failed: %s", err)
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = "file not found"
 		ret.Msg = "file not found"
 		return
 		return
@@ -122,7 +123,7 @@ func importData(c *gin.Context) {
 	defer os.RemoveAll(dataZipPath)
 	defer os.RemoveAll(dataZipPath)
 	dataZipFile, err := os.Create(dataZipPath)
 	dataZipFile, err := os.Create(dataZipPath)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("create temp file failed: %s", err)
+		logging.LogErrorf("create temp file failed: %s", err)
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = "create temp file failed"
 		ret.Msg = "create temp file failed"
 		return
 		return
@@ -130,20 +131,20 @@ func importData(c *gin.Context) {
 	file := form.File["file"][0]
 	file := form.File["file"][0]
 	fileReader, err := file.Open()
 	fileReader, err := file.Open()
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("open upload file failed: %s", err)
+		logging.LogErrorf("open upload file failed: %s", err)
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = "open file failed"
 		ret.Msg = "open file failed"
 		return
 		return
 	}
 	}
 	_, err = io.Copy(dataZipFile, fileReader)
 	_, err = io.Copy(dataZipFile, fileReader)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read upload file failed: %s", err)
+		logging.LogErrorf("read upload file failed: %s", err)
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = "read file failed"
 		ret.Msg = "read file failed"
 		return
 		return
 	}
 	}
 	if err = dataZipFile.Close(); nil != err {
 	if err = dataZipFile.Close(); nil != err {
-		util.LogErrorf("close file failed: %s", err)
+		logging.LogErrorf("close file failed: %s", err)
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = "close file failed"
 		ret.Msg = "close file failed"
 		return
 		return

+ 2 - 1
kernel/api/lute.go

@@ -27,6 +27,7 @@ import (
 	"github.com/88250/lute/render"
 	"github.com/88250/lute/render"
 	"github.com/88250/protyle"
 	"github.com/88250/protyle"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
@@ -112,7 +113,7 @@ func html2BlockDOM(c *gin.Context) {
 			name = name + "-" + ast.NewNodeID() + ext
 			name = name + "-" + ast.NewNodeID() + ext
 			targetPath := filepath.Join(util.DataDir, "assets", name)
 			targetPath := filepath.Join(util.DataDir, "assets", name)
 			if err = gulu.File.CopyFile(localPath, targetPath); nil != err {
 			if err = gulu.File.CopyFile(localPath, targetPath); nil != err {
-				util.LogErrorf("copy asset from [%s] to [%s] failed: %s", localPath, targetPath, err)
+				logging.LogErrorf("copy asset from [%s] to [%s] failed: %s", localPath, targetPath, err)
 				return ast.WalkStop
 				return ast.WalkStop
 			}
 			}
 			n.Tokens = gulu.Str.ToBytes("assets/" + name)
 			n.Tokens = gulu.Str.ToBytes("assets/" + name)

+ 5 - 4
kernel/api/system.go

@@ -26,6 +26,7 @@ import (
 
 
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/conf"
 	"github.com/siyuan-note/siyuan/kernel/conf"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
@@ -38,7 +39,7 @@ func getEmojiConf(c *gin.Context) {
 	builtConfPath := filepath.Join(util.AppearancePath, "emojis", "conf.json")
 	builtConfPath := filepath.Join(util.AppearancePath, "emojis", "conf.json")
 	data, err := os.ReadFile(builtConfPath)
 	data, err := os.ReadFile(builtConfPath)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read emojis conf.json failed: %s", err)
+		logging.LogErrorf("read emojis conf.json failed: %s", err)
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = err.Error()
 		ret.Msg = err.Error()
 		return
 		return
@@ -46,7 +47,7 @@ func getEmojiConf(c *gin.Context) {
 
 
 	var conf []map[string]interface{}
 	var conf []map[string]interface{}
 	if err = gulu.JSON.UnmarshalJSON(data, &conf); nil != err {
 	if err = gulu.JSON.UnmarshalJSON(data, &conf); nil != err {
-		util.LogErrorf("unmarshal emojis conf.json failed: %s", err)
+		logging.LogErrorf("unmarshal emojis conf.json failed: %s", err)
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = err.Error()
 		ret.Msg = err.Error()
 		return
 		return
@@ -64,7 +65,7 @@ func getEmojiConf(c *gin.Context) {
 		model.CustomEmojis = sync.Map{}
 		model.CustomEmojis = sync.Map{}
 		customEmojis, err := os.ReadDir(customConfDir)
 		customEmojis, err := os.ReadDir(customConfDir)
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("read custom emojis failed: %s", err)
+			logging.LogErrorf("read custom emojis failed: %s", err)
 		} else {
 		} else {
 			for _, customEmoji := range customEmojis {
 			for _, customEmoji := range customEmojis {
 				name := customEmoji.Name()
 				name := customEmoji.Name()
@@ -76,7 +77,7 @@ func getEmojiConf(c *gin.Context) {
 					// 子级
 					// 子级
 					subCustomEmojis, err := os.ReadDir(filepath.Join(customConfDir, name))
 					subCustomEmojis, err := os.ReadDir(filepath.Join(customConfDir, name))
 					if nil != err {
 					if nil != err {
-						util.LogErrorf("read custom emojis failed: %s", err)
+						logging.LogErrorf("read custom emojis failed: %s", err)
 						continue
 						continue
 					}
 					}
 
 

+ 3 - 2
kernel/api/transaction.go

@@ -25,6 +25,7 @@ import (
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
@@ -78,12 +79,12 @@ func performTransactions(c *gin.Context) {
 	if nil != err {
 	if nil != err {
 		tx, txErr := sql.BeginTx()
 		tx, txErr := sql.BeginTx()
 		if nil != txErr {
 		if nil != txErr {
-			util.LogFatalf("transaction failed: %s", txErr)
+			logging.LogFatalf("transaction failed: %s", txErr)
 			return
 			return
 		}
 		}
 		sql.ClearBoxHash(tx)
 		sql.ClearBoxHash(tx)
 		sql.CommitTx(tx)
 		sql.CommitTx(tx)
-		util.LogFatalf("transaction failed: %s", err)
+		logging.LogFatalf("transaction failed: %s", err)
 		return
 		return
 	}
 	}
 
 

+ 4 - 3
kernel/api/workspace.go

@@ -26,6 +26,7 @@ import (
 
 
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
@@ -39,7 +40,7 @@ func listWorkspaceDirs(c *gin.Context) {
 	data, err := os.ReadFile(workspaceConf)
 	data, err := os.ReadFile(workspaceConf)
 	var workspacePaths []string
 	var workspacePaths []string
 	if err = gulu.JSON.UnmarshalJSON(data, &workspacePaths); nil != err {
 	if err = gulu.JSON.UnmarshalJSON(data, &workspacePaths); nil != err {
-		util.LogErrorf("unmarshal workspace conf [%s] failed: %s", workspaceConf, err)
+		logging.LogErrorf("unmarshal workspace conf [%s] failed: %s", workspaceConf, err)
 		return
 		return
 	}
 	}
 	ret.Data = workspacePaths
 	ret.Data = workspacePaths
@@ -76,10 +77,10 @@ func setWorkspaceDir(c *gin.Context) {
 	workspaceConf := filepath.Join(util.HomeDir, ".config", "siyuan", "workspace.json")
 	workspaceConf := filepath.Join(util.HomeDir, ".config", "siyuan", "workspace.json")
 	data, err := os.ReadFile(workspaceConf)
 	data, err := os.ReadFile(workspaceConf)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read workspace conf failed: %s", err)
+		logging.LogErrorf("read workspace conf failed: %s", err)
 	} else {
 	} else {
 		if err = gulu.JSON.UnmarshalJSON(data, &workspacePaths); nil != err {
 		if err = gulu.JSON.UnmarshalJSON(data, &workspacePaths); nil != err {
-			util.LogErrorf("unmarshal workspace conf failed: %s", err)
+			logging.LogErrorf("unmarshal workspace conf failed: %s", err)
 		}
 		}
 	}
 	}
 
 

+ 7 - 6
kernel/bazaar/icon.go

@@ -26,6 +26,7 @@ import (
 	"github.com/dustin/go-humanize"
 	"github.com/dustin/go-humanize"
 	ants "github.com/panjf2000/ants/v2"
 	ants "github.com/panjf2000/ants/v2"
 	"github.com/siyuan-note/httpclient"
 	"github.com/siyuan-note/httpclient"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
 
 
@@ -68,11 +69,11 @@ func Icons() (icons []*Icon) {
 	u := util.BazaarOSSServer + "/bazaar@" + bazaarHash + "/stage/icons.json"
 	u := util.BazaarOSSServer + "/bazaar@" + bazaarHash + "/stage/icons.json"
 	resp, err := request.SetResult(&result).Get(u)
 	resp, err := request.SetResult(&result).Get(u)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("get community stage index [%s] failed: %s", u, err)
+		logging.LogErrorf("get community stage index [%s] failed: %s", u, err)
 		return
 		return
 	}
 	}
 	if 200 != resp.StatusCode {
 	if 200 != resp.StatusCode {
-		util.LogErrorf("get community stage index [%s] failed: %d", u, resp.StatusCode)
+		logging.LogErrorf("get community stage index [%s] failed: %d", u, resp.StatusCode)
 		return
 		return
 	}
 	}
 	repos := result["repos"].([]interface{})
 	repos := result["repos"].([]interface{})
@@ -88,11 +89,11 @@ func Icons() (icons []*Icon) {
 		innerU := util.BazaarOSSServer + "/package/" + repoURL + "/icon.json"
 		innerU := util.BazaarOSSServer + "/package/" + repoURL + "/icon.json"
 		innerResp, innerErr := httpclient.NewBrowserRequest().SetResult(icon).Get(innerU)
 		innerResp, innerErr := httpclient.NewBrowserRequest().SetResult(icon).Get(innerU)
 		if nil != innerErr {
 		if nil != innerErr {
-			util.LogErrorf("get bazaar package [%s] failed: %s", repoURL, innerErr)
+			logging.LogErrorf("get bazaar package [%s] failed: %s", repoURL, innerErr)
 			return
 			return
 		}
 		}
 		if 200 != innerResp.StatusCode {
 		if 200 != innerResp.StatusCode {
-			util.LogErrorf("get bazaar package [%s] failed: %d", innerU, innerResp.StatusCode)
+			logging.LogErrorf("get bazaar package [%s] failed: %d", innerU, innerResp.StatusCode)
 			return
 			return
 		}
 		}
 
 
@@ -137,9 +138,9 @@ func InstallIcon(repoURL, repoHash, installPath string, chinaCDN bool, systemID
 
 
 func UninstallIcon(installPath string) error {
 func UninstallIcon(installPath string) error {
 	if err := os.RemoveAll(installPath); nil != err {
 	if err := os.RemoveAll(installPath); nil != err {
-		util.LogErrorf("remove icon [%s] failed: %s", installPath, err)
+		logging.LogErrorf("remove icon [%s] failed: %s", installPath, err)
 		return errors.New("remove community icon failed")
 		return errors.New("remove community icon failed")
 	}
 	}
-	//util.Logger.Infof("uninstalled icon [%s]", installPath)
+	//logging.Logger.Infof("uninstalled icon [%s]", installPath)
 	return nil
 	return nil
 }
 }

+ 7 - 6
kernel/bazaar/package.go

@@ -31,6 +31,7 @@ import (
 	"github.com/araddon/dateparse"
 	"github.com/araddon/dateparse"
 	"github.com/imroc/req/v3"
 	"github.com/imroc/req/v3"
 	"github.com/siyuan-note/httpclient"
 	"github.com/siyuan-note/httpclient"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	textUnicode "golang.org/x/text/encoding/unicode"
 	textUnicode "golang.org/x/text/encoding/unicode"
 	"golang.org/x/text/transform"
 	"golang.org/x/text/transform"
@@ -60,7 +61,7 @@ func GetPackageREADME(repoURL, repoHash string, chinaCDN bool, systemID string)
 	ret = luteEngine.Md2HTML(string(data))
 	ret = luteEngine.Md2HTML(string(data))
 	doc, err := goquery.NewDocumentFromReader(strings.NewReader(ret))
 	doc, err := goquery.NewDocumentFromReader(strings.NewReader(ret))
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("parse HTML failed: %s", err)
+		logging.LogErrorf("parse HTML failed: %s", err)
 		return ret
 		return ret
 	}
 	}
 
 
@@ -96,12 +97,12 @@ func downloadPackage(repoURLHash string, chinaCDN, pushProgress bool, systemID s
 			}
 			}
 		}).Get(u)
 		}).Get(u)
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("get bazaar package [%s] failed: %s", u, err)
+			logging.LogErrorf("get bazaar package [%s] failed: %s", u, err)
 			return nil, errors.New("get bazaar package failed")
 			return nil, errors.New("get bazaar package failed")
 		}
 		}
 	}
 	}
 	if 200 != resp.StatusCode {
 	if 200 != resp.StatusCode {
-		util.LogErrorf("get bazaar package [%s] failed: %d", u, resp.StatusCode)
+		logging.LogErrorf("get bazaar package [%s] failed: %d", u, resp.StatusCode)
 		return nil, errors.New("get bazaar package failed")
 		return nil, errors.New("get bazaar package failed")
 	}
 	}
 	data = buf.Bytes()
 	data = buf.Bytes()
@@ -137,7 +138,7 @@ func installPackage(data []byte, installPath string) (err error) {
 
 
 	unzipPath := filepath.Join(dir, name)
 	unzipPath := filepath.Join(dir, name)
 	if err = gulu.Zip.Unzip(tmp, unzipPath); nil != err {
 	if err = gulu.Zip.Unzip(tmp, unzipPath); nil != err {
-		util.LogErrorf("write file [%s] failed: %s", installPath, err)
+		logging.LogErrorf("write file [%s] failed: %s", installPath, err)
 		err = errors.New("write file failed")
 		err = errors.New("write file failed")
 		return
 		return
 	}
 	}
@@ -195,11 +196,11 @@ func getBazaarIndex() map[string]*bazaarPackage {
 	u := util.BazaarStatServer + "/bazaar/index.json"
 	u := util.BazaarStatServer + "/bazaar/index.json"
 	resp, reqErr := request.SetResult(&cachedBazaarIndex).Get(u)
 	resp, reqErr := request.SetResult(&cachedBazaarIndex).Get(u)
 	if nil != reqErr {
 	if nil != reqErr {
-		util.LogErrorf("get bazaar index [%s] failed: %s", u, reqErr)
+		logging.LogErrorf("get bazaar index [%s] failed: %s", u, reqErr)
 		return cachedBazaarIndex
 		return cachedBazaarIndex
 	}
 	}
 	if 200 != resp.StatusCode {
 	if 200 != resp.StatusCode {
-		util.LogErrorf("get bazaar index [%s] failed: %d", u, resp.StatusCode)
+		logging.LogErrorf("get bazaar index [%s] failed: %d", u, resp.StatusCode)
 		return cachedBazaarIndex
 		return cachedBazaarIndex
 	}
 	}
 	bazaarIndexCacheTime = now
 	bazaarIndexCacheTime = now

+ 7 - 6
kernel/bazaar/template.go

@@ -27,6 +27,7 @@ import (
 	"github.com/dustin/go-humanize"
 	"github.com/dustin/go-humanize"
 	"github.com/panjf2000/ants/v2"
 	"github.com/panjf2000/ants/v2"
 	"github.com/siyuan-note/httpclient"
 	"github.com/siyuan-note/httpclient"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
 
 
@@ -68,11 +69,11 @@ func Templates() (templates []*Template) {
 	u := util.BazaarOSSServer + "/bazaar@" + bazaarHash + "/stage/templates.json"
 	u := util.BazaarOSSServer + "/bazaar@" + bazaarHash + "/stage/templates.json"
 	resp, reqErr := request.SetResult(&result).Get(u)
 	resp, reqErr := request.SetResult(&result).Get(u)
 	if nil != reqErr {
 	if nil != reqErr {
-		util.LogErrorf("get community stage index [%s] failed: %s", u, reqErr)
+		logging.LogErrorf("get community stage index [%s] failed: %s", u, reqErr)
 		return
 		return
 	}
 	}
 	if 200 != resp.StatusCode {
 	if 200 != resp.StatusCode {
-		util.LogErrorf("get community stage index [%s] failed: %d", u, resp.StatusCode)
+		logging.LogErrorf("get community stage index [%s] failed: %d", u, resp.StatusCode)
 		return
 		return
 	}
 	}
 
 
@@ -89,11 +90,11 @@ func Templates() (templates []*Template) {
 		innerU := util.BazaarOSSServer + "/package/" + repoURL + "/template.json"
 		innerU := util.BazaarOSSServer + "/package/" + repoURL + "/template.json"
 		innerResp, innerErr := httpclient.NewBrowserRequest().SetResult(template).Get(innerU)
 		innerResp, innerErr := httpclient.NewBrowserRequest().SetResult(template).Get(innerU)
 		if nil != innerErr {
 		if nil != innerErr {
-			util.LogErrorf("get community template [%s] failed: %s", repoURL, innerErr)
+			logging.LogErrorf("get community template [%s] failed: %s", repoURL, innerErr)
 			return
 			return
 		}
 		}
 		if 200 != innerResp.StatusCode {
 		if 200 != innerResp.StatusCode {
-			util.LogErrorf("get bazaar package [%s] failed: %d", innerU, innerResp.StatusCode)
+			logging.LogErrorf("get bazaar package [%s] failed: %d", innerU, innerResp.StatusCode)
 			return
 			return
 		}
 		}
 
 
@@ -140,7 +141,7 @@ func InstallTemplate(repoURL, repoHash, installPath string, chinaCDN bool, syste
 
 
 func UninstallTemplate(installPath string) error {
 func UninstallTemplate(installPath string) error {
 	if err := os.RemoveAll(installPath); nil != err {
 	if err := os.RemoveAll(installPath); nil != err {
-		util.LogErrorf("remove template [%s] failed: %s", installPath, err)
+		logging.LogErrorf("remove template [%s] failed: %s", installPath, err)
 		return errors.New("remove community template failed")
 		return errors.New("remove community template failed")
 	}
 	}
 	return nil
 	return nil
@@ -153,7 +154,7 @@ func filterLegacyTemplates(templates []*Template) (ret []*Template) {
 			updated := theme.Updated[:len("2006-01-02T15:04:05")]
 			updated := theme.Updated[:len("2006-01-02T15:04:05")]
 			t, err := time.Parse("2006-01-02T15:04:05", updated)
 			t, err := time.Parse("2006-01-02T15:04:05", updated)
 			if nil != err {
 			if nil != err {
-				util.LogErrorf("convert update time [%s] failed: %s", updated, err)
+				logging.LogErrorf("convert update time [%s] failed: %s", updated, err)
 				continue
 				continue
 			}
 			}
 			if t.After(verTime) {
 			if t.After(verTime) {

+ 7 - 6
kernel/bazaar/theme.go

@@ -26,6 +26,7 @@ import (
 	"github.com/dustin/go-humanize"
 	"github.com/dustin/go-humanize"
 	ants "github.com/panjf2000/ants/v2"
 	ants "github.com/panjf2000/ants/v2"
 	"github.com/siyuan-note/httpclient"
 	"github.com/siyuan-note/httpclient"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
 
 
@@ -69,11 +70,11 @@ func Themes() (ret []*Theme) {
 	u := util.BazaarOSSServer + "/bazaar@" + bazaarHash + "/stage/themes.json"
 	u := util.BazaarOSSServer + "/bazaar@" + bazaarHash + "/stage/themes.json"
 	resp, reqErr := request.SetResult(&result).Get(u)
 	resp, reqErr := request.SetResult(&result).Get(u)
 	if nil != reqErr {
 	if nil != reqErr {
-		util.LogErrorf("get community stage index [%s] failed: %s", u, reqErr)
+		logging.LogErrorf("get community stage index [%s] failed: %s", u, reqErr)
 		return
 		return
 	}
 	}
 	if 200 != resp.StatusCode {
 	if 200 != resp.StatusCode {
-		util.LogErrorf("get community stage index [%s] failed: %d", u, resp.StatusCode)
+		logging.LogErrorf("get community stage index [%s] failed: %d", u, resp.StatusCode)
 		return
 		return
 	}
 	}
 
 
@@ -90,11 +91,11 @@ func Themes() (ret []*Theme) {
 		innerU := util.BazaarOSSServer + "/package/" + repoURL + "/theme.json"
 		innerU := util.BazaarOSSServer + "/package/" + repoURL + "/theme.json"
 		innerResp, innerErr := httpclient.NewBrowserRequest().SetResult(theme).Get(innerU)
 		innerResp, innerErr := httpclient.NewBrowserRequest().SetResult(theme).Get(innerU)
 		if nil != innerErr {
 		if nil != innerErr {
-			util.LogErrorf("get bazaar package [%s] failed: %s", innerU, innerErr)
+			logging.LogErrorf("get bazaar package [%s] failed: %s", innerU, innerErr)
 			return
 			return
 		}
 		}
 		if 200 != innerResp.StatusCode {
 		if 200 != innerResp.StatusCode {
-			util.LogErrorf("get bazaar package [%s] failed: %d", innerU, resp.StatusCode)
+			logging.LogErrorf("get bazaar package [%s] failed: %d", innerU, resp.StatusCode)
 			return
 			return
 		}
 		}
 
 
@@ -139,9 +140,9 @@ func InstallTheme(repoURL, repoHash, installPath string, chinaCDN bool, systemID
 
 
 func UninstallTheme(installPath string) error {
 func UninstallTheme(installPath string) error {
 	if err := os.RemoveAll(installPath); nil != err {
 	if err := os.RemoveAll(installPath); nil != err {
-		util.LogErrorf("remove theme [%s] failed: %s", installPath, err)
+		logging.LogErrorf("remove theme [%s] failed: %s", installPath, err)
 		return errors.New("remove community theme failed")
 		return errors.New("remove community theme failed")
 	}
 	}
-	//util.Logger.Infof("uninstalled theme [%s]", installPath)
+	//logging.Logger.Infof("uninstalled theme [%s]", installPath)
 	return nil
 	return nil
 }
 }

+ 7 - 6
kernel/bazaar/widget.go

@@ -26,6 +26,7 @@ import (
 	"github.com/dustin/go-humanize"
 	"github.com/dustin/go-humanize"
 	ants "github.com/panjf2000/ants/v2"
 	ants "github.com/panjf2000/ants/v2"
 	"github.com/siyuan-note/httpclient"
 	"github.com/siyuan-note/httpclient"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
 
 
@@ -68,11 +69,11 @@ func Widgets() (widgets []*Widget) {
 	u := util.BazaarOSSServer + "/bazaar@" + bazaarHash + "/stage/widgets.json"
 	u := util.BazaarOSSServer + "/bazaar@" + bazaarHash + "/stage/widgets.json"
 	resp, err := request.SetResult(&result).Get(u)
 	resp, err := request.SetResult(&result).Get(u)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("get community stage index [%s] failed: %s", u, err)
+		logging.LogErrorf("get community stage index [%s] failed: %s", u, err)
 		return
 		return
 	}
 	}
 	if 200 != resp.StatusCode {
 	if 200 != resp.StatusCode {
-		util.LogErrorf("get community stage index [%s] failed: %d", u, resp.StatusCode)
+		logging.LogErrorf("get community stage index [%s] failed: %d", u, resp.StatusCode)
 		return
 		return
 	}
 	}
 
 
@@ -89,11 +90,11 @@ func Widgets() (widgets []*Widget) {
 		innerU := util.BazaarOSSServer + "/package/" + repoURL + "/widget.json"
 		innerU := util.BazaarOSSServer + "/package/" + repoURL + "/widget.json"
 		innerResp, innerErr := httpclient.NewBrowserRequest().SetResult(widget).Get(innerU)
 		innerResp, innerErr := httpclient.NewBrowserRequest().SetResult(widget).Get(innerU)
 		if nil != innerErr {
 		if nil != innerErr {
-			util.LogErrorf("get bazaar package [%s] failed: %s", repoURL, innerErr)
+			logging.LogErrorf("get bazaar package [%s] failed: %s", repoURL, innerErr)
 			return
 			return
 		}
 		}
 		if 200 != innerResp.StatusCode {
 		if 200 != innerResp.StatusCode {
-			util.LogErrorf("get bazaar package [%s] failed: %d", innerU, innerResp.StatusCode)
+			logging.LogErrorf("get bazaar package [%s] failed: %d", innerU, innerResp.StatusCode)
 			return
 			return
 		}
 		}
 
 
@@ -138,9 +139,9 @@ func InstallWidget(repoURL, repoHash, installPath string, chinaCDN bool, systemI
 
 
 func UninstallWidget(installPath string) error {
 func UninstallWidget(installPath string) error {
 	if err := os.RemoveAll(installPath); nil != err {
 	if err := os.RemoveAll(installPath); nil != err {
-		util.LogErrorf("remove widget [%s] failed: %s", installPath, err)
+		logging.LogErrorf("remove widget [%s] failed: %s", installPath, err)
 		return errors.New("remove community widget failed")
 		return errors.New("remove community widget failed")
 	}
 	}
-	//util.Logger.Infof("uninstalled widget [%s]", installPath)
+	//logging.Logger.Infof("uninstalled widget [%s]", installPath)
 	return nil
 	return nil
 }
 }

+ 2 - 1
kernel/cache/asset.go

@@ -23,6 +23,7 @@ import (
 	"sync"
 	"sync"
 	"time"
 	"time"
 
 
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
 
 
@@ -60,6 +61,6 @@ func LoadAssets() {
 	})
 	})
 	elapsed := time.Since(start)
 	elapsed := time.Since(start)
 	if 2000 < elapsed.Milliseconds() {
 	if 2000 < elapsed.Milliseconds() {
-		util.LogInfof("loaded assets [%.2fs]", elapsed.Seconds())
+		logging.LogInfof("loaded assets [%.2fs]", elapsed.Seconds())
 	}
 	}
 }
 }

+ 2 - 1
kernel/cmd/cmd.go

@@ -18,6 +18,7 @@ package cmd
 
 
 import (
 import (
 	"github.com/88250/melody"
 	"github.com/88250/melody"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
 
 
@@ -78,7 +79,7 @@ func NewCommand(cmdStr string, cmdId float64, param map[string]interface{}, sess
 func Exec(cmd Cmd) {
 func Exec(cmd Cmd) {
 	go func() {
 	go func() {
 		//start := time.Now()
 		//start := time.Now()
-		defer util.Recover()
+		defer logging.Recover()
 		cmd.Exec()
 		cmd.Exec()
 		//end := time.Now()
 		//end := time.Now()
 		//util.Logger.Infof("cmd [%s] exec consumed [%d]ms", cmd.Name(), end.Sub(start).Milliseconds())
 		//util.Logger.Infof("cmd [%s] exec consumed [%d]ms", cmd.Name(), end.Sub(start).Milliseconds())

+ 13 - 12
kernel/filesys/tree.go

@@ -30,6 +30,7 @@ import (
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/parse"
 	"github.com/88250/protyle"
 	"github.com/88250/protyle"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/cache"
 	"github.com/siyuan-note/siyuan/kernel/cache"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
@@ -73,13 +74,13 @@ func LoadTree(boxID, p string, luteEngine *lute.Lute) (ret *parse.Tree, err erro
 		parentPath = filepath.Join(util.DataDir, boxID, parentPath)
 		parentPath = filepath.Join(util.DataDir, boxID, parentPath)
 		parentData, readErr := filelock.LockFileRead(parentPath)
 		parentData, readErr := filelock.LockFileRead(parentPath)
 		if nil != readErr {
 		if nil != readErr {
-			util.LogWarnf("read tree data [%s] failed: %s", parentPath, readErr)
+			logging.LogWarnf("read tree data [%s] failed: %s", parentPath, readErr)
 			hPathBuilder.WriteString("Untitled/")
 			hPathBuilder.WriteString("Untitled/")
 			continue
 			continue
 		}
 		}
 		parentTree, parseErr := protyle.ParseJSONWithoutFix(luteEngine, parentData)
 		parentTree, parseErr := protyle.ParseJSONWithoutFix(luteEngine, parentData)
 		if nil != parseErr {
 		if nil != parseErr {
-			util.LogWarnf("parse tree [%s] failed: %s", parentPath, parseErr)
+			logging.LogWarnf("parse tree [%s] failed: %s", parentPath, parseErr)
 			hPathBuilder.WriteString("Untitled/")
 			hPathBuilder.WriteString("Untitled/")
 			continue
 			continue
 		}
 		}
@@ -118,7 +119,7 @@ func WriteTree(tree *parse.Tree) (err error) {
 	}
 	}
 	if err = filelock.LockFileWrite(filePath, output); nil != err {
 	if err = filelock.LockFileWrite(filePath, output); nil != err {
 		msg := fmt.Sprintf("write data [%s] failed: %s", filePath, err)
 		msg := fmt.Sprintf("write data [%s] failed: %s", filePath, err)
-		util.LogErrorf(msg)
+		logging.LogErrorf(msg)
 		return errors.New(msg)
 		return errors.New(msg)
 	}
 	}
 
 
@@ -131,39 +132,39 @@ func recoverParseJSON2Tree(boxID, p, filePath string, luteEngine *lute.Lute) (re
 	// 尝试从临时文件恢复
 	// 尝试从临时文件恢复
 	tmp := util.LatestTmpFile(filePath)
 	tmp := util.LatestTmpFile(filePath)
 	if "" == tmp {
 	if "" == tmp {
-		util.LogWarnf("recover tree [%s] not found tmp", filePath)
+		logging.LogWarnf("recover tree [%s] not found tmp", filePath)
 		return
 		return
 	}
 	}
 
 
 	stat, err := os.Stat(filePath)
 	stat, err := os.Stat(filePath)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("stat tmp [%s] failed: %s", tmp, err)
+		logging.LogErrorf("stat tmp [%s] failed: %s", tmp, err)
 		return
 		return
 	}
 	}
 
 
 	if stat.ModTime().Before(time.Now().Add(-time.Hour * 24)) {
 	if stat.ModTime().Before(time.Now().Add(-time.Hour * 24)) {
-		util.LogWarnf("tmp [%s] is too old, remove it", tmp)
+		logging.LogWarnf("tmp [%s] is too old, remove it", tmp)
 		os.RemoveAll(tmp)
 		os.RemoveAll(tmp)
 		return
 		return
 	}
 	}
 
 
 	data, err := filelock.NoLockFileRead(tmp)
 	data, err := filelock.NoLockFileRead(tmp)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("recover tree read from tmp [%s] failed: %s", tmp, err)
+		logging.LogErrorf("recover tree read from tmp [%s] failed: %s", tmp, err)
 		return
 		return
 	}
 	}
 	if err = filelock.NoLockFileWrite(filePath, data); nil != err {
 	if err = filelock.NoLockFileWrite(filePath, data); nil != err {
-		util.LogErrorf("recover tree write [%s] from tmp [%s] failed: %s", filePath, tmp, err)
+		logging.LogErrorf("recover tree write [%s] from tmp [%s] failed: %s", filePath, tmp, err)
 		return
 		return
 	}
 	}
 
 
 	ret = parseJSON2Tree(boxID, p, data, luteEngine)
 	ret = parseJSON2Tree(boxID, p, data, luteEngine)
 	if nil == ret {
 	if nil == ret {
-		util.LogErrorf("recover tree from tmp [%s] parse failed, remove it", tmp)
+		logging.LogErrorf("recover tree from tmp [%s] parse failed, remove it", tmp)
 		os.RemoveAll(tmp)
 		os.RemoveAll(tmp)
 		return
 		return
 	}
 	}
-	util.LogInfof("recovered tree [%s] from [%s]", filePath, tmp)
+	logging.LogInfof("recovered tree [%s] from [%s]", filePath, tmp)
 	os.RemoveAll(tmp)
 	os.RemoveAll(tmp)
 	return
 	return
 }
 }
@@ -173,7 +174,7 @@ func parseJSON2Tree(boxID, p string, jsonData []byte, luteEngine *lute.Lute) (re
 	var needFix bool
 	var needFix bool
 	ret, needFix, err = protyle.ParseJSON(luteEngine, jsonData)
 	ret, needFix, err = protyle.ParseJSON(luteEngine, jsonData)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("parse json [%s] to tree failed: %s", boxID+p, err)
+		logging.LogErrorf("parse json [%s] to tree failed: %s", boxID+p, err)
 		return
 		return
 	}
 	}
 
 
@@ -196,7 +197,7 @@ func parseJSON2Tree(boxID, p string, jsonData []byte, luteEngine *lute.Lute) (re
 		}
 		}
 		if err = filelock.LockFileWrite(filePath, output); nil != err {
 		if err = filelock.LockFileWrite(filePath, output); nil != err {
 			msg := fmt.Sprintf("write data [%s] failed: %s", filePath, err)
 			msg := fmt.Sprintf("write data [%s] failed: %s", filePath, err)
-			util.LogErrorf(msg)
+			logging.LogErrorf(msg)
 		}
 		}
 	}
 	}
 	return
 	return

+ 1 - 0
kernel/go.mod

@@ -44,6 +44,7 @@ require (
 	github.com/siyuan-note/eventbus v0.0.0-20220624162334-ca7c06dc771f
 	github.com/siyuan-note/eventbus v0.0.0-20220624162334-ca7c06dc771f
 	github.com/siyuan-note/filelock v0.0.0-20220704090116-54dfb035283f
 	github.com/siyuan-note/filelock v0.0.0-20220704090116-54dfb035283f
 	github.com/siyuan-note/httpclient v0.0.0-20220709030145-2bfb50f28e73
 	github.com/siyuan-note/httpclient v0.0.0-20220709030145-2bfb50f28e73
+	github.com/siyuan-note/logging v0.0.0-20220717040626-f796b05ee520
 	github.com/steambap/captcha v1.4.1
 	github.com/steambap/captcha v1.4.1
 	github.com/vmihailenco/msgpack/v5 v5.3.5
 	github.com/vmihailenco/msgpack/v5 v5.3.5
 	github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673
 	github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673

+ 2 - 0
kernel/go.sum

@@ -524,6 +524,8 @@ github.com/siyuan-note/filelock v0.0.0-20220704090116-54dfb035283f h1:IXZ4SWPjQL
 github.com/siyuan-note/filelock v0.0.0-20220704090116-54dfb035283f/go.mod h1:c4vwvWRrnfa75OXiO21K/76BFRJ4cFITKNoVs5lFdwc=
 github.com/siyuan-note/filelock v0.0.0-20220704090116-54dfb035283f/go.mod h1:c4vwvWRrnfa75OXiO21K/76BFRJ4cFITKNoVs5lFdwc=
 github.com/siyuan-note/httpclient v0.0.0-20220709030145-2bfb50f28e73 h1:NAw9IJtD0/NU2lhraQjELAcU9Bf6mRLrhvx57Q3qmsw=
 github.com/siyuan-note/httpclient v0.0.0-20220709030145-2bfb50f28e73 h1:NAw9IJtD0/NU2lhraQjELAcU9Bf6mRLrhvx57Q3qmsw=
 github.com/siyuan-note/httpclient v0.0.0-20220709030145-2bfb50f28e73/go.mod h1:sCMZurEZaMFiwGbdppizHT3NPO/HUdd+1FqtAyfdEsE=
 github.com/siyuan-note/httpclient v0.0.0-20220709030145-2bfb50f28e73/go.mod h1:sCMZurEZaMFiwGbdppizHT3NPO/HUdd+1FqtAyfdEsE=
+github.com/siyuan-note/logging v0.0.0-20220717040626-f796b05ee520 h1:kscYjMt7jXYdd7Qj2OSUoBnoHc5B0U/E6OSx86VRLr4=
+github.com/siyuan-note/logging v0.0.0-20220717040626-f796b05ee520/go.mod h1:t1zRGxK13L/9ZFoGyTD39IbFCbee3CsypDj4b5dt4qM=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=

+ 27 - 26
kernel/model/appearance.go

@@ -27,19 +27,20 @@ import (
 
 
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/fsnotify/fsnotify"
 	"github.com/fsnotify/fsnotify"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
 
 
 func InitAppearance() {
 func InitAppearance() {
 	util.SetBootDetails("Initializing appearance...")
 	util.SetBootDetails("Initializing appearance...")
 	if err := os.Mkdir(util.AppearancePath, 0755); nil != err && !os.IsExist(err) {
 	if err := os.Mkdir(util.AppearancePath, 0755); nil != err && !os.IsExist(err) {
-		util.LogFatalf("create appearance folder [%s] failed: %s", util.AppearancePath, err)
+		logging.LogFatalf("create appearance folder [%s] failed: %s", util.AppearancePath, err)
 	}
 	}
 
 
 	unloadThemes()
 	unloadThemes()
 	from := filepath.Join(util.WorkingDir, "appearance")
 	from := filepath.Join(util.WorkingDir, "appearance")
 	if err := gulu.File.Copy(from, util.AppearancePath); nil != err {
 	if err := gulu.File.Copy(from, util.AppearancePath); nil != err {
-		util.LogFatalf("copy appearance resources from [%s] to [%s] failed: %s", from, util.AppearancePath, err)
+		logging.LogFatalf("copy appearance resources from [%s] to [%s] failed: %s", from, util.AppearancePath, err)
 	}
 	}
 	loadThemes()
 	loadThemes()
 
 
@@ -65,7 +66,7 @@ var themeWatchers = sync.Map{} // [string]*fsnotify.Watcher{}
 func closeThemeWatchers() {
 func closeThemeWatchers() {
 	themeWatchers.Range(func(key, value interface{}) bool {
 	themeWatchers.Range(func(key, value interface{}) bool {
 		if err := value.(*fsnotify.Watcher).Close(); nil != err {
 		if err := value.(*fsnotify.Watcher).Close(); nil != err {
-			util.LogErrorf("close file watcher failed: %s", err)
+			logging.LogErrorf("close file watcher failed: %s", err)
 		}
 		}
 		return true
 		return true
 	})
 	})
@@ -78,12 +79,12 @@ func unloadThemes() {
 
 
 	dir, err := os.Open(util.ThemesPath)
 	dir, err := os.Open(util.ThemesPath)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("open appearance themes folder [%s] failed: %s", util.ThemesPath, err)
+		logging.LogErrorf("open appearance themes folder [%s] failed: %s", util.ThemesPath, err)
 		return
 		return
 	}
 	}
 	themeDirs, err := dir.Readdir(-1)
 	themeDirs, err := dir.Readdir(-1)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read appearance themes folder failed: %s", err)
+		logging.LogErrorf("read appearance themes folder failed: %s", err)
 		return
 		return
 	}
 	}
 	dir.Close()
 	dir.Close()
@@ -99,11 +100,11 @@ func unloadThemes() {
 func loadThemes() {
 func loadThemes() {
 	dir, err := os.Open(util.ThemesPath)
 	dir, err := os.Open(util.ThemesPath)
 	if nil != err {
 	if nil != err {
-		util.LogFatalf("open appearance themes folder [%s] failed: %s", util.ThemesPath, err)
+		logging.LogFatalf("open appearance themes folder [%s] failed: %s", util.ThemesPath, err)
 	}
 	}
 	themeDirs, err := dir.Readdir(-1)
 	themeDirs, err := dir.Readdir(-1)
 	if nil != err {
 	if nil != err {
-		util.LogFatalf("read appearance themes folder failed: %s", err)
+		logging.LogFatalf("read appearance themes folder failed: %s", err)
 	}
 	}
 	dir.Close()
 	dir.Close()
 
 
@@ -152,15 +153,15 @@ func themeJSON(themeName string) (ret map[string]interface{}, err error) {
 	}
 	}
 	data, err := os.ReadFile(p)
 	data, err := os.ReadFile(p)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read theme.json [%s] failed: %s", p, err)
+		logging.LogErrorf("read theme.json [%s] failed: %s", p, err)
 		return
 		return
 	}
 	}
 	if err = gulu.JSON.UnmarshalJSON(data, &ret); nil != err {
 	if err = gulu.JSON.UnmarshalJSON(data, &ret); nil != err {
-		util.LogErrorf("parse theme.json [%s] failed: %s", p, err)
+		logging.LogErrorf("parse theme.json [%s] failed: %s", p, err)
 		return
 		return
 	}
 	}
 	if 5 > len(ret) {
 	if 5 > len(ret) {
-		util.LogWarnf("invalid theme.json [%s]", p)
+		logging.LogWarnf("invalid theme.json [%s]", p)
 		return nil, errors.New("invalid theme.json")
 		return nil, errors.New("invalid theme.json")
 	}
 	}
 	return
 	return
@@ -174,15 +175,15 @@ func iconJSON(iconName string) (ret map[string]interface{}, err error) {
 	}
 	}
 	data, err := os.ReadFile(p)
 	data, err := os.ReadFile(p)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read icon.json [%s] failed: %s", p, err)
+		logging.LogErrorf("read icon.json [%s] failed: %s", p, err)
 		return
 		return
 	}
 	}
 	if err = gulu.JSON.UnmarshalJSON(data, &ret); nil != err {
 	if err = gulu.JSON.UnmarshalJSON(data, &ret); nil != err {
-		util.LogErrorf("parse icon.json [%s] failed: %s", p, err)
+		logging.LogErrorf("parse icon.json [%s] failed: %s", p, err)
 		return
 		return
 	}
 	}
 	if 4 > len(ret) {
 	if 4 > len(ret) {
-		util.LogWarnf("invalid icon.json [%s]", p)
+		logging.LogWarnf("invalid icon.json [%s]", p)
 		return nil, errors.New("invalid icon.json")
 		return nil, errors.New("invalid icon.json")
 	}
 	}
 	return
 	return
@@ -196,15 +197,15 @@ func templateJSON(templateName string) (ret map[string]interface{}, err error) {
 	}
 	}
 	data, err := os.ReadFile(p)
 	data, err := os.ReadFile(p)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read template.json [%s] failed: %s", p, err)
+		logging.LogErrorf("read template.json [%s] failed: %s", p, err)
 		return
 		return
 	}
 	}
 	if err = gulu.JSON.UnmarshalJSON(data, &ret); nil != err {
 	if err = gulu.JSON.UnmarshalJSON(data, &ret); nil != err {
-		util.LogErrorf("parse template.json [%s] failed: %s", p, err)
+		logging.LogErrorf("parse template.json [%s] failed: %s", p, err)
 		return
 		return
 	}
 	}
 	if 4 > len(ret) {
 	if 4 > len(ret) {
-		util.LogWarnf("invalid template.json [%s]", p)
+		logging.LogWarnf("invalid template.json [%s]", p)
 		return nil, errors.New("invalid template.json")
 		return nil, errors.New("invalid template.json")
 	}
 	}
 	return
 	return
@@ -218,15 +219,15 @@ func widgetJSON(widgetName string) (ret map[string]interface{}, err error) {
 	}
 	}
 	data, err := os.ReadFile(p)
 	data, err := os.ReadFile(p)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read widget.json [%s] failed: %s", p, err)
+		logging.LogErrorf("read widget.json [%s] failed: %s", p, err)
 		return
 		return
 	}
 	}
 	if err = gulu.JSON.UnmarshalJSON(data, &ret); nil != err {
 	if err = gulu.JSON.UnmarshalJSON(data, &ret); nil != err {
-		util.LogErrorf("parse widget.json [%s] failed: %s", p, err)
+		logging.LogErrorf("parse widget.json [%s] failed: %s", p, err)
 		return
 		return
 	}
 	}
 	if 4 > len(ret) {
 	if 4 > len(ret) {
-		util.LogWarnf("invalid widget.json [%s]", p)
+		logging.LogWarnf("invalid widget.json [%s]", p)
 		return nil, errors.New("invalid widget.json")
 		return nil, errors.New("invalid widget.json")
 	}
 	}
 	return
 	return
@@ -235,11 +236,11 @@ func widgetJSON(widgetName string) (ret map[string]interface{}, err error) {
 func loadIcons() {
 func loadIcons() {
 	dir, err := os.Open(util.IconsPath)
 	dir, err := os.Open(util.IconsPath)
 	if nil != err {
 	if nil != err {
-		util.LogFatalf("open appearance icons folder [%s] failed: %s", util.IconsPath, err)
+		logging.LogFatalf("open appearance icons folder [%s] failed: %s", util.IconsPath, err)
 	}
 	}
 	iconDirs, err := dir.Readdir(-1)
 	iconDirs, err := dir.Readdir(-1)
 	if nil != err {
 	if nil != err {
-		util.LogFatalf("read appearance icons folder failed: %s", err)
+		logging.LogFatalf("read appearance icons folder failed: %s", err)
 	}
 	}
 	dir.Close()
 	dir.Close()
 
 
@@ -278,7 +279,7 @@ func watchTheme(folder string) {
 
 
 	var err error
 	var err error
 	if themeWatcher, err = fsnotify.NewWatcher(); nil != err {
 	if themeWatcher, err = fsnotify.NewWatcher(); nil != err {
-		util.LogErrorf("add theme file watcher for folder [%s] failed: %s", folder, err)
+		logging.LogErrorf("add theme file watcher for folder [%s] failed: %s", folder, err)
 		return
 		return
 	}
 	}
 	themeWatchers.Store(folder, themeWatcher)
 	themeWatchers.Store(folder, themeWatcher)
@@ -292,7 +293,7 @@ func watchTheme(folder string) {
 					return
 					return
 				}
 				}
 
 
-				//util.LogInfof(event.String())
+				//logging.LogInfof(event.String())
 				if event.Op&fsnotify.Write == fsnotify.Write &&
 				if event.Op&fsnotify.Write == fsnotify.Write &&
 					(strings.HasSuffix(event.Name, "theme.css") || strings.HasSuffix(event.Name, "custom.css")) {
 					(strings.HasSuffix(event.Name, "theme.css") || strings.HasSuffix(event.Name, "custom.css")) {
 					var themeName string
 					var themeName string
@@ -318,14 +319,14 @@ func watchTheme(folder string) {
 				if !ok {
 				if !ok {
 					return
 					return
 				}
 				}
-				util.LogErrorf("watch theme file failed: %s", err)
+				logging.LogErrorf("watch theme file failed: %s", err)
 			}
 			}
 		}
 		}
 	}()
 	}()
 
 
-	//util.LogInfof("add file watcher [%s]", folder)
+	//logging.LogInfof("add file watcher [%s]", folder)
 	if err := themeWatcher.Add(folder); err != nil {
 	if err := themeWatcher.Add(folder); err != nil {
-		util.LogErrorf("add theme files watcher for folder [%s] failed: %s", folder, err)
+		logging.LogErrorf("add theme files watcher for folder [%s] failed: %s", folder, err)
 	}
 	}
 	<-done
 	<-done
 }
 }

+ 29 - 28
kernel/model/assets.go

@@ -37,6 +37,7 @@ import (
 	"github.com/gabriel-vasile/mimetype"
 	"github.com/gabriel-vasile/mimetype"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/httpclient"
 	"github.com/siyuan-note/httpclient"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/cache"
 	"github.com/siyuan-note/siyuan/kernel/cache"
 	"github.com/siyuan-note/siyuan/kernel/search"
 	"github.com/siyuan-note/siyuan/kernel/search"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
@@ -96,16 +97,16 @@ func NetImg2LocalAssets(rootID string) (err error) {
 				request := httpclient.NewBrowserRequest()
 				request := httpclient.NewBrowserRequest()
 				resp, reqErr := request.Get(u)
 				resp, reqErr := request.Get(u)
 				if nil != reqErr {
 				if nil != reqErr {
-					util.LogErrorf("download net img [%s] failed: %s", u, reqErr)
+					logging.LogErrorf("download net img [%s] failed: %s", u, reqErr)
 					return ast.WalkSkipChildren
 					return ast.WalkSkipChildren
 				}
 				}
 				if 200 != resp.StatusCode {
 				if 200 != resp.StatusCode {
-					util.LogErrorf("download net img [%s] failed: %d", u, resp.StatusCode)
+					logging.LogErrorf("download net img [%s] failed: %d", u, resp.StatusCode)
 					return ast.WalkSkipChildren
 					return ast.WalkSkipChildren
 				}
 				}
 				data, repErr := resp.ToBytes()
 				data, repErr := resp.ToBytes()
 				if nil != repErr {
 				if nil != repErr {
-					util.LogErrorf("download net img [%s] failed: %s", u, repErr)
+					logging.LogErrorf("download net img [%s] failed: %s", u, repErr)
 					return ast.WalkSkipChildren
 					return ast.WalkSkipChildren
 				}
 				}
 				var name string
 				var name string
@@ -138,7 +139,7 @@ func NetImg2LocalAssets(rootID string) (err error) {
 				name = "net-img-" + name + "-" + ast.NewNodeID() + ext
 				name = "net-img-" + name + "-" + ast.NewNodeID() + ext
 				writePath := filepath.Join(util.DataDir, "assets", name)
 				writePath := filepath.Join(util.DataDir, "assets", name)
 				if err = gulu.File.WriteFileSafer(writePath, data, 0644); nil != err {
 				if err = gulu.File.WriteFileSafer(writePath, data, 0644); nil != err {
-					util.LogErrorf("write downloaded net img [%s] to local assets [%s] failed: %s", u, writePath, err)
+					logging.LogErrorf("write downloaded net img [%s] to local assets [%s] failed: %s", u, writePath, err)
 					return ast.WalkSkipChildren
 					return ast.WalkSkipChildren
 				}
 				}
 
 
@@ -259,11 +260,11 @@ func uploadCloud(sqlAssets []*sql.Asset) (err error) {
 		var absPath string
 		var absPath string
 		absPath, err = GetAssetAbsPath(asset)
 		absPath, err = GetAssetAbsPath(asset)
 		if nil != err {
 		if nil != err {
-			util.LogWarnf("get asset [%s] abs path failed: %s", asset, err)
+			logging.LogWarnf("get asset [%s] abs path failed: %s", asset, err)
 			return
 			return
 		}
 		}
 		if "" == absPath {
 		if "" == absPath {
-			util.LogErrorf("not found asset [%s]", asset)
+			logging.LogErrorf("not found asset [%s]", asset)
 			err = errors.New(fmt.Sprintf(Conf.Language(12), asset))
 			err = errors.New(fmt.Sprintf(Conf.Language(12), asset))
 			return
 			return
 		}
 		}
@@ -277,7 +278,7 @@ func uploadCloud(sqlAssets []*sql.Asset) (err error) {
 
 
 	uploadAbsAssets = gulu.Str.RemoveDuplicatedElem(uploadAbsAssets)
 	uploadAbsAssets = gulu.Str.RemoveDuplicatedElem(uploadAbsAssets)
 
 
-	util.LogInfof("uploading [%d] assets", len(uploadAbsAssets))
+	logging.LogInfof("uploading [%d] assets", len(uploadAbsAssets))
 	if loadErr := LoadUploadToken(); nil != loadErr {
 	if loadErr := LoadUploadToken(); nil != loadErr {
 		util.PushMsg(loadErr.Error(), 5000)
 		util.PushMsg(loadErr.Error(), 5000)
 		return
 		return
@@ -286,10 +287,10 @@ func uploadCloud(sqlAssets []*sql.Asset) (err error) {
 	var completedUploadAssets []string
 	var completedUploadAssets []string
 	for _, absAsset := range uploadAbsAssets {
 	for _, absAsset := range uploadAbsAssets {
 		if fi, statErr := os.Stat(absAsset); nil != statErr {
 		if fi, statErr := os.Stat(absAsset); nil != statErr {
-			util.LogErrorf("stat file [%s] failed: %s", absAsset, statErr)
+			logging.LogErrorf("stat file [%s] failed: %s", absAsset, statErr)
 			return statErr
 			return statErr
 		} else if util.CloudSingleFileMaxSizeLimit/10 <= fi.Size() {
 		} else if util.CloudSingleFileMaxSizeLimit/10 <= fi.Size() {
-			util.LogWarnf("file [%s] larger than 10MB, ignore uploading it", absAsset)
+			logging.LogWarnf("file [%s] larger than 10MB, ignore uploading it", absAsset)
 			continue
 			continue
 		}
 		}
 
 
@@ -301,7 +302,7 @@ func uploadCloud(sqlAssets []*sql.Asset) (err error) {
 			SetCookies(&http.Cookie{Name: "symphony", Value: uploadToken}).
 			SetCookies(&http.Cookie{Name: "symphony", Value: uploadToken}).
 			Post(util.AliyunServer + "/apis/siyuan/upload?ver=" + util.Ver)
 			Post(util.AliyunServer + "/apis/siyuan/upload?ver=" + util.Ver)
 		if nil != reqErr {
 		if nil != reqErr {
-			util.LogErrorf("upload assets failed: %s", reqErr)
+			logging.LogErrorf("upload assets failed: %s", reqErr)
 			return ErrFailedToConnectCloudServer
 			return ErrFailedToConnectCloudServer
 		}
 		}
 
 
@@ -311,7 +312,7 @@ func uploadCloud(sqlAssets []*sql.Asset) (err error) {
 		}
 		}
 
 
 		if 0 != requestResult.Code {
 		if 0 != requestResult.Code {
-			util.LogErrorf("upload assets failed: %s", requestResult.Msg)
+			logging.LogErrorf("upload assets failed: %s", requestResult.Msg)
 			err = errors.New(fmt.Sprintf(Conf.Language(94), requestResult.Msg))
 			err = errors.New(fmt.Sprintf(Conf.Language(94), requestResult.Msg))
 			return
 			return
 		}
 		}
@@ -319,12 +320,12 @@ func uploadCloud(sqlAssets []*sql.Asset) (err error) {
 		absAsset = filepath.ToSlash(absAsset)
 		absAsset = filepath.ToSlash(absAsset)
 		relAsset := absAsset[strings.Index(absAsset, "assets/"):]
 		relAsset := absAsset[strings.Index(absAsset, "assets/"):]
 		completedUploadAssets = append(completedUploadAssets, relAsset)
 		completedUploadAssets = append(completedUploadAssets, relAsset)
-		util.LogInfof("uploaded asset [%s]", relAsset)
+		logging.LogInfof("uploaded asset [%s]", relAsset)
 	}
 	}
 
 
 	if 0 < len(completedUploadAssets) {
 	if 0 < len(completedUploadAssets) {
 		syncedAssets = readWorkspaceAssets()
 		syncedAssets = readWorkspaceAssets()
-		util.LogInfof("uploaded [%d] assets", len(completedUploadAssets))
+		logging.LogInfof("uploaded [%d] assets", len(completedUploadAssets))
 		for _, completedSyncAsset := range completedUploadAssets {
 		for _, completedSyncAsset := range completedUploadAssets {
 			syncedAssets = append(syncedAssets, completedSyncAsset)
 			syncedAssets = append(syncedAssets, completedSyncAsset)
 		}
 		}
@@ -337,7 +338,7 @@ func readWorkspaceAssets() (ret []string) {
 	ret = []string{}
 	ret = []string{}
 	confDir := filepath.Join(util.DataDir, "assets", ".siyuan")
 	confDir := filepath.Join(util.DataDir, "assets", ".siyuan")
 	if err := os.MkdirAll(confDir, 0755); nil != err {
 	if err := os.MkdirAll(confDir, 0755); nil != err {
-		util.LogErrorf("create assets conf dir [%s] failed: %s", confDir, err)
+		logging.LogErrorf("create assets conf dir [%s] failed: %s", confDir, err)
 		return
 		return
 	}
 	}
 	confPath := filepath.Join(confDir, "assets.json")
 	confPath := filepath.Join(confDir, "assets.json")
@@ -347,11 +348,11 @@ func readWorkspaceAssets() (ret []string) {
 
 
 	data, err := os.ReadFile(confPath)
 	data, err := os.ReadFile(confPath)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read assets conf failed: %s", err)
+		logging.LogErrorf("read assets conf failed: %s", err)
 		return
 		return
 	}
 	}
 	if err = gulu.JSON.UnmarshalJSON(data, &ret); nil != err {
 	if err = gulu.JSON.UnmarshalJSON(data, &ret); nil != err {
-		util.LogErrorf("parse assets conf failed: %s, re-init it", err)
+		logging.LogErrorf("parse assets conf failed: %s, re-init it", err)
 		return
 		return
 	}
 	}
 	return
 	return
@@ -360,7 +361,7 @@ func readWorkspaceAssets() (ret []string) {
 func saveWorkspaceAssets(assets []string) {
 func saveWorkspaceAssets(assets []string) {
 	confDir := filepath.Join(util.DataDir, "assets", ".siyuan")
 	confDir := filepath.Join(util.DataDir, "assets", ".siyuan")
 	if err := os.MkdirAll(confDir, 0755); nil != err {
 	if err := os.MkdirAll(confDir, 0755); nil != err {
-		util.LogErrorf("create assets conf dir [%s] failed: %s", confDir, err)
+		logging.LogErrorf("create assets conf dir [%s] failed: %s", confDir, err)
 		return
 		return
 	}
 	}
 	confPath := filepath.Join(confDir, "assets.json")
 	confPath := filepath.Join(confDir, "assets.json")
@@ -369,11 +370,11 @@ func saveWorkspaceAssets(assets []string) {
 	sort.Strings(assets)
 	sort.Strings(assets)
 	data, err := gulu.JSON.MarshalIndentJSON(assets, "", "  ")
 	data, err := gulu.JSON.MarshalIndentJSON(assets, "", "  ")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("create assets conf failed: %s", err)
+		logging.LogErrorf("create assets conf failed: %s", err)
 		return
 		return
 	}
 	}
 	if err = gulu.File.WriteFileSafer(confPath, data, 0644); nil != err {
 	if err = gulu.File.WriteFileSafer(confPath, data, 0644); nil != err {
-		util.LogErrorf("write assets conf failed: %s", err)
+		logging.LogErrorf("write assets conf failed: %s", err)
 		return
 		return
 	}
 	}
 }
 }
@@ -390,7 +391,7 @@ func RemoveUnusedAssets() (ret []string) {
 
 
 	historyDir, err := util.GetHistoryDir("delete")
 	historyDir, err := util.GetHistoryDir("delete")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("get history dir failed: %s", err)
+		logging.LogErrorf("get history dir failed: %s", err)
 		return
 		return
 	}
 	}
 
 
@@ -406,7 +407,7 @@ func RemoveUnusedAssets() (ret []string) {
 	for _, unusedAsset := range unusedAssets {
 	for _, unusedAsset := range unusedAssets {
 		if unusedAsset = filepath.Join(util.DataDir, unusedAsset); gulu.File.IsExist(unusedAsset) {
 		if unusedAsset = filepath.Join(util.DataDir, unusedAsset); gulu.File.IsExist(unusedAsset) {
 			if err := os.RemoveAll(unusedAsset); nil != err {
 			if err := os.RemoveAll(unusedAsset); nil != err {
-				util.LogErrorf("remove unused asset [%s] failed: %s", unusedAsset, err)
+				logging.LogErrorf("remove unused asset [%s] failed: %s", unusedAsset, err)
 			}
 			}
 		}
 		}
 		ret = append(ret, unusedAsset)
 		ret = append(ret, unusedAsset)
@@ -425,7 +426,7 @@ func RemoveUnusedAsset(p string) (ret string) {
 
 
 	historyDir, err := util.GetHistoryDir("delete")
 	historyDir, err := util.GetHistoryDir("delete")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("get history dir failed: %s", err)
+		logging.LogErrorf("get history dir failed: %s", err)
 		return
 		return
 	}
 	}
 
 
@@ -436,7 +437,7 @@ func RemoveUnusedAsset(p string) (ret string) {
 	}
 	}
 
 
 	if err = os.RemoveAll(p); nil != err {
 	if err = os.RemoveAll(p); nil != err {
-		util.LogErrorf("remove unused asset [%s] failed: %s", p, err)
+		logging.LogErrorf("remove unused asset [%s] failed: %s", p, err)
 	}
 	}
 	ret = p
 	ret = p
 	IncSync()
 	IncSync()
@@ -464,7 +465,7 @@ func RenameAsset(oldPath, newName string) (err error) {
 	newName = util.AssetName(newName) + filepath.Ext(oldPath)
 	newName = util.AssetName(newName) + filepath.Ext(oldPath)
 	newPath := "assets/" + newName
 	newPath := "assets/" + newName
 	if err = gulu.File.Copy(filepath.Join(util.DataDir, oldPath), filepath.Join(util.DataDir, newPath)); nil != err {
 	if err = gulu.File.Copy(filepath.Join(util.DataDir, oldPath), filepath.Join(util.DataDir, newPath)); nil != err {
-		util.LogErrorf("copy asset [%s] failed: %s", oldPath, err)
+		logging.LogErrorf("copy asset [%s] failed: %s", oldPath, err)
 		return
 		return
 	}
 	}
 	oldName := path.Base(oldPath)
 	oldName := path.Base(oldPath)
@@ -479,7 +480,7 @@ func RenameAsset(oldPath, newName string) (err error) {
 			for _, treeAbsPath := range paths {
 			for _, treeAbsPath := range paths {
 				data, readErr := filelock.NoLockFileRead(treeAbsPath)
 				data, readErr := filelock.NoLockFileRead(treeAbsPath)
 				if nil != readErr {
 				if nil != readErr {
-					util.LogErrorf("get data [path=%s] failed: %s", treeAbsPath, readErr)
+					logging.LogErrorf("get data [path=%s] failed: %s", treeAbsPath, readErr)
 					err = readErr
 					err = readErr
 					return
 					return
 				}
 				}
@@ -490,7 +491,7 @@ func RenameAsset(oldPath, newName string) (err error) {
 
 
 				data = bytes.Replace(data, []byte(oldName), []byte(newName), -1)
 				data = bytes.Replace(data, []byte(oldName), []byte(newName), -1)
 				if writeErr := filelock.NoLockFileWrite(treeAbsPath, data); nil != writeErr {
 				if writeErr := filelock.NoLockFileWrite(treeAbsPath, data); nil != writeErr {
-					util.LogErrorf("write data [path=%s] failed: %s", treeAbsPath, writeErr)
+					logging.LogErrorf("write data [path=%s] failed: %s", treeAbsPath, writeErr)
 					err = writeErr
 					err = writeErr
 					return
 					return
 				}
 				}
@@ -498,7 +499,7 @@ func RenameAsset(oldPath, newName string) (err error) {
 				p := filepath.ToSlash(strings.TrimPrefix(treeAbsPath, filepath.Join(util.DataDir, notebook.ID)))
 				p := filepath.ToSlash(strings.TrimPrefix(treeAbsPath, filepath.Join(util.DataDir, notebook.ID)))
 				tree, parseErr := LoadTree(notebook.ID, p)
 				tree, parseErr := LoadTree(notebook.ID, p)
 				if nil != parseErr {
 				if nil != parseErr {
-					util.LogErrorf("parse json to tree [%s] failed: %s", treeAbsPath, parseErr)
+					logging.LogErrorf("parse json to tree [%s] failed: %s", treeAbsPath, parseErr)
 					err = parseErr
 					err = parseErr
 					return
 					return
 				}
 				}
@@ -795,7 +796,7 @@ func copyAssetsToDataAssets(rootPath string) {
 	dataAssetsPath := filepath.Join(util.DataDir, "assets")
 	dataAssetsPath := filepath.Join(util.DataDir, "assets")
 	for _, assetsDirPath := range assetsDirPaths {
 	for _, assetsDirPath := range assetsDirPaths {
 		if err := gulu.File.Copy(assetsDirPath, dataAssetsPath); nil != err {
 		if err := gulu.File.Copy(assetsDirPath, dataAssetsPath); nil != err {
-			util.LogErrorf("copy tree assets from [%s] to [%s] failed: %s", assetsDirPaths, dataAssetsPath, err)
+			logging.LogErrorf("copy tree assets from [%s] to [%s] failed: %s", assetsDirPaths, dataAssetsPath, err)
 		}
 		}
 	}
 	}
 }
 }

+ 6 - 5
kernel/model/assets_watcher.go

@@ -23,6 +23,7 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/fsnotify/fsnotify"
 	"github.com/fsnotify/fsnotify"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/cache"
 	"github.com/siyuan-note/siyuan/kernel/cache"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
@@ -47,7 +48,7 @@ func watchAssets() {
 
 
 	var err error
 	var err error
 	if assetsWatcher, err = fsnotify.NewWatcher(); nil != err {
 	if assetsWatcher, err = fsnotify.NewWatcher(); nil != err {
-		util.LogErrorf("add assets watcher for folder [%s] failed: %s", assetsDir, err)
+		logging.LogErrorf("add assets watcher for folder [%s] failed: %s", assetsDir, err)
 		return
 		return
 	}
 	}
 
 
@@ -72,9 +73,9 @@ func watchAssets() {
 				if !ok {
 				if !ok {
 					return
 					return
 				}
 				}
-				util.LogErrorf("watch assets failed: %s", err)
+				logging.LogErrorf("watch assets failed: %s", err)
 			case <-timer.C:
 			case <-timer.C:
-				//util.LogInfof("assets changed: %s", lastEvent)
+				//logging.LogInfof("assets changed: %s", lastEvent)
 				if lastEvent.Op&fsnotify.Write == fsnotify.Write {
 				if lastEvent.Op&fsnotify.Write == fsnotify.Write {
 					// 外部修改已有资源文件后纳入云端同步 https://github.com/siyuan-note/siyuan/issues/4694
 					// 外部修改已有资源文件后纳入云端同步 https://github.com/siyuan-note/siyuan/issues/4694
 					IncSync()
 					IncSync()
@@ -87,9 +88,9 @@ func watchAssets() {
 	}()
 	}()
 
 
 	if err = assetsWatcher.Add(assetsDir); err != nil {
 	if err = assetsWatcher.Add(assetsDir); err != nil {
-		util.LogErrorf("add assets watcher for folder [%s] failed: %s", assetsDir, err)
+		logging.LogErrorf("add assets watcher for folder [%s] failed: %s", assetsDir, err)
 	}
 	}
-	//util.LogInfof("added file watcher [%s]", assetsDir)
+	//logging.LogInfof("added file watcher [%s]", assetsDir)
 }
 }
 
 
 func CloseWatchAssets() {
 func CloseWatchAssets() {

+ 2 - 1
kernel/model/backlink.go

@@ -29,6 +29,7 @@ import (
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/parse"
 	"github.com/emirpasic/gods/sets/hashset"
 	"github.com/emirpasic/gods/sets/hashset"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/search"
 	"github.com/siyuan-note/siyuan/kernel/search"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
@@ -51,7 +52,7 @@ func RefreshBacklink(id string) {
 		if nil == tree {
 		if nil == tree {
 			tree, err = loadTreeByBlockID(ref.RootID)
 			tree, err = loadTreeByBlockID(ref.RootID)
 			if nil != err {
 			if nil != err {
-				util.LogErrorf("refresh tree refs failed: %s", err)
+				logging.LogErrorf("refresh tree refs failed: %s", err)
 				continue
 				continue
 			}
 			}
 			trees[ref.RootID] = tree
 			trees[ref.RootID] = tree

+ 2 - 1
kernel/model/blockinfo.go

@@ -28,6 +28,7 @@ import (
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/html"
 	"github.com/88250/lute/html"
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/parse"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
@@ -48,7 +49,7 @@ func GetDocInfo(rootID string) (ret *BlockInfo) {
 
 
 	tree, err := loadTreeByBlockID(rootID)
 	tree, err := loadTreeByBlockID(rootID)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("load tree by root id [%s] failed: %s", rootID, err)
+		logging.LogErrorf("load tree by root id [%s] failed: %s", rootID, err)
 		return
 		return
 	}
 	}
 
 

+ 16 - 15
kernel/model/box.go

@@ -33,6 +33,7 @@ import (
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/parse"
 	"github.com/facette/natsort"
 	"github.com/facette/natsort"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/conf"
 	"github.com/siyuan-note/siyuan/kernel/conf"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
@@ -65,7 +66,7 @@ func ListNotebooks() (ret []*Box, err error) {
 	ret = []*Box{}
 	ret = []*Box{}
 	dirs, err := os.ReadDir(util.DataDir)
 	dirs, err := os.ReadDir(util.DataDir)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read dir [%s] failed: %s", util.DataDir, err)
+		logging.LogErrorf("read dir [%s] failed: %s", util.DataDir, err)
 		return ret, err
 		return ret, err
 	}
 	}
 	for _, dir := range dirs {
 	for _, dir := range dirs {
@@ -87,18 +88,18 @@ func ListNotebooks() (ret []*Box, err error) {
 			if isUserGuide(dir.Name()) {
 			if isUserGuide(dir.Name()) {
 				filelock.ReleaseAllFileLocks()
 				filelock.ReleaseAllFileLocks()
 				os.RemoveAll(filepath.Join(util.DataDir, dir.Name()))
 				os.RemoveAll(filepath.Join(util.DataDir, dir.Name()))
-				util.LogWarnf("not found user guid box conf [%s], removed it", boxConfPath)
+				logging.LogWarnf("not found user guid box conf [%s], removed it", boxConfPath)
 				continue
 				continue
 			}
 			}
-			util.LogWarnf("not found box conf [%s], recreate it", boxConfPath)
+			logging.LogWarnf("not found box conf [%s], recreate it", boxConfPath)
 		} else {
 		} else {
 			data, readErr := filelock.NoLockFileRead(boxConfPath)
 			data, readErr := filelock.NoLockFileRead(boxConfPath)
 			if nil != readErr {
 			if nil != readErr {
-				util.LogErrorf("read box conf [%s] failed: %s", boxConfPath, readErr)
+				logging.LogErrorf("read box conf [%s] failed: %s", boxConfPath, readErr)
 				continue
 				continue
 			}
 			}
 			if readErr = gulu.JSON.UnmarshalJSON(data, boxConf); nil != readErr {
 			if readErr = gulu.JSON.UnmarshalJSON(data, boxConf); nil != readErr {
-				util.LogErrorf("parse box conf [%s] failed: %s", boxConfPath, readErr)
+				logging.LogErrorf("parse box conf [%s] failed: %s", boxConfPath, readErr)
 				continue
 				continue
 			}
 			}
 		}
 		}
@@ -154,12 +155,12 @@ func (box *Box) GetConf() (ret *conf.BoxConf) {
 
 
 	data, err := filelock.LockFileRead(confPath)
 	data, err := filelock.LockFileRead(confPath)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read box conf [%s] failed: %s", confPath, err)
+		logging.LogErrorf("read box conf [%s] failed: %s", confPath, err)
 		return
 		return
 	}
 	}
 
 
 	if err = gulu.JSON.UnmarshalJSON(data, ret); nil != err {
 	if err = gulu.JSON.UnmarshalJSON(data, ret); nil != err {
-		util.LogErrorf("parse box conf [%s] failed: %s", confPath, err)
+		logging.LogErrorf("parse box conf [%s] failed: %s", confPath, err)
 		return
 		return
 	}
 	}
 	return
 	return
@@ -169,7 +170,7 @@ func (box *Box) SaveConf(conf *conf.BoxConf) {
 	confPath := filepath.Join(util.DataDir, box.ID, ".siyuan/conf.json")
 	confPath := filepath.Join(util.DataDir, box.ID, ".siyuan/conf.json")
 	newData, err := gulu.JSON.MarshalIndentJSON(conf, "", "  ")
 	newData, err := gulu.JSON.MarshalIndentJSON(conf, "", "  ")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("marshal box conf [%s] failed: %s", confPath, err)
+		logging.LogErrorf("marshal box conf [%s] failed: %s", confPath, err)
 		return
 		return
 	}
 	}
 
 
@@ -189,10 +190,10 @@ func (box *Box) SaveConf(conf *conf.BoxConf) {
 func (box *Box) saveConf0(data []byte) {
 func (box *Box) saveConf0(data []byte) {
 	confPath := filepath.Join(util.DataDir, box.ID, ".siyuan/conf.json")
 	confPath := filepath.Join(util.DataDir, box.ID, ".siyuan/conf.json")
 	if err := os.MkdirAll(filepath.Join(util.DataDir, box.ID, ".siyuan"), 0755); nil != err {
 	if err := os.MkdirAll(filepath.Join(util.DataDir, box.ID, ".siyuan"), 0755); nil != err {
-		util.LogErrorf("save box conf [%s] failed: %s", confPath, err)
+		logging.LogErrorf("save box conf [%s] failed: %s", confPath, err)
 	}
 	}
 	if err := filelock.LockFileWrite(confPath, data); nil != err {
 	if err := filelock.LockFileWrite(confPath, data); nil != err {
-		util.LogErrorf("save box conf [%s] failed: %s", confPath, err)
+		logging.LogErrorf("save box conf [%s] failed: %s", confPath, err)
 	}
 	}
 }
 }
 
 
@@ -238,7 +239,7 @@ func (box *Box) Stat(p string) (ret *FileInfo) {
 	info, err := os.Stat(absPath)
 	info, err := os.Stat(absPath)
 	if nil != err {
 	if nil != err {
 		if !os.IsNotExist(err) {
 		if !os.IsNotExist(err) {
-			util.LogErrorf("stat [%s] failed: %s", absPath, err)
+			logging.LogErrorf("stat [%s] failed: %s", absPath, err)
 		}
 		}
 		return
 		return
 	}
 	}
@@ -258,7 +259,7 @@ func (box *Box) Exist(p string) bool {
 func (box *Box) Mkdir(path string) error {
 func (box *Box) Mkdir(path string) error {
 	if err := os.Mkdir(filepath.Join(util.DataDir, box.ID, path), 0755); nil != err {
 	if err := os.Mkdir(filepath.Join(util.DataDir, box.ID, path), 0755); nil != err {
 		msg := fmt.Sprintf(Conf.Language(6), box.Name, path, err)
 		msg := fmt.Sprintf(Conf.Language(6), box.Name, path, err)
-		util.LogErrorf("mkdir [path=%s] in box [%s] failed: %s", path, box.ID, err)
+		logging.LogErrorf("mkdir [path=%s] in box [%s] failed: %s", path, box.ID, err)
 		return errors.New(msg)
 		return errors.New(msg)
 	}
 	}
 	IncSync()
 	IncSync()
@@ -268,7 +269,7 @@ func (box *Box) Mkdir(path string) error {
 func (box *Box) MkdirAll(path string) error {
 func (box *Box) MkdirAll(path string) error {
 	if err := os.MkdirAll(filepath.Join(util.DataDir, box.ID, path), 0755); nil != err {
 	if err := os.MkdirAll(filepath.Join(util.DataDir, box.ID, path), 0755); nil != err {
 		msg := fmt.Sprintf(Conf.Language(6), box.Name, path, err)
 		msg := fmt.Sprintf(Conf.Language(6), box.Name, path, err)
-		util.LogErrorf("mkdir all [path=%s] in box [%s] failed: %s", path, box.ID, err)
+		logging.LogErrorf("mkdir all [path=%s] in box [%s] failed: %s", path, box.ID, err)
 		return errors.New(msg)
 		return errors.New(msg)
 	}
 	}
 	IncSync()
 	IncSync()
@@ -282,7 +283,7 @@ func (box *Box) Move(oldPath, newPath string) error {
 	filelock.ReleaseFileLocks(fromPath)
 	filelock.ReleaseFileLocks(fromPath)
 	if err := os.Rename(fromPath, toPath); nil != err {
 	if err := os.Rename(fromPath, toPath); nil != err {
 		msg := fmt.Sprintf(Conf.Language(5), box.Name, fromPath, err)
 		msg := fmt.Sprintf(Conf.Language(5), box.Name, fromPath, err)
-		util.LogErrorf("move [path=%s] in box [%s] failed: %s", fromPath, box.Name, err)
+		logging.LogErrorf("move [path=%s] in box [%s] failed: %s", fromPath, box.Name, err)
 		return errors.New(msg)
 		return errors.New(msg)
 	}
 	}
 
 
@@ -302,7 +303,7 @@ func (box *Box) Remove(path string) error {
 	filelock.ReleaseFileLocks(filePath)
 	filelock.ReleaseFileLocks(filePath)
 	if err := os.RemoveAll(filePath); nil != err {
 	if err := os.RemoveAll(filePath); nil != err {
 		msg := fmt.Sprintf(Conf.Language(7), box.Name, path, err)
 		msg := fmt.Sprintf(Conf.Language(7), box.Name, path, err)
-		util.LogErrorf("remove [path=%s] in box [%s] failed: %s", path, box.ID, err)
+		logging.LogErrorf("remove [path=%s] in box [%s] failed: %s", path, box.ID, err)
 		return errors.New(msg)
 		return errors.New(msg)
 	}
 	}
 	IncSync()
 	IncSync()

+ 26 - 25
kernel/model/conf.go

@@ -34,6 +34,7 @@ import (
 	humanize "github.com/dustin/go-humanize"
 	humanize "github.com/dustin/go-humanize"
 	"github.com/getsentry/sentry-go"
 	"github.com/getsentry/sentry-go"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/conf"
 	"github.com/siyuan-note/siyuan/kernel/conf"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
@@ -78,7 +79,7 @@ func InitConf() {
 	windowStateConf := filepath.Join(util.ConfDir, "windowState.json")
 	windowStateConf := filepath.Join(util.ConfDir, "windowState.json")
 	if !gulu.File.IsExist(windowStateConf) {
 	if !gulu.File.IsExist(windowStateConf) {
 		if err := gulu.File.WriteFileSafer(windowStateConf, []byte("{}"), 0644); nil != err {
 		if err := gulu.File.WriteFileSafer(windowStateConf, []byte("{}"), 0644); nil != err {
-			util.LogErrorf("create [windowState.json] failed: %s", err)
+			logging.LogErrorf("create [windowState.json] failed: %s", err)
 		}
 		}
 	}
 	}
 
 
@@ -87,17 +88,17 @@ func InitConf() {
 	if gulu.File.IsExist(confPath) {
 	if gulu.File.IsExist(confPath) {
 		data, err := os.ReadFile(confPath)
 		data, err := os.ReadFile(confPath)
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("load conf [%s] failed: %s", confPath, err)
+			logging.LogErrorf("load conf [%s] failed: %s", confPath, err)
 		}
 		}
 		err = gulu.JSON.UnmarshalJSON(data, Conf)
 		err = gulu.JSON.UnmarshalJSON(data, Conf)
 		if err != nil {
 		if err != nil {
-			util.LogErrorf("parse conf [%s] failed: %s", confPath, err)
+			logging.LogErrorf("parse conf [%s] failed: %s", confPath, err)
 		}
 		}
 	}
 	}
 
 
 	if "" != util.Lang {
 	if "" != util.Lang {
 		Conf.Lang = util.Lang
 		Conf.Lang = util.Lang
-		util.LogInfof("initialized the specified language [%s]", util.Lang)
+		logging.LogInfof("initialized the specified language [%s]", util.Lang)
 	} else {
 	} else {
 		if "" == Conf.Lang {
 		if "" == Conf.Lang {
 			// 未指定外观语言时使用系统语言
 			// 未指定外观语言时使用系统语言
@@ -108,7 +109,7 @@ func InitConf() {
 					if tag, err := language.Parse(lang); nil == err {
 					if tag, err := language.Parse(lang); nil == err {
 						supportLangs = append(supportLangs, tag)
 						supportLangs = append(supportLangs, tag)
 					} else {
 					} else {
-						util.LogErrorf("load language [%s] failed: %s", lang, err)
+						logging.LogErrorf("load language [%s] failed: %s", lang, err)
 					}
 					}
 				}
 				}
 				matcher := language.NewMatcher(supportLangs)
 				matcher := language.NewMatcher(supportLangs)
@@ -117,9 +118,9 @@ func InitConf() {
 				region, _ := lang.Region()
 				region, _ := lang.Region()
 				util.Lang = base.String() + "_" + region.String()
 				util.Lang = base.String() + "_" + region.String()
 				Conf.Lang = util.Lang
 				Conf.Lang = util.Lang
-				util.LogInfof("initialized language [%s] based on device locale", Conf.Lang)
+				logging.LogInfof("initialized language [%s] based on device locale", Conf.Lang)
 			} else {
 			} else {
-				util.LogDebugf("check device locale failed [%s], using default language [en_US]", err)
+				logging.LogDebugf("check device locale failed [%s], using default language [en_US]", err)
 				util.Lang = "en_US"
 				util.Lang = "en_US"
 				Conf.Lang = util.Lang
 				Conf.Lang = util.Lang
 			}
 			}
@@ -235,7 +236,7 @@ func InitConf() {
 	}
 	}
 	if !gulu.File.IsExist(Conf.Backup.GetSaveDir()) {
 	if !gulu.File.IsExist(Conf.Backup.GetSaveDir()) {
 		if err := os.MkdirAll(Conf.Backup.GetSaveDir(), 0755); nil != err {
 		if err := os.MkdirAll(Conf.Backup.GetSaveDir(), 0755); nil != err {
-			util.LogErrorf("create backup dir [%s] failed: %s", Conf.Backup.GetSaveDir(), err)
+			logging.LogErrorf("create backup dir [%s] failed: %s", Conf.Backup.GetSaveDir(), err)
 		}
 		}
 	}
 	}
 
 
@@ -244,7 +245,7 @@ func InitConf() {
 	}
 	}
 	if !gulu.File.IsExist(Conf.Sync.GetSaveDir()) {
 	if !gulu.File.IsExist(Conf.Sync.GetSaveDir()) {
 		if err := os.MkdirAll(Conf.Sync.GetSaveDir(), 0755); nil != err {
 		if err := os.MkdirAll(Conf.Sync.GetSaveDir(), 0755); nil != err {
-			util.LogErrorf("create sync dir [%s] failed: %s", Conf.Sync.GetSaveDir(), err)
+			logging.LogErrorf("create sync dir [%s] failed: %s", Conf.Sync.GetSaveDir(), err)
 		}
 		}
 	}
 	}
 	if 0 == Conf.Sync.Mode {
 	if 0 == Conf.Sync.Mode {
@@ -282,10 +283,10 @@ func InitConf() {
 	Conf.LocalIPs = util.GetLocalIPs()
 	Conf.LocalIPs = util.GetLocalIPs()
 
 
 	Conf.Save()
 	Conf.Save()
-	util.SetLogLevel(Conf.LogLevel)
+	logging.SetLogLevel(Conf.LogLevel)
 
 
 	if Conf.System.UploadErrLog {
 	if Conf.System.UploadErrLog {
-		util.LogInfof("user has enabled [Automatically upload error messages and diagnostic data]")
+		logging.LogInfof("user has enabled [Automatically upload error messages and diagnostic data]")
 		sentry.Init(sentry.ClientOptions{
 		sentry.Init(sentry.ClientOptions{
 			Dsn:         "https://bdff135f14654ae58a054adeceb2c308@o1173696.ingest.sentry.io/6269178",
 			Dsn:         "https://bdff135f14654ae58a054adeceb2c308@o1173696.ingest.sentry.io/6269178",
 			Release:     util.Ver,
 			Release:     util.Ver,
@@ -303,25 +304,25 @@ func initLang() {
 	p := filepath.Join(util.WorkingDir, "appearance", "langs")
 	p := filepath.Join(util.WorkingDir, "appearance", "langs")
 	dir, err := os.Open(p)
 	dir, err := os.Open(p)
 	if nil != err {
 	if nil != err {
-		util.LogFatalf("open language configuration folder [%s] failed: %s", p, err)
+		logging.LogFatalf("open language configuration folder [%s] failed: %s", p, err)
 	}
 	}
 	defer dir.Close()
 	defer dir.Close()
 
 
 	langNames, err := dir.Readdirnames(-1)
 	langNames, err := dir.Readdirnames(-1)
 	if nil != err {
 	if nil != err {
-		util.LogFatalf("list language configuration folder [%s] failed: %s", p, err)
+		logging.LogFatalf("list language configuration folder [%s] failed: %s", p, err)
 	}
 	}
 
 
 	for _, langName := range langNames {
 	for _, langName := range langNames {
 		jsonPath := filepath.Join(p, langName)
 		jsonPath := filepath.Join(p, langName)
 		data, err := os.ReadFile(jsonPath)
 		data, err := os.ReadFile(jsonPath)
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("read language configuration [%s] failed: %s", jsonPath, err)
+			logging.LogErrorf("read language configuration [%s] failed: %s", jsonPath, err)
 			continue
 			continue
 		}
 		}
 		langMap := map[string]interface{}{}
 		langMap := map[string]interface{}{}
 		if err := gulu.JSON.UnmarshalJSON(data, &langMap); nil != err {
 		if err := gulu.JSON.UnmarshalJSON(data, &langMap); nil != err {
-			util.LogErrorf("parse language configuration failed [%s] failed: %s", jsonPath, err)
+			logging.LogErrorf("parse language configuration failed [%s] failed: %s", jsonPath, err)
 			continue
 			continue
 		}
 		}
 
 
@@ -331,7 +332,7 @@ func initLang() {
 		for k, v := range kernelLangs {
 		for k, v := range kernelLangs {
 			num, err := strconv.Atoi(k)
 			num, err := strconv.Atoi(k)
 			if nil != err {
 			if nil != err {
-				util.LogErrorf("parse language configuration [%s] item [%d] failed [%s] failed: %s", p, num, err)
+				logging.LogErrorf("parse language configuration [%s] item [%d] failed [%s] failed: %s", p, num, err)
 				continue
 				continue
 			}
 			}
 			kernelMap[num] = v.(string)
 			kernelMap[num] = v.(string)
@@ -382,7 +383,7 @@ func Close(force bool) (err error) {
 	sql.CloseDatabase()
 	sql.CloseDatabase()
 	util.WebSocketServer.Close()
 	util.WebSocketServer.Close()
 	clearWorkspaceTemp()
 	clearWorkspaceTemp()
-	util.LogInfof("exited kernel")
+	logging.LogInfof("exited kernel")
 	go func() {
 	go func() {
 		time.Sleep(500 * time.Millisecond)
 		time.Sleep(500 * time.Millisecond)
 		os.Exit(util.ExitCodeOk)
 		os.Exit(util.ExitCodeOk)
@@ -431,7 +432,7 @@ func (conf *AppConf) Save() {
 func (conf *AppConf) save0(data []byte) {
 func (conf *AppConf) save0(data []byte) {
 	confPath := filepath.Join(util.ConfDir, "conf.json")
 	confPath := filepath.Join(util.ConfDir, "conf.json")
 	if err := filelock.LockFileWrite(confPath, data); nil != err {
 	if err := filelock.LockFileWrite(confPath, data); nil != err {
-		util.LogFatalf("write conf [%s] failed: %s", confPath, err)
+		logging.LogFatalf("write conf [%s] failed: %s", confPath, err)
 	}
 	}
 }
 }
 
 
@@ -539,7 +540,7 @@ func InitBoxes() {
 	if dbFile, err := os.Stat(util.DBPath); nil == err {
 	if dbFile, err := os.Stat(util.DBPath); nil == err {
 		dbSize = humanize.Bytes(uint64(dbFile.Size()))
 		dbSize = humanize.Bytes(uint64(dbFile.Size()))
 	}
 	}
-	util.LogInfof("database size [%s], block count [%d]", dbSize, blockCount)
+	logging.LogInfof("database size [%s], block count [%d]", dbSize, blockCount)
 }
 }
 
 
 func IsSubscriber() bool {
 func IsSubscriber() bool {
@@ -554,25 +555,25 @@ func clearWorkspaceTemp() {
 
 
 	tmps, err := filepath.Glob(filepath.Join(util.TempDir, "*.tmp"))
 	tmps, err := filepath.Glob(filepath.Join(util.TempDir, "*.tmp"))
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("glob temp files failed: %s", err)
+		logging.LogErrorf("glob temp files failed: %s", err)
 	}
 	}
 	for _, tmp := range tmps {
 	for _, tmp := range tmps {
 		if err = os.RemoveAll(tmp); nil != err {
 		if err = os.RemoveAll(tmp); nil != err {
-			util.LogErrorf("remove temp file [%s] failed: %s", tmp, err)
+			logging.LogErrorf("remove temp file [%s] failed: %s", tmp, err)
 		} else {
 		} else {
-			util.LogInfof("removed temp file [%s]", tmp)
+			logging.LogInfof("removed temp file [%s]", tmp)
 		}
 		}
 	}
 	}
 
 
 	tmps, err = filepath.Glob(filepath.Join(util.DataDir, ".siyuan", "*.tmp"))
 	tmps, err = filepath.Glob(filepath.Join(util.DataDir, ".siyuan", "*.tmp"))
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("glob temp files failed: %s", err)
+		logging.LogErrorf("glob temp files failed: %s", err)
 	}
 	}
 	for _, tmp := range tmps {
 	for _, tmp := range tmps {
 		if err = os.RemoveAll(tmp); nil != err {
 		if err = os.RemoveAll(tmp); nil != err {
-			util.LogErrorf("remove temp file [%s] failed: %s", tmp, err)
+			logging.LogErrorf("remove temp file [%s] failed: %s", tmp, err)
 		} else {
 		} else {
-			util.LogInfof("removed temp file [%s]", tmp)
+			logging.LogInfof("removed temp file [%s]", tmp)
 		}
 		}
 	}
 	}
 }
 }

+ 7 - 6
kernel/model/css.go

@@ -26,6 +26,7 @@ import (
 
 
 	"github.com/88250/css"
 	"github.com/88250/css"
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
 
 
@@ -133,7 +134,7 @@ func currentCSSValue(key string) string {
 	if 1 > len(data) {
 	if 1 > len(data) {
 		data, err = os.ReadFile(theme)
 		data, err = os.ReadFile(theme)
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("read theme css [%s] failed: %s", theme, err)
+			logging.LogErrorf("read theme css [%s] failed: %s", theme, err)
 			return "#ffffff"
 			return "#ffffff"
 		}
 		}
 	}
 	}
@@ -161,14 +162,14 @@ func ReadCustomCSS(themeName string) (ret map[string]map[string]string, err erro
 
 
 	if !gulu.File.IsExist(custom) {
 	if !gulu.File.IsExist(custom) {
 		if err = gulu.File.CopyFile(theme, custom); nil != err {
 		if err = gulu.File.CopyFile(theme, custom); nil != err {
-			util.LogErrorf("copy theme [%s] to [%s] failed: %s", theme, custom, err)
+			logging.LogErrorf("copy theme [%s] to [%s] failed: %s", theme, custom, err)
 			return
 			return
 		}
 		}
 	}
 	}
 
 
 	data, err := os.ReadFile(custom)
 	data, err := os.ReadFile(custom)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read custom css [%s] failed: %s", custom, err)
+		logging.LogErrorf("read custom css [%s] failed: %s", custom, err)
 		return
 		return
 	}
 	}
 
 
@@ -186,7 +187,7 @@ func ReadCustomCSS(themeName string) (ret map[string]map[string]string, err erro
 	// 补充现有主题中的样式
 	// 补充现有主题中的样式
 	data, err = os.ReadFile(theme)
 	data, err = os.ReadFile(theme)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read theme css [%s] failed: %s", theme, err)
+		logging.LogErrorf("read theme css [%s] failed: %s", theme, err)
 		return
 		return
 	}
 	}
 	ss = css.Parse(string(data))
 	ss = css.Parse(string(data))
@@ -232,7 +233,7 @@ func WriteCustomCSS(themeName string, cssMap map[string]interface{}) (err error)
 	custom := filepath.Join(themePath, "custom.css")
 	custom := filepath.Join(themePath, "custom.css")
 	data, err := os.ReadFile(custom)
 	data, err := os.ReadFile(custom)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read custom css [%s] failed: %s", custom, err)
+		logging.LogErrorf("read custom css [%s] failed: %s", custom, err)
 		return
 		return
 	}
 	}
 
 
@@ -268,7 +269,7 @@ func WriteCustomCSS(themeName string, cssMap map[string]interface{}) (err error)
 	}
 	}
 
 
 	if err := gulu.File.WriteFileSafer(custom, buf.Bytes(), 0644); nil != err {
 	if err := gulu.File.WriteFileSafer(custom, buf.Bytes(), 0644); nil != err {
-		util.LogErrorf("write custom css [%s] failed: %s", custom, err)
+		logging.LogErrorf("write custom css [%s] failed: %s", custom, err)
 	}
 	}
 
 
 	util.BroadcastByType("main", "refreshtheme", 0, "", map[string]interface{}{
 	util.BroadcastByType("main", "refreshtheme", 0, "", map[string]interface{}{

+ 47 - 46
kernel/model/export.go

@@ -41,6 +41,7 @@ import (
 	"github.com/emirpasic/gods/sets/hashset"
 	"github.com/emirpasic/gods/sets/hashset"
 	"github.com/emirpasic/gods/stacks/linkedliststack"
 	"github.com/emirpasic/gods/stacks/linkedliststack"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
@@ -49,7 +50,7 @@ import (
 func ExportSY(id string) (name, zipPath string) {
 func ExportSY(id string) (name, zipPath string) {
 	block := treenode.GetBlockTree(id)
 	block := treenode.GetBlockTree(id)
 	if nil == block {
 	if nil == block {
-		util.LogErrorf("not found block [%s]", id)
+		logging.LogErrorf("not found block [%s]", id)
 		return
 		return
 	}
 	}
 
 
@@ -108,7 +109,7 @@ func ExportData() (zipPath string) {
 func exportData(exportFolder string) (err error) {
 func exportData(exportFolder string) (err error) {
 	baseFolderName := "data-" + util.CurrentTimeSecondsStr()
 	baseFolderName := "data-" + util.CurrentTimeSecondsStr()
 	if err = os.MkdirAll(exportFolder, 0755); nil != err {
 	if err = os.MkdirAll(exportFolder, 0755); nil != err {
-		util.LogErrorf("create export temp folder failed: %s", err)
+		logging.LogErrorf("create export temp folder failed: %s", err)
 		return
 		return
 	}
 	}
 
 
@@ -119,7 +120,7 @@ func exportData(exportFolder string) (err error) {
 
 
 	data := filepath.Join(util.WorkspaceDir, "data")
 	data := filepath.Join(util.WorkspaceDir, "data")
 	if err = stableCopy(data, exportFolder); nil != err {
 	if err = stableCopy(data, exportFolder); nil != err {
-		util.LogErrorf("copy data dir from [%s] to [%s] failed: %s", data, baseFolderName, err)
+		logging.LogErrorf("copy data dir from [%s] to [%s] failed: %s", data, baseFolderName, err)
 		err = errors.New(fmt.Sprintf(Conf.Language(14), formatErrorMsg(err)))
 		err = errors.New(fmt.Sprintf(Conf.Language(14), formatErrorMsg(err)))
 		return
 		return
 	}
 	}
@@ -127,17 +128,17 @@ func exportData(exportFolder string) (err error) {
 	zipPath := exportFolder + ".zip"
 	zipPath := exportFolder + ".zip"
 	zip, err := gulu.Zip.Create(zipPath)
 	zip, err := gulu.Zip.Create(zipPath)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("create export data zip [%s] failed: %s", exportFolder, err)
+		logging.LogErrorf("create export data zip [%s] failed: %s", exportFolder, err)
 		return
 		return
 	}
 	}
 
 
 	if err = zip.AddDirectory(baseFolderName, exportFolder); nil != err {
 	if err = zip.AddDirectory(baseFolderName, exportFolder); nil != err {
-		util.LogErrorf("create export data zip [%s] failed: %s", exportFolder, err)
+		logging.LogErrorf("create export data zip [%s] failed: %s", exportFolder, err)
 		return
 		return
 	}
 	}
 
 
 	if err = zip.Close(); nil != err {
 	if err = zip.Close(); nil != err {
-		util.LogErrorf("close export data zip failed: %s", err)
+		logging.LogErrorf("close export data zip failed: %s", err)
 	}
 	}
 
 
 	os.RemoveAll(exportFolder)
 	os.RemoveAll(exportFolder)
@@ -174,19 +175,19 @@ func ExportDocx(id, savePath string) (err error) {
 	pandoc.Stdin = bytes.NewBufferString(dom)
 	pandoc.Stdin = bytes.NewBufferString(dom)
 	output, err := pandoc.CombinedOutput()
 	output, err := pandoc.CombinedOutput()
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("export docx failed: %s", gulu.Str.FromBytes(output))
+		logging.LogErrorf("export docx failed: %s", gulu.Str.FromBytes(output))
 		msg := fmt.Sprintf(Conf.Language(14), gulu.Str.FromBytes(output))
 		msg := fmt.Sprintf(Conf.Language(14), gulu.Str.FromBytes(output))
 		return errors.New(msg)
 		return errors.New(msg)
 	}
 	}
 
 
 	if err = gulu.File.Copy(tmpDocxPath, filepath.Join(savePath, name+".docx")); nil != err {
 	if err = gulu.File.Copy(tmpDocxPath, filepath.Join(savePath, name+".docx")); nil != err {
-		util.LogErrorf("export docx failed: %s", err)
+		logging.LogErrorf("export docx failed: %s", err)
 		return errors.New(fmt.Sprintf(Conf.Language(14), err))
 		return errors.New(fmt.Sprintf(Conf.Language(14), err))
 	}
 	}
 	tmpAssets := filepath.Join(tmpDir, "assets")
 	tmpAssets := filepath.Join(tmpDir, "assets")
 	if gulu.File.IsDir(tmpAssets) {
 	if gulu.File.IsDir(tmpAssets) {
 		if err = gulu.File.Copy(tmpAssets, filepath.Join(savePath, "assets")); nil != err {
 		if err = gulu.File.Copy(tmpAssets, filepath.Join(savePath, "assets")); nil != err {
-			util.LogErrorf("export docx failed: %s", err)
+			logging.LogErrorf("export docx failed: %s", err)
 			return errors.New(fmt.Sprintf(Conf.Language(14), err))
 			return errors.New(fmt.Sprintf(Conf.Language(14), err))
 		}
 		}
 	}
 	}
@@ -200,7 +201,7 @@ func ExportMarkdownHTML(id, savePath string, docx bool) (name, dom string) {
 	name = path.Base(tree.HPath)
 	name = path.Base(tree.HPath)
 
 
 	if err := os.MkdirAll(savePath, 0755); nil != err {
 	if err := os.MkdirAll(savePath, 0755); nil != err {
-		util.LogErrorf("mkdir [%s] failed: %s", savePath, err)
+		logging.LogErrorf("mkdir [%s] failed: %s", savePath, err)
 		return
 		return
 	}
 	}
 
 
@@ -209,12 +210,12 @@ func ExportMarkdownHTML(id, savePath string, docx bool) (name, dom string) {
 		if strings.HasPrefix(asset, "assets/") {
 		if strings.HasPrefix(asset, "assets/") {
 			srcAbsPath, err := GetAssetAbsPath(asset)
 			srcAbsPath, err := GetAssetAbsPath(asset)
 			if nil != err {
 			if nil != err {
-				util.LogWarnf("resolve path of asset [%s] failed: %s", asset, err)
+				logging.LogWarnf("resolve path of asset [%s] failed: %s", asset, err)
 				continue
 				continue
 			}
 			}
 			targetAbsPath := filepath.Join(savePath, asset)
 			targetAbsPath := filepath.Join(savePath, asset)
 			if err = gulu.File.Copy(srcAbsPath, targetAbsPath); nil != err {
 			if err = gulu.File.Copy(srcAbsPath, targetAbsPath); nil != err {
-				util.LogWarnf("copy asset from [%s] to [%s] failed: %s", srcAbsPath, targetAbsPath, err)
+				logging.LogWarnf("copy asset from [%s] to [%s] failed: %s", srcAbsPath, targetAbsPath, err)
 			}
 			}
 		}
 		}
 	}
 	}
@@ -224,7 +225,7 @@ func ExportMarkdownHTML(id, savePath string, docx bool) (name, dom string) {
 		from := filepath.Join(util.WorkingDir, src)
 		from := filepath.Join(util.WorkingDir, src)
 		to := filepath.Join(savePath, src)
 		to := filepath.Join(savePath, src)
 		if err := gulu.File.Copy(from, to); nil != err {
 		if err := gulu.File.Copy(from, to); nil != err {
-			util.LogWarnf("copy stage from [%s] to [%s] failed: %s", from, savePath, err)
+			logging.LogWarnf("copy stage from [%s] to [%s] failed: %s", from, savePath, err)
 			return
 			return
 		}
 		}
 	}
 	}
@@ -238,7 +239,7 @@ func ExportMarkdownHTML(id, savePath string, docx bool) (name, dom string) {
 		from := filepath.Join(util.AppearancePath, src)
 		from := filepath.Join(util.AppearancePath, src)
 		to := filepath.Join(savePath, "appearance", src)
 		to := filepath.Join(savePath, "appearance", src)
 		if err := gulu.File.Copy(from, to); nil != err {
 		if err := gulu.File.Copy(from, to); nil != err {
-			util.LogErrorf("copy appearance from [%s] to [%s] failed: %s", from, savePath, err)
+			logging.LogErrorf("copy appearance from [%s] to [%s] failed: %s", from, savePath, err)
 			return
 			return
 		}
 		}
 	}
 	}
@@ -283,7 +284,7 @@ func ExportHTML(id, savePath string, pdf bool) (name, dom string) {
 	name = path.Base(tree.Path)
 	name = path.Base(tree.Path)
 
 
 	if err := os.MkdirAll(savePath, 0755); nil != err {
 	if err := os.MkdirAll(savePath, 0755); nil != err {
-		util.LogErrorf("mkdir [%s] failed: %s", savePath, err)
+		logging.LogErrorf("mkdir [%s] failed: %s", savePath, err)
 		return
 		return
 	}
 	}
 
 
@@ -291,12 +292,12 @@ func ExportHTML(id, savePath string, pdf bool) (name, dom string) {
 	for _, asset := range assets {
 	for _, asset := range assets {
 		srcAbsPath, err := GetAssetAbsPath(asset)
 		srcAbsPath, err := GetAssetAbsPath(asset)
 		if nil != err {
 		if nil != err {
-			util.LogWarnf("resolve path of asset [%s] failed: %s", asset, err)
+			logging.LogWarnf("resolve path of asset [%s] failed: %s", asset, err)
 			continue
 			continue
 		}
 		}
 		targetAbsPath := filepath.Join(savePath, asset)
 		targetAbsPath := filepath.Join(savePath, asset)
 		if err = gulu.File.Copy(srcAbsPath, targetAbsPath); nil != err {
 		if err = gulu.File.Copy(srcAbsPath, targetAbsPath); nil != err {
-			util.LogWarnf("copy asset from [%s] to [%s] failed: %s", srcAbsPath, targetAbsPath, err)
+			logging.LogWarnf("copy asset from [%s] to [%s] failed: %s", srcAbsPath, targetAbsPath, err)
 		}
 		}
 	}
 	}
 
 
@@ -307,7 +308,7 @@ func ExportHTML(id, savePath string, pdf bool) (name, dom string) {
 			from := filepath.Join(util.WorkingDir, src)
 			from := filepath.Join(util.WorkingDir, src)
 			to := filepath.Join(savePath, src)
 			to := filepath.Join(savePath, src)
 			if err := gulu.File.Copy(from, to); nil != err {
 			if err := gulu.File.Copy(from, to); nil != err {
-				util.LogErrorf("copy stage from [%s] to [%s] failed: %s", from, savePath, err)
+				logging.LogErrorf("copy stage from [%s] to [%s] failed: %s", from, savePath, err)
 				return
 				return
 			}
 			}
 		}
 		}
@@ -321,7 +322,7 @@ func ExportHTML(id, savePath string, pdf bool) (name, dom string) {
 			from := filepath.Join(util.AppearancePath, src)
 			from := filepath.Join(util.AppearancePath, src)
 			to := filepath.Join(savePath, "appearance", src)
 			to := filepath.Join(savePath, "appearance", src)
 			if err := gulu.File.Copy(from, to); nil != err {
 			if err := gulu.File.Copy(from, to); nil != err {
-				util.LogErrorf("copy appearance from [%s] to [%s] failed: %s", from, savePath, err)
+				logging.LogErrorf("copy appearance from [%s] to [%s] failed: %s", from, savePath, err)
 				return
 				return
 			}
 			}
 		}
 		}
@@ -444,7 +445,7 @@ func AddPDFOutline(id, p string) (err error) {
 	outFile := inFile + ".tmp"
 	outFile := inFile + ".tmp"
 	err = api.AddBookmarksFile(inFile, outFile, topBms, nil)
 	err = api.AddBookmarksFile(inFile, outFile, topBms, nil)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("add bookmark failed: %s", err)
+		logging.LogErrorf("add bookmark failed: %s", err)
 		return
 		return
 	}
 	}
 	err = os.Rename(outFile, inFile)
 	err = os.Rename(outFile, inFile)
@@ -467,7 +468,7 @@ func CopyStdMarkdown(id string) string {
 func ExportMarkdown(id string) (name, zipPath string) {
 func ExportMarkdown(id string) (name, zipPath string) {
 	block := treenode.GetBlockTree(id)
 	block := treenode.GetBlockTree(id)
 	if nil == block {
 	if nil == block {
-		util.LogErrorf("not found block [%s]", id)
+		logging.LogErrorf("not found block [%s]", id)
 		return
 		return
 	}
 	}
 
 
@@ -496,7 +497,7 @@ func BatchExportMarkdown(boxID, folderPath string) (zipPath string) {
 	} else {
 	} else {
 		block := treenode.GetBlockTreeRootByHPath(box.ID, folderPath)
 		block := treenode.GetBlockTreeRootByHPath(box.ID, folderPath)
 		if nil == block {
 		if nil == block {
-			util.LogErrorf("not found block")
+			logging.LogErrorf("not found block")
 			return
 			return
 		}
 		}
 		baseFolderName = path.Base(block.HPath)
 		baseFolderName = path.Base(block.HPath)
@@ -527,7 +528,7 @@ func exportMarkdownZip(boxID, baseFolderName string, docPaths []string) (zipPath
 
 
 	exportFolder := filepath.Join(util.TempDir, "export", baseFolderName)
 	exportFolder := filepath.Join(util.TempDir, "export", baseFolderName)
 	if err := os.MkdirAll(exportFolder, 0755); nil != err {
 	if err := os.MkdirAll(exportFolder, 0755); nil != err {
-		util.LogErrorf("create export temp folder failed: %s", err)
+		logging.LogErrorf("create export temp folder failed: %s", err)
 		return
 		return
 	}
 	}
 
 
@@ -553,11 +554,11 @@ func exportMarkdownZip(boxID, baseFolderName string, docPaths []string) (zipPath
 		}
 		}
 		writeFolder := filepath.Dir(writePath)
 		writeFolder := filepath.Dir(writePath)
 		if err := os.MkdirAll(writeFolder, 0755); nil != err {
 		if err := os.MkdirAll(writeFolder, 0755); nil != err {
-			util.LogErrorf("create export temp folder [%s] failed: %s", writeFolder, err)
+			logging.LogErrorf("create export temp folder [%s] failed: %s", writeFolder, err)
 			continue
 			continue
 		}
 		}
 		if err := gulu.File.WriteFileSafer(writePath, gulu.Str.ToBytes(md), 0644); nil != err {
 		if err := gulu.File.WriteFileSafer(writePath, gulu.Str.ToBytes(md), 0644); nil != err {
-			util.LogErrorf("write export markdown file [%s] failed: %s", writePath, err)
+			logging.LogErrorf("write export markdown file [%s] failed: %s", writePath, err)
 			continue
 			continue
 		}
 		}
 
 
@@ -573,7 +574,7 @@ func exportMarkdownZip(boxID, baseFolderName string, docPaths []string) (zipPath
 
 
 			srcPath, err := GetAssetAbsPath(asset)
 			srcPath, err := GetAssetAbsPath(asset)
 			if nil != err {
 			if nil != err {
-				util.LogWarnf("get asset [%s] abs path failed: %s", asset, err)
+				logging.LogWarnf("get asset [%s] abs path failed: %s", asset, err)
 				continue
 				continue
 			}
 			}
 
 
@@ -584,7 +585,7 @@ func exportMarkdownZip(boxID, baseFolderName string, docPaths []string) (zipPath
 				err = gulu.File.CopyFile(srcPath, destPath)
 				err = gulu.File.CopyFile(srcPath, destPath)
 			}
 			}
 			if nil != err {
 			if nil != err {
-				util.LogErrorf("copy asset from [%s] to [%s] failed: %s", srcPath, destPath, err)
+				logging.LogErrorf("copy asset from [%s] to [%s] failed: %s", srcPath, destPath, err)
 				continue
 				continue
 			}
 			}
 		}
 		}
@@ -593,17 +594,17 @@ func exportMarkdownZip(boxID, baseFolderName string, docPaths []string) (zipPath
 	zipPath = exportFolder + ".zip"
 	zipPath = exportFolder + ".zip"
 	zip, err := gulu.Zip.Create(zipPath)
 	zip, err := gulu.Zip.Create(zipPath)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("create export markdown zip [%s] failed: %s", exportFolder, err)
+		logging.LogErrorf("create export markdown zip [%s] failed: %s", exportFolder, err)
 		return ""
 		return ""
 	}
 	}
 
 
 	if err = zip.AddDirectory(baseFolderName, exportFolder); nil != err {
 	if err = zip.AddDirectory(baseFolderName, exportFolder); nil != err {
-		util.LogErrorf("create export markdown zip [%s] failed: %s", exportFolder, err)
+		logging.LogErrorf("create export markdown zip [%s] failed: %s", exportFolder, err)
 		return ""
 		return ""
 	}
 	}
 
 
 	if err = zip.Close(); nil != err {
 	if err = zip.Close(); nil != err {
-		util.LogErrorf("close export markdown zip failed: %s", err)
+		logging.LogErrorf("close export markdown zip failed: %s", err)
 	}
 	}
 
 
 	os.RemoveAll(exportFolder)
 	os.RemoveAll(exportFolder)
@@ -624,7 +625,7 @@ func exportSYZip(boxID, rootDirPath, baseFolderName string, docPaths []string) (
 
 
 	exportFolder := filepath.Join(util.TempDir, "export", baseFolderName)
 	exportFolder := filepath.Join(util.TempDir, "export", baseFolderName)
 	if err := os.MkdirAll(exportFolder, 0755); nil != err {
 	if err := os.MkdirAll(exportFolder, 0755); nil != err {
-		util.LogErrorf("create export temp folder failed: %s", err)
+		logging.LogErrorf("create export temp folder failed: %s", err)
 		return
 		return
 	}
 	}
 
 
@@ -657,7 +658,7 @@ func exportSYZip(boxID, rootDirPath, baseFolderName string, docPaths []string) (
 		readPath := filepath.Join(util.DataDir, tree.Box, tree.Path)
 		readPath := filepath.Join(util.DataDir, tree.Box, tree.Path)
 		data, readErr := filelock.NoLockFileRead(readPath)
 		data, readErr := filelock.NoLockFileRead(readPath)
 		if nil != readErr {
 		if nil != readErr {
-			util.LogErrorf("read file [%s] failed: %s", readPath, readErr)
+			logging.LogErrorf("read file [%s] failed: %s", readPath, readErr)
 			continue
 			continue
 		}
 		}
 
 
@@ -665,11 +666,11 @@ func exportSYZip(boxID, rootDirPath, baseFolderName string, docPaths []string) (
 		writePath = filepath.Join(exportFolder, writePath)
 		writePath = filepath.Join(exportFolder, writePath)
 		writeFolder := filepath.Dir(writePath)
 		writeFolder := filepath.Dir(writePath)
 		if mkdirErr := os.MkdirAll(writeFolder, 0755); nil != mkdirErr {
 		if mkdirErr := os.MkdirAll(writeFolder, 0755); nil != mkdirErr {
-			util.LogErrorf("create export temp folder [%s] failed: %s", writeFolder, mkdirErr)
+			logging.LogErrorf("create export temp folder [%s] failed: %s", writeFolder, mkdirErr)
 			continue
 			continue
 		}
 		}
 		if writeErr := os.WriteFile(writePath, data, 0644); nil != writeErr {
 		if writeErr := os.WriteFile(writePath, data, 0644); nil != writeErr {
-			util.LogErrorf("write export file [%s] failed: %s", writePath, writeErr)
+			logging.LogErrorf("write export file [%s] failed: %s", writePath, writeErr)
 			continue
 			continue
 		}
 		}
 	}
 	}
@@ -679,14 +680,14 @@ func exportSYZip(boxID, rootDirPath, baseFolderName string, docPaths []string) (
 		readPath := filepath.Join(util.DataDir, tree.Box, tree.Path)
 		readPath := filepath.Join(util.DataDir, tree.Box, tree.Path)
 		data, readErr := filelock.NoLockFileRead(readPath)
 		data, readErr := filelock.NoLockFileRead(readPath)
 		if nil != readErr {
 		if nil != readErr {
-			util.LogErrorf("read file [%s] failed: %s", readPath, readErr)
+			logging.LogErrorf("read file [%s] failed: %s", readPath, readErr)
 			continue
 			continue
 		}
 		}
 
 
 		writePath := strings.TrimPrefix(tree.Path, rootDirPath)
 		writePath := strings.TrimPrefix(tree.Path, rootDirPath)
 		writePath = filepath.Join(exportFolder, treeID+".sy")
 		writePath = filepath.Join(exportFolder, treeID+".sy")
 		if writeErr := os.WriteFile(writePath, data, 0644); nil != writeErr {
 		if writeErr := os.WriteFile(writePath, data, 0644); nil != writeErr {
-			util.LogErrorf("write export file [%s] failed: %s", writePath, writeErr)
+			logging.LogErrorf("write export file [%s] failed: %s", writePath, writeErr)
 			continue
 			continue
 		}
 		}
 	}
 	}
@@ -713,7 +714,7 @@ func exportSYZip(boxID, rootDirPath, baseFolderName string, docPaths []string) (
 
 
 			srcPath, assetErr := GetAssetAbsPath(asset)
 			srcPath, assetErr := GetAssetAbsPath(asset)
 			if nil != assetErr {
 			if nil != assetErr {
-				util.LogWarnf("get asset [%s] abs path failed: %s", asset, assetErr)
+				logging.LogWarnf("get asset [%s] abs path failed: %s", asset, assetErr)
 				continue
 				continue
 			}
 			}
 
 
@@ -724,7 +725,7 @@ func exportSYZip(boxID, rootDirPath, baseFolderName string, docPaths []string) (
 				assetErr = gulu.File.CopyFile(srcPath, destPath)
 				assetErr = gulu.File.CopyFile(srcPath, destPath)
 			}
 			}
 			if nil != assetErr {
 			if nil != assetErr {
-				util.LogErrorf("copy asset from [%s] to [%s] failed: %s", srcPath, destPath, assetErr)
+				logging.LogErrorf("copy asset from [%s] to [%s] failed: %s", srcPath, destPath, assetErr)
 				continue
 				continue
 			}
 			}
 
 
@@ -735,17 +736,17 @@ func exportSYZip(boxID, rootDirPath, baseFolderName string, docPaths []string) (
 	zipPath = exportFolder + ".sy.zip"
 	zipPath = exportFolder + ".sy.zip"
 	zip, err := gulu.Zip.Create(zipPath)
 	zip, err := gulu.Zip.Create(zipPath)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("create export markdown zip [%s] failed: %s", exportFolder, err)
+		logging.LogErrorf("create export markdown zip [%s] failed: %s", exportFolder, err)
 		return ""
 		return ""
 	}
 	}
 
 
 	if err = zip.AddDirectory(baseFolderName, exportFolder); nil != err {
 	if err = zip.AddDirectory(baseFolderName, exportFolder); nil != err {
-		util.LogErrorf("create export markdown zip [%s] failed: %s", exportFolder, err)
+		logging.LogErrorf("create export markdown zip [%s] failed: %s", exportFolder, err)
 		return ""
 		return ""
 	}
 	}
 
 
 	if err = zip.Close(); nil != err {
 	if err = zip.Close(); nil != err {
-		util.LogErrorf("close export markdown zip failed: %s", err)
+		logging.LogErrorf("close export markdown zip failed: %s", err)
 	}
 	}
 
 
 	os.RemoveAll(exportFolder)
 	os.RemoveAll(exportFolder)
@@ -987,24 +988,24 @@ func exportTree(tree *parse.Tree, wysiwyg bool) (ret *parse.Tree) {
 			p := refID[:strings.LastIndex(refID, "/")]
 			p := refID[:strings.LastIndex(refID, "/")]
 			absPath, err := GetAssetAbsPath(p)
 			absPath, err := GetAssetAbsPath(p)
 			if nil != err {
 			if nil != err {
-				util.LogWarnf("get assets abs path by rel path [%s] failed: %s", p, err)
+				logging.LogWarnf("get assets abs path by rel path [%s] failed: %s", p, err)
 				return ast.WalkSkipChildren
 				return ast.WalkSkipChildren
 			}
 			}
 			sya := absPath + ".sya"
 			sya := absPath + ".sya"
 			syaData, err := os.ReadFile(sya)
 			syaData, err := os.ReadFile(sya)
 			if nil != err {
 			if nil != err {
-				util.LogErrorf("read file [%s] failed: %s", sya, err)
+				logging.LogErrorf("read file [%s] failed: %s", sya, err)
 				return ast.WalkSkipChildren
 				return ast.WalkSkipChildren
 			}
 			}
 			syaJSON := map[string]interface{}{}
 			syaJSON := map[string]interface{}{}
 			if err = gulu.JSON.UnmarshalJSON(syaData, &syaJSON); nil != err {
 			if err = gulu.JSON.UnmarshalJSON(syaData, &syaJSON); nil != err {
-				util.LogErrorf("unmarshal file [%s] failed: %s", sya, err)
+				logging.LogErrorf("unmarshal file [%s] failed: %s", sya, err)
 				return ast.WalkSkipChildren
 				return ast.WalkSkipChildren
 			}
 			}
 			annotationID := refID[strings.LastIndex(refID, "/")+1:]
 			annotationID := refID[strings.LastIndex(refID, "/")+1:]
 			annotationData := syaJSON[annotationID]
 			annotationData := syaJSON[annotationID]
 			if nil == annotationData {
 			if nil == annotationData {
-				util.LogErrorf("not found annotation [%s] in .sya", annotationID)
+				logging.LogErrorf("not found annotation [%s] in .sya", annotationID)
 				return ast.WalkSkipChildren
 				return ast.WalkSkipChildren
 			}
 			}
 			pages := annotationData.(map[string]interface{})["pages"].([]interface{})
 			pages := annotationData.(map[string]interface{})["pages"].([]interface{})
@@ -1293,7 +1294,7 @@ func collectFootnotesDefs(id string, refFootnotes *[]*refAsFootnotes, treeCache
 	}
 	}
 	node := treenode.GetNodeInTree(t, b.ID)
 	node := treenode.GetNodeInTree(t, b.ID)
 	if nil == node {
 	if nil == node {
-		util.LogErrorf("not found node [%s] in tree [%s]", b.ID, t.Root.ID)
+		logging.LogErrorf("not found node [%s] in tree [%s]", b.ID, t.Root.ID)
 		return
 		return
 	}
 	}
 	collectFootnotesDefs0(node, refFootnotes, treeCache, depth)
 	collectFootnotesDefs0(node, refFootnotes, treeCache, depth)

+ 41 - 40
kernel/model/file.go

@@ -40,6 +40,7 @@ import (
 	"github.com/facette/natsort"
 	"github.com/facette/natsort"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/cache"
 	"github.com/siyuan-note/siyuan/kernel/cache"
 	"github.com/siyuan-note/siyuan/kernel/filesys"
 	"github.com/siyuan-note/siyuan/kernel/filesys"
 	"github.com/siyuan-note/siyuan/kernel/search"
 	"github.com/siyuan-note/siyuan/kernel/search"
@@ -138,19 +139,19 @@ func (box *Box) docIAL(p string) (ret map[string]string) {
 	if util.IsCorruptedSYData(data) {
 	if util.IsCorruptedSYData(data) {
 		filelock.UnlockFile(filePath)
 		filelock.UnlockFile(filePath)
 		if removeErr := os.RemoveAll(filePath); nil == removeErr {
 		if removeErr := os.RemoveAll(filePath); nil == removeErr {
-			util.LogInfof("removed corrupted data file [path=%s, length=%d]", filePath, len(data))
+			logging.LogInfof("removed corrupted data file [path=%s, length=%d]", filePath, len(data))
 		} else {
 		} else {
-			util.LogWarnf("remove corrupted data file [path=%s, length=%d] failed: %s", filePath, len(data), removeErr)
+			logging.LogWarnf("remove corrupted data file [path=%s, length=%d] failed: %s", filePath, len(data), removeErr)
 		}
 		}
 		return nil
 		return nil
 	}
 	}
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read file [%s] failed: %s", p, err)
+		logging.LogErrorf("read file [%s] failed: %s", p, err)
 		return nil
 		return nil
 	}
 	}
 	ret = readDocIAL(data)
 	ret = readDocIAL(data)
 	if nil == ret {
 	if nil == ret {
-		util.LogWarnf("tree [%s] is corrupted", filePath)
+		logging.LogWarnf("tree [%s] is corrupted", filePath)
 		return nil
 		return nil
 	}
 	}
 	cache.PutDocIAL(p, ret)
 	cache.PutDocIAL(p, ret)
@@ -160,7 +161,7 @@ func (box *Box) docIAL(p string) (ret map[string]string) {
 func readDocIAL(data []byte) (ret map[string]string) {
 func readDocIAL(data []byte) (ret map[string]string) {
 	doc := map[string]interface{}{}
 	doc := map[string]interface{}{}
 	if err := gulu.JSON.UnmarshalJSON(data, &doc); nil != err {
 	if err := gulu.JSON.UnmarshalJSON(data, &doc); nil != err {
-		util.LogErrorf("unmarshal data failed: %s", err)
+		logging.LogErrorf("unmarshal data failed: %s", err)
 		return nil
 		return nil
 	}
 	}
 
 
@@ -241,7 +242,7 @@ func ListDocTree(boxID, path string, sortMode int) (ret []*File, totals int, err
 	}
 	}
 	elapsed := time.Now().Sub(start).Milliseconds()
 	elapsed := time.Now().Sub(start).Milliseconds()
 	if 100 < elapsed {
 	if 100 < elapsed {
-		util.LogWarnf("ls elapsed [%dms]", elapsed)
+		logging.LogWarnf("ls elapsed [%dms]", elapsed)
 	}
 	}
 
 
 	start = time.Now()
 	start = time.Now()
@@ -286,7 +287,7 @@ func ListDocTree(boxID, path string, sortMode int) (ret []*File, totals int, err
 	}
 	}
 	elapsed = time.Now().Sub(start).Milliseconds()
 	elapsed = time.Now().Sub(start).Milliseconds()
 	if 500 < elapsed {
 	if 500 < elapsed {
-		util.LogWarnf("build docs elapsed [%dms]", elapsed)
+		logging.LogWarnf("build docs elapsed [%dms]", elapsed)
 	}
 	}
 
 
 	start = time.Now()
 	start = time.Now()
@@ -298,7 +299,7 @@ func ListDocTree(boxID, path string, sortMode int) (ret []*File, totals int, err
 	}
 	}
 	elapsed = time.Now().Sub(start).Milliseconds()
 	elapsed = time.Now().Sub(start).Milliseconds()
 	if 500 < elapsed {
 	if 500 < elapsed {
-		util.LogWarnf("query root block ref count elapsed [%dms]", elapsed)
+		logging.LogWarnf("query root block ref count elapsed [%dms]", elapsed)
 	}
 	}
 
 
 	start = time.Now()
 	start = time.Now()
@@ -359,7 +360,7 @@ func ListDocTree(boxID, path string, sortMode int) (ret []*File, totals int, err
 
 
 	elapsed = time.Now().Sub(start).Milliseconds()
 	elapsed = time.Now().Sub(start).Milliseconds()
 	if 200 < elapsed {
 	if 200 < elapsed {
-		util.LogInfof("sort docs elapsed [%dms]", elapsed)
+		logging.LogInfof("sort docs elapsed [%dms]", elapsed)
 	}
 	}
 	return
 	return
 }
 }
@@ -376,7 +377,7 @@ func BlocksWordCount(ids []string) (runeCount, wordCount int) {
 	for _, id := range ids {
 	for _, id := range ids {
 		bt := treenode.GetBlockTree(id)
 		bt := treenode.GetBlockTree(id)
 		if nil == bt {
 		if nil == bt {
-			util.LogWarnf("block tree not found [%s]", id)
+			logging.LogWarnf("block tree not found [%s]", id)
 			continue
 			continue
 		}
 		}
 
 
@@ -908,12 +909,12 @@ func DuplicateDoc(rootID string) (err error) {
 	if nil != err {
 	if nil != err {
 		tx, txErr := sql.BeginTx()
 		tx, txErr := sql.BeginTx()
 		if nil != txErr {
 		if nil != txErr {
-			util.LogFatalf("transaction failed: %s", txErr)
+			logging.LogFatalf("transaction failed: %s", txErr)
 			return
 			return
 		}
 		}
 		sql.ClearBoxHash(tx)
 		sql.ClearBoxHash(tx)
 		sql.CommitTx(tx)
 		sql.CommitTx(tx)
-		util.LogFatalf("transaction failed: %s", err)
+		logging.LogFatalf("transaction failed: %s", err)
 		return
 		return
 	}
 	}
 	sql.WaitForWritingDatabase()
 	sql.WaitForWritingDatabase()
@@ -1090,7 +1091,7 @@ func MoveDoc(fromBoxID, fromPath, toBoxID, toPath string) (newPath string, err e
 			}
 			}
 			if err = os.Rename(absFromPath, absToPath); nil != err {
 			if err = os.Rename(absFromPath, absToPath); nil != err {
 				msg := fmt.Sprintf(Conf.Language(5), fromBox.Name, fromPath, err)
 				msg := fmt.Sprintf(Conf.Language(5), fromBox.Name, fromPath, err)
-				util.LogErrorf("move [path=%s] in box [%s] failed: %s", fromPath, fromBoxID, err)
+				logging.LogErrorf("move [path=%s] in box [%s] failed: %s", fromPath, fromBoxID, err)
 				err = errors.New(msg)
 				err = errors.New(msg)
 				return
 				return
 			}
 			}
@@ -1116,7 +1117,7 @@ func MoveDoc(fromBoxID, fromPath, toBoxID, toPath string) (newPath string, err e
 		filelock.ReleaseFileLocks(absFromPath)
 		filelock.ReleaseFileLocks(absFromPath)
 		if err = os.Rename(absFromPath, absToPath); nil != err {
 		if err = os.Rename(absFromPath, absToPath); nil != err {
 			msg := fmt.Sprintf(Conf.Language(5), fromBox.Name, fromPath, err)
 			msg := fmt.Sprintf(Conf.Language(5), fromBox.Name, fromPath, err)
-			util.LogErrorf("move [path=%s] in box [%s] failed: %s", fromPath, fromBoxID, err)
+			logging.LogErrorf("move [path=%s] in box [%s] failed: %s", fromPath, fromBoxID, err)
 			err = errors.New(msg)
 			err = errors.New(msg)
 			return
 			return
 		}
 		}
@@ -1152,7 +1153,7 @@ func RemoveDoc(boxID, p string) (err error) {
 
 
 	historyDir, err := util.GetHistoryDir("delete")
 	historyDir, err := util.GetHistoryDir("delete")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("get history dir failed: %s", err)
+		logging.LogErrorf("get history dir failed: %s", err)
 		return
 		return
 	}
 	}
 
 
@@ -1290,11 +1291,11 @@ func CreateDailyNote(boxID string) (p string, err error) {
 	if "" != boxConf.DailyNoteTemplatePath {
 	if "" != boxConf.DailyNoteTemplatePath {
 		tplPath := filepath.Join(util.DataDir, "templates", boxConf.DailyNoteTemplatePath)
 		tplPath := filepath.Join(util.DataDir, "templates", boxConf.DailyNoteTemplatePath)
 		if !gulu.File.IsExist(tplPath) {
 		if !gulu.File.IsExist(tplPath) {
-			util.LogWarnf("not found daily note template [%s]", tplPath)
+			logging.LogWarnf("not found daily note template [%s]", tplPath)
 		} else {
 		} else {
 			dom, err = renderTemplate(tplPath, id)
 			dom, err = renderTemplate(tplPath, id)
 			if nil != err {
 			if nil != err {
-				util.LogWarnf("render daily note template [%s] failed: %s", boxConf.DailyNoteTemplatePath, err)
+				logging.LogWarnf("render daily note template [%s] failed: %s", boxConf.DailyNoteTemplatePath, err)
 			}
 			}
 		}
 		}
 	}
 	}
@@ -1350,7 +1351,7 @@ func createDoc(boxID, p, title, dom string) (err error) {
 		parentID := path.Base(folder)
 		parentID := path.Base(folder)
 		parentTree, err := loadTreeByBlockID(parentID)
 		parentTree, err := loadTreeByBlockID(parentID)
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("get parent tree [id=%s] failed", parentID)
+			logging.LogErrorf("get parent tree [id=%s] failed", parentID)
 			return ErrBlockNotFound
 			return ErrBlockNotFound
 		}
 		}
 		hPath = path.Join(parentTree.HPath, title)
 		hPath = path.Join(parentTree.HPath, title)
@@ -1392,12 +1393,12 @@ func createDoc(boxID, p, title, dom string) (err error) {
 	if nil != err {
 	if nil != err {
 		tx, txErr := sql.BeginTx()
 		tx, txErr := sql.BeginTx()
 		if nil != txErr {
 		if nil != txErr {
-			util.LogFatalf("transaction failed: %s", txErr)
+			logging.LogFatalf("transaction failed: %s", txErr)
 			return
 			return
 		}
 		}
 		sql.ClearBoxHash(tx)
 		sql.ClearBoxHash(tx)
 		sql.CommitTx(tx)
 		sql.CommitTx(tx)
-		util.LogFatalf("transaction failed: %s", err)
+		logging.LogFatalf("transaction failed: %s", err)
 		return
 		return
 	}
 	}
 	WaitForWritingFiles()
 	WaitForWritingFiles()
@@ -1417,12 +1418,12 @@ func moveSorts(rootID, fromBox, toBox string) {
 	if gulu.File.IsExist(fromConfPath) {
 	if gulu.File.IsExist(fromConfPath) {
 		data, err := filelock.LockFileRead(fromConfPath)
 		data, err := filelock.LockFileRead(fromConfPath)
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("read sort conf failed: %s", err)
+			logging.LogErrorf("read sort conf failed: %s", err)
 			return
 			return
 		}
 		}
 
 
 		if err = gulu.JSON.UnmarshalJSON(data, &fromFullSortIDs); nil != err {
 		if err = gulu.JSON.UnmarshalJSON(data, &fromFullSortIDs); nil != err {
-			util.LogErrorf("unmarshal sort conf failed: %s", err)
+			logging.LogErrorf("unmarshal sort conf failed: %s", err)
 		}
 		}
 	}
 	}
 	for _, id := range ids {
 	for _, id := range ids {
@@ -1434,12 +1435,12 @@ func moveSorts(rootID, fromBox, toBox string) {
 	if gulu.File.IsExist(toConfPath) {
 	if gulu.File.IsExist(toConfPath) {
 		data, err := filelock.LockFileRead(toConfPath)
 		data, err := filelock.LockFileRead(toConfPath)
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("read sort conf failed: %s", err)
+			logging.LogErrorf("read sort conf failed: %s", err)
 			return
 			return
 		}
 		}
 
 
 		if err = gulu.JSON.UnmarshalJSON(data, &toFullSortIDs); nil != err {
 		if err = gulu.JSON.UnmarshalJSON(data, &toFullSortIDs); nil != err {
-			util.LogErrorf("unmarshal sort conf failed: %s", err)
+			logging.LogErrorf("unmarshal sort conf failed: %s", err)
 			return
 			return
 		}
 		}
 	}
 	}
@@ -1450,11 +1451,11 @@ func moveSorts(rootID, fromBox, toBox string) {
 
 
 	data, err := gulu.JSON.MarshalIndentJSON(toFullSortIDs, "", "  ")
 	data, err := gulu.JSON.MarshalIndentJSON(toFullSortIDs, "", "  ")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("marshal sort conf failed: %s", err)
+		logging.LogErrorf("marshal sort conf failed: %s", err)
 		return
 		return
 	}
 	}
 	if err = filelock.LockFileWrite(toConfPath, data); nil != err {
 	if err = filelock.LockFileWrite(toConfPath, data); nil != err {
-		util.LogErrorf("write sort conf failed: %s", err)
+		logging.LogErrorf("write sort conf failed: %s", err)
 		return
 		return
 	}
 	}
 }
 }
@@ -1507,7 +1508,7 @@ func ChangeFileTreeSort(boxID string, paths []string) {
 	absParentPath := filepath.Join(util.DataDir, boxID, parentPath)
 	absParentPath := filepath.Join(util.DataDir, boxID, parentPath)
 	files, err := os.ReadDir(absParentPath)
 	files, err := os.ReadDir(absParentPath)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read dir [%s] failed: %s", err)
+		logging.LogErrorf("read dir [%s] failed: %s", err)
 	}
 	}
 
 
 	sortFolderIDs := map[string]int{}
 	sortFolderIDs := map[string]int{}
@@ -1527,7 +1528,7 @@ func ChangeFileTreeSort(boxID string, paths []string) {
 
 
 	confDir := filepath.Join(util.DataDir, box.ID, ".siyuan")
 	confDir := filepath.Join(util.DataDir, box.ID, ".siyuan")
 	if err = os.MkdirAll(confDir, 0755); nil != err {
 	if err = os.MkdirAll(confDir, 0755); nil != err {
-		util.LogErrorf("create conf dir failed: %s", err)
+		logging.LogErrorf("create conf dir failed: %s", err)
 		return
 		return
 	}
 	}
 	confPath := filepath.Join(confDir, "sort.json")
 	confPath := filepath.Join(confDir, "sort.json")
@@ -1536,12 +1537,12 @@ func ChangeFileTreeSort(boxID string, paths []string) {
 	if gulu.File.IsExist(confPath) {
 	if gulu.File.IsExist(confPath) {
 		data, err = filelock.LockFileRead(confPath)
 		data, err = filelock.LockFileRead(confPath)
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("read sort conf failed: %s", err)
+			logging.LogErrorf("read sort conf failed: %s", err)
 			return
 			return
 		}
 		}
 
 
 		if err = gulu.JSON.UnmarshalJSON(data, &fullSortIDs); nil != err {
 		if err = gulu.JSON.UnmarshalJSON(data, &fullSortIDs); nil != err {
-			util.LogErrorf("unmarshal sort conf failed: %s", err)
+			logging.LogErrorf("unmarshal sort conf failed: %s", err)
 		}
 		}
 	}
 	}
 
 
@@ -1551,11 +1552,11 @@ func ChangeFileTreeSort(boxID string, paths []string) {
 
 
 	data, err = gulu.JSON.MarshalIndentJSON(fullSortIDs, "", "  ")
 	data, err = gulu.JSON.MarshalIndentJSON(fullSortIDs, "", "  ")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("marshal sort conf failed: %s", err)
+		logging.LogErrorf("marshal sort conf failed: %s", err)
 		return
 		return
 	}
 	}
 	if err = filelock.LockFileWrite(confPath, data); nil != err {
 	if err = filelock.LockFileWrite(confPath, data); nil != err {
-		util.LogErrorf("write sort conf failed: %s", err)
+		logging.LogErrorf("write sort conf failed: %s", err)
 		return
 		return
 	}
 	}
 
 
@@ -1570,13 +1571,13 @@ func (box *Box) fillSort(files *[]*File) {
 
 
 	data, err := filelock.LockFileRead(confPath)
 	data, err := filelock.LockFileRead(confPath)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read sort conf failed: %s", err)
+		logging.LogErrorf("read sort conf failed: %s", err)
 		return
 		return
 	}
 	}
 
 
 	fullSortIDs := map[string]int{}
 	fullSortIDs := map[string]int{}
 	if err = gulu.JSON.UnmarshalJSON(data, &fullSortIDs); nil != err {
 	if err = gulu.JSON.UnmarshalJSON(data, &fullSortIDs); nil != err {
-		util.LogErrorf("unmarshal sort conf failed: %s", err)
+		logging.LogErrorf("unmarshal sort conf failed: %s", err)
 		return
 		return
 	}
 	}
 
 
@@ -1617,13 +1618,13 @@ func (box *Box) removeSort(rootID, path string) {
 
 
 	data, err := filelock.LockFileRead(confPath)
 	data, err := filelock.LockFileRead(confPath)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read sort conf failed: %s", err)
+		logging.LogErrorf("read sort conf failed: %s", err)
 		return
 		return
 	}
 	}
 
 
 	fullSortIDs := map[string]int{}
 	fullSortIDs := map[string]int{}
 	if err = gulu.JSON.UnmarshalJSON(data, &fullSortIDs); nil != err {
 	if err = gulu.JSON.UnmarshalJSON(data, &fullSortIDs); nil != err {
-		util.LogErrorf("unmarshal sort conf failed: %s", err)
+		logging.LogErrorf("unmarshal sort conf failed: %s", err)
 		return
 		return
 	}
 	}
 
 
@@ -1633,11 +1634,11 @@ func (box *Box) removeSort(rootID, path string) {
 
 
 	data, err = gulu.JSON.MarshalIndentJSON(fullSortIDs, "", "  ")
 	data, err = gulu.JSON.MarshalIndentJSON(fullSortIDs, "", "  ")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("marshal sort conf failed: %s", err)
+		logging.LogErrorf("marshal sort conf failed: %s", err)
 		return
 		return
 	}
 	}
 	if err = filelock.LockFileWrite(confPath, data); nil != err {
 	if err = filelock.LockFileWrite(confPath, data); nil != err {
-		util.LogErrorf("write sort conf failed: %s", err)
+		logging.LogErrorf("write sort conf failed: %s", err)
 		return
 		return
 	}
 	}
 }
 }
@@ -1647,10 +1648,10 @@ func ServeFile(c *gin.Context, filePath string) (err error) {
 
 
 	if filelock.IsLocked(filePath) {
 	if filelock.IsLocked(filePath) {
 		if err = filelock.UnlockFile(filePath); nil == err {
 		if err = filelock.UnlockFile(filePath); nil == err {
-			util.LogInfof("unlocked file [%s]", filePath)
+			logging.LogInfof("unlocked file [%s]", filePath)
 		} else {
 		} else {
 			msg := fmt.Sprintf("unlock file [%s] failed: %s", filePath, err)
 			msg := fmt.Sprintf("unlock file [%s] failed: %s", filePath, err)
-			util.LogErrorf(msg)
+			logging.LogErrorf(msg)
 			return errors.New(msg)
 			return errors.New(msg)
 		}
 		}
 	}
 	}

+ 5 - 4
kernel/model/format.go

@@ -25,6 +25,7 @@ import (
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/render"
 	"github.com/88250/lute/render"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
@@ -94,24 +95,24 @@ func AutoSpace(rootID string) (err error) {
 func generateFormatHistory(tree *parse.Tree) {
 func generateFormatHistory(tree *parse.Tree) {
 	historyDir, err := util.GetHistoryDir("format")
 	historyDir, err := util.GetHistoryDir("format")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("get history dir failed: %s", err)
+		logging.LogErrorf("get history dir failed: %s", err)
 		return
 		return
 	}
 	}
 
 
 	historyPath := filepath.Join(historyDir, tree.Box, tree.Path)
 	historyPath := filepath.Join(historyDir, tree.Box, tree.Path)
 	if err = os.MkdirAll(filepath.Dir(historyPath), 0755); nil != err {
 	if err = os.MkdirAll(filepath.Dir(historyPath), 0755); nil != err {
-		util.LogErrorf("generate history failed: %s", err)
+		logging.LogErrorf("generate history failed: %s", err)
 		return
 		return
 	}
 	}
 
 
 	var data []byte
 	var data []byte
 	if data, err = filelock.NoLockFileRead(filepath.Join(util.DataDir, tree.Box, tree.Path)); err != nil {
 	if data, err = filelock.NoLockFileRead(filepath.Join(util.DataDir, tree.Box, tree.Path)); err != nil {
-		util.LogErrorf("generate history failed: %s", err)
+		logging.LogErrorf("generate history failed: %s", err)
 		return
 		return
 	}
 	}
 
 
 	if err = gulu.File.WriteFileSafer(historyPath, data, 0644); err != nil {
 	if err = gulu.File.WriteFileSafer(historyPath, data, 0644); err != nil {
-		util.LogErrorf("generate history failed: %s", err)
+		logging.LogErrorf("generate history failed: %s", err)
 		return
 		return
 	}
 	}
 
 

+ 2 - 2
kernel/model/graph.go

@@ -25,9 +25,9 @@ import (
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/html"
 	"github.com/88250/lute/html"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
-	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
 
 
 type GraphNode struct {
 type GraphNode struct {
@@ -462,7 +462,7 @@ func pruneUnref(nodes *[]*GraphNode, links *[]*GraphLink) {
 		}
 		}
 
 
 		if maxBlocks < len(tmpNodes) {
 		if maxBlocks < len(tmpNodes) {
-			util.LogWarnf("exceeded the maximum number of render nodes [%d]", maxBlocks)
+			logging.LogWarnf("exceeded the maximum number of render nodes [%d]", maxBlocks)
 			break
 			break
 		}
 		}
 	}
 	}

+ 28 - 27
kernel/model/history.go

@@ -29,6 +29,7 @@ import (
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/88250/protyle"
 	"github.com/88250/protyle"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/conf"
 	"github.com/siyuan-note/siyuan/kernel/conf"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
@@ -82,10 +83,10 @@ func ClearWorkspaceHistory() (err error) {
 	historyDir := util.HistoryDir
 	historyDir := util.HistoryDir
 	if gulu.File.IsDir(historyDir) {
 	if gulu.File.IsDir(historyDir) {
 		if err = os.RemoveAll(historyDir); nil != err {
 		if err = os.RemoveAll(historyDir); nil != err {
-			util.LogErrorf("remove workspace history dir [%s] failed: %s", historyDir, err)
+			logging.LogErrorf("remove workspace history dir [%s] failed: %s", historyDir, err)
 			return
 			return
 		}
 		}
-		util.LogInfof("removed workspace history dir [%s]", historyDir)
+		logging.LogInfof("removed workspace history dir [%s]", historyDir)
 	}
 	}
 
 
 	// 以下部分是老版本的清理逻辑,暂时保留
 	// 以下部分是老版本的清理逻辑,暂时保留
@@ -103,27 +104,27 @@ func ClearWorkspaceHistory() (err error) {
 		}
 		}
 
 
 		if err = os.RemoveAll(historyDir); nil != err {
 		if err = os.RemoveAll(historyDir); nil != err {
-			util.LogErrorf("remove notebook history dir [%s] failed: %s", historyDir, err)
+			logging.LogErrorf("remove notebook history dir [%s] failed: %s", historyDir, err)
 			return
 			return
 		}
 		}
-		util.LogInfof("removed notebook history dir [%s]", historyDir)
+		logging.LogInfof("removed notebook history dir [%s]", historyDir)
 	}
 	}
 
 
 	historyDir = filepath.Join(util.DataDir, ".siyuan", "history")
 	historyDir = filepath.Join(util.DataDir, ".siyuan", "history")
 	if gulu.File.IsDir(historyDir) {
 	if gulu.File.IsDir(historyDir) {
 		if err = os.RemoveAll(historyDir); nil != err {
 		if err = os.RemoveAll(historyDir); nil != err {
-			util.LogErrorf("remove data history dir [%s] failed: %s", historyDir, err)
+			logging.LogErrorf("remove data history dir [%s] failed: %s", historyDir, err)
 			return
 			return
 		}
 		}
-		util.LogInfof("removed data history dir [%s]", historyDir)
+		logging.LogInfof("removed data history dir [%s]", historyDir)
 	}
 	}
 	historyDir = filepath.Join(util.DataDir, "assets", ".siyuan", "history")
 	historyDir = filepath.Join(util.DataDir, "assets", ".siyuan", "history")
 	if gulu.File.IsDir(historyDir) {
 	if gulu.File.IsDir(historyDir) {
 		if err = os.RemoveAll(historyDir); nil != err {
 		if err = os.RemoveAll(historyDir); nil != err {
-			util.LogErrorf("remove assets history dir [%s] failed: %s", historyDir, err)
+			logging.LogErrorf("remove assets history dir [%s] failed: %s", historyDir, err)
 			return
 			return
 		}
 		}
-		util.LogInfof("removed assets history dir [%s]", historyDir)
+		logging.LogInfof("removed assets history dir [%s]", historyDir)
 	}
 	}
 	return
 	return
 }
 }
@@ -135,13 +136,13 @@ func GetDocHistoryContent(historyPath string) (content string, err error) {
 
 
 	data, err := filelock.NoLockFileRead(historyPath)
 	data, err := filelock.NoLockFileRead(historyPath)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read file [%s] failed: %s", historyPath, err)
+		logging.LogErrorf("read file [%s] failed: %s", historyPath, err)
 		return
 		return
 	}
 	}
 	luteEngine := NewLute()
 	luteEngine := NewLute()
 	historyTree, err := protyle.ParseJSONWithoutFix(luteEngine, data)
 	historyTree, err := protyle.ParseJSONWithoutFix(luteEngine, data)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("parse tree from file [%s] failed, remove it", historyPath)
+		logging.LogErrorf("parse tree from file [%s] failed, remove it", historyPath)
 		os.RemoveAll(historyPath)
 		os.RemoveAll(historyPath)
 		return
 		return
 	}
 	}
@@ -217,7 +218,7 @@ func RollbackAssetsHistory(historyPath string) (err error) {
 	to := filepath.Join(util.DataDir, "assets", filepath.Base(historyPath))
 	to := filepath.Join(util.DataDir, "assets", filepath.Base(historyPath))
 
 
 	if err = gulu.File.Copy(from, to); nil != err {
 	if err = gulu.File.Copy(from, to); nil != err {
-		util.LogErrorf("copy file [%s] to [%s] failed: %s", from, to, err)
+		logging.LogErrorf("copy file [%s] to [%s] failed: %s", from, to, err)
 		return
 		return
 	}
 	}
 	IncSync()
 	IncSync()
@@ -233,7 +234,7 @@ func RollbackNotebookHistory(historyPath string) (err error) {
 	to := filepath.Join(util.DataDir, filepath.Base(historyPath))
 	to := filepath.Join(util.DataDir, filepath.Base(historyPath))
 
 
 	if err = gulu.File.Copy(from, to); nil != err {
 	if err = gulu.File.Copy(from, to); nil != err {
-		util.LogErrorf("copy file [%s] to [%s] failed: %s", from, to, err)
+		logging.LogErrorf("copy file [%s] to [%s] failed: %s", from, to, err)
 		return
 		return
 	}
 	}
 
 
@@ -264,7 +265,7 @@ func GetDocHistory(boxID string) (ret []*History, err error) {
 
 
 	historyBoxDirs, err := filepath.Glob(historyDir + "/*/" + boxID)
 	historyBoxDirs, err := filepath.Glob(historyDir + "/*/" + boxID)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read dir [%s] failed: %s", historyDir, err)
+		logging.LogErrorf("read dir [%s] failed: %s", historyDir, err)
 		return
 		return
 	}
 	}
 	sort.Slice(historyBoxDirs, func(i, j int) bool {
 	sort.Slice(historyBoxDirs, func(i, j int) bool {
@@ -287,12 +288,12 @@ func GetDocHistory(boxID string) (ret []*History, err error) {
 
 
 			data, err := filelock.NoLockFileRead(path)
 			data, err := filelock.NoLockFileRead(path)
 			if nil != err {
 			if nil != err {
-				util.LogErrorf("read file [%s] failed: %s", path, err)
+				logging.LogErrorf("read file [%s] failed: %s", path, err)
 				return nil
 				return nil
 			}
 			}
 			historyTree, err := protyle.ParseJSONWithoutFix(luteEngine, data)
 			historyTree, err := protyle.ParseJSONWithoutFix(luteEngine, data)
 			if nil != err {
 			if nil != err {
-				util.LogErrorf("parse tree from file [%s] failed, remove it", path)
+				logging.LogErrorf("parse tree from file [%s] failed, remove it", path)
 				os.RemoveAll(path)
 				os.RemoveAll(path)
 				return nil
 				return nil
 			}
 			}
@@ -349,7 +350,7 @@ func GetNotebookHistory() (ret []*History, err error) {
 
 
 	historyNotebookConfs, err := filepath.Glob(historyDir + "/*-delete/*/.siyuan/conf.json")
 	historyNotebookConfs, err := filepath.Glob(historyDir + "/*-delete/*/.siyuan/conf.json")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read dir [%s] failed: %s", historyDir, err)
+		logging.LogErrorf("read dir [%s] failed: %s", historyDir, err)
 		return
 		return
 	}
 	}
 	sort.Slice(historyNotebookConfs, func(i, j int) bool {
 	sort.Slice(historyNotebookConfs, func(i, j int) bool {
@@ -369,11 +370,11 @@ func GetNotebookHistory() (ret []*History, err error) {
 		var c conf.BoxConf
 		var c conf.BoxConf
 		data, readErr := os.ReadFile(historyNotebookConf)
 		data, readErr := os.ReadFile(historyNotebookConf)
 		if nil != readErr {
 		if nil != readErr {
-			util.LogErrorf("read notebook conf [%s] failed: %s", historyNotebookConf, readErr)
+			logging.LogErrorf("read notebook conf [%s] failed: %s", historyNotebookConf, readErr)
 			continue
 			continue
 		}
 		}
 		if err = json.Unmarshal(data, &c); nil != err {
 		if err = json.Unmarshal(data, &c); nil != err {
-			util.LogErrorf("parse notebook conf [%s] failed: %s", historyNotebookConf, err)
+			logging.LogErrorf("parse notebook conf [%s] failed: %s", historyNotebookConf, err)
 			continue
 			continue
 		}
 		}
 
 
@@ -409,7 +410,7 @@ func GetAssetsHistory() (ret []*History, err error) {
 
 
 	historyAssetsDirs, err := filepath.Glob(historyDir + "/*/assets")
 	historyAssetsDirs, err := filepath.Glob(historyDir + "/*/assets")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read dir [%s] failed: %s", historyDir, err)
+		logging.LogErrorf("read dir [%s] failed: %s", historyDir, err)
 		return
 		return
 	}
 	}
 	sort.Slice(historyAssetsDirs, func(i, j int) bool {
 	sort.Slice(historyAssetsDirs, func(i, j int) bool {
@@ -477,25 +478,25 @@ func (box *Box) generateDocHistory0() {
 
 
 	historyDir, err := util.GetHistoryDir("update")
 	historyDir, err := util.GetHistoryDir("update")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("get history dir failed: %s", err)
+		logging.LogErrorf("get history dir failed: %s", err)
 		return
 		return
 	}
 	}
 
 
 	for _, file := range files {
 	for _, file := range files {
 		historyPath := filepath.Join(historyDir, box.ID, strings.TrimPrefix(file, filepath.Join(util.DataDir, box.ID)))
 		historyPath := filepath.Join(historyDir, box.ID, strings.TrimPrefix(file, filepath.Join(util.DataDir, box.ID)))
 		if err = os.MkdirAll(filepath.Dir(historyPath), 0755); nil != err {
 		if err = os.MkdirAll(filepath.Dir(historyPath), 0755); nil != err {
-			util.LogErrorf("generate history failed: %s", err)
+			logging.LogErrorf("generate history failed: %s", err)
 			return
 			return
 		}
 		}
 
 
 		var data []byte
 		var data []byte
 		if data, err = filelock.NoLockFileRead(file); err != nil {
 		if data, err = filelock.NoLockFileRead(file); err != nil {
-			util.LogErrorf("generate history failed: %s", err)
+			logging.LogErrorf("generate history failed: %s", err)
 			return
 			return
 		}
 		}
 
 
 		if err = gulu.File.WriteFileSafer(historyPath, data, 0644); err != nil {
 		if err = gulu.File.WriteFileSafer(historyPath, data, 0644); err != nil {
-			util.LogErrorf("generate history failed: %s", err)
+			logging.LogErrorf("generate history failed: %s", err)
 			return
 			return
 		}
 		}
 	}
 	}
@@ -509,7 +510,7 @@ func clearOutdatedHistoryDir(historyDir string) {
 
 
 	dirs, err := os.ReadDir(historyDir)
 	dirs, err := os.ReadDir(historyDir)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("clear history [%s] failed: %s", historyDir, err)
+		logging.LogErrorf("clear history [%s] failed: %s", historyDir, err)
 		return
 		return
 	}
 	}
 
 
@@ -518,7 +519,7 @@ func clearOutdatedHistoryDir(historyDir string) {
 	for _, dir := range dirs {
 	for _, dir := range dirs {
 		dirInfo, err := dir.Info()
 		dirInfo, err := dir.Info()
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("read history dir [%s] failed: %s", dir.Name(), err)
+			logging.LogErrorf("read history dir [%s] failed: %s", dir.Name(), err)
 			continue
 			continue
 		}
 		}
 		if Conf.Editor.HistoryRetentionDays < int(now.Sub(dirInfo.ModTime()).Hours()/24) {
 		if Conf.Editor.HistoryRetentionDays < int(now.Sub(dirInfo.ModTime()).Hours()/24) {
@@ -527,10 +528,10 @@ func clearOutdatedHistoryDir(historyDir string) {
 	}
 	}
 	for _, dir := range removes {
 	for _, dir := range removes {
 		if err = os.RemoveAll(dir); nil != err {
 		if err = os.RemoveAll(dir); nil != err {
-			util.LogErrorf("remove history dir [%s] failed: %s", dir, err)
+			logging.LogErrorf("remove history dir [%s] failed: %s", dir, err)
 			continue
 			continue
 		}
 		}
-		//util.LogInfof("auto removed history dir [%s]", dir)
+		//logging.LogInfof("auto removed history dir [%s]", dir)
 	}
 	}
 }
 }
 
 

+ 19 - 18
kernel/model/import.go

@@ -39,6 +39,7 @@ import (
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/parse"
 	"github.com/88250/protyle"
 	"github.com/88250/protyle"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/filesys"
 	"github.com/siyuan-note/siyuan/kernel/filesys"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
@@ -76,7 +77,7 @@ func ImportSY(zipPath, boxID, toPath string) (err error) {
 		return
 		return
 	}
 	}
 	if 1 != len(unzipRootPaths) {
 	if 1 != len(unzipRootPaths) {
-		util.LogErrorf("invalid .sy.zip")
+		logging.LogErrorf("invalid .sy.zip")
 		return errors.New("invalid .sy.zip")
 		return errors.New("invalid .sy.zip")
 	}
 	}
 	unzipRootPath := unzipRootPaths[0]
 	unzipRootPath := unzipRootPaths[0]
@@ -88,13 +89,13 @@ func ImportSY(zipPath, boxID, toPath string) (err error) {
 	for _, syPath := range syPaths {
 	for _, syPath := range syPaths {
 		data, readErr := os.ReadFile(syPath)
 		data, readErr := os.ReadFile(syPath)
 		if nil != readErr {
 		if nil != readErr {
-			util.LogErrorf("read .sy [%s] failed: %s", syPath, readErr)
+			logging.LogErrorf("read .sy [%s] failed: %s", syPath, readErr)
 			err = readErr
 			err = readErr
 			return
 			return
 		}
 		}
 		tree, _, parseErr := protyle.ParseJSON(luteEngine, data)
 		tree, _, parseErr := protyle.ParseJSON(luteEngine, data)
 		if nil != parseErr {
 		if nil != parseErr {
-			util.LogErrorf("parse .sy [%s] failed: %s", syPath, parseErr)
+			logging.LogErrorf("parse .sy [%s] failed: %s", syPath, parseErr)
 			err = parseErr
 			err = parseErr
 			return
 			return
 		}
 		}
@@ -127,7 +128,7 @@ func ImportSY(zipPath, boxID, toPath string) (err error) {
 				if "" != newDefID {
 				if "" != newDefID {
 					n.Tokens = gulu.Str.ToBytes(newDefID)
 					n.Tokens = gulu.Str.ToBytes(newDefID)
 				} else {
 				} else {
-					util.LogWarnf("not found def [" + n.TokensStr() + "]")
+					logging.LogWarnf("not found def [" + n.TokensStr() + "]")
 				}
 				}
 			} else if ast.NodeBlockQueryEmbedScript == n.Type {
 			} else if ast.NodeBlockQueryEmbedScript == n.Type {
 				for oldID, newID := range blockIDs {
 				for oldID, newID := range blockIDs {
@@ -153,12 +154,12 @@ func ImportSY(zipPath, boxID, toPath string) (err error) {
 		data = buf.Bytes()
 		data = buf.Bytes()
 
 
 		if err = os.WriteFile(syPath, data, 0644); nil != err {
 		if err = os.WriteFile(syPath, data, 0644); nil != err {
-			util.LogErrorf("write .sy [%s] failed: %s", syPath, err)
+			logging.LogErrorf("write .sy [%s] failed: %s", syPath, err)
 			return
 			return
 		}
 		}
 		newSyPath := filepath.Join(filepath.Dir(syPath), tree.ID+".sy")
 		newSyPath := filepath.Join(filepath.Dir(syPath), tree.ID+".sy")
 		if err = os.Rename(syPath, newSyPath); nil != err {
 		if err = os.Rename(syPath, newSyPath); nil != err {
-			util.LogErrorf("rename .sy from [%s] to [%s] failed: %s", syPath, newSyPath, err)
+			logging.LogErrorf("rename .sy from [%s] to [%s] failed: %s", syPath, newSyPath, err)
 			return
 			return
 		}
 		}
 	}
 	}
@@ -210,7 +211,7 @@ func ImportSY(zipPath, boxID, toPath string) (err error) {
 	for i, oldPath := range oldPaths {
 	for i, oldPath := range oldPaths {
 		newPath := renamePaths[oldPath]
 		newPath := renamePaths[oldPath]
 		if err = os.Rename(oldPath, newPath); nil != err {
 		if err = os.Rename(oldPath, newPath); nil != err {
-			util.LogErrorf("rename path from [%s] to [%s] failed: %s", oldPath, renamePaths[oldPath], err)
+			logging.LogErrorf("rename path from [%s] to [%s] failed: %s", oldPath, renamePaths[oldPath], err)
 			return errors.New("rename path failed")
 			return errors.New("rename path failed")
 		}
 		}
 
 
@@ -249,7 +250,7 @@ func ImportSY(zipPath, boxID, toPath string) (err error) {
 		if gulu.File.IsDir(assets) {
 		if gulu.File.IsDir(assets) {
 			dataAssets := filepath.Join(util.DataDir, "assets")
 			dataAssets := filepath.Join(util.DataDir, "assets")
 			if err = gulu.File.Copy(assets, dataAssets); nil != err {
 			if err = gulu.File.Copy(assets, dataAssets); nil != err {
-				util.LogErrorf("copy assets from [%s] to [%s] failed: %s", assets, dataAssets, err)
+				logging.LogErrorf("copy assets from [%s] to [%s] failed: %s", assets, dataAssets, err)
 				return
 				return
 			}
 			}
 		}
 		}
@@ -267,7 +268,7 @@ func ImportSY(zipPath, boxID, toPath string) (err error) {
 	} else {
 	} else {
 		block := treenode.GetBlockTreeRootByPath(boxID, toPath)
 		block := treenode.GetBlockTreeRootByPath(boxID, toPath)
 		if nil == block {
 		if nil == block {
-			util.LogErrorf("not found block by path [%s]", toPath)
+			logging.LogErrorf("not found block by path [%s]", toPath)
 			return nil
 			return nil
 		}
 		}
 		baseTargetPath = strings.TrimSuffix(block.Path, ".sy")
 		baseTargetPath = strings.TrimSuffix(block.Path, ".sy")
@@ -279,7 +280,7 @@ func ImportSY(zipPath, boxID, toPath string) (err error) {
 	}
 	}
 
 
 	if err = stableCopy(unzipRootPath, targetDir); nil != err {
 	if err = stableCopy(unzipRootPath, targetDir); nil != err {
-		util.LogErrorf("copy data dir from [%s] to [%s] failed: %s", unzipRootPath, util.DataDir, err)
+		logging.LogErrorf("copy data dir from [%s] to [%s] failed: %s", unzipRootPath, util.DataDir, err)
 		err = errors.New("copy data failed")
 		err = errors.New("copy data failed")
 		return
 		return
 	}
 	}
@@ -305,7 +306,7 @@ func ImportData(zipPath string) (err error) {
 
 
 	files, err := filepath.Glob(filepath.Join(unzipPath, "*/*.sy"))
 	files, err := filepath.Glob(filepath.Join(unzipPath, "*/*.sy"))
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("check data.zip failed: %s", err)
+		logging.LogErrorf("check data.zip failed: %s", err)
 		return errors.New("check data.zip failed")
 		return errors.New("check data.zip failed")
 	}
 	}
 	if 0 < len(files) {
 	if 0 < len(files) {
@@ -313,7 +314,7 @@ func ImportData(zipPath string) (err error) {
 	}
 	}
 	dirs, err := os.ReadDir(unzipPath)
 	dirs, err := os.ReadDir(unzipPath)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("check data.zip failed: %s", err)
+		logging.LogErrorf("check data.zip failed: %s", err)
 		return errors.New("check data.zip failed")
 		return errors.New("check data.zip failed")
 	}
 	}
 	if 1 != len(dirs) {
 	if 1 != len(dirs) {
@@ -326,7 +327,7 @@ func ImportData(zipPath string) (err error) {
 	filelock.ReleaseAllFileLocks()
 	filelock.ReleaseAllFileLocks()
 	tmpDataPath := filepath.Join(unzipPath, dirs[0].Name())
 	tmpDataPath := filepath.Join(unzipPath, dirs[0].Name())
 	if err = stableCopy(tmpDataPath, util.DataDir); nil != err {
 	if err = stableCopy(tmpDataPath, util.DataDir); nil != err {
-		util.LogErrorf("copy data dir from [%s] to [%s] failed: %s", tmpDataPath, util.DataDir, err)
+		logging.LogErrorf("copy data dir from [%s] to [%s] failed: %s", tmpDataPath, util.DataDir, err)
 		err = errors.New("copy data failed")
 		err = errors.New("copy data failed")
 		return
 		return
 	}
 	}
@@ -350,7 +351,7 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) {
 	} else {
 	} else {
 		block := treenode.GetBlockTreeRootByPath(boxID, toPath)
 		block := treenode.GetBlockTreeRootByPath(boxID, toPath)
 		if nil == block {
 		if nil == block {
-			util.LogErrorf("not found block by path [%s]", toPath)
+			logging.LogErrorf("not found block by path [%s]", toPath)
 			return nil
 			return nil
 		}
 		}
 		baseHPath = block.HPath
 		baseHPath = block.HPath
@@ -436,7 +437,7 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) {
 
 
 			tree = parseKTree(data)
 			tree = parseKTree(data)
 			if nil == tree {
 			if nil == tree {
-				util.LogErrorf("parse tree [%s] failed", currentPath)
+				logging.LogErrorf("parse tree [%s] failed", currentPath)
 				return nil
 				return nil
 			}
 			}
 			tree.ID = id
 			tree.ID = id
@@ -476,7 +477,7 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) {
 						name = util.AssetName(name)
 						name = util.AssetName(name)
 						assetTargetPath := filepath.Join(assetDirPath, name)
 						assetTargetPath := filepath.Join(assetDirPath, name)
 						if err = gulu.File.Copy(fullPath, assetTargetPath); nil != err {
 						if err = gulu.File.Copy(fullPath, assetTargetPath); nil != err {
-							util.LogErrorf("copy asset from [%s] to [%s] failed: %s", fullPath, assetTargetPath, err)
+							logging.LogErrorf("copy asset from [%s] to [%s] failed: %s", fullPath, assetTargetPath, err)
 							return ast.WalkContinue
 							return ast.WalkContinue
 						}
 						}
 						assetsDone[absDest] = name
 						assetsDone[absDest] = name
@@ -524,7 +525,7 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) {
 		tree := parseKTree(data)
 		tree := parseKTree(data)
 		if nil == tree {
 		if nil == tree {
 			msg := fmt.Sprintf("parse tree [%s] failed", localPath)
 			msg := fmt.Sprintf("parse tree [%s] failed", localPath)
-			util.LogErrorf(msg)
+			logging.LogErrorf(msg)
 			return errors.New(msg)
 			return errors.New(msg)
 		}
 		}
 		tree.ID = id
 		tree.ID = id
@@ -563,7 +564,7 @@ func ImportFromLocalPath(boxID, localPath string, toPath string) (err error) {
 				name = util.AssetName(name)
 				name = util.AssetName(name)
 				assetTargetPath := filepath.Join(assetDirPath, name)
 				assetTargetPath := filepath.Join(assetDirPath, name)
 				if err = gulu.File.CopyFile(absolutePath, assetTargetPath); nil != err {
 				if err = gulu.File.CopyFile(absolutePath, assetTargetPath); nil != err {
-					util.LogErrorf("copy asset from [%s] to [%s] failed: %s", absolutePath, assetTargetPath, err)
+					logging.LogErrorf("copy asset from [%s] to [%s] failed: %s", absolutePath, assetTargetPath, err)
 					return ast.WalkContinue
 					return ast.WalkContinue
 				}
 				}
 				n.Tokens = gulu.Str.ToBytes("assets/" + name)
 				n.Tokens = gulu.Str.ToBytes("assets/" + name)

+ 10 - 9
kernel/model/index.go

@@ -32,6 +32,7 @@ import (
 	"github.com/dustin/go-humanize"
 	"github.com/dustin/go-humanize"
 	"github.com/emirpasic/gods/sets/hashset"
 	"github.com/emirpasic/gods/sets/hashset"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/cache"
 	"github.com/siyuan-note/siyuan/kernel/cache"
 	"github.com/siyuan-note/siyuan/kernel/filesys"
 	"github.com/siyuan-note/siyuan/kernel/filesys"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
@@ -59,7 +60,7 @@ func (box *Box) BootIndex() {
 		p := file.path
 		p := file.path
 		tree, err := filesys.LoadTree(box.ID, p, luteEngine)
 		tree, err := filesys.LoadTree(box.ID, p, luteEngine)
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("read box [%s] tree [%s] failed: %s", box.ID, p, err)
+			logging.LogErrorf("read box [%s] tree [%s] failed: %s", box.ID, p, err)
 			continue
 			continue
 		}
 		}
 
 
@@ -113,7 +114,7 @@ func (box *Box) Index(fullRebuildIndex bool) (treeCount int, treeSize int64) {
 
 
 		tree, err := filesys.LoadTree(box.ID, p, luteEngine)
 		tree, err := filesys.LoadTree(box.ID, p, luteEngine)
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("read box [%s] tree [%s] failed: %s", box.ID, p, err)
+			logging.LogErrorf("read box [%s] tree [%s] failed: %s", box.ID, p, err)
 			continue
 			continue
 		}
 		}
 
 
@@ -155,7 +156,7 @@ func (box *Box) Index(fullRebuildIndex bool) (treeCount int, treeSize int64) {
 
 
 	dbBoxHash := sql.GetBoxHash(box.ID)
 	dbBoxHash := sql.GetBoxHash(box.ID)
 	if boxHash == dbBoxHash {
 	if boxHash == dbBoxHash {
-		//util.LogInfof("use existing database for box [%s]", box.ID)
+		//logging.LogInfof("use existing database for box [%s]", box.ID)
 		util.SetBootDetails("Use existing database for notebook " + box.ID)
 		util.SetBootDetails("Use existing database for notebook " + box.ID)
 		return
 		return
 	}
 	}
@@ -194,7 +195,7 @@ func (box *Box) Index(fullRebuildIndex bool) (treeCount int, treeSize int64) {
 
 
 		tree, err := filesys.LoadTree(box.ID, file.path, luteEngine)
 		tree, err := filesys.LoadTree(box.ID, file.path, luteEngine)
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("read box [%s] tree [%s] failed: %s", box.ID, file.path, err)
+			logging.LogErrorf("read box [%s] tree [%s] failed: %s", box.ID, file.path, err)
 			continue
 			continue
 		}
 		}
 
 
@@ -218,7 +219,7 @@ func (box *Box) Index(fullRebuildIndex bool) (treeCount int, treeSize int64) {
 
 
 	end := time.Now()
 	end := time.Now()
 	elapsed := end.Sub(start).Seconds()
 	elapsed := end.Sub(start).Seconds()
-	util.LogInfof("rebuilt database for notebook [%s] in [%.2fs], tree [count=%d, size=%s]", box.ID, elapsed, treeCount, humanize.Bytes(uint64(treeSize)))
+	logging.LogInfof("rebuilt database for notebook [%s] in [%.2fs], tree [count=%d, size=%s]", box.ID, elapsed, treeCount, humanize.Bytes(uint64(treeSize)))
 
 
 	util.PushEndlessProgress(fmt.Sprintf(Conf.Language(56), treeCount))
 	util.PushEndlessProgress(fmt.Sprintf(Conf.Language(56), treeCount))
 	return
 	return
@@ -286,12 +287,12 @@ func IndexRefs() {
 				util.IncBootProgress(bootProgressPart, "Persisting block ref text "+util.ShortPathForBootingDisplay(dynamicRefTreeID))
 				util.IncBootProgress(bootProgressPart, "Persisting block ref text "+util.ShortPathForBootingDisplay(dynamicRefTreeID))
 				tree, err := loadTreeByBlockID(dynamicRefTreeID)
 				tree, err := loadTreeByBlockID(dynamicRefTreeID)
 				if nil != err {
 				if nil != err {
-					util.LogErrorf("tree [%s] dynamic ref text to static failed: %s", dynamicRefTreeID, err)
+					logging.LogErrorf("tree [%s] dynamic ref text to static failed: %s", dynamicRefTreeID, err)
 					continue
 					continue
 				}
 				}
 				legacyDynamicRefTreeToStatic(tree)
 				legacyDynamicRefTreeToStatic(tree)
 				if err := filesys.WriteTree(tree); nil == err {
 				if err := filesys.WriteTree(tree); nil == err {
-					//util.LogInfof("persisted tree [%s] dynamic ref text", tree.Box+tree.Path)
+					//logging.LogInfof("persisted tree [%s] dynamic ref text", tree.Box+tree.Path)
 				}
 				}
 			}
 			}
 		}
 		}
@@ -335,7 +336,7 @@ func IndexRefs() {
 
 
 				tree, err := filesys.LoadTree(box.ID, file.path, luteEngine)
 				tree, err := filesys.LoadTree(box.ID, file.path, luteEngine)
 				if nil != err {
 				if nil != err {
-					util.LogErrorf("parse box [%s] tree [%s] failed", box.ID, file.path)
+					logging.LogErrorf("parse box [%s] tree [%s] failed", box.ID, file.path)
 					continue
 					continue
 				}
 				}
 
 
@@ -355,7 +356,7 @@ func IndexRefs() {
 			}
 			}
 		}
 		}
 	}
 	}
-	util.LogInfof("resolved refs [%d] in [%dms]", len(refBlocks), time.Now().Sub(start).Milliseconds())
+	logging.LogInfof("resolved refs [%d] in [%dms]", len(refBlocks), time.Now().Sub(start).Milliseconds())
 }
 }
 
 
 func legacyDynamicRefTreeToStatic(tree *parse.Tree) {
 func legacyDynamicRefTreeToStatic(tree *parse.Tree) {

+ 29 - 28
kernel/model/liandi.go

@@ -29,6 +29,7 @@ import (
 
 
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/siyuan-note/httpclient"
 	"github.com/siyuan-note/httpclient"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/conf"
 	"github.com/siyuan-note/siyuan/kernel/conf"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
@@ -47,7 +48,7 @@ func StartFreeTrial() (err error) {
 		SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
 		SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
 		Post(util.AliyunServer + "/apis/siyuan/user/startFreeTrial")
 		Post(util.AliyunServer + "/apis/siyuan/user/startFreeTrial")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("start free trial failed: %s", err)
+		logging.LogErrorf("start free trial failed: %s", err)
 		return ErrFailedToConnectCloudServer
 		return ErrFailedToConnectCloudServer
 	}
 	}
 	if 0 != requestResult.Code {
 	if 0 != requestResult.Code {
@@ -64,7 +65,7 @@ func DeactivateUser() (err error) {
 		SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
 		SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
 		Post(util.AliyunServer + "/apis/siyuan/user/deactivate")
 		Post(util.AliyunServer + "/apis/siyuan/user/deactivate")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("deactivate user failed: %s", err)
+		logging.LogErrorf("deactivate user failed: %s", err)
 		return ErrFailedToConnectCloudServer
 		return ErrFailedToConnectCloudServer
 	}
 	}
 
 
@@ -74,7 +75,7 @@ func DeactivateUser() (err error) {
 	}
 	}
 
 
 	if 0 != requestResult.Code {
 	if 0 != requestResult.Code {
-		util.LogErrorf("deactivate user failed: %s", requestResult.Msg)
+		logging.LogErrorf("deactivate user failed: %s", requestResult.Msg)
 		return errors.New(requestResult.Msg)
 		return errors.New(requestResult.Msg)
 	}
 	}
 	return
 	return
@@ -90,7 +91,7 @@ func SetCloudBlockReminder(id, data string, timed int64) (err error) {
 		SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
 		SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
 		Post(util.AliyunServer + "/apis/siyuan/calendar/setBlockReminder")
 		Post(util.AliyunServer + "/apis/siyuan/calendar/setBlockReminder")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("set block reminder failed: %s", err)
+		logging.LogErrorf("set block reminder failed: %s", err)
 		return ErrFailedToConnectCloudServer
 		return ErrFailedToConnectCloudServer
 	}
 	}
 
 
@@ -100,7 +101,7 @@ func SetCloudBlockReminder(id, data string, timed int64) (err error) {
 	}
 	}
 
 
 	if 0 != requestResult.Code {
 	if 0 != requestResult.Code {
-		util.LogErrorf("set block reminder failed: %s", requestResult.Msg)
+		logging.LogErrorf("set block reminder failed: %s", requestResult.Msg)
 		return errors.New(requestResult.Msg)
 		return errors.New(requestResult.Msg)
 	}
 	}
 	return
 	return
@@ -122,7 +123,7 @@ func LoadUploadToken() (err error) {
 		SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
 		SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
 		Post(util.AliyunServer + "/apis/siyuan/upload/token")
 		Post(util.AliyunServer + "/apis/siyuan/upload/token")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("get upload token failed: %s", err)
+		logging.LogErrorf("get upload token failed: %s", err)
 		return ErrFailedToConnectCloudServer
 		return ErrFailedToConnectCloudServer
 	}
 	}
 
 
@@ -132,7 +133,7 @@ func LoadUploadToken() (err error) {
 	}
 	}
 
 
 	if 0 != requestResult.Code {
 	if 0 != requestResult.Code {
-		util.LogErrorf("get upload token failed: %s", requestResult.Msg)
+		logging.LogErrorf("get upload token failed: %s", requestResult.Msg)
 		return
 		return
 	}
 	}
 
 
@@ -152,7 +153,7 @@ func AutoRefreshUser() {
 		if !subscriptionExpirationReminded {
 		if !subscriptionExpirationReminded {
 			subscriptionExpirationReminded = true
 			subscriptionExpirationReminded = true
 			go func() {
 			go func() {
-				defer util.Recover()
+				defer logging.Recover()
 
 
 				if "ios" == util.Container {
 				if "ios" == util.Container {
 					return
 					return
@@ -175,7 +176,7 @@ func AutoRefreshUser() {
 		}
 		}
 
 
 		go func() {
 		go func() {
-			defer util.Recover()
+			defer logging.Recover()
 
 
 			if nil != Conf.User {
 			if nil != Conf.User {
 				time.Sleep(2 * time.Minute)
 				time.Sleep(2 * time.Minute)
@@ -187,7 +188,7 @@ func AutoRefreshUser() {
 		}()
 		}()
 
 
 		go func() {
 		go func() {
-			defer util.Recover()
+			defer logging.Recover()
 
 
 			time.Sleep(1 * time.Minute)
 			time.Sleep(1 * time.Minute)
 			announcementConf := filepath.Join(util.HomeDir, ".config", "siyuan", "announcement.json")
 			announcementConf := filepath.Join(util.HomeDir, ".config", "siyuan", "announcement.json")
@@ -195,11 +196,11 @@ func AutoRefreshUser() {
 			if gulu.File.IsExist(announcementConf) {
 			if gulu.File.IsExist(announcementConf) {
 				data, err := os.ReadFile(announcementConf)
 				data, err := os.ReadFile(announcementConf)
 				if nil != err {
 				if nil != err {
-					util.LogErrorf("read announcement conf failed: %s", err)
+					logging.LogErrorf("read announcement conf failed: %s", err)
 					return
 					return
 				}
 				}
 				if err = gulu.JSON.UnmarshalJSON(data, &existingAnnouncements); nil != err {
 				if err = gulu.JSON.UnmarshalJSON(data, &existingAnnouncements); nil != err {
-					util.LogErrorf("unmarshal announcement conf failed: %s", err)
+					logging.LogErrorf("unmarshal announcement conf failed: %s", err)
 					os.Remove(announcementConf)
 					os.Remove(announcementConf)
 					return
 					return
 				}
 				}
@@ -221,11 +222,11 @@ func AutoRefreshUser() {
 
 
 			data, err := gulu.JSON.MarshalJSON(existingAnnouncements)
 			data, err := gulu.JSON.MarshalJSON(existingAnnouncements)
 			if nil != err {
 			if nil != err {
-				util.LogErrorf("marshal announcement conf failed: %s", err)
+				logging.LogErrorf("marshal announcement conf failed: %s", err)
 				return
 				return
 			}
 			}
 			if err = os.WriteFile(announcementConf, data, 0644); nil != err {
 			if err = os.WriteFile(announcementConf, data, 0644); nil != err {
-				util.LogErrorf("write announcement conf failed: %s", err)
+				logging.LogErrorf("write announcement conf failed: %s", err)
 				return
 				return
 			}
 			}
 
 
@@ -251,7 +252,7 @@ func RefreshUser(token string) error {
 		var tokenExpireTime int64
 		var tokenExpireTime int64
 		tokenExpireTime, err := strconv.ParseInt(Conf.User.UserTokenExpireTime+"000", 10, 64)
 		tokenExpireTime, err := strconv.ParseInt(Conf.User.UserTokenExpireTime+"000", 10, 64)
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("convert token expire time [%s] failed: %s", Conf.User.UserTokenExpireTime, err)
+			logging.LogErrorf("convert token expire time [%s] failed: %s", Conf.User.UserTokenExpireTime, err)
 			return errors.New(Conf.Language(19))
 			return errors.New(Conf.Language(19))
 		}
 		}
 
 
@@ -273,7 +274,7 @@ Net:
 		var tokenExpireTime int64
 		var tokenExpireTime int64
 		tokenExpireTime, err = strconv.ParseInt(Conf.User.UserTokenExpireTime+"000", 10, 64)
 		tokenExpireTime, err = strconv.ParseInt(Conf.User.UserTokenExpireTime+"000", 10, 64)
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("convert token expire time [%s] failed: %s", Conf.User.UserTokenExpireTime, err)
+			logging.LogErrorf("convert token expire time [%s] failed: %s", Conf.User.UserTokenExpireTime, err)
 			return errors.New(Conf.Language(19))
 			return errors.New(Conf.Language(19))
 		}
 		}
 
 
@@ -289,7 +290,7 @@ Net:
 	Conf.Save()
 	Conf.Save()
 
 
 	if elapsed := time.Now().Sub(start).Milliseconds(); 3000 < elapsed {
 	if elapsed := time.Now().Sub(start).Milliseconds(); 3000 < elapsed {
-		util.LogInfof("get cloud user elapsed [%dms]", elapsed)
+		logging.LogInfof("get cloud user elapsed [%dms]", elapsed)
 	}
 	}
 	return nil
 	return nil
 }
 }
@@ -320,7 +321,7 @@ func RemoveCloudShorthands(ids []string) (err error) {
 		SetBody(body).
 		SetBody(body).
 		Post(util.AliyunServer + "/apis/siyuan/inbox/removeCloudShorthands")
 		Post(util.AliyunServer + "/apis/siyuan/inbox/removeCloudShorthands")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("remove cloud shorthands failed: %s", err)
+		logging.LogErrorf("remove cloud shorthands failed: %s", err)
 		err = ErrFailedToConnectCloudServer
 		err = ErrFailedToConnectCloudServer
 		return
 		return
 	}
 	}
@@ -332,7 +333,7 @@ func RemoveCloudShorthands(ids []string) (err error) {
 
 
 	code := result["code"].(float64)
 	code := result["code"].(float64)
 	if 0 != code {
 	if 0 != code {
-		util.LogErrorf("remove cloud shorthands failed: %s", result["msg"])
+		logging.LogErrorf("remove cloud shorthands failed: %s", result["msg"])
 		err = errors.New(result["msg"].(string))
 		err = errors.New(result["msg"].(string))
 		return
 		return
 	}
 	}
@@ -347,7 +348,7 @@ func GetCloudShorthands(page int) (result map[string]interface{}, err error) {
 		SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
 		SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
 		Post(util.AliyunServer + "/apis/siyuan/inbox/getCloudShorthands?p=" + strconv.Itoa(page))
 		Post(util.AliyunServer + "/apis/siyuan/inbox/getCloudShorthands?p=" + strconv.Itoa(page))
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("get cloud shorthands failed: %s", err)
+		logging.LogErrorf("get cloud shorthands failed: %s", err)
 		err = ErrFailedToConnectCloudServer
 		err = ErrFailedToConnectCloudServer
 		return
 		return
 	}
 	}
@@ -359,7 +360,7 @@ func GetCloudShorthands(page int) (result map[string]interface{}, err error) {
 
 
 	code := result["code"].(float64)
 	code := result["code"].(float64)
 	if 0 != code {
 	if 0 != code {
-		util.LogErrorf("get cloud shorthands failed: %s", result["msg"])
+		logging.LogErrorf("get cloud shorthands failed: %s", result["msg"])
 		err = errors.New(result["msg"].(string))
 		err = errors.New(result["msg"].(string))
 		return
 		return
 	}
 	}
@@ -384,7 +385,7 @@ func getUser(token string) (*conf.User, error) {
 		SetBody(map[string]string{"token": token}).
 		SetBody(map[string]string{"token": token}).
 		Post(util.AliyunServer + "/apis/siyuan/user")
 		Post(util.AliyunServer + "/apis/siyuan/user")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("get community user failed: %s", err)
+		logging.LogErrorf("get community user failed: %s", err)
 		return nil, errors.New(Conf.Language(18))
 		return nil, errors.New(Conf.Language(18))
 	}
 	}
 
 
@@ -393,7 +394,7 @@ func getUser(token string) (*conf.User, error) {
 		if 255 == code {
 		if 255 == code {
 			return nil, errInvalidUser
 			return nil, errInvalidUser
 		}
 		}
-		util.LogErrorf("get community user failed: %s", result["msg"])
+		logging.LogErrorf("get community user failed: %s", result["msg"])
 		return nil, errors.New(Conf.Language(18))
 		return nil, errors.New(Conf.Language(18))
 	}
 	}
 
 
@@ -401,7 +402,7 @@ func getUser(token string) (*conf.User, error) {
 	data := util.AESDecrypt(dataStr)
 	data := util.AESDecrypt(dataStr)
 	user := &conf.User{}
 	user := &conf.User{}
 	if err = gulu.JSON.UnmarshalJSON(data, &user); nil != err {
 	if err = gulu.JSON.UnmarshalJSON(data, &user); nil != err {
-		util.LogErrorf("get community user failed: %s", err)
+		logging.LogErrorf("get community user failed: %s", err)
 		return nil, errors.New(Conf.Language(18))
 		return nil, errors.New(Conf.Language(18))
 	}
 	}
 	return user, nil
 	return user, nil
@@ -418,7 +419,7 @@ func UseActivationcode(code string) (err error) {
 		SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
 		SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
 		Post(util.AliyunServer + "/apis/siyuan/useActivationcode")
 		Post(util.AliyunServer + "/apis/siyuan/useActivationcode")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("check activation code failed: %s", err)
+		logging.LogErrorf("check activation code failed: %s", err)
 		return ErrFailedToConnectCloudServer
 		return ErrFailedToConnectCloudServer
 	}
 	}
 	if 0 != requestResult.Code {
 	if 0 != requestResult.Code {
@@ -439,7 +440,7 @@ func CheckActivationcode(code string) (retCode int, msg string) {
 		SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
 		SetCookies(&http.Cookie{Name: "symphony", Value: Conf.User.UserToken}).
 		Post(util.AliyunServer + "/apis/siyuan/checkActivationcode")
 		Post(util.AliyunServer + "/apis/siyuan/checkActivationcode")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("check activation code failed: %s", err)
+		logging.LogErrorf("check activation code failed: %s", err)
 		msg = ErrFailedToConnectCloudServer.Error()
 		msg = ErrFailedToConnectCloudServer.Error()
 		return
 		return
 	}
 	}
@@ -458,7 +459,7 @@ func Login(userName, password, captcha string) (ret *gulu.Result, err error) {
 		SetBody(map[string]string{"userName": userName, "userPassword": password, "captcha": captcha}).
 		SetBody(map[string]string{"userName": userName, "userPassword": password, "captcha": captcha}).
 		Post(util.AliyunServer + "/apis/siyuan/login")
 		Post(util.AliyunServer + "/apis/siyuan/login")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("login failed: %s", err)
+		logging.LogErrorf("login failed: %s", err)
 		return nil, errors.New(Conf.Language(18))
 		return nil, errors.New(Conf.Language(18))
 	}
 	}
 	ret = &gulu.Result{
 	ret = &gulu.Result{
@@ -485,7 +486,7 @@ func Login2fa(token, code string) (map[string]interface{}, error) {
 		SetHeader("token", token).
 		SetHeader("token", token).
 		Post(util.AliyunServer + "/apis/siyuan/login/2fa")
 		Post(util.AliyunServer + "/apis/siyuan/login/2fa")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("login 2fa failed: %s", err)
+		logging.LogErrorf("login 2fa failed: %s", err)
 		return nil, errors.New(Conf.Language(18))
 		return nil, errors.New(Conf.Language(18))
 	}
 	}
 	return result, nil
 	return result, nil

+ 3 - 2
kernel/model/mount.go

@@ -28,6 +28,7 @@ import (
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/ast"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
@@ -92,13 +93,13 @@ func RemoveBox(boxID string) (err error) {
 		var historyDir string
 		var historyDir string
 		historyDir, err = util.GetHistoryDir("delete")
 		historyDir, err = util.GetHistoryDir("delete")
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("get history dir failed: %s", err)
+			logging.LogErrorf("get history dir failed: %s", err)
 			return
 			return
 		}
 		}
 		p := strings.TrimPrefix(localPath, util.DataDir)
 		p := strings.TrimPrefix(localPath, util.DataDir)
 		historyPath := filepath.Join(historyDir, p)
 		historyPath := filepath.Join(historyDir, p)
 		if err = gulu.File.Copy(localPath, historyPath); nil != err {
 		if err = gulu.File.Copy(localPath, historyPath); nil != err {
-			util.LogErrorf("gen sync history failed: %s", err)
+			logging.LogErrorf("gen sync history failed: %s", err)
 			return
 			return
 		}
 		}
 
 

+ 2 - 1
kernel/model/path.go

@@ -26,6 +26,7 @@ import (
 
 
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/ast"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/search"
 	"github.com/siyuan-note/siyuan/kernel/search"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
@@ -65,7 +66,7 @@ func createDocsByHPath(boxID, hPath, content string) (id string, err error) {
 			if isNotLast {
 			if isNotLast {
 				dirPath := filepath.Join(util.DataDir, boxID, pathBuilder.String())
 				dirPath := filepath.Join(util.DataDir, boxID, pathBuilder.String())
 				if err = os.MkdirAll(dirPath, 0755); nil != err {
 				if err = os.MkdirAll(dirPath, 0755); nil != err {
-					util.LogErrorf("mkdir [%s] failed: %s", dirPath, err)
+					logging.LogErrorf("mkdir [%s] failed: %s", dirPath, err)
 					return
 					return
 				}
 				}
 			}
 			}

+ 3 - 2
kernel/model/process.go

@@ -22,6 +22,7 @@ import (
 	"syscall"
 	"syscall"
 	"time"
 	"time"
 
 
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
 
 
@@ -32,7 +33,7 @@ func HookResident() {
 
 
 	for range time.Tick(time.Second * 30) {
 	for range time.Tick(time.Second * 30) {
 		if 0 == util.CountSessions() {
 		if 0 == util.CountSessions() {
-			util.LogInfof("no active session, exit kernel process now")
+			logging.LogInfof("no active session, exit kernel process now")
 			Close(false)
 			Close(false)
 		}
 		}
 	}
 	}
@@ -42,6 +43,6 @@ func HandleSignal() {
 	c := make(chan os.Signal)
 	c := make(chan os.Signal)
 	signal.Notify(c, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
 	signal.Notify(c, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
 	s := <-c
 	s := <-c
-	util.LogInfof("received os signal [%s], exit kernel process now", s)
+	logging.LogInfof("received os signal [%s], exit kernel process now", s)
 	Close(false)
 	Close(false)
 }
 }

+ 14 - 13
kernel/model/repository.go

@@ -34,6 +34,7 @@ import (
 	"github.com/siyuan-note/eventbus"
 	"github.com/siyuan-note/eventbus"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/httpclient"
 	"github.com/siyuan-note/httpclient"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/cache"
 	"github.com/siyuan-note/siyuan/kernel/cache"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
@@ -62,7 +63,7 @@ func GetRepoSnapshots(page int) (logs []*dejavu.Log, pageCount, totalCount int,
 			return
 			return
 		}
 		}
 
 
-		util.LogErrorf("get data repo index logs failed: %s", err)
+		logging.LogErrorf("get data repo index logs failed: %s", err)
 		return
 		return
 	}
 	}
 	return
 	return
@@ -80,7 +81,7 @@ func ImportRepoKey(base64Key string) (err error) {
 
 
 	key, err := base64.StdEncoding.DecodeString(base64Key)
 	key, err := base64.StdEncoding.DecodeString(base64Key)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("import data repo key failed: %s", err)
+		logging.LogErrorf("import data repo key failed: %s", err)
 		return errors.New(Conf.Language(157))
 		return errors.New(Conf.Language(157))
 	}
 	}
 	if 32 != len(key) {
 	if 32 != len(key) {
@@ -142,14 +143,14 @@ func InitRepoKey() (err error) {
 	randomBytes = make([]byte, 16)
 	randomBytes = make([]byte, 16)
 	_, err = rand.Read(randomBytes)
 	_, err = rand.Read(randomBytes)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("init data repo key failed: %s", err)
+		logging.LogErrorf("init data repo key failed: %s", err)
 		return
 		return
 	}
 	}
 	salt := string(randomBytes)
 	salt := string(randomBytes)
 
 
 	key, err := encryption.KDF(password, salt)
 	key, err := encryption.KDF(password, salt)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("init data repo key failed: %s", err)
+		logging.LogErrorf("init data repo key failed: %s", err)
 		return
 		return
 	}
 	}
 	Conf.Repo.Key = key
 	Conf.Repo.Key = key
@@ -447,7 +448,7 @@ func syncRepo(boot, exit, byHand bool) {
 		planSyncAfter(fixSyncInterval)
 		planSyncAfter(fixSyncInterval)
 
 
 		msg := fmt.Sprintf("sync repo failed: %s", err)
 		msg := fmt.Sprintf("sync repo failed: %s", err)
-		util.LogErrorf(msg)
+		logging.LogErrorf(msg)
 		util.PushStatusBar(msg)
 		util.PushStatusBar(msg)
 		util.PushErrMsg(msg, 0)
 		util.PushErrMsg(msg, 0)
 		return
 		return
@@ -473,7 +474,7 @@ func syncRepo(boot, exit, byHand bool) {
 		syncDownloadErrCount++
 		syncDownloadErrCount++
 		planSyncAfter(fixSyncInterval)
 		planSyncAfter(fixSyncInterval)
 
 
-		util.LogErrorf("sync data repo failed: %s", err)
+		logging.LogErrorf("sync data repo failed: %s", err)
 		msg := fmt.Sprintf(Conf.Language(80), formatErrorMsg(err))
 		msg := fmt.Sprintf(Conf.Language(80), formatErrorMsg(err))
 		if errors.Is(err, dejavu.ErrCloudStorageSizeExceeded) {
 		if errors.Is(err, dejavu.ErrCloudStorageSizeExceeded) {
 			msg = fmt.Sprintf(Conf.Language(43), humanize.Bytes(uint64(Conf.User.UserSiYuanRepoSize)))
 			msg = fmt.Sprintf(Conf.Language(43), humanize.Bytes(uint64(Conf.User.UserSiYuanRepoSize)))
@@ -542,7 +543,7 @@ func indexRepoBeforeCloudSync(repo *dejavu.Repo) (err error) {
 		msg := fmt.Sprintf(Conf.Language(140), err)
 		msg := fmt.Sprintf(Conf.Language(140), err)
 		util.PushStatusBar(msg)
 		util.PushStatusBar(msg)
 		util.PushErrMsg(msg, 5000)
 		util.PushErrMsg(msg, 5000)
-		util.LogErrorf("index data repo before cloud sync failed: %s", err)
+		logging.LogErrorf("index data repo before cloud sync failed: %s", err)
 		return
 		return
 	}
 	}
 	elapsed := time.Since(start)
 	elapsed := time.Since(start)
@@ -552,7 +553,7 @@ func indexRepoBeforeCloudSync(repo *dejavu.Repo) (err error) {
 		index.Memo = fmt.Sprintf("[Sync] Cloud sync, completed in %.2fs", elapsed.Seconds())
 		index.Memo = fmt.Sprintf("[Sync] Cloud sync, completed in %.2fs", elapsed.Seconds())
 		if err = repo.PutIndex(index); nil != err {
 		if err = repo.PutIndex(index); nil != err {
 			util.PushStatusBar("Save data snapshot for cloud sync failed")
 			util.PushStatusBar("Save data snapshot for cloud sync failed")
-			util.LogErrorf("put index into data repo before cloud sync failed: %s", err)
+			logging.LogErrorf("put index into data repo before cloud sync failed: %s", err)
 			return
 			return
 		}
 		}
 		util.PushStatusBar(fmt.Sprintf(Conf.Language(147), elapsed.Seconds()))
 		util.PushStatusBar(fmt.Sprintf(Conf.Language(147), elapsed.Seconds()))
@@ -561,7 +562,7 @@ func indexRepoBeforeCloudSync(repo *dejavu.Repo) (err error) {
 	}
 	}
 
 
 	if 7000 < elapsed.Milliseconds() {
 	if 7000 < elapsed.Milliseconds() {
-		util.LogWarnf("index data repo before cloud sync elapsed [%dms]", elapsed.Milliseconds())
+		logging.LogWarnf("index data repo before cloud sync elapsed [%dms]", elapsed.Milliseconds())
 	}
 	}
 	return
 	return
 }
 }
@@ -571,7 +572,7 @@ func newRepository() (ret *dejavu.Repo, err error) {
 	ignoreLines = append(ignoreLines, "/.siyuan/conf.json") // 忽略旧版同步配置
 	ignoreLines = append(ignoreLines, "/.siyuan/conf.json") // 忽略旧版同步配置
 	ret, err = dejavu.NewRepo(util.DataDir, util.RepoDir, util.HistoryDir, util.TempDir, Conf.Repo.Key, ignoreLines)
 	ret, err = dejavu.NewRepo(util.DataDir, util.RepoDir, util.HistoryDir, util.TempDir, Conf.Repo.Key, ignoreLines)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("init data repo failed: %s", err)
+		logging.LogErrorf("init data repo failed: %s", err)
 	}
 	}
 	return
 	return
 }
 }
@@ -738,7 +739,7 @@ func contextPushMsg(context map[string]interface{}, msg string) {
 
 
 func buildCloudInfo() (ret *dejavu.CloudInfo, err error) {
 func buildCloudInfo() (ret *dejavu.CloudInfo, err error) {
 	if !IsValidCloudDirName(Conf.Sync.CloudName) {
 	if !IsValidCloudDirName(Conf.Sync.CloudName) {
-		util.LogWarnf("invalid cloud repo name, rename it to [main]")
+		logging.LogWarnf("invalid cloud repo name, rename it to [main]")
 		Conf.Sync.CloudName = "main"
 		Conf.Sync.CloudName = "main"
 		Conf.Save()
 		Conf.Save()
 	}
 	}
@@ -816,7 +817,7 @@ func getCloudSpaceOSS() (sync, backup map[string]interface{}, assetSize int64, e
 		Post(util.AliyunServer + "/apis/siyuan/dejavu/getRepoStat?uid=" + Conf.User.UserId)
 		Post(util.AliyunServer + "/apis/siyuan/dejavu/getRepoStat?uid=" + Conf.User.UserId)
 
 
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("get cloud space failed: %s", err)
+		logging.LogErrorf("get cloud space failed: %s", err)
 		err = ErrFailedToConnectCloudServer
 		err = ErrFailedToConnectCloudServer
 		return
 		return
 	}
 	}
@@ -828,7 +829,7 @@ func getCloudSpaceOSS() (sync, backup map[string]interface{}, assetSize int64, e
 
 
 	code := result["code"].(float64)
 	code := result["code"].(float64)
 	if 0 != code {
 	if 0 != code {
-		util.LogErrorf("get cloud space failed: %s", result["msg"])
+		logging.LogErrorf("get cloud space failed: %s", result["msg"])
 		err = errors.New(result["msg"].(string))
 		err = errors.New(result["msg"].(string))
 		return
 		return
 	}
 	}

+ 2 - 1
kernel/model/search.go

@@ -28,6 +28,7 @@ import (
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/parse"
 	"github.com/jinzhu/copier"
 	"github.com/jinzhu/copier"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/conf"
 	"github.com/siyuan-note/siyuan/kernel/conf"
 	"github.com/siyuan-note/siyuan/kernel/search"
 	"github.com/siyuan-note/siyuan/kernel/search"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
@@ -201,7 +202,7 @@ func FullTextSearchBlock(query, box, path string, types map[string]bool, querySy
 func searchFilter(types map[string]bool) string {
 func searchFilter(types map[string]bool) string {
 	s := conf.NewSearch()
 	s := conf.NewSearch()
 	if err := copier.Copy(s, Conf.Search); nil != err {
 	if err := copier.Copy(s, Conf.Search); nil != err {
-		util.LogErrorf("copy search conf failed: %s", err)
+		logging.LogErrorf("copy search conf failed: %s", err)
 	}
 	}
 	if nil != types {
 	if nil != types {
 		s.Document = types["document"]
 		s.Document = types["document"]

+ 8 - 7
kernel/model/session.go

@@ -23,6 +23,7 @@ import (
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	ginSessions "github.com/gin-contrib/sessions"
 	ginSessions "github.com/gin-contrib/sessions"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/steambap/captcha"
 	"github.com/steambap/captcha"
 )
 )
@@ -45,7 +46,7 @@ func LogoutAuth(c *gin.Context) {
 	})
 	})
 	session.Clear()
 	session.Clear()
 	if err := session.Save(); nil != err {
 	if err := session.Save(); nil != err {
-		util.LogErrorf("saves session failed: " + err.Error())
+		logging.LogErrorf("saves session failed: " + err.Error())
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = "save session failed"
 		ret.Msg = "save session failed"
 	}
 	}
@@ -90,7 +91,7 @@ func LoginAuth(c *gin.Context) {
 		}
 		}
 
 
 		if err := session.Save(c); nil != err {
 		if err := session.Save(c); nil != err {
-			util.LogErrorf("save session failed: " + err.Error())
+			logging.LogErrorf("save session failed: " + err.Error())
 			c.Status(500)
 			c.Status(500)
 			return
 			return
 		}
 		}
@@ -101,7 +102,7 @@ func LoginAuth(c *gin.Context) {
 	session.WrongAuthCount = 0
 	session.WrongAuthCount = 0
 	session.Captcha = gulu.Rand.String(7)
 	session.Captcha = gulu.Rand.String(7)
 	if err := session.Save(c); nil != err {
 	if err := session.Save(c); nil != err {
-		util.LogErrorf("save session failed: " + err.Error())
+		logging.LogErrorf("save session failed: " + err.Error())
 		c.Status(500)
 		c.Status(500)
 		return
 		return
 	}
 	}
@@ -114,7 +115,7 @@ func GetCaptcha(c *gin.Context) {
 		options.CurveNumber = 0
 		options.CurveNumber = 0
 	})
 	})
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("generates captcha failed: " + err.Error())
+		logging.LogErrorf("generates captcha failed: " + err.Error())
 		c.Status(500)
 		c.Status(500)
 		return
 		return
 	}
 	}
@@ -122,13 +123,13 @@ func GetCaptcha(c *gin.Context) {
 	session := util.GetSession(c)
 	session := util.GetSession(c)
 	session.Captcha = img.Text
 	session.Captcha = img.Text
 	if err = session.Save(c); nil != err {
 	if err = session.Save(c); nil != err {
-		util.LogErrorf("save session failed: " + err.Error())
+		logging.LogErrorf("save session failed: " + err.Error())
 		c.Status(500)
 		c.Status(500)
 		return
 		return
 	}
 	}
 
 
 	if err = img.WriteImage(c.Writer); nil != err {
 	if err = img.WriteImage(c.Writer); nil != err {
-		util.LogErrorf("writes captcha image failed: " + err.Error())
+		logging.LogErrorf("writes captcha image failed: " + err.Error())
 		c.Status(500)
 		c.Status(500)
 		return
 		return
 	}
 	}
@@ -148,7 +149,7 @@ func CheckReadonly(c *gin.Context) {
 }
 }
 
 
 func CheckAuth(c *gin.Context) {
 func CheckAuth(c *gin.Context) {
-	//util.LogInfof("check auth for [%s]", c.Request.RequestURI)
+	//logging.LogInfof("check auth for [%s]", c.Request.RequestURI)
 
 
 	// 放过 /appearance/
 	// 放过 /appearance/
 	if strings.HasPrefix(c.Request.RequestURI, "/appearance/") ||
 	if strings.HasPrefix(c.Request.RequestURI, "/appearance/") ||

+ 9 - 8
kernel/model/sync.go

@@ -30,6 +30,7 @@ import (
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/dustin/go-humanize"
 	"github.com/dustin/go-humanize"
 	"github.com/siyuan-note/dejavu"
 	"github.com/siyuan-note/dejavu"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
@@ -55,14 +56,14 @@ func AutoSync() {
 }
 }
 
 
 func SyncData(boot, exit, byHand bool) {
 func SyncData(boot, exit, byHand bool) {
-	defer util.Recover()
+	defer logging.Recover()
 
 
 	if !boot && !exit && 2 == Conf.Sync.Mode && !byHand {
 	if !boot && !exit && 2 == Conf.Sync.Mode && !byHand {
 		return
 		return
 	}
 	}
 
 
 	if util.IsMutexLocked(&syncLock) {
 	if util.IsMutexLocked(&syncLock) {
-		util.LogWarnf("sync is in progress")
+		logging.LogWarnf("sync is in progress")
 		planSyncAfter(30 * time.Second)
 		planSyncAfter(30 * time.Second)
 		return
 		return
 	}
 	}
@@ -90,15 +91,15 @@ func SyncData(boot, exit, byHand bool) {
 	}
 	}
 
 
 	if boot {
 	if boot {
-		util.LogInfof("sync before boot")
+		logging.LogInfof("sync before boot")
 	}
 	}
 	if exit {
 	if exit {
-		util.LogInfof("sync before exit")
+		logging.LogInfof("sync before exit")
 		util.PushMsg(Conf.Language(81), 1000*60*15)
 		util.PushMsg(Conf.Language(81), 1000*60*15)
 	}
 	}
 
 
 	if 7 < syncDownloadErrCount && !byHand {
 	if 7 < syncDownloadErrCount && !byHand {
-		util.LogErrorf("sync download error too many times, cancel auto sync, try to sync by hand")
+		logging.LogErrorf("sync download error too many times, cancel auto sync, try to sync by hand")
 		util.PushErrMsg(Conf.Language(125), 1000*60*60)
 		util.PushErrMsg(Conf.Language(125), 1000*60*60)
 		planSyncAfter(64 * time.Minute)
 		planSyncAfter(64 * time.Minute)
 		return
 		return
@@ -329,13 +330,13 @@ func getIgnoreLines() (ret []string) {
 	}
 	}
 	if !gulu.File.IsExist(ignore) {
 	if !gulu.File.IsExist(ignore) {
 		if err = gulu.File.WriteFileSafer(ignore, nil, 0644); nil != err {
 		if err = gulu.File.WriteFileSafer(ignore, nil, 0644); nil != err {
-			util.LogErrorf("create syncignore [%s] failed: %s", ignore, err)
+			logging.LogErrorf("create syncignore [%s] failed: %s", ignore, err)
 			return
 			return
 		}
 		}
 	}
 	}
 	data, err := os.ReadFile(ignore)
 	data, err := os.ReadFile(ignore)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read syncignore [%s] failed: %s", ignore, err)
+		logging.LogErrorf("read syncignore [%s] failed: %s", ignore, err)
 		return
 		return
 	}
 	}
 	dataStr := string(data)
 	dataStr := string(data)
@@ -383,7 +384,7 @@ func stableCopy(src, dest string) (err error) {
 			strings.Contains(err.Error(), "exit status 7") {
 			strings.Contains(err.Error(), "exit status 7") {
 			return nil
 			return nil
 		}
 		}
-		util.LogErrorf("robocopy data from [%s] to [%s] failed: %s %s", src, dest, string(output), err)
+		logging.LogErrorf("robocopy data from [%s] to [%s] failed: %s %s", src, dest, string(output), err)
 	}
 	}
 	return gulu.File.Copy(src, dest)
 	return gulu.File.Copy(src, dest)
 }
 }

+ 3 - 2
kernel/model/template.go

@@ -33,6 +33,7 @@ import (
 	"github.com/88250/lute/render"
 	"github.com/88250/lute/render"
 	"github.com/88250/protyle"
 	"github.com/88250/protyle"
 	"github.com/araddon/dateparse"
 	"github.com/araddon/dateparse"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 
 
@@ -167,7 +168,7 @@ func renderTemplate(p, id string) (string, error) {
 		now := time.Now()
 		now := time.Now()
 		ret, err := dateparse.ParseIn(dateStr, now.Location())
 		ret, err := dateparse.ParseIn(dateStr, now.Location())
 		if nil != err {
 		if nil != err {
-			util.LogWarnf("parse date [%s] failed [%s], return current time instead", dateStr, err)
+			logging.LogWarnf("parse date [%s] failed [%s], return current time instead", dateStr, err)
 			return now
 			return now
 		}
 		}
 		return ret
 		return ret
@@ -188,7 +189,7 @@ func renderTemplate(p, id string) (string, error) {
 	tree = parseKTree(md)
 	tree = parseKTree(md)
 	if nil == tree {
 	if nil == tree {
 		msg := fmt.Sprintf("parse tree [%s] failed", p)
 		msg := fmt.Sprintf("parse tree [%s] failed", p)
-		util.LogErrorf(msg)
+		logging.LogErrorf(msg)
 		return "", errors.New(msg)
 		return "", errors.New(msg)
 	}
 	}
 
 

+ 42 - 41
kernel/model/transaction.go

@@ -33,6 +33,7 @@ import (
 	util2 "github.com/88250/lute/util"
 	util2 "github.com/88250/lute/util"
 	"github.com/emirpasic/gods/sets/hashset"
 	"github.com/emirpasic/gods/sets/hashset"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/cache"
 	"github.com/siyuan-note/siyuan/kernel/cache"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
@@ -88,11 +89,11 @@ func WaitForWritingFiles() {
 	for i := 0; isWritingFiles(); i++ {
 	for i := 0; isWritingFiles(); i++ {
 		time.Sleep(5 * time.Millisecond)
 		time.Sleep(5 * time.Millisecond)
 		if 2000 < i && !printLog { // 10s 后打日志
 		if 2000 < i && !printLog { // 10s 后打日志
-			util.LogWarnf("file is writing: \n%s", util.ShortStack())
+			logging.LogWarnf("file is writing: \n%s", logging.ShortStack())
 			printLog = true
 			printLog = true
 		}
 		}
 		if 12000 < i && !lastPrintLog { // 60s 后打日志
 		if 12000 < i && !lastPrintLog { // 60s 后打日志
-			util.LogWarnf("file is still writing")
+			logging.LogWarnf("file is still writing")
 			lastPrintLog = true
 			lastPrintLog = true
 		}
 		}
 	}
 	}
@@ -116,7 +117,7 @@ func AutoFlushTx() {
 func flushTx() {
 func flushTx() {
 	writingDataLock.Lock()
 	writingDataLock.Lock()
 	defer writingDataLock.Unlock()
 	defer writingDataLock.Unlock()
-	defer util.Recover()
+	defer logging.Recover()
 
 
 	currentTx = mergeTx()
 	currentTx = mergeTx()
 	start := time.Now()
 	start := time.Now()
@@ -129,13 +130,13 @@ func flushTx() {
 			util.PushTxErr(Conf.Language(76), txErr.code, txErr.id)
 			util.PushTxErr(Conf.Language(76), txErr.code, txErr.id)
 			return
 			return
 		default:
 		default:
-			util.LogFatalf("transaction failed: %s", txErr.msg)
+			logging.LogFatalf("transaction failed: %s", txErr.msg)
 		}
 		}
 	}
 	}
 	elapsed := time.Now().Sub(start).Milliseconds()
 	elapsed := time.Now().Sub(start).Milliseconds()
 	if 0 < len(currentTx.DoOperations) {
 	if 0 < len(currentTx.DoOperations) {
 		if 2000 < elapsed {
 		if 2000 < elapsed {
-			util.LogWarnf("tx [%dms]", elapsed)
+			logging.LogWarnf("tx [%dms]", elapsed)
 		}
 		}
 	}
 	}
 	currentTx = nil
 	currentTx = nil
@@ -214,7 +215,7 @@ func performTx(tx *Transaction) (ret *TxErr) {
 		if strings.Contains(err.Error(), "database is closed") {
 		if strings.Contains(err.Error(), "database is closed") {
 			return
 			return
 		}
 		}
-		util.LogErrorf("begin tx failed: %s", err)
+		logging.LogErrorf("begin tx failed: %s", err)
 		ret = &TxErr{msg: err.Error()}
 		ret = &TxErr{msg: err.Error()}
 		return
 		return
 	}
 	}
@@ -225,7 +226,7 @@ func performTx(tx *Transaction) (ret *TxErr) {
 			return
 			return
 		}
 		}
 		if cr := tx.commit(); nil != cr {
 		if cr := tx.commit(); nil != cr {
-			util.LogErrorf("commit tx failed: %s", cr)
+			logging.LogErrorf("commit tx failed: %s", cr)
 			return &TxErr{msg: cr.Error()}
 			return &TxErr{msg: cr.Error()}
 		}
 		}
 		return
 		return
@@ -263,7 +264,7 @@ func performTx(tx *Transaction) (ret *TxErr) {
 	}
 	}
 
 
 	if cr := tx.commit(); nil != cr {
 	if cr := tx.commit(); nil != cr {
-		util.LogErrorf("commit tx failed: %s", cr)
+		logging.LogErrorf("commit tx failed: %s", cr)
 		return &TxErr{msg: cr.Error()}
 		return &TxErr{msg: cr.Error()}
 	}
 	}
 	elapsed := int(time.Now().Sub(start).Milliseconds())
 	elapsed := int(time.Now().Sub(start).Milliseconds())
@@ -279,13 +280,13 @@ func (tx *Transaction) doMove(operation *Operation) (ret *TxErr) {
 	id := operation.ID
 	id := operation.ID
 	srcTree, err := tx.loadTree(id)
 	srcTree, err := tx.loadTree(id)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("load tree [id=%s] failed: %s", id, err)
+		logging.LogErrorf("load tree [id=%s] failed: %s", id, err)
 		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
 	}
 	}
 
 
 	srcNode := treenode.GetNodeInTree(srcTree, id)
 	srcNode := treenode.GetNodeInTree(srcTree, id)
 	if nil == srcNode {
 	if nil == srcNode {
-		util.LogErrorf("get node [%s] in tree [%s] failed", id, srcTree.Root.ID)
+		logging.LogErrorf("get node [%s] in tree [%s] failed", id, srcTree.Root.ID)
 		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
 	}
 	}
 
 
@@ -309,7 +310,7 @@ func (tx *Transaction) doMove(operation *Operation) (ret *TxErr) {
 		var targetTree *parse.Tree
 		var targetTree *parse.Tree
 		targetTree, err = tx.loadTree(targetPreviousID)
 		targetTree, err = tx.loadTree(targetPreviousID)
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("load tree [id=%s] failed: %s", targetPreviousID, err)
+			logging.LogErrorf("load tree [id=%s] failed: %s", targetPreviousID, err)
 			return &TxErr{code: TxErrCodeBlockNotFound, id: targetPreviousID}
 			return &TxErr{code: TxErrCodeBlockNotFound, id: targetPreviousID}
 		}
 		}
 		isSameTree := srcTree.ID == targetTree.ID
 		isSameTree := srcTree.ID == targetTree.ID
@@ -319,7 +320,7 @@ func (tx *Transaction) doMove(operation *Operation) (ret *TxErr) {
 
 
 		targetNode := treenode.GetNodeInTree(targetTree, targetPreviousID)
 		targetNode := treenode.GetNodeInTree(targetTree, targetPreviousID)
 		if nil == targetNode {
 		if nil == targetNode {
-			util.LogErrorf("get node [%s] in tree [%s] failed", targetPreviousID, targetTree.Root.ID)
+			logging.LogErrorf("get node [%s] in tree [%s] failed", targetPreviousID, targetTree.Root.ID)
 			return &TxErr{code: TxErrCodeBlockNotFound, id: targetPreviousID}
 			return &TxErr{code: TxErrCodeBlockNotFound, id: targetPreviousID}
 		}
 		}
 
 
@@ -357,7 +358,7 @@ func (tx *Transaction) doMove(operation *Operation) (ret *TxErr) {
 
 
 	targetTree, err := tx.loadTree(targetParentID)
 	targetTree, err := tx.loadTree(targetParentID)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("load tree [id=%s] failed: %s", targetParentID, err)
+		logging.LogErrorf("load tree [id=%s] failed: %s", targetParentID, err)
 		return &TxErr{code: TxErrCodeBlockNotFound, id: targetParentID}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: targetParentID}
 	}
 	}
 	isSameTree := srcTree.ID == targetTree.ID
 	isSameTree := srcTree.ID == targetTree.ID
@@ -367,7 +368,7 @@ func (tx *Transaction) doMove(operation *Operation) (ret *TxErr) {
 
 
 	targetNode := treenode.GetNodeInTree(targetTree, targetParentID)
 	targetNode := treenode.GetNodeInTree(targetTree, targetParentID)
 	if nil == targetNode {
 	if nil == targetNode {
-		util.LogErrorf("get node [%s] in tree [%s] failed", targetParentID, targetTree.Root.ID)
+		logging.LogErrorf("get node [%s] in tree [%s] failed", targetParentID, targetTree.Root.ID)
 		return &TxErr{code: TxErrCodeBlockNotFound, id: targetParentID}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: targetParentID}
 	}
 	}
 
 
@@ -430,7 +431,7 @@ func (tx *Transaction) doPrependInsert(operation *Operation) (ret *TxErr) {
 	block := treenode.GetBlockTree(operation.ParentID)
 	block := treenode.GetBlockTree(operation.ParentID)
 	if nil == block {
 	if nil == block {
 		msg := fmt.Sprintf("not found parent block [id=%s]", operation.ParentID)
 		msg := fmt.Sprintf("not found parent block [id=%s]", operation.ParentID)
-		util.LogErrorf(msg)
+		logging.LogErrorf(msg)
 		return &TxErr{code: TxErrCodeBlockNotFound, id: operation.ParentID}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: operation.ParentID}
 	}
 	}
 	tree, err := tx.loadTree(block.ID)
 	tree, err := tx.loadTree(block.ID)
@@ -439,7 +440,7 @@ func (tx *Transaction) doPrependInsert(operation *Operation) (ret *TxErr) {
 	}
 	}
 	if nil != err {
 	if nil != err {
 		msg := fmt.Sprintf("load tree [id=%s] failed: %s", block.ID, err)
 		msg := fmt.Sprintf("load tree [id=%s] failed: %s", block.ID, err)
-		util.LogErrorf(msg)
+		logging.LogErrorf(msg)
 		return &TxErr{code: TxErrCodeBlockNotFound, id: block.ID}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: block.ID}
 	}
 	}
 
 
@@ -467,7 +468,7 @@ func (tx *Transaction) doPrependInsert(operation *Operation) (ret *TxErr) {
 
 
 	node := treenode.GetNodeInTree(tree, operation.ParentID)
 	node := treenode.GetNodeInTree(tree, operation.ParentID)
 	if nil == node {
 	if nil == node {
-		util.LogErrorf("get node [%s] in tree [%s] failed", operation.ParentID, tree.Root.ID)
+		logging.LogErrorf("get node [%s] in tree [%s] failed", operation.ParentID, tree.Root.ID)
 		return &TxErr{code: TxErrCodeBlockNotFound, id: operation.ParentID}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: operation.ParentID}
 	}
 	}
 	isContainer := node.IsContainerBlock()
 	isContainer := node.IsContainerBlock()
@@ -518,7 +519,7 @@ func (tx *Transaction) doAppendInsert(operation *Operation) (ret *TxErr) {
 	block := treenode.GetBlockTree(operation.ParentID)
 	block := treenode.GetBlockTree(operation.ParentID)
 	if nil == block {
 	if nil == block {
 		msg := fmt.Sprintf("not found parent block [id=%s]", operation.ParentID)
 		msg := fmt.Sprintf("not found parent block [id=%s]", operation.ParentID)
-		util.LogErrorf(msg)
+		logging.LogErrorf(msg)
 		return &TxErr{code: TxErrCodeBlockNotFound, id: operation.ParentID}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: operation.ParentID}
 	}
 	}
 	tree, err := tx.loadTree(block.ID)
 	tree, err := tx.loadTree(block.ID)
@@ -527,7 +528,7 @@ func (tx *Transaction) doAppendInsert(operation *Operation) (ret *TxErr) {
 	}
 	}
 	if nil != err {
 	if nil != err {
 		msg := fmt.Sprintf("load tree [id=%s] failed: %s", block.ID, err)
 		msg := fmt.Sprintf("load tree [id=%s] failed: %s", block.ID, err)
-		util.LogErrorf(msg)
+		logging.LogErrorf(msg)
 		return &TxErr{code: TxErrCodeBlockNotFound, id: block.ID}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: block.ID}
 	}
 	}
 
 
@@ -555,7 +556,7 @@ func (tx *Transaction) doAppendInsert(operation *Operation) (ret *TxErr) {
 
 
 	node := treenode.GetNodeInTree(tree, operation.ParentID)
 	node := treenode.GetNodeInTree(tree, operation.ParentID)
 	if nil == node {
 	if nil == node {
-		util.LogErrorf("get node [%s] in tree [%s] failed", operation.ParentID, tree.Root.ID)
+		logging.LogErrorf("get node [%s] in tree [%s] failed", operation.ParentID, tree.Root.ID)
 		return &TxErr{code: TxErrCodeBlockNotFound, id: operation.ParentID}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: operation.ParentID}
 	}
 	}
 	isContainer := node.IsContainerBlock()
 	isContainer := node.IsContainerBlock()
@@ -594,18 +595,18 @@ func (tx *Transaction) doAppend(operation *Operation) (ret *TxErr) {
 	id := operation.ID
 	id := operation.ID
 	srcTree, err := tx.loadTree(id)
 	srcTree, err := tx.loadTree(id)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("load tree [id=%s] failed: %s", id, err)
+		logging.LogErrorf("load tree [id=%s] failed: %s", id, err)
 		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
 	}
 	}
 
 
 	srcNode := treenode.GetNodeInTree(srcTree, id)
 	srcNode := treenode.GetNodeInTree(srcTree, id)
 	if nil == srcNode {
 	if nil == srcNode {
-		util.LogErrorf("get node [%s] in tree [%s] failed", id, srcTree.Root.ID)
+		logging.LogErrorf("get node [%s] in tree [%s] failed", id, srcTree.Root.ID)
 		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
 	}
 	}
 
 
 	if ast.NodeDocument == srcNode.Type {
 	if ast.NodeDocument == srcNode.Type {
-		util.LogWarnf("can't append a root to another root")
+		logging.LogWarnf("can't append a root to another root")
 		return
 		return
 	}
 	}
 
 
@@ -626,13 +627,13 @@ func (tx *Transaction) doAppend(operation *Operation) (ret *TxErr) {
 
 
 	targetRootID := operation.ParentID
 	targetRootID := operation.ParentID
 	if id == targetRootID {
 	if id == targetRootID {
-		util.LogWarnf("target root id is nil")
+		logging.LogWarnf("target root id is nil")
 		return
 		return
 	}
 	}
 
 
 	targetTree, err := tx.loadTree(targetRootID)
 	targetTree, err := tx.loadTree(targetRootID)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("load tree [id=%s] failed: %s", targetRootID, err)
+		logging.LogErrorf("load tree [id=%s] failed: %s", targetRootID, err)
 		return &TxErr{code: TxErrCodeBlockNotFound, id: targetRootID}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: targetRootID}
 	}
 	}
 	isSameTree := srcTree.ID == targetTree.ID
 	isSameTree := srcTree.ID == targetTree.ID
@@ -717,7 +718,7 @@ func (tx *Transaction) doLargeInsert() (ret *TxErr) {
 		parentID := operations[0].ParentID
 		parentID := operations[0].ParentID
 		parentBlock = treenode.GetBlockTree(parentID)
 		parentBlock = treenode.GetBlockTree(parentID)
 		if nil == parentBlock {
 		if nil == parentBlock {
-			util.LogErrorf("not found previous block [id=%s]", parentID)
+			logging.LogErrorf("not found previous block [id=%s]", parentID)
 			return &TxErr{code: TxErrCodeBlockNotFound, id: parentID}
 			return &TxErr{code: TxErrCodeBlockNotFound, id: parentID}
 		}
 		}
 	}
 	}
@@ -727,7 +728,7 @@ func (tx *Transaction) doLargeInsert() (ret *TxErr) {
 		return &TxErr{code: TxErrCodeUnableLockFile, msg: err.Error(), id: id}
 		return &TxErr{code: TxErrCodeUnableLockFile, msg: err.Error(), id: id}
 	}
 	}
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("load tree [id=%s] failed: %s", id, err)
+		logging.LogErrorf("load tree [id=%s] failed: %s", id, err)
 		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
 	}
 	}
 
 
@@ -751,7 +752,7 @@ func (tx *Transaction) doLargeInsert() (ret *TxErr) {
 
 
 		node := treenode.GetNodeInTree(tree, previousID)
 		node := treenode.GetNodeInTree(tree, previousID)
 		if nil == node {
 		if nil == node {
-			util.LogErrorf("get node [%s] in tree [%s] failed", previousID, tree.Root.ID)
+			logging.LogErrorf("get node [%s] in tree [%s] failed", previousID, tree.Root.ID)
 			return &TxErr{code: TxErrCodeBlockNotFound, id: previousID}
 			return &TxErr{code: TxErrCodeBlockNotFound, id: previousID}
 		}
 		}
 		if ast.NodeList == insertedNode.Type && nil != node.Parent && ast.NodeList == node.Parent.Type {
 		if ast.NodeList == insertedNode.Type && nil != node.Parent && ast.NodeList == node.Parent.Type {
@@ -765,7 +766,7 @@ func (tx *Transaction) doLargeInsert() (ret *TxErr) {
 	if "delete" == operations[length-1].Action {
 	if "delete" == operations[length-1].Action {
 		node := treenode.GetNodeInTree(tree, previousID)
 		node := treenode.GetNodeInTree(tree, previousID)
 		if nil == node {
 		if nil == node {
-			util.LogErrorf("get node [%s] in tree [%s] failed", previousID, tree.Root.ID)
+			logging.LogErrorf("get node [%s] in tree [%s] failed", previousID, tree.Root.ID)
 			return &TxErr{code: TxErrCodeBlockNotFound, id: previousID}
 			return &TxErr{code: TxErrCodeBlockNotFound, id: previousID}
 		}
 		}
 		node.Unlink()
 		node.Unlink()
@@ -779,7 +780,7 @@ func (tx *Transaction) doLargeInsert() (ret *TxErr) {
 }
 }
 
 
 func (tx *Transaction) doDelete(operation *Operation) (ret *TxErr) {
 func (tx *Transaction) doDelete(operation *Operation) (ret *TxErr) {
-	//	util.LogInfof("commit delete [%+v]", operation)
+	//	logging.LogInfof("commit delete [%+v]", operation)
 
 
 	var err error
 	var err error
 	id := operation.ID
 	id := operation.ID
@@ -793,7 +794,7 @@ func (tx *Transaction) doDelete(operation *Operation) (ret *TxErr) {
 
 
 	if nil != err {
 	if nil != err {
 		msg := fmt.Sprintf("load tree [id=%s] failed: %s", id, err)
 		msg := fmt.Sprintf("load tree [id=%s] failed: %s", id, err)
-		util.LogErrorf(msg)
+		logging.LogErrorf(msg)
 		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
 	}
 	}
 
 
@@ -830,7 +831,7 @@ func (tx *Transaction) doInsert(operation *Operation) (ret *TxErr) {
 		block = treenode.GetBlockTree(operation.PreviousID)
 		block = treenode.GetBlockTree(operation.PreviousID)
 		if nil == block {
 		if nil == block {
 			msg := fmt.Sprintf("not found previous block [id=%s]", operation.PreviousID)
 			msg := fmt.Sprintf("not found previous block [id=%s]", operation.PreviousID)
-			util.LogErrorf(msg)
+			logging.LogErrorf(msg)
 			return &TxErr{code: TxErrCodeBlockNotFound, id: operation.PreviousID}
 			return &TxErr{code: TxErrCodeBlockNotFound, id: operation.PreviousID}
 		}
 		}
 	}
 	}
@@ -840,7 +841,7 @@ func (tx *Transaction) doInsert(operation *Operation) (ret *TxErr) {
 	}
 	}
 	if nil != err {
 	if nil != err {
 		msg := fmt.Sprintf("load tree [id=%s] failed: %s", block.ID, err)
 		msg := fmt.Sprintf("load tree [id=%s] failed: %s", block.ID, err)
-		util.LogErrorf(msg)
+		logging.LogErrorf(msg)
 		return &TxErr{code: TxErrCodeBlockNotFound, id: block.ID}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: block.ID}
 	}
 	}
 
 
@@ -862,7 +863,7 @@ func (tx *Transaction) doInsert(operation *Operation) (ret *TxErr) {
 				assetP := gulu.Str.FromBytes(n.Tokens)
 				assetP := gulu.Str.FromBytes(n.Tokens)
 				assetPath, e := GetAssetAbsPath(assetP)
 				assetPath, e := GetAssetAbsPath(assetP)
 				if nil != e {
 				if nil != e {
-					util.LogErrorf("get path of asset [%s] failed: %s", assetP, err)
+					logging.LogErrorf("get path of asset [%s] failed: %s", assetP, err)
 					return ast.WalkContinue
 					return ast.WalkContinue
 				}
 				}
 
 
@@ -874,7 +875,7 @@ func (tx *Transaction) doInsert(operation *Operation) (ret *TxErr) {
 				// 只有全局 assets 才移动到相对 assets
 				// 只有全局 assets 才移动到相对 assets
 				targetP := filepath.Join(assets, filepath.Base(assetPath))
 				targetP := filepath.Join(assets, filepath.Base(assetPath))
 				if e = os.Rename(assetPath, targetP); nil != err {
 				if e = os.Rename(assetPath, targetP); nil != err {
-					util.LogErrorf("copy path of asset from [%s] to [%s] failed: %s", assetPath, targetP, err)
+					logging.LogErrorf("copy path of asset from [%s] to [%s] failed: %s", assetPath, targetP, err)
 					return ast.WalkContinue
 					return ast.WalkContinue
 				}
 				}
 			}
 			}
@@ -905,7 +906,7 @@ func (tx *Transaction) doInsert(operation *Operation) (ret *TxErr) {
 	if "" != previousID {
 	if "" != previousID {
 		node = treenode.GetNodeInTree(tree, previousID)
 		node = treenode.GetNodeInTree(tree, previousID)
 		if nil == node {
 		if nil == node {
-			util.LogErrorf("get node [%s] in tree [%s] failed", previousID, tree.Root.ID)
+			logging.LogErrorf("get node [%s] in tree [%s] failed", previousID, tree.Root.ID)
 			return &TxErr{code: TxErrCodeBlockNotFound, id: previousID}
 			return &TxErr{code: TxErrCodeBlockNotFound, id: previousID}
 		}
 		}
 
 
@@ -926,7 +927,7 @@ func (tx *Transaction) doInsert(operation *Operation) (ret *TxErr) {
 	} else {
 	} else {
 		node = treenode.GetNodeInTree(tree, operation.ParentID)
 		node = treenode.GetNodeInTree(tree, operation.ParentID)
 		if nil == node {
 		if nil == node {
-			util.LogErrorf("get node [%s] in tree [%s] failed", operation.ParentID, tree.Root.ID)
+			logging.LogErrorf("get node [%s] in tree [%s] failed", operation.ParentID, tree.Root.ID)
 			return &TxErr{code: TxErrCodeBlockNotFound, id: operation.ParentID}
 			return &TxErr{code: TxErrCodeBlockNotFound, id: operation.ParentID}
 		}
 		}
 		if ast.NodeSuperBlock == node.Type {
 		if ast.NodeSuperBlock == node.Type {
@@ -973,13 +974,13 @@ func (tx *Transaction) doUpdate(operation *Operation) (ret *TxErr) {
 		return &TxErr{code: TxErrCodeUnableLockFile, msg: err.Error(), id: id}
 		return &TxErr{code: TxErrCodeUnableLockFile, msg: err.Error(), id: id}
 	}
 	}
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("load tree [id=%s] failed: %s", id, err)
+		logging.LogErrorf("load tree [id=%s] failed: %s", id, err)
 		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
 	}
 	}
 
 
 	data := strings.ReplaceAll(operation.Data.(string), util2.FrontEndCaret, "")
 	data := strings.ReplaceAll(operation.Data.(string), util2.FrontEndCaret, "")
 	if "" == data {
 	if "" == data {
-		util.LogErrorf("update data is nil")
+		logging.LogErrorf("update data is nil")
 		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
 		return &TxErr{code: TxErrCodeBlockNotFound, id: id}
 	}
 	}
 
 
@@ -988,7 +989,7 @@ func (tx *Transaction) doUpdate(operation *Operation) (ret *TxErr) {
 	subTree.ID, subTree.Box, subTree.Path = tree.ID, tree.Box, tree.Path
 	subTree.ID, subTree.Box, subTree.Path = tree.ID, tree.Box, tree.Path
 	oldNode := treenode.GetNodeInTree(tree, id)
 	oldNode := treenode.GetNodeInTree(tree, id)
 	if nil == oldNode {
 	if nil == oldNode {
-		util.LogErrorf("get node [%s] in tree [%s] failed", id, tree.Root.ID)
+		logging.LogErrorf("get node [%s] in tree [%s] failed", id, tree.Root.ID)
 		return &TxErr{msg: ErrBlockNotFound.Error(), id: id}
 		return &TxErr{msg: ErrBlockNotFound.Error(), id: id}
 	}
 	}
 
 
@@ -1016,7 +1017,7 @@ func (tx *Transaction) doUpdate(operation *Operation) (ret *TxErr) {
 
 
 	updatedNode := subTree.Root.FirstChild
 	updatedNode := subTree.Root.FirstChild
 	if nil == updatedNode {
 	if nil == updatedNode {
-		util.LogErrorf("get fist node in sub tree [%s] failed", subTree.Root.ID)
+		logging.LogErrorf("get fist node in sub tree [%s] failed", subTree.Root.ID)
 		return &TxErr{msg: ErrBlockNotFound.Error(), id: id}
 		return &TxErr{msg: ErrBlockNotFound.Error(), id: id}
 	}
 	}
 	if ast.NodeList == updatedNode.Type && ast.NodeList == oldNode.Parent.Type {
 	if ast.NodeList == updatedNode.Type && ast.NodeList == oldNode.Parent.Type {

+ 4 - 4
kernel/model/tree.go

@@ -26,9 +26,9 @@ import (
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/parse"
 	"github.com/88250/protyle"
 	"github.com/88250/protyle"
 	"github.com/siyuan-note/filelock"
 	"github.com/siyuan-note/filelock"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/filesys"
 	"github.com/siyuan-note/siyuan/kernel/filesys"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
-	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
 
 
 func pagedPaths(localPath string, pageSize int) (ret map[int][]string) {
 func pagedPaths(localPath string, pageSize int) (ret map[int][]string) {
@@ -55,13 +55,13 @@ func pagedPaths(localPath string, pageSize int) (ret map[int][]string) {
 func loadTree(localPath string, luteEngine *lute.Lute) (ret *parse.Tree, err error) {
 func loadTree(localPath string, luteEngine *lute.Lute) (ret *parse.Tree, err error) {
 	data, err := filelock.NoLockFileRead(localPath)
 	data, err := filelock.NoLockFileRead(localPath)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("get data [path=%s] failed: %s", localPath, err)
+		logging.LogErrorf("get data [path=%s] failed: %s", localPath, err)
 		return
 		return
 	}
 	}
 
 
 	ret, err = protyle.ParseJSONWithoutFix(luteEngine, data)
 	ret, err = protyle.ParseJSONWithoutFix(luteEngine, data)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("parse json to tree [%s] failed: %s", localPath, err)
+		logging.LogErrorf("parse json to tree [%s] failed: %s", localPath, err)
 		return
 		return
 	}
 	}
 	return
 	return
@@ -91,7 +91,7 @@ func LoadTree(boxID, p string) (*parse.Tree, error) {
 	luteEngine := NewLute()
 	luteEngine := NewLute()
 	tree, err := filesys.LoadTree(boxID, p, luteEngine)
 	tree, err := filesys.LoadTree(boxID, p, luteEngine)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("load tree [%s] failed: %s", boxID+p, err)
+		logging.LogErrorf("load tree [%s] failed: %s", boxID+p, err)
 		return nil, err
 		return nil, err
 	}
 	}
 	return tree, nil
 	return tree, nil

+ 2 - 1
kernel/model/updater.go

@@ -20,6 +20,7 @@ import (
 	"fmt"
 	"fmt"
 	"sync"
 	"sync"
 
 
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
 
 
@@ -36,7 +37,7 @@ type Announcement struct {
 func GetAnnouncements() (ret []*Announcement) {
 func GetAnnouncements() (ret []*Announcement) {
 	result, err := util.GetRhyResult(false)
 	result, err := util.GetRhyResult(false)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("get ")
+		logging.LogErrorf("get announcement failed: %s", err)
 		return
 		return
 	}
 	}
 
 

+ 2 - 1
kernel/model/upload.go

@@ -27,6 +27,7 @@ import (
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/ast"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/sql"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
@@ -102,7 +103,7 @@ func Upload(c *gin.Context) {
 
 
 	form, err := c.MultipartForm()
 	form, err := c.MultipartForm()
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("insert asset failed: %s", err)
+		logging.LogErrorf("insert asset failed: %s", err)
 		ret.Code = -1
 		ret.Code = -1
 		ret.Msg = err.Error()
 		ret.Msg = err.Error()
 		return
 		return

+ 2 - 1
kernel/model/widget.go

@@ -21,6 +21,7 @@ import (
 	"path/filepath"
 	"path/filepath"
 	"strings"
 	"strings"
 
 
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 
 
 	"github.com/siyuan-note/siyuan/kernel/search"
 	"github.com/siyuan-note/siyuan/kernel/search"
@@ -31,7 +32,7 @@ func SearchWidget(keyword string) (ret []*Block) {
 	widgets := filepath.Join(util.DataDir, "widgets")
 	widgets := filepath.Join(util.DataDir, "widgets")
 	dirs, err := os.ReadDir(widgets)
 	dirs, err := os.ReadDir(widgets)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read dir [%s] failed: %s", widgets, err)
+		logging.LogErrorf("read dir [%s] failed: %s", widgets, err)
 		return
 		return
 	}
 	}
 
 

+ 17 - 16
kernel/server/serve.go

@@ -33,6 +33,7 @@ import (
 	"github.com/gin-contrib/sessions/cookie"
 	"github.com/gin-contrib/sessions/cookie"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
 	"github.com/mssola/user_agent"
 	"github.com/mssola/user_agent"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/api"
 	"github.com/siyuan-note/siyuan/kernel/api"
 	"github.com/siyuan-note/siyuan/kernel/cmd"
 	"github.com/siyuan-note/siyuan/kernel/cmd"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/model"
@@ -75,11 +76,11 @@ func Serve(fastMode bool) {
 	} else {
 	} else {
 		addr = "127.0.0.1:" + util.ServerPort
 		addr = "127.0.0.1:" + util.ServerPort
 	}
 	}
-	util.LogInfof("kernel is booting [%s]", "http://"+addr)
+	logging.LogInfof("kernel is booting [%s]", "http://"+addr)
 	util.HttpServing = true
 	util.HttpServing = true
 	if err := ginServer.Run(addr); nil != err {
 	if err := ginServer.Run(addr); nil != err {
 		if !fastMode {
 		if !fastMode {
-			util.LogErrorf("boot kernel failed: %s", err)
+			logging.LogErrorf("boot kernel failed: %s", err)
 			os.Exit(util.ExitCodeUnavailablePort)
 			os.Exit(util.ExitCodeUnavailablePort)
 		}
 		}
 	}
 	}
@@ -137,12 +138,12 @@ func serveAppearance(ginServer *gin.Engine) {
 				enUSFilePath := filepath.Join(appearancePath, "langs", "en_US.json")
 				enUSFilePath := filepath.Join(appearancePath, "langs", "en_US.json")
 				enUSData, err := os.ReadFile(enUSFilePath)
 				enUSData, err := os.ReadFile(enUSFilePath)
 				if nil != err {
 				if nil != err {
-					util.LogFatalf("read en_US.json [%s] failed: %s", enUSFilePath, err)
+					logging.LogFatalf("read en_US.json [%s] failed: %s", enUSFilePath, err)
 					return
 					return
 				}
 				}
 				enUSMap := map[string]interface{}{}
 				enUSMap := map[string]interface{}{}
 				if err = gulu.JSON.UnmarshalJSON(enUSData, &enUSMap); nil != err {
 				if err = gulu.JSON.UnmarshalJSON(enUSData, &enUSMap); nil != err {
-					util.LogFatalf("unmarshal en_US.json [%s] failed: %s", enUSFilePath, err)
+					logging.LogFatalf("unmarshal en_US.json [%s] failed: %s", enUSFilePath, err)
 					return
 					return
 				}
 				}
 
 
@@ -155,7 +156,7 @@ func serveAppearance(ginServer *gin.Engine) {
 
 
 					langMap := map[string]interface{}{}
 					langMap := map[string]interface{}{}
 					if err = gulu.JSON.UnmarshalJSON(data, &langMap); nil != err {
 					if err = gulu.JSON.UnmarshalJSON(data, &langMap); nil != err {
-						util.LogErrorf("unmarshal json [%s] failed: %s", filePath, err)
+						logging.LogErrorf("unmarshal json [%s] failed: %s", filePath, err)
 						c.JSON(200, enUSMap)
 						c.JSON(200, enUSMap)
 						return
 						return
 					}
 					}
@@ -183,7 +184,7 @@ func serveAppearance(ginServer *gin.Engine) {
 func serveCheckAuth(c *gin.Context) {
 func serveCheckAuth(c *gin.Context) {
 	data, err := os.ReadFile(filepath.Join(util.WorkingDir, "stage/auth.html"))
 	data, err := os.ReadFile(filepath.Join(util.WorkingDir, "stage/auth.html"))
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("load auth page failed: %s", err)
+		logging.LogErrorf("load auth page failed: %s", err)
 		c.Status(500)
 		c.Status(500)
 		return
 		return
 	}
 	}
@@ -237,7 +238,7 @@ func serveWebSocket(ginServer *gin.Engine) {
 
 
 	ginServer.GET("/ws", func(c *gin.Context) {
 	ginServer.GET("/ws", func(c *gin.Context) {
 		if err := util.WebSocketServer.HandleRequest(c.Writer, c.Request); nil != err {
 		if err := util.WebSocketServer.HandleRequest(c.Writer, c.Request); nil != err {
-			util.LogErrorf("handle command failed: %s", err)
+			logging.LogErrorf("handle command failed: %s", err)
 		}
 		}
 	})
 	})
 
 
@@ -246,14 +247,14 @@ func serveWebSocket(ginServer *gin.Engine) {
 	})
 	})
 
 
 	util.WebSocketServer.HandleConnect(func(s *melody.Session) {
 	util.WebSocketServer.HandleConnect(func(s *melody.Session) {
-		//util.LogInfof("ws check auth for [%s]", s.Request.RequestURI)
+		//logging.LogInfof("ws check auth for [%s]", s.Request.RequestURI)
 		authOk := true
 		authOk := true
 
 
 		if "" != model.Conf.AccessAuthCode {
 		if "" != model.Conf.AccessAuthCode {
 			session, err := cookieStore.Get(s.Request, "siyuan")
 			session, err := cookieStore.Get(s.Request, "siyuan")
 			if nil != err {
 			if nil != err {
 				authOk = false
 				authOk = false
-				util.LogErrorf("get cookie failed: %s", err)
+				logging.LogErrorf("get cookie failed: %s", err)
 			} else {
 			} else {
 				val := session.Values["data"]
 				val := session.Values["data"]
 				if nil == val {
 				if nil == val {
@@ -263,7 +264,7 @@ func serveWebSocket(ginServer *gin.Engine) {
 					err = gulu.JSON.UnmarshalJSON([]byte(val.(string)), &sess)
 					err = gulu.JSON.UnmarshalJSON([]byte(val.(string)), &sess)
 					if nil != err {
 					if nil != err {
 						authOk = false
 						authOk = false
-						util.LogErrorf("unmarshal cookie failed: %s", err)
+						logging.LogErrorf("unmarshal cookie failed: %s", err)
 					} else {
 					} else {
 						authOk = sess["AccessAuthCode"].(string) == model.Conf.AccessAuthCode
 						authOk = sess["AccessAuthCode"].(string) == model.Conf.AccessAuthCode
 					}
 					}
@@ -273,13 +274,13 @@ func serveWebSocket(ginServer *gin.Engine) {
 
 
 		if !authOk {
 		if !authOk {
 			s.CloseWithMsg([]byte("  unauthenticated"))
 			s.CloseWithMsg([]byte("  unauthenticated"))
-			//util.LogWarnf("closed a unauthenticated session [%s]", util.GetRemoteAddr(s))
+			//logging.LogWarnf("closed a unauthenticated session [%s]", util.GetRemoteAddr(s))
 			return
 			return
 		}
 		}
 
 
 		util.AddPushChan(s)
 		util.AddPushChan(s)
 		//sessionId, _ := s.Get("id")
 		//sessionId, _ := s.Get("id")
-		//util.LogInfof("ws [%s] connected", sessionId)
+		//logging.LogInfof("ws [%s] connected", sessionId)
 	})
 	})
 
 
 	util.WebSocketServer.HandleDisconnect(func(s *melody.Session) {
 	util.WebSocketServer.HandleDisconnect(func(s *melody.Session) {
@@ -290,18 +291,18 @@ func serveWebSocket(ginServer *gin.Engine) {
 
 
 	util.WebSocketServer.HandleError(func(s *melody.Session, err error) {
 	util.WebSocketServer.HandleError(func(s *melody.Session, err error) {
 		//sessionId, _ := s.Get("id")
 		//sessionId, _ := s.Get("id")
-		//util.LogDebugf("ws [%s] failed: %s", sessionId, err)
+		//logging.LogDebugf("ws [%s] failed: %s", sessionId, err)
 	})
 	})
 
 
 	util.WebSocketServer.HandleClose(func(s *melody.Session, i int, str string) error {
 	util.WebSocketServer.HandleClose(func(s *melody.Session, i int, str string) error {
 		//sessionId, _ := s.Get("id")
 		//sessionId, _ := s.Get("id")
-		//util.LogDebugf("ws [%s] closed: %v, %v", sessionId, i, str)
+		//logging.LogDebugf("ws [%s] closed: %v, %v", sessionId, i, str)
 		return nil
 		return nil
 	})
 	})
 
 
 	util.WebSocketServer.HandleMessage(func(s *melody.Session, msg []byte) {
 	util.WebSocketServer.HandleMessage(func(s *melody.Session, msg []byte) {
 		start := time.Now()
 		start := time.Now()
-		util.LogTracef("request [%s]", shortReqMsg(msg))
+		logging.LogTracef("request [%s]", shortReqMsg(msg))
 		request := map[string]interface{}{}
 		request := map[string]interface{}{}
 		if err := gulu.JSON.UnmarshalJSON(msg, &request); nil != err {
 		if err := gulu.JSON.UnmarshalJSON(msg, &request); nil != err {
 			result := util.NewResult()
 			result := util.NewResult()
@@ -340,7 +341,7 @@ func serveWebSocket(ginServer *gin.Engine) {
 		}
 		}
 
 
 		end := time.Now()
 		end := time.Now()
-		util.LogTracef("parse cmd [%s] consumed [%d]ms", command.Name(), end.Sub(start).Milliseconds())
+		logging.LogTracef("parse cmd [%s] consumed [%d]ms", command.Name(), end.Sub(start).Milliseconds())
 
 
 		cmd.Exec(command)
 		cmd.Exec(command)
 	})
 	})

+ 5 - 4
kernel/sql/aseet.go

@@ -25,6 +25,7 @@ import (
 
 
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/ast"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
@@ -73,7 +74,7 @@ func docTitleImgAsset(root *ast.Node) *Asset {
 		var err error
 		var err error
 		absPath := filepath.Join(util.DataDir, p)
 		absPath := filepath.Join(util.DataDir, p)
 		if hash, err = util.GetEtag(absPath); nil != err {
 		if hash, err = util.GetEtag(absPath); nil != err {
-			util.LogErrorf("read asset [%s] data failed: %s", absPath, err)
+			logging.LogErrorf("read asset [%s] data failed: %s", absPath, err)
 			hash = fmt.Sprintf("%x", sha256.Sum256([]byte(gulu.Rand.String(7))))
 			hash = fmt.Sprintf("%x", sha256.Sum256([]byte(gulu.Rand.String(7))))
 		}
 		}
 		name, _ := util.LastID(p)
 		name, _ := util.LastID(p)
@@ -99,7 +100,7 @@ func QueryAssetByHash(hash string) (ret *Asset) {
 	var asset Asset
 	var asset Asset
 	if err := row.Scan(&asset.ID, &asset.BlockID, &asset.RootID, &asset.Box, &asset.DocPath, &asset.Path, &asset.Name, &asset.Title, &asset.Hash); nil != err {
 	if err := row.Scan(&asset.ID, &asset.BlockID, &asset.RootID, &asset.Box, &asset.DocPath, &asset.Path, &asset.Name, &asset.Title, &asset.Hash); nil != err {
 		if sql.ErrNoRows != err {
 		if sql.ErrNoRows != err {
-			util.LogErrorf("query scan field failed: %s", err)
+			logging.LogErrorf("query scan field failed: %s", err)
 		}
 		}
 		return
 		return
 	}
 	}
@@ -111,7 +112,7 @@ func QueryRootBlockAssets(rootID string) (ret []*Asset) {
 	sqlStmt := "SELECT * FROM assets WHERE root_id = ?"
 	sqlStmt := "SELECT * FROM assets WHERE root_id = ?"
 	rows, err := query(sqlStmt, rootID)
 	rows, err := query(sqlStmt, rootID)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query [%s] failed: %s", sqlStmt, err)
+		logging.LogErrorf("sql query [%s] failed: %s", sqlStmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -125,7 +126,7 @@ func QueryRootBlockAssets(rootID string) (ret []*Asset) {
 func scanAssetRows(rows *sql.Rows) (ret *Asset) {
 func scanAssetRows(rows *sql.Rows) (ret *Asset) {
 	var asset Asset
 	var asset Asset
 	if err := rows.Scan(&asset.ID, &asset.BlockID, &asset.RootID, &asset.Box, &asset.DocPath, &asset.Path, &asset.Name, &asset.Title, &asset.Hash); nil != err {
 	if err := rows.Scan(&asset.ID, &asset.BlockID, &asset.RootID, &asset.Box, &asset.DocPath, &asset.Path, &asset.Name, &asset.Title, &asset.Hash); nil != err {
-		util.LogErrorf("query scan field failed: %s", err)
+		logging.LogErrorf("query scan field failed: %s", err)
 		return
 		return
 	}
 	}
 	ret = &asset
 	ret = &asset

+ 27 - 26
kernel/sql/block_query.go

@@ -26,6 +26,7 @@ import (
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/ast"
 	"github.com/88250/vitess-sqlparser/sqlparser"
 	"github.com/88250/vitess-sqlparser/sqlparser"
 	"github.com/emirpasic/gods/sets/hashset"
 	"github.com/emirpasic/gods/sets/hashset"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
@@ -34,7 +35,7 @@ func queryBlockHashes(rootID string) (ret map[string]string) {
 	stmt := "SELECT id, hash FROM blocks WHERE root_id = ?"
 	stmt := "SELECT id, hash FROM blocks WHERE root_id = ?"
 	rows, err := query(stmt, rootID)
 	rows, err := query(stmt, rootID)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", stmt, err)
+		logging.LogErrorf("sql query failed: %s", stmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -42,7 +43,7 @@ func queryBlockHashes(rootID string) (ret map[string]string) {
 	for rows.Next() {
 	for rows.Next() {
 		var id, hash string
 		var id, hash string
 		if err = rows.Scan(&id, &hash); nil != err {
 		if err = rows.Scan(&id, &hash); nil != err {
-			util.LogErrorf("query scan field failed: %s", err)
+			logging.LogErrorf("query scan field failed: %s", err)
 			return
 			return
 		}
 		}
 		ret[id] = hash
 		ret[id] = hash
@@ -54,7 +55,7 @@ func QueryRootBlockByCondition(condition string) (ret []*Block) {
 	sqlStmt := "SELECT *, length(hpath) - length(replace(hpath, '/', '')) AS lv FROM blocks WHERE type = 'd' AND " + condition + " ORDER BY box DESC,lv ASC LIMIT 128"
 	sqlStmt := "SELECT *, length(hpath) - length(replace(hpath, '/', '')) AS lv FROM blocks WHERE type = 'd' AND " + condition + " ORDER BY box DESC,lv ASC LIMIT 128"
 	rows, err := query(sqlStmt)
 	rows, err := query(sqlStmt)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", sqlStmt, err)
+		logging.LogErrorf("sql query failed: %s", sqlStmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -62,7 +63,7 @@ func QueryRootBlockByCondition(condition string) (ret []*Block) {
 		var block Block
 		var block Block
 		var sepCount int
 		var sepCount int
 		if err = rows.Scan(&block.ID, &block.ParentID, &block.RootID, &block.Hash, &block.Box, &block.Path, &block.HPath, &block.Name, &block.Alias, &block.Memo, &block.Tag, &block.Content, &block.FContent, &block.Markdown, &block.Length, &block.Type, &block.SubType, &block.IAL, &block.Sort, &block.Created, &block.Updated, &sepCount); nil != err {
 		if err = rows.Scan(&block.ID, &block.ParentID, &block.RootID, &block.Hash, &block.Box, &block.Path, &block.HPath, &block.Name, &block.Alias, &block.Memo, &block.Tag, &block.Content, &block.FContent, &block.Markdown, &block.Length, &block.Type, &block.SubType, &block.IAL, &block.Sort, &block.Created, &block.Updated, &sepCount); nil != err {
-			util.LogErrorf("query scan field failed: %s", err)
+			logging.LogErrorf("query scan field failed: %s", err)
 			return
 			return
 		}
 		}
 		ret = append(ret, &block)
 		ret = append(ret, &block)
@@ -85,7 +86,7 @@ func IsBlockFolded(id string) (ret bool) {
 		var pid, ial string
 		var pid, ial string
 		if err := row.Scan(&pid, &ial); nil != err {
 		if err := row.Scan(&pid, &ial); nil != err {
 			if sql.ErrNoRows != err {
 			if sql.ErrNoRows != err {
-				util.LogErrorf("query scan field failed: %s", err)
+				logging.LogErrorf("query scan field failed: %s", err)
 			}
 			}
 			return
 			return
 		}
 		}
@@ -110,7 +111,7 @@ func queryBlockIDByParentID(parentID string) (ret []string) {
 	sqlStmt := "SELECT id FROM blocks WHERE parent_id = ?"
 	sqlStmt := "SELECT id FROM blocks WHERE parent_id = ?"
 	rows, err := query(sqlStmt, parentID)
 	rows, err := query(sqlStmt, parentID)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", sqlStmt, err)
+		logging.LogErrorf("sql query failed: %s", sqlStmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -129,7 +130,7 @@ func QueryRecentUpdatedBlocks() (ret []*Block) {
 	}
 	}
 	rows, err := query(sqlStmt)
 	rows, err := query(sqlStmt)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", sqlStmt, err)
+		logging.LogErrorf("sql query failed: %s", sqlStmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -152,7 +153,7 @@ func QueryBlockAliases(rootID string) (ret []string) {
 	sqlStmt := "SELECT alias FROM blocks WHERE root_id = ? AND alias != ''"
 	sqlStmt := "SELECT alias FROM blocks WHERE root_id = ? AND alias != ''"
 	rows, err := query(sqlStmt, rootID)
 	rows, err := query(sqlStmt, rootID)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", sqlStmt, err)
+		logging.LogErrorf("sql query failed: %s", sqlStmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -185,7 +186,7 @@ func queryNames() (ret []string) {
 	sqlStmt := "SELECT name FROM blocks WHERE name != '' LIMIT ?"
 	sqlStmt := "SELECT name FROM blocks WHERE name != '' LIMIT ?"
 	rows, err := query(sqlStmt, 10240)
 	rows, err := query(sqlStmt, 10240)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", sqlStmt, err)
+		logging.LogErrorf("sql query failed: %s", sqlStmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -218,7 +219,7 @@ func queryAliases() (ret []string) {
 	sqlStmt := "SELECT alias FROM blocks WHERE alias != '' LIMIT ?"
 	sqlStmt := "SELECT alias FROM blocks WHERE alias != '' LIMIT ?"
 	rows, err := query(sqlStmt, 10240)
 	rows, err := query(sqlStmt, 10240)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", sqlStmt, err)
+		logging.LogErrorf("sql query failed: %s", sqlStmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -252,7 +253,7 @@ func queryDocIDsByTitle(title string, excludeIDs []string) (ret []string) {
 	sqlStmt := "SELECT id FROM blocks WHERE type = 'd' AND content = ? AND id NOT IN " + notIn + " LIMIT ?"
 	sqlStmt := "SELECT id FROM blocks WHERE type = 'd' AND content = ? AND id NOT IN " + notIn + " LIMIT ?"
 	rows, err := query(sqlStmt, title, 32)
 	rows, err := query(sqlStmt, title, 32)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", sqlStmt, err)
+		logging.LogErrorf("sql query failed: %s", sqlStmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -275,7 +276,7 @@ func queryDocTitles() (ret []string) {
 	sqlStmt := "SELECT content FROM blocks WHERE type = 'd' LIMIT ?"
 	sqlStmt := "SELECT content FROM blocks WHERE type = 'd' LIMIT ?"
 	rows, err := query(sqlStmt, 10240)
 	rows, err := query(sqlStmt, 10240)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", sqlStmt, err)
+		logging.LogErrorf("sql query failed: %s", sqlStmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -307,7 +308,7 @@ func QueryBlockNamesByRootID(rootID string) (ret []string) {
 	sqlStmt := "SELECT DISTINCT name FROM blocks WHERE root_id = ? AND name != ''"
 	sqlStmt := "SELECT DISTINCT name FROM blocks WHERE root_id = ? AND name != ''"
 	rows, err := query(sqlStmt, rootID)
 	rows, err := query(sqlStmt, rootID)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", sqlStmt, err)
+		logging.LogErrorf("sql query failed: %s", sqlStmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -323,7 +324,7 @@ func QueryBookmarkBlocksByKeyword(bookmark string) (ret []*Block) {
 	sqlStmt := "SELECT * FROM blocks WHERE ial LIKE ?"
 	sqlStmt := "SELECT * FROM blocks WHERE ial LIKE ?"
 	rows, err := query(sqlStmt, "%bookmark=%")
 	rows, err := query(sqlStmt, "%bookmark=%")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query [%s] failed: %s", sqlStmt, err)
+		logging.LogErrorf("sql query [%s] failed: %s", sqlStmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -339,7 +340,7 @@ func QueryBookmarkBlocks() (ret []*Block) {
 	sqlStmt := "SELECT * FROM blocks WHERE ial LIKE ?"
 	sqlStmt := "SELECT * FROM blocks WHERE ial LIKE ?"
 	rows, err := query(sqlStmt, "%bookmark=%")
 	rows, err := query(sqlStmt, "%bookmark=%")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query [%s] failed: %s", sqlStmt, err)
+		logging.LogErrorf("sql query [%s] failed: %s", sqlStmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -356,7 +357,7 @@ func QueryBookmarkLabels() (ret []string) {
 	sqlStmt := "SELECT * FROM blocks WHERE ial LIKE ?"
 	sqlStmt := "SELECT * FROM blocks WHERE ial LIKE ?"
 	rows, err := query(sqlStmt, "%bookmark=%")
 	rows, err := query(sqlStmt, "%bookmark=%")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query [%s] failed: %s", sqlStmt, err)
+		logging.LogErrorf("sql query [%s] failed: %s", sqlStmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -380,7 +381,7 @@ func Query(stmt string) (ret []map[string]interface{}, err error) {
 	ret = []map[string]interface{}{}
 	ret = []map[string]interface{}{}
 	rows, err := query(stmt)
 	rows, err := query(stmt)
 	if nil != err {
 	if nil != err {
-		util.LogWarnf("sql query [%s] failed: %s", stmt, err)
+		logging.LogWarnf("sql query [%s] failed: %s", stmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -447,7 +448,7 @@ func SelectBlocksRawStmt(stmt string, limit int) (ret []*Block) {
 		if strings.Contains(err.Error(), "syntax error") {
 		if strings.Contains(err.Error(), "syntax error") {
 			return
 			return
 		}
 		}
-		util.LogWarnf("sql query [%s] failed: %s", stmt, err)
+		logging.LogWarnf("sql query [%s] failed: %s", stmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -484,7 +485,7 @@ func selectBlocksRawStmt(stmt string, limit int) (ret []*Block) {
 func scanBlockRows(rows *sql.Rows) (ret *Block) {
 func scanBlockRows(rows *sql.Rows) (ret *Block) {
 	var block Block
 	var block Block
 	if err := rows.Scan(&block.ID, &block.ParentID, &block.RootID, &block.Hash, &block.Box, &block.Path, &block.HPath, &block.Name, &block.Alias, &block.Memo, &block.Tag, &block.Content, &block.FContent, &block.Markdown, &block.Length, &block.Type, &block.SubType, &block.IAL, &block.Sort, &block.Created, &block.Updated); nil != err {
 	if err := rows.Scan(&block.ID, &block.ParentID, &block.RootID, &block.Hash, &block.Box, &block.Path, &block.HPath, &block.Name, &block.Alias, &block.Memo, &block.Tag, &block.Content, &block.FContent, &block.Markdown, &block.Length, &block.Type, &block.SubType, &block.IAL, &block.Sort, &block.Created, &block.Updated); nil != err {
-		util.LogErrorf("query scan field failed: %s\n%s", err, util.ShortStack())
+		logging.LogErrorf("query scan field failed: %s\n%s", err, logging.ShortStack())
 		return
 		return
 	}
 	}
 	ret = &block
 	ret = &block
@@ -495,7 +496,7 @@ func scanBlockRow(row *sql.Row) (ret *Block) {
 	var block Block
 	var block Block
 	if err := row.Scan(&block.ID, &block.ParentID, &block.RootID, &block.Hash, &block.Box, &block.Path, &block.HPath, &block.Name, &block.Alias, &block.Memo, &block.Tag, &block.Content, &block.FContent, &block.Markdown, &block.Length, &block.Type, &block.SubType, &block.IAL, &block.Sort, &block.Created, &block.Updated); nil != err {
 	if err := row.Scan(&block.ID, &block.ParentID, &block.RootID, &block.Hash, &block.Box, &block.Path, &block.HPath, &block.Name, &block.Alias, &block.Memo, &block.Tag, &block.Content, &block.FContent, &block.Markdown, &block.Length, &block.Type, &block.SubType, &block.IAL, &block.Sort, &block.Created, &block.Updated); nil != err {
 		if sql.ErrNoRows != err {
 		if sql.ErrNoRows != err {
-			util.LogErrorf("query scan field failed: %s\n%s", err, util.ShortStack())
+			logging.LogErrorf("query scan field failed: %s\n%s", err, logging.ShortStack())
 		}
 		}
 		return
 		return
 	}
 	}
@@ -517,7 +518,7 @@ func GetChildBlocks(parentID, condition string) (ret []*Block) {
 	}
 	}
 	rows, err := query(sqlStmt)
 	rows, err := query(sqlStmt)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query [%s] failed: %s", sqlStmt, err)
+		logging.LogErrorf("sql query [%s] failed: %s", sqlStmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -537,7 +538,7 @@ func GetAllChildBlocks(rootID, condition string) (ret []*Block) {
 	}
 	}
 	rows, err := query(sqlStmt, rootID)
 	rows, err := query(sqlStmt, rootID)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query [%s] failed: %s", sqlStmt, err)
+		logging.LogErrorf("sql query [%s] failed: %s", sqlStmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -553,7 +554,7 @@ func GetRefUnresolvedBlocks() (ret []*Block) {
 	stmt := "SELECT * FROM blocks WHERE content LIKE ?"
 	stmt := "SELECT * FROM blocks WHERE content LIKE ?"
 	rows, err := query(stmt, "%ref resolve failed%")
 	rows, err := query(stmt, "%ref resolve failed%")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query [%s] failed: %s", stmt, err)
+		logging.LogErrorf("sql query [%s] failed: %s", stmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -569,7 +570,7 @@ func GetRefExistedBlocks() (ret []*Block) {
 	stmt := "SELECT * FROM blocks WHERE markdown LIKE ? OR markdown LIKE ?"
 	stmt := "SELECT * FROM blocks WHERE markdown LIKE ? OR markdown LIKE ?"
 	rows, err := query(stmt, "%((20%", "%<<20%")
 	rows, err := query(stmt, "%((20%", "%<<20%")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query [%s] failed: %s", stmt, err)
+		logging.LogErrorf("sql query [%s] failed: %s", stmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -598,7 +599,7 @@ func GetAllRootBlocks() (ret []*Block) {
 	stmt := "SELECT * FROM blocks WHERE type = 'd'"
 	stmt := "SELECT * FROM blocks WHERE type = 'd'"
 	rows, err := query(stmt)
 	rows, err := query(stmt)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query [%s] failed: %s", stmt, err)
+		logging.LogErrorf("sql query [%s] failed: %s", stmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -626,7 +627,7 @@ func GetBlocks(ids []string) (ret []*Block) {
 	sqlStmt := stmtBuilder.String()
 	sqlStmt := stmtBuilder.String()
 	rows, err := query(sqlStmt, args...)
 	rows, err := query(sqlStmt, args...)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query [%s] failed: %s", sqlStmt, err)
+		logging.LogErrorf("sql query [%s] failed: %s", sqlStmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()

+ 23 - 23
kernel/sql/block_ref_query.go

@@ -24,7 +24,7 @@ import (
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/parse"
 	"github.com/emirpasic/gods/sets/hashset"
 	"github.com/emirpasic/gods/sets/hashset"
-	"github.com/siyuan-note/siyuan/kernel/util"
+	"github.com/siyuan-note/logging"
 )
 )
 
 
 func QueryVirtualRefKeywords(name, alias, anchor, doc bool) (ret []string) {
 func QueryVirtualRefKeywords(name, alias, anchor, doc bool) (ret []string) {
@@ -58,7 +58,7 @@ func queryRefTexts() (ret []string) {
 	sqlStmt := "SELECT DISTINCT content FROM refs LIMIT 1024"
 	sqlStmt := "SELECT DISTINCT content FROM refs LIMIT 1024"
 	rows, err := query(sqlStmt)
 	rows, err := query(sqlStmt)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", sqlStmt, err)
+		logging.LogErrorf("sql query failed: %s", sqlStmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -82,7 +82,7 @@ func QueryRootChildrenRefCount(defRootID string) (ret map[string]int) {
 	ret = map[string]int{}
 	ret = map[string]int{}
 	rows, err := query("SELECT def_block_id, COUNT(*) AS ref_cnt FROM refs WHERE def_block_root_id = ? GROUP BY def_block_id", defRootID)
 	rows, err := query("SELECT def_block_id, COUNT(*) AS ref_cnt FROM refs WHERE def_block_root_id = ? GROUP BY def_block_id", defRootID)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", err)
+		logging.LogErrorf("sql query failed: %s", err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -90,7 +90,7 @@ func QueryRootChildrenRefCount(defRootID string) (ret map[string]int) {
 		var id string
 		var id string
 		var cnt int
 		var cnt int
 		if err = rows.Scan(&id, &cnt); nil != err {
 		if err = rows.Scan(&id, &cnt); nil != err {
-			util.LogErrorf("query scan field failed: %s", err)
+			logging.LogErrorf("query scan field failed: %s", err)
 			return
 			return
 		}
 		}
 		ret[id] = cnt
 		ret[id] = cnt
@@ -103,7 +103,7 @@ func QueryRootBlockRefCount() (ret map[string]int) {
 
 
 	rows, err := query("SELECT def_block_root_id, COUNT(*) AS ref_cnt FROM refs GROUP BY def_block_root_id")
 	rows, err := query("SELECT def_block_root_id, COUNT(*) AS ref_cnt FROM refs GROUP BY def_block_root_id")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", err)
+		logging.LogErrorf("sql query failed: %s", err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -111,7 +111,7 @@ func QueryRootBlockRefCount() (ret map[string]int) {
 		var id string
 		var id string
 		var cnt int
 		var cnt int
 		if err = rows.Scan(&id, &cnt); nil != err {
 		if err = rows.Scan(&id, &cnt); nil != err {
-			util.LogErrorf("query scan field failed: %s", err)
+			logging.LogErrorf("query scan field failed: %s", err)
 			return
 			return
 		}
 		}
 		ret[id] = cnt
 		ret[id] = cnt
@@ -122,7 +122,7 @@ func QueryRootBlockRefCount() (ret map[string]int) {
 func QueryDefRootBlocksByRefRootID(refRootID string) (ret []*Block) {
 func QueryDefRootBlocksByRefRootID(refRootID string) (ret []*Block) {
 	rows, err := query("SELECT * FROM blocks WHERE id IN (SELECT DISTINCT def_block_root_id FROM refs WHERE root_id = ?)", refRootID)
 	rows, err := query("SELECT * FROM blocks WHERE id IN (SELECT DISTINCT def_block_root_id FROM refs WHERE root_id = ?)", refRootID)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", err)
+		logging.LogErrorf("sql query failed: %s", err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -137,7 +137,7 @@ func QueryDefRootBlocksByRefRootID(refRootID string) (ret []*Block) {
 func QueryRefRootBlocksByDefRootID(defRootID string) (ret []*Block) {
 func QueryRefRootBlocksByDefRootID(defRootID string) (ret []*Block) {
 	rows, err := query("SELECT * FROM blocks WHERE id IN (SELECT DISTINCT root_id FROM refs WHERE def_block_root_id = ?)", defRootID)
 	rows, err := query("SELECT * FROM blocks WHERE id IN (SELECT DISTINCT root_id FROM refs WHERE def_block_root_id = ?)", defRootID)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", err)
+		logging.LogErrorf("sql query failed: %s", err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -197,14 +197,14 @@ func queryDefIDsByDefText(keyword string, excludeIDs []string) (ret []string) {
 	notIn := "('" + strings.Join(excludeIDs, "','") + "')"
 	notIn := "('" + strings.Join(excludeIDs, "','") + "')"
 	rows, err := query("SELECT DISTINCT(def_block_id) FROM refs WHERE content = ? AND def_block_id NOT IN "+notIn, keyword)
 	rows, err := query("SELECT DISTINCT(def_block_id) FROM refs WHERE content = ? AND def_block_id NOT IN "+notIn, keyword)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", err)
+		logging.LogErrorf("sql query failed: %s", err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
 	for rows.Next() {
 	for rows.Next() {
 		var id string
 		var id string
 		if err = rows.Scan(&id); nil != err {
 		if err = rows.Scan(&id); nil != err {
-			util.LogErrorf("query scan field failed: %s", err)
+			logging.LogErrorf("query scan field failed: %s", err)
 			return
 			return
 		}
 		}
 		ret = append(ret, id)
 		ret = append(ret, id)
@@ -217,14 +217,14 @@ func queryDefIDsByNameAlias(keyword string, excludeIDs []string) (ret []string)
 	notIn := "('" + strings.Join(excludeIDs, "','") + "')"
 	notIn := "('" + strings.Join(excludeIDs, "','") + "')"
 	rows, err := query("SELECT DISTINCT(id), name, alias FROM blocks WHERE (name = ? OR alias LIKE ?) AND id NOT IN "+notIn, keyword, "%"+keyword+"%")
 	rows, err := query("SELECT DISTINCT(id), name, alias FROM blocks WHERE (name = ? OR alias LIKE ?) AND id NOT IN "+notIn, keyword, "%"+keyword+"%")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", err)
+		logging.LogErrorf("sql query failed: %s", err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
 	for rows.Next() {
 	for rows.Next() {
 		var id, name, alias string
 		var id, name, alias string
 		if err = rows.Scan(&id, &name, &alias); nil != err {
 		if err = rows.Scan(&id, &name, &alias); nil != err {
-			util.LogErrorf("query scan field failed: %s", err)
+			logging.LogErrorf("query scan field failed: %s", err)
 			return
 			return
 		}
 		}
 		if name == keyword {
 		if name == keyword {
@@ -254,14 +254,14 @@ func QueryChildDefIDsByRootDefID(rootDefID string) (ret []string) {
 	ret = []string{}
 	ret = []string{}
 	rows, err := query("SELECT DISTINCT(def_block_id) FROM refs WHERE def_block_root_id = ?", rootDefID)
 	rows, err := query("SELECT DISTINCT(def_block_id) FROM refs WHERE def_block_root_id = ?", rootDefID)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", err)
+		logging.LogErrorf("sql query failed: %s", err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
 	for rows.Next() {
 	for rows.Next() {
 		var id string
 		var id string
 		if err = rows.Scan(&id); nil != err {
 		if err = rows.Scan(&id); nil != err {
-			util.LogErrorf("query scan field failed: %s", err)
+			logging.LogErrorf("query scan field failed: %s", err)
 			return
 			return
 		}
 		}
 		ret = append(ret, id)
 		ret = append(ret, id)
@@ -279,14 +279,14 @@ func QueryRefIDsByDefID(defID string, containChildren bool) (refIDs, refTexts []
 		rows, err = query("SELECT block_id, content FROM refs WHERE def_block_id = ?", defID)
 		rows, err = query("SELECT block_id, content FROM refs WHERE def_block_id = ?", defID)
 	}
 	}
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", err)
+		logging.LogErrorf("sql query failed: %s", err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
 	for rows.Next() {
 	for rows.Next() {
 		var id, content string
 		var id, content string
 		if err = rows.Scan(&id, &content); nil != err {
 		if err = rows.Scan(&id, &content); nil != err {
-			util.LogErrorf("query scan field failed: %s", err)
+			logging.LogErrorf("query scan field failed: %s", err)
 			return
 			return
 		}
 		}
 		refIDs = append(refIDs, id)
 		refIDs = append(refIDs, id)
@@ -298,7 +298,7 @@ func QueryRefIDsByDefID(defID string, containChildren bool) (refIDs, refTexts []
 func QueryRefsRecent() (ret []*Ref) {
 func QueryRefsRecent() (ret []*Ref) {
 	rows, err := query("SELECT * FROM refs GROUP BY def_block_id ORDER BY id desc LIMIT 32")
 	rows, err := query("SELECT * FROM refs GROUP BY def_block_id ORDER BY id desc LIMIT 32")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", err)
+		logging.LogErrorf("sql query failed: %s", err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -332,7 +332,7 @@ func QueryRefsByDefID(defBlockID string, containChildren bool) (ret []*Ref) {
 		}
 		}
 	}
 	}
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", err)
+		logging.LogErrorf("sql query failed: %s", err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -347,7 +347,7 @@ func QueryRefsByDefIDRefID(defBlockID, refBlockID string) (ret []*Ref) {
 	stmt := "SELECT * FROM refs WHERE def_block_id = ? AND block_id = ?"
 	stmt := "SELECT * FROM refs WHERE def_block_id = ? AND block_id = ?"
 	rows, err := query(stmt, defBlockID, refBlockID)
 	rows, err := query(stmt, defBlockID, refBlockID)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", err)
+		logging.LogErrorf("sql query failed: %s", err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -367,7 +367,7 @@ func DefRefs(condition string) (ret []map[*Block]*Block) {
 
 
 	rows, err := query(stmt)
 	rows, err := query(stmt)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", err)
+		logging.LogErrorf("sql query failed: %s", err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -377,7 +377,7 @@ func DefRefs(condition string) (ret []map[*Block]*Block) {
 		var rel string
 		var rel string
 		if err = rows.Scan(&ref.ID, &ref.ParentID, &ref.RootID, &ref.Hash, &ref.Box, &ref.Path, &ref.HPath, &ref.Name, &ref.Alias, &ref.Memo, &ref.Tag, &ref.Content, &ref.FContent, &ref.Markdown, &ref.Length, &ref.Type, &ref.SubType, &ref.IAL, &ref.Sort, &ref.Created, &ref.Updated,
 		if err = rows.Scan(&ref.ID, &ref.ParentID, &ref.RootID, &ref.Hash, &ref.Box, &ref.Path, &ref.HPath, &ref.Name, &ref.Alias, &ref.Memo, &ref.Tag, &ref.Content, &ref.FContent, &ref.Markdown, &ref.Length, &ref.Type, &ref.SubType, &ref.IAL, &ref.Sort, &ref.Created, &ref.Updated,
 			&rel); nil != err {
 			&rel); nil != err {
-			util.LogErrorf("query scan field failed: %s", err)
+			logging.LogErrorf("query scan field failed: %s", err)
 			return
 			return
 		}
 		}
 		refs[rel] = &ref
 		refs[rel] = &ref
@@ -385,7 +385,7 @@ func DefRefs(condition string) (ret []map[*Block]*Block) {
 
 
 	rows, err = query("SELECT def.* FROM blocks AS def, refs AS r WHERE def.id = r.def_block_id")
 	rows, err = query("SELECT def.* FROM blocks AS def, refs AS r WHERE def.id = r.def_block_id")
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", err)
+		logging.LogErrorf("sql query failed: %s", err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -412,7 +412,7 @@ func DefRefs(condition string) (ret []map[*Block]*Block) {
 func scanRefRows(rows *sql.Rows) (ret *Ref) {
 func scanRefRows(rows *sql.Rows) (ret *Ref) {
 	var ref Ref
 	var ref Ref
 	if err := rows.Scan(&ref.ID, &ref.DefBlockID, &ref.DefBlockParentID, &ref.DefBlockRootID, &ref.DefBlockPath, &ref.BlockID, &ref.RootID, &ref.Box, &ref.Path, &ref.Content, &ref.Markdown, &ref.Type); nil != err {
 	if err := rows.Scan(&ref.ID, &ref.DefBlockID, &ref.DefBlockParentID, &ref.DefBlockRootID, &ref.DefBlockPath, &ref.BlockID, &ref.RootID, &ref.Box, &ref.Path, &ref.Content, &ref.Markdown, &ref.Type); nil != err {
-		util.LogErrorf("query scan field failed: %s", err)
+		logging.LogErrorf("query scan field failed: %s", err)
 		return
 		return
 	}
 	}
 	ret = &ref
 	ret = &ref

+ 26 - 25
kernel/sql/database.go

@@ -33,6 +33,7 @@ import (
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/parse"
 	"github.com/mattn/go-sqlite3"
 	"github.com/mattn/go-sqlite3"
 	_ "github.com/mattn/go-sqlite3"
 	_ "github.com/mattn/go-sqlite3"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
@@ -69,7 +70,7 @@ func InitDatabase(forceRebuild bool) (err error) {
 	db.Close()
 	db.Close()
 	if gulu.File.IsExist(util.DBPath) {
 	if gulu.File.IsExist(util.DBPath) {
 		if err = removeDatabaseFile(); nil != err {
 		if err = removeDatabaseFile(); nil != err {
-			util.LogErrorf("remove database file [%s] failed: %s", util.DBPath, err)
+			logging.LogErrorf("remove database file [%s] failed: %s", util.DBPath, err)
 			util.PushClearProgress()
 			util.PushClearProgress()
 			return
 			return
 		}
 		}
@@ -81,7 +82,7 @@ func InitDatabase(forceRebuild bool) (err error) {
 	initDBConnection()
 	initDBConnection()
 	initDBTables()
 	initDBTables()
 
 
-	util.LogInfof("reinitialized database [%s]", util.DBPath)
+	logging.LogInfof("reinitialized database [%s]", util.DBPath)
 	return
 	return
 }
 }
 
 
@@ -89,56 +90,56 @@ func initDBTables() {
 	db.Exec("DROP TABLE stat")
 	db.Exec("DROP TABLE stat")
 	_, err := db.Exec("CREATE TABLE stat (key, value)")
 	_, err := db.Exec("CREATE TABLE stat (key, value)")
 	if nil != err {
 	if nil != err {
-		util.LogFatalf("create table [stat] failed: %s", err)
+		logging.LogFatalf("create table [stat] failed: %s", err)
 	}
 	}
 	setDatabaseVer()
 	setDatabaseVer()
 
 
 	db.Exec("DROP TABLE blocks")
 	db.Exec("DROP TABLE blocks")
 	_, err = db.Exec("CREATE TABLE blocks (id, parent_id, root_id, hash, box, path, hpath, name, alias, memo, tag, content, fcontent, markdown, length, type, subtype, ial, sort, created, updated)")
 	_, err = db.Exec("CREATE TABLE blocks (id, parent_id, root_id, hash, box, path, hpath, name, alias, memo, tag, content, fcontent, markdown, length, type, subtype, ial, sort, created, updated)")
 	if nil != err {
 	if nil != err {
-		util.LogFatalf("create table [blocks] failed: %s", err)
+		logging.LogFatalf("create table [blocks] failed: %s", err)
 	}
 	}
 
 
 	db.Exec("DROP TABLE blocks_fts")
 	db.Exec("DROP TABLE blocks_fts")
 	_, err = db.Exec("CREATE VIRTUAL TABLE blocks_fts USING fts5(id UNINDEXED, parent_id UNINDEXED, root_id UNINDEXED, hash UNINDEXED, box UNINDEXED, path UNINDEXED, hpath, name, alias, memo, tag, content, fcontent, markdown UNINDEXED, length UNINDEXED, type UNINDEXED, subtype UNINDEXED, ial, sort UNINDEXED, created UNINDEXED, updated UNINDEXED, tokenize=\"siyuan\")")
 	_, err = db.Exec("CREATE VIRTUAL TABLE blocks_fts USING fts5(id UNINDEXED, parent_id UNINDEXED, root_id UNINDEXED, hash UNINDEXED, box UNINDEXED, path UNINDEXED, hpath, name, alias, memo, tag, content, fcontent, markdown UNINDEXED, length UNINDEXED, type UNINDEXED, subtype UNINDEXED, ial, sort UNINDEXED, created UNINDEXED, updated UNINDEXED, tokenize=\"siyuan\")")
 	if nil != err {
 	if nil != err {
-		util.LogFatalf("create table [blocks_fts] failed: %s", err)
+		logging.LogFatalf("create table [blocks_fts] failed: %s", err)
 	}
 	}
 
 
 	db.Exec("DROP TABLE blocks_fts_case_insensitive")
 	db.Exec("DROP TABLE blocks_fts_case_insensitive")
 	_, err = db.Exec("CREATE VIRTUAL TABLE blocks_fts_case_insensitive USING fts5(id UNINDEXED, parent_id UNINDEXED, root_id UNINDEXED, hash UNINDEXED, box UNINDEXED, path UNINDEXED, hpath, name, alias, memo, tag, content, fcontent, markdown UNINDEXED, length UNINDEXED, type UNINDEXED, subtype UNINDEXED, ial, sort UNINDEXED, created UNINDEXED, updated UNINDEXED, tokenize=\"siyuan case_insensitive\")")
 	_, err = db.Exec("CREATE VIRTUAL TABLE blocks_fts_case_insensitive USING fts5(id UNINDEXED, parent_id UNINDEXED, root_id UNINDEXED, hash UNINDEXED, box UNINDEXED, path UNINDEXED, hpath, name, alias, memo, tag, content, fcontent, markdown UNINDEXED, length UNINDEXED, type UNINDEXED, subtype UNINDEXED, ial, sort UNINDEXED, created UNINDEXED, updated UNINDEXED, tokenize=\"siyuan case_insensitive\")")
 	if nil != err {
 	if nil != err {
-		util.LogFatalf("create table [blocks_fts_case_insensitive] failed: %s", err)
+		logging.LogFatalf("create table [blocks_fts_case_insensitive] failed: %s", err)
 	}
 	}
 
 
 	db.Exec("DROP TABLE spans")
 	db.Exec("DROP TABLE spans")
 	_, err = db.Exec("CREATE TABLE spans (id, block_id, root_id, box, path, content, markdown, type, ial)")
 	_, err = db.Exec("CREATE TABLE spans (id, block_id, root_id, box, path, content, markdown, type, ial)")
 	if nil != err {
 	if nil != err {
-		util.LogFatalf("create table [spans] failed: %s", err)
+		logging.LogFatalf("create table [spans] failed: %s", err)
 	}
 	}
 
 
 	db.Exec("DROP TABLE assets")
 	db.Exec("DROP TABLE assets")
 	_, err = db.Exec("CREATE TABLE assets (id, block_id, root_id, box, docpath, path, name, title, hash)")
 	_, err = db.Exec("CREATE TABLE assets (id, block_id, root_id, box, docpath, path, name, title, hash)")
 	if nil != err {
 	if nil != err {
-		util.LogFatalf("create table [assets] failed: %s", err)
+		logging.LogFatalf("create table [assets] failed: %s", err)
 	}
 	}
 
 
 	db.Exec("DROP TABLE attributes")
 	db.Exec("DROP TABLE attributes")
 	_, err = db.Exec("CREATE TABLE attributes (id, name, value, type, block_id, root_id, box, path)")
 	_, err = db.Exec("CREATE TABLE attributes (id, name, value, type, block_id, root_id, box, path)")
 	if nil != err {
 	if nil != err {
-		util.LogFatalf("create table [attributes] failed: %s", err)
+		logging.LogFatalf("create table [attributes] failed: %s", err)
 	}
 	}
 
 
 	db.Exec("DROP TABLE refs")
 	db.Exec("DROP TABLE refs")
 	_, err = db.Exec("CREATE TABLE refs (id, def_block_id, def_block_parent_id, def_block_root_id, def_block_path, block_id, root_id, box, path, content, markdown, type)")
 	_, err = db.Exec("CREATE TABLE refs (id, def_block_id, def_block_parent_id, def_block_root_id, def_block_path, block_id, root_id, box, path, content, markdown, type)")
 	if nil != err {
 	if nil != err {
-		util.LogFatalf("create table [refs] failed: %s", err)
+		logging.LogFatalf("create table [refs] failed: %s", err)
 	}
 	}
 
 
 	db.Exec("DROP TABLE file_annotation_refs")
 	db.Exec("DROP TABLE file_annotation_refs")
 	_, err = db.Exec("CREATE TABLE file_annotation_refs (id, file_path, annotation_id, block_id, root_id, box, path, content, type)")
 	_, err = db.Exec("CREATE TABLE file_annotation_refs (id, file_path, annotation_id, block_id, root_id, box, path, content, type)")
 	if nil != err {
 	if nil != err {
-		util.LogFatalf("create table [refs] failed: %s", err)
+		logging.LogFatalf("create table [refs] failed: %s", err)
 	}
 	}
 }
 }
 
 
@@ -159,7 +160,7 @@ func IndexMode() {
 	var err error
 	var err error
 	db, err = sql.Open("sqlite3_extended", dsn)
 	db, err = sql.Open("sqlite3_extended", dsn)
 	if nil != err {
 	if nil != err {
-		util.LogFatalf("create database failed: %s", err)
+		logging.LogFatalf("create database failed: %s", err)
 	}
 	}
 	db.SetMaxIdleConns(1)
 	db.SetMaxIdleConns(1)
 	db.SetMaxOpenConns(1)
 	db.SetMaxOpenConns(1)
@@ -186,7 +187,7 @@ func initDBConnection() {
 	var err error
 	var err error
 	db, err = sql.Open("sqlite3_extended", dsn)
 	db, err = sql.Open("sqlite3_extended", dsn)
 	if nil != err {
 	if nil != err {
-		util.LogFatalf("create database failed: %s", err)
+		logging.LogFatalf("create database failed: %s", err)
 	}
 	}
 	db.SetMaxIdleConns(20)
 	db.SetMaxIdleConns(20)
 	db.SetMaxOpenConns(20)
 	db.SetMaxOpenConns(20)
@@ -542,7 +543,7 @@ func buildSpanFromNode(n *ast.Node, tree *parse.Tree, rootID, boxID, p string) (
 			if !gulu.File.IsDir(lp) {
 			if !gulu.File.IsDir(lp) {
 				hash, hashErr = util.GetEtag(lp)
 				hash, hashErr = util.GetEtag(lp)
 				if nil != hashErr {
 				if nil != hashErr {
-					util.LogErrorf("calc asset [%s] hash failed: %s", lp, hashErr)
+					logging.LogErrorf("calc asset [%s] hash failed: %s", lp, hashErr)
 				}
 				}
 			}
 			}
 		}
 		}
@@ -572,7 +573,7 @@ func buildSpanFromNode(n *ast.Node, tree *parse.Tree, rootID, boxID, p string) (
 		htmlRoot := &html.Node{Type: html.ElementNode}
 		htmlRoot := &html.Node{Type: html.ElementNode}
 		nodes, err := html.ParseFragment(strings.NewReader(gulu.Str.FromBytes(n.Tokens)), htmlRoot)
 		nodes, err := html.ParseFragment(strings.NewReader(gulu.Str.FromBytes(n.Tokens)), htmlRoot)
 		if nil != err {
 		if nil != err {
-			util.LogErrorf("parse HTML failed: %s", err)
+			logging.LogErrorf("parse HTML failed: %s", err)
 			walkStatus = ast.WalkContinue
 			walkStatus = ast.WalkContinue
 			return
 			return
 		}
 		}
@@ -616,7 +617,7 @@ func buildSpanFromNode(n *ast.Node, tree *parse.Tree, rootID, boxID, p string) (
 		if lp := assetLocalPath(dest, boxLocalPath, docDirLocalPath); "" != lp {
 		if lp := assetLocalPath(dest, boxLocalPath, docDirLocalPath); "" != lp {
 			hash, hashErr = util.GetEtag(lp)
 			hash, hashErr = util.GetEtag(lp)
 			if nil != hashErr {
 			if nil != hashErr {
-				util.LogErrorf("calc asset [%s] hash failed: %s", lp, hashErr)
+				logging.LogErrorf("calc asset [%s] hash failed: %s", lp, hashErr)
 			}
 			}
 		}
 		}
 
 
@@ -1027,14 +1028,14 @@ func batchUpdateHPath(tx *sql.Tx, boxID, rootID, oldHPath, newHPath string) (err
 
 
 func CloseDatabase() {
 func CloseDatabase() {
 	if err := db.Close(); nil != err {
 	if err := db.Close(); nil != err {
-		util.LogErrorf("close database failed: %s", err)
+		logging.LogErrorf("close database failed: %s", err)
 	}
 	}
 }
 }
 
 
 func queryRow(query string, args ...interface{}) *sql.Row {
 func queryRow(query string, args ...interface{}) *sql.Row {
 	query = strings.TrimSpace(query)
 	query = strings.TrimSpace(query)
 	if "" == query {
 	if "" == query {
-		util.LogErrorf("statement is empty")
+		logging.LogErrorf("statement is empty")
 		return nil
 		return nil
 	}
 	}
 	return db.QueryRow(query, args...)
 	return db.QueryRow(query, args...)
@@ -1050,7 +1051,7 @@ func query(query string, args ...interface{}) (*sql.Rows, error) {
 
 
 func BeginTx() (tx *sql.Tx, err error) {
 func BeginTx() (tx *sql.Tx, err error) {
 	if tx, err = db.Begin(); nil != err {
 	if tx, err = db.Begin(); nil != err {
-		util.LogErrorf("begin tx failed: %s\n  %s", err, util.ShortStack())
+		logging.LogErrorf("begin tx failed: %s\n  %s", err, logging.ShortStack())
 		if strings.Contains(err.Error(), "database is locked") {
 		if strings.Contains(err.Error(), "database is locked") {
 			os.Exit(util.ExitCodeReadOnlyDatabase)
 			os.Exit(util.ExitCodeReadOnlyDatabase)
 		}
 		}
@@ -1060,19 +1061,19 @@ func BeginTx() (tx *sql.Tx, err error) {
 
 
 func CommitTx(tx *sql.Tx) (err error) {
 func CommitTx(tx *sql.Tx) (err error) {
 	if nil == tx {
 	if nil == tx {
-		util.LogErrorf("tx is nil")
+		logging.LogErrorf("tx is nil")
 		return errors.New("tx is nil")
 		return errors.New("tx is nil")
 	}
 	}
 
 
 	if err = tx.Commit(); nil != err {
 	if err = tx.Commit(); nil != err {
-		util.LogErrorf("commit tx failed: %s\n  %s", err, util.ShortStack())
+		logging.LogErrorf("commit tx failed: %s\n  %s", err, logging.ShortStack())
 	}
 	}
 	return
 	return
 }
 }
 
 
 func RollbackTx(tx *sql.Tx) {
 func RollbackTx(tx *sql.Tx) {
 	if err := tx.Rollback(); nil != err {
 	if err := tx.Rollback(); nil != err {
-		util.LogErrorf("rollback tx failed: %s\n  %s", err, util.ShortStack())
+		logging.LogErrorf("rollback tx failed: %s\n  %s", err, logging.ShortStack())
 	}
 	}
 }
 }
 
 
@@ -1082,7 +1083,7 @@ func prepareExecInsertTx(tx *sql.Tx, stmtSQL string, args []interface{}) (err er
 		return
 		return
 	}
 	}
 	if _, err = stmt.Exec(args...); nil != err {
 	if _, err = stmt.Exec(args...); nil != err {
-		util.LogErrorf("exec database stmt [%s] failed: %s", stmtSQL, err)
+		logging.LogErrorf("exec database stmt [%s] failed: %s", stmtSQL, err)
 		return
 		return
 	}
 	}
 	return
 	return
@@ -1094,9 +1095,9 @@ func execStmtTx(tx *sql.Tx, stmt string, args ...interface{}) (err error) {
 			tx.Rollback()
 			tx.Rollback()
 			db.Close()
 			db.Close()
 			removeDatabaseFile()
 			removeDatabaseFile()
-			util.LogFatalf("database disk image [%s] is malformed, please restart SiYuan kernel to rebuild it", util.DBPath)
+			logging.LogFatalf("database disk image [%s] is malformed, please restart SiYuan kernel to rebuild it", util.DBPath)
 		}
 		}
-		util.LogErrorf("exec database stmt [%s] failed: %s\n  %s", stmt, err, util.ShortStack())
+		logging.LogErrorf("exec database stmt [%s] failed: %s\n  %s", stmt, err, logging.ShortStack())
 		return
 		return
 	}
 	}
 	return
 	return

+ 3 - 3
kernel/sql/file_annotation_ref.go

@@ -17,7 +17,7 @@
 package sql
 package sql
 
 
 import (
 import (
-	"github.com/siyuan-note/siyuan/kernel/util"
+	"github.com/siyuan-note/logging"
 )
 )
 
 
 type FileAnnotationRef struct {
 type FileAnnotationRef struct {
@@ -36,14 +36,14 @@ func QueryRefIDsByAnnotationID(annotationID string) (refIDs, refTexts []string)
 	refIDs = []string{}
 	refIDs = []string{}
 	rows, err := query("SELECT block_id, content FROM file_annotation_refs WHERE annotation_id = ?", annotationID)
 	rows, err := query("SELECT block_id, content FROM file_annotation_refs WHERE annotation_id = ?", annotationID)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", err)
+		logging.LogErrorf("sql query failed: %s", err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
 	for rows.Next() {
 	for rows.Next() {
 		var id, content string
 		var id, content string
 		if err = rows.Scan(&id, &content); nil != err {
 		if err = rows.Scan(&id, &content); nil != err {
-			util.LogErrorf("query scan field failed: %s", err)
+			logging.LogErrorf("query scan field failed: %s", err)
 			return
 			return
 		}
 		}
 		refIDs = append(refIDs, id)
 		refIDs = append(refIDs, id)

+ 9 - 8
kernel/sql/queue.go

@@ -27,6 +27,7 @@ import (
 
 
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/parse"
 	"github.com/emirpasic/gods/sets/hashset"
 	"github.com/emirpasic/gods/sets/hashset"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
 
 
@@ -64,11 +65,11 @@ func WaitForWritingDatabase() {
 	for i := 0; isWritingDatabase(); i++ {
 	for i := 0; isWritingDatabase(); i++ {
 		time.Sleep(50 * time.Millisecond)
 		time.Sleep(50 * time.Millisecond)
 		if 200 < i && !printLog { // 10s 后打日志
 		if 200 < i && !printLog { // 10s 后打日志
-			util.LogWarnf("database is writing: \n%s", util.ShortStack())
+			logging.LogWarnf("database is writing: \n%s", logging.ShortStack())
 			printLog = true
 			printLog = true
 		}
 		}
 		if 1200 < i && !lastPrintLog { // 60s 后打日志
 		if 1200 < i && !lastPrintLog { // 60s 后打日志
-			util.LogWarnf("database is still writing")
+			logging.LogWarnf("database is still writing")
 			lastPrintLog = true
 			lastPrintLog = true
 		}
 		}
 	}
 	}
@@ -102,7 +103,7 @@ func flushTreeQueue() {
 		case "upsert":
 		case "upsert":
 			tree := op.upsertTree
 			tree := op.upsertTree
 			if err = upsertTree(tx, tree); nil != err {
 			if err = upsertTree(tx, tree); nil != err {
-				util.LogErrorf("upsert tree [%s] into database failed: %s", tree.Box+tree.Path, err)
+				logging.LogErrorf("upsert tree [%s] into database failed: %s", tree.Box+tree.Path, err)
 			}
 			}
 			boxes.Add(op.upsertTree.Box)
 			boxes.Add(op.upsertTree.Box)
 		case "delete":
 		case "delete":
@@ -116,13 +117,13 @@ func flushTreeQueue() {
 			updateRootContent(tx, path.Base(op.renameTreeNewHPath), op.renameTreeID)
 			updateRootContent(tx, path.Base(op.renameTreeNewHPath), op.renameTreeID)
 			boxes.Add(op.renameTreeBox)
 			boxes.Add(op.renameTreeBox)
 		default:
 		default:
-			util.LogErrorf("unknown operation [%s]", op.action)
+			logging.LogErrorf("unknown operation [%s]", op.action)
 		}
 		}
 	}
 	}
 	CommitTx(tx)
 	CommitTx(tx)
 	elapsed := time.Now().Sub(start).Milliseconds()
 	elapsed := time.Now().Sub(start).Milliseconds()
 	if 5000 < elapsed {
 	if 5000 < elapsed {
-		util.LogInfof("op tx [%dms]", elapsed)
+		logging.LogInfof("op tx [%dms]", elapsed)
 	}
 	}
 
 
 	start = time.Now()
 	start = time.Now()
@@ -136,7 +137,7 @@ func flushTreeQueue() {
 	CommitTx(tx)
 	CommitTx(tx)
 	elapsed = time.Now().Sub(start).Milliseconds()
 	elapsed = time.Now().Sub(start).Milliseconds()
 	if 1000 < elapsed {
 	if 1000 < elapsed {
-		util.LogInfof("hash tx [%dms]", elapsed)
+		logging.LogInfof("hash tx [%dms]", elapsed)
 	}
 	}
 }
 }
 
 
@@ -219,7 +220,7 @@ func updateBoxHash(tx *sql.Tx, boxID string) {
 func boxChecksum(box string) (ret string) {
 func boxChecksum(box string) (ret string) {
 	rows, err := query("SELECT hash FROM blocks WHERE type = 'd' AND box = ? ORDER BY id DESC", box)
 	rows, err := query("SELECT hash FROM blocks WHERE type = 'd' AND box = ? ORDER BY id DESC", box)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", err)
+		logging.LogErrorf("sql query failed: %s", err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -227,7 +228,7 @@ func boxChecksum(box string) (ret string) {
 	for rows.Next() {
 	for rows.Next() {
 		var hash string
 		var hash string
 		if err = rows.Scan(&hash); nil != err {
 		if err = rows.Scan(&hash); nil != err {
-			util.LogErrorf("query scan field failed: %s", err)
+			logging.LogErrorf("query scan field failed: %s", err)
 			return
 			return
 		}
 		}
 		buf.WriteString(hash)
 		buf.WriteString(hash)

+ 6 - 6
kernel/sql/span.go

@@ -22,7 +22,7 @@ import (
 	"strings"
 	"strings"
 
 
 	"github.com/88250/vitess-sqlparser/sqlparser"
 	"github.com/88250/vitess-sqlparser/sqlparser"
-	"github.com/siyuan-note/siyuan/kernel/util"
+	"github.com/siyuan-note/logging"
 )
 )
 
 
 type Span struct {
 type Span struct {
@@ -40,7 +40,7 @@ type Span struct {
 func SelectSpansRawStmt(stmt string, limit int) (ret []*Span) {
 func SelectSpansRawStmt(stmt string, limit int) (ret []*Span) {
 	parsedStmt, err := sqlparser.Parse(stmt)
 	parsedStmt, err := sqlparser.Parse(stmt)
 	if nil != err {
 	if nil != err {
-		//util.LogErrorf("select [%s] failed: %s", stmt, err)
+		//logging.LogErrorf("select [%s] failed: %s", stmt, err)
 		return
 		return
 	}
 	}
 	switch parsedStmt.(type) {
 	switch parsedStmt.(type) {
@@ -69,7 +69,7 @@ func SelectSpansRawStmt(stmt string, limit int) (ret []*Span) {
 		if strings.Contains(err.Error(), "syntax error") {
 		if strings.Contains(err.Error(), "syntax error") {
 			return
 			return
 		}
 		}
-		util.LogWarnf("sql query [%s] failed: %s", stmt, err)
+		logging.LogWarnf("sql query [%s] failed: %s", stmt, err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -85,7 +85,7 @@ func QueryTagSpansByKeyword(keyword string, limit int) (ret []*Span) {
 	stmt += " LIMIT " + strconv.Itoa(limit)
 	stmt += " LIMIT " + strconv.Itoa(limit)
 	rows, err := query(stmt)
 	rows, err := query(stmt)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", err)
+		logging.LogErrorf("sql query failed: %s", err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -104,7 +104,7 @@ func QueryTagSpans(p string, limit int) (ret []*Span) {
 	stmt += " LIMIT " + strconv.Itoa(limit)
 	stmt += " LIMIT " + strconv.Itoa(limit)
 	rows, err := query(stmt)
 	rows, err := query(stmt)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("sql query failed: %s", err)
+		logging.LogErrorf("sql query failed: %s", err)
 		return
 		return
 	}
 	}
 	defer rows.Close()
 	defer rows.Close()
@@ -118,7 +118,7 @@ func QueryTagSpans(p string, limit int) (ret []*Span) {
 func scanSpanRows(rows *sql.Rows) (ret *Span) {
 func scanSpanRows(rows *sql.Rows) (ret *Span) {
 	var span Span
 	var span Span
 	if err := rows.Scan(&span.ID, &span.BlockID, &span.RootID, &span.Box, &span.Path, &span.Content, &span.Markdown, &span.Type, &span.IAL); nil != err {
 	if err := rows.Scan(&span.ID, &span.BlockID, &span.RootID, &span.Box, &span.Path, &span.Content, &span.Markdown, &span.Type, &span.IAL); nil != err {
-		util.LogErrorf("query scan field failed: %s", err)
+		logging.LogErrorf("query scan field failed: %s", err)
 		return
 		return
 	}
 	}
 	ret = &span
 	ret = &span

+ 2 - 1
kernel/sql/stat.go

@@ -20,6 +20,7 @@ import (
 	"database/sql"
 	"database/sql"
 	"strings"
 	"strings"
 
 
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
 
 
@@ -34,7 +35,7 @@ func getDatabaseVer() (ret string) {
 	row := db.QueryRow(stmt, key)
 	row := db.QueryRow(stmt, key)
 	if err := row.Scan(&ret); nil != err {
 	if err := row.Scan(&ret); nil != err {
 		if !strings.Contains(err.Error(), "no such table") {
 		if !strings.Contains(err.Error(), "no such table") {
-			util.LogErrorf("query database version failed: %s", err)
+			logging.LogErrorf("query database version failed: %s", err)
 		}
 		}
 	}
 	}
 	return
 	return

+ 4 - 3
kernel/sql/upsert.go

@@ -23,6 +23,7 @@ import (
 
 
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/parse"
 	"github.com/emirpasic/gods/sets/hashset"
 	"github.com/emirpasic/gods/sets/hashset"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
@@ -35,14 +36,14 @@ func init() {
 
 
 func InsertBlocksSpans(tx *sql.Tx, tree *parse.Tree) (err error) {
 func InsertBlocksSpans(tx *sql.Tx, tree *parse.Tree) (err error) {
 	if err = insertBlocksSpans(tx, tree); nil != err {
 	if err = insertBlocksSpans(tx, tree); nil != err {
-		util.LogErrorf("insert tree [%s] into database failed: %s", tree.Box+tree.Path, err)
+		logging.LogErrorf("insert tree [%s] into database failed: %s", tree.Box+tree.Path, err)
 	}
 	}
 	return
 	return
 }
 }
 
 
 func InsertRefs(tx *sql.Tx, tree *parse.Tree) {
 func InsertRefs(tx *sql.Tx, tree *parse.Tree) {
 	if err := insertRef(tx, tree); nil != err {
 	if err := insertRef(tx, tree); nil != err {
-		util.LogErrorf("insert refs tree [%s] into database failed: %s", tree.Box+tree.Path, err)
+		logging.LogErrorf("insert refs tree [%s] into database failed: %s", tree.Box+tree.Path, err)
 	}
 	}
 }
 }
 
 
@@ -465,7 +466,7 @@ func upsertTree(tx *sql.Tx, tree *parse.Tree) (err error) {
 		}
 		}
 		subTree := parse.Parse("", []byte(block.Markdown), luteEngine.ParseOptions)
 		subTree := parse.Parse("", []byte(block.Markdown), luteEngine.ParseOptions)
 		if nil == subTree {
 		if nil == subTree {
-			util.LogErrorf("parse temp block [%s] failed: %s", block.ID, err)
+			logging.LogErrorf("parse temp block [%s] failed: %s", block.ID, err)
 			continue
 			continue
 		}
 		}
 		if 0 < len(treenode.GetLegacyDynamicBlockRefDefIDs(subTree.Root)) {
 		if 0 < len(treenode.GetLegacyDynamicBlockRefDefIDs(subTree.Root)) {

+ 12 - 11
kernel/treenode/blocktree.go

@@ -29,6 +29,7 @@ import (
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/parse"
 	"github.com/dustin/go-humanize"
 	"github.com/dustin/go-humanize"
+	"github.com/siyuan-note/logging"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/vmihailenco/msgpack/v5"
 	"github.com/vmihailenco/msgpack/v5"
 )
 )
@@ -226,28 +227,28 @@ func InitBlockTree() {
 
 
 	var err error
 	var err error
 	if err = blocktreeFileLock.Lock(); nil != err {
 	if err = blocktreeFileLock.Lock(); nil != err {
-		util.LogErrorf("read block tree failed: %s", err)
+		logging.LogErrorf("read block tree failed: %s", err)
 		os.Exit(util.ExitCodeBlockTreeErr)
 		os.Exit(util.ExitCodeBlockTreeErr)
 		return
 		return
 	}
 	}
 
 
 	fh := blocktreeFileLock.Fh()
 	fh := blocktreeFileLock.Fh()
 	if _, err = fh.Seek(0, io.SeekStart); nil != err {
 	if _, err = fh.Seek(0, io.SeekStart); nil != err {
-		util.LogErrorf("read block tree failed: %s", err)
+		logging.LogErrorf("read block tree failed: %s", err)
 		os.Exit(util.ExitCodeBlockTreeErr)
 		os.Exit(util.ExitCodeBlockTreeErr)
 		return
 		return
 	}
 	}
 	data, err := io.ReadAll(fh)
 	data, err := io.ReadAll(fh)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("read block tree failed: %s", err)
+		logging.LogErrorf("read block tree failed: %s", err)
 		os.Exit(util.ExitCodeBlockTreeErr)
 		os.Exit(util.ExitCodeBlockTreeErr)
 		return
 		return
 	}
 	}
 	blockTreesLock.Lock()
 	blockTreesLock.Lock()
 	if err = msgpack.Unmarshal(data, &blockTrees); nil != err {
 	if err = msgpack.Unmarshal(data, &blockTrees); nil != err {
-		util.LogErrorf("unmarshal block tree failed: %s", err)
+		logging.LogErrorf("unmarshal block tree failed: %s", err)
 		if err = os.RemoveAll(util.BlockTreePath); nil != err {
 		if err = os.RemoveAll(util.BlockTreePath); nil != err {
-			util.LogErrorf("removed corrupted block tree failed: %s", err)
+			logging.LogErrorf("removed corrupted block tree failed: %s", err)
 		}
 		}
 		os.Exit(util.ExitCodeBlockTreeErr)
 		os.Exit(util.ExitCodeBlockTreeErr)
 		return
 		return
@@ -255,7 +256,7 @@ func InitBlockTree() {
 	blockTreesLock.Unlock()
 	blockTreesLock.Unlock()
 	debug.FreeOSMemory()
 	debug.FreeOSMemory()
 	if elapsed := time.Since(start).Seconds(); 2 < elapsed {
 	if elapsed := time.Since(start).Seconds(); 2 < elapsed {
-		util.LogWarnf("read block tree [%s] to [%s], elapsed [%.2fs]", humanize.Bytes(uint64(len(data))), util.BlockTreePath, elapsed)
+		logging.LogWarnf("read block tree [%s] to [%s], elapsed [%.2fs]", humanize.Bytes(uint64(len(data))), util.BlockTreePath, elapsed)
 	}
 	}
 	return
 	return
 }
 }
@@ -268,7 +269,7 @@ func SaveBlockTree() {
 	}
 	}
 
 
 	if err := blocktreeFileLock.Lock(); nil != err {
 	if err := blocktreeFileLock.Lock(); nil != err {
-		util.LogErrorf("read block tree failed: %s", err)
+		logging.LogErrorf("read block tree failed: %s", err)
 		os.Exit(util.ExitCodeBlockTreeErr)
 		os.Exit(util.ExitCodeBlockTreeErr)
 		return
 		return
 	}
 	}
@@ -276,7 +277,7 @@ func SaveBlockTree() {
 	blockTreesLock.Lock()
 	blockTreesLock.Lock()
 	data, err := msgpack.Marshal(blockTrees)
 	data, err := msgpack.Marshal(blockTrees)
 	if nil != err {
 	if nil != err {
-		util.LogErrorf("marshal block tree failed: %s", err)
+		logging.LogErrorf("marshal block tree failed: %s", err)
 		os.Exit(util.ExitCodeBlockTreeErr)
 		os.Exit(util.ExitCodeBlockTreeErr)
 		return
 		return
 	}
 	}
@@ -284,19 +285,19 @@ func SaveBlockTree() {
 
 
 	fh := blocktreeFileLock.Fh()
 	fh := blocktreeFileLock.Fh()
 	if err = gulu.File.WriteFileSaferByHandle(fh, data); nil != err {
 	if err = gulu.File.WriteFileSaferByHandle(fh, data); nil != err {
-		util.LogErrorf("write block tree failed: %s", err)
+		logging.LogErrorf("write block tree failed: %s", err)
 		os.Exit(util.ExitCodeBlockTreeErr)
 		os.Exit(util.ExitCodeBlockTreeErr)
 		return
 		return
 	}
 	}
 	debug.FreeOSMemory()
 	debug.FreeOSMemory()
 	if elapsed := time.Since(start).Seconds(); 2 < elapsed {
 	if elapsed := time.Since(start).Seconds(); 2 < elapsed {
-		util.LogWarnf("save block tree [size=%s] to [%s], elapsed [%.2fs]", humanize.Bytes(uint64(len(data))), util.BlockTreePath, elapsed)
+		logging.LogWarnf("save block tree [size=%s] to [%s], elapsed [%.2fs]", humanize.Bytes(uint64(len(data))), util.BlockTreePath, elapsed)
 	}
 	}
 }
 }
 
 
 func CloseBlockTree() {
 func CloseBlockTree() {
 	SaveBlockTree()
 	SaveBlockTree()
 	if err := blocktreeFileLock.Unlock(); nil != err {
 	if err := blocktreeFileLock.Unlock(); nil != err {
-		util.LogErrorf("close block tree failed: %s", err)
+		logging.LogErrorf("close block tree failed: %s", err)
 	}
 	}
 }
 }

+ 2 - 2
kernel/treenode/node.go

@@ -25,7 +25,7 @@ import (
 	"github.com/88250/lute/html"
 	"github.com/88250/lute/html"
 	"github.com/88250/lute/lex"
 	"github.com/88250/lute/lex"
 	"github.com/88250/lute/parse"
 	"github.com/88250/lute/parse"
-	"github.com/siyuan-note/siyuan/kernel/util"
+	"github.com/siyuan-note/logging"
 )
 )
 
 
 func NodeStaticMdContent(node *ast.Node, luteEngine *lute.Lute) (md, content string) {
 func NodeStaticMdContent(node *ast.Node, luteEngine *lute.Lute) (md, content string) {
@@ -38,7 +38,7 @@ func FormatNode(node *ast.Node, luteEngine *lute.Lute) string {
 	markdown, err := lute.FormatNodeSync(node, luteEngine.ParseOptions, luteEngine.RenderOptions)
 	markdown, err := lute.FormatNodeSync(node, luteEngine.ParseOptions, luteEngine.RenderOptions)
 	if nil != err {
 	if nil != err {
 		root := TreeRoot(node)
 		root := TreeRoot(node)
-		util.LogFatalf("format node [%s] in tree [%s] failed: %s", node.ID, root.ID, err)
+		logging.LogFatalf("format node [%s] in tree [%s] failed: %s", node.ID, root.ID, err)
 	}
 	}
 	return markdown
 	return markdown
 }
 }

+ 5 - 3
kernel/util/crypt.go

@@ -21,6 +21,8 @@ import (
 	"crypto/aes"
 	"crypto/aes"
 	"crypto/cipher"
 	"crypto/cipher"
 	"encoding/hex"
 	"encoding/hex"
+
+	"github.com/siyuan-note/logging"
 )
 )
 
 
 var SK = []byte("696D897C9AA0611B")
 var SK = []byte("696D897C9AA0611B")
@@ -30,13 +32,13 @@ func AESEncrypt(str string) string {
 	buf.Grow(4096)
 	buf.Grow(4096)
 	_, err := hex.NewEncoder(buf).Write([]byte(str))
 	_, err := hex.NewEncoder(buf).Write([]byte(str))
 	if nil != err {
 	if nil != err {
-		LogErrorf("encrypt failed: %s", err)
+		logging.LogErrorf("encrypt failed: %s", err)
 		return ""
 		return ""
 	}
 	}
 	data := buf.Bytes()
 	data := buf.Bytes()
 	block, err := aes.NewCipher(SK)
 	block, err := aes.NewCipher(SK)
 	if nil != err {
 	if nil != err {
-		LogErrorf("encrypt failed: %s", err)
+		logging.LogErrorf("encrypt failed: %s", err)
 		return ""
 		return ""
 	}
 	}
 	cbc := cipher.NewCBCEncrypter(block, []byte("RandomInitVector"))
 	cbc := cipher.NewCBCEncrypter(block, []byte("RandomInitVector"))
@@ -56,7 +58,7 @@ func pkcs5Padding(ciphertext []byte, blockSize int) []byte {
 func AESDecrypt(cryptStr string) []byte {
 func AESDecrypt(cryptStr string) []byte {
 	crypt, err := hex.DecodeString(cryptStr)
 	crypt, err := hex.DecodeString(cryptStr)
 	if nil != err {
 	if nil != err {
-		LogErrorf("decrypt failed: %s", err)
+		logging.LogErrorf("decrypt failed: %s", err)
 		return nil
 		return nil
 	}
 	}
 
 

+ 5 - 4
kernel/util/file.go

@@ -25,6 +25,7 @@ import (
 
 
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/88250/lute/ast"
 	"github.com/88250/lute/ast"
+	"github.com/siyuan-note/logging"
 )
 )
 
 
 func IsEmptyDir(p string) bool {
 func IsEmptyDir(p string) bool {
@@ -79,7 +80,7 @@ func LatestTmpFile(p string) string {
 	dir, base := filepath.Split(p)
 	dir, base := filepath.Split(p)
 	files, err := os.ReadDir(dir)
 	files, err := os.ReadDir(dir)
 	if nil != err {
 	if nil != err {
-		LogErrorf("read dir [%s] failed: %s", dir, err)
+		logging.LogErrorf("read dir [%s] failed: %s", dir, err)
 		return ""
 		return ""
 	}
 	}
 
 
@@ -100,12 +101,12 @@ func LatestTmpFile(p string) string {
 	sort.Slice(tmps, func(i, j int) bool {
 	sort.Slice(tmps, func(i, j int) bool {
 		info1, err := tmps[i].Info()
 		info1, err := tmps[i].Info()
 		if nil != err {
 		if nil != err {
-			LogErrorf("read file info [%s] failed: %s", tmps[i].Name(), err)
+			logging.LogErrorf("read file info [%s] failed: %s", tmps[i].Name(), err)
 			return false
 			return false
 		}
 		}
 		info2, err := tmps[j].Info()
 		info2, err := tmps[j].Info()
 		if nil != err {
 		if nil != err {
-			LogErrorf("read file info [%s] failed: %s", tmps[j].Name(), err)
+			logging.LogErrorf("read file info [%s] failed: %s", tmps[j].Name(), err)
 			return false
 			return false
 		}
 		}
 		return info1.ModTime().After(info2.ModTime())
 		return info1.ModTime().After(info2.ModTime())
@@ -208,7 +209,7 @@ func SizeOfDirectory(path string, includeBigFile bool) (int64, error) {
 		return nil
 		return nil
 	})
 	})
 	if nil != err {
 	if nil != err {
-		LogErrorf("size of dir [%s] failed: %s", path, err)
+		logging.LogErrorf("size of dir [%s] failed: %s", path, err)
 	}
 	}
 	return size, err
 	return size, err
 }
 }

+ 2 - 1
kernel/util/font.go

@@ -24,6 +24,7 @@ import (
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/ConradIrwin/font/sfnt"
 	"github.com/ConradIrwin/font/sfnt"
 	"github.com/flopp/go-findfont"
 	"github.com/flopp/go-findfont"
+	"github.com/siyuan-note/logging"
 	ttc "golang.org/x/image/font/sfnt"
 	ttc "golang.org/x/image/font/sfnt"
 	textUnicode "golang.org/x/text/encoding/unicode"
 	textUnicode "golang.org/x/text/encoding/unicode"
 	"golang.org/x/text/transform"
 	"golang.org/x/text/transform"
@@ -54,7 +55,7 @@ func loadFonts(currentLanguage string) (ret []string) {
 		if strings.HasSuffix(strings.ToLower(f), ".ttc") {
 		if strings.HasSuffix(strings.ToLower(f), ".ttc") {
 			data, err := os.ReadFile(f)
 			data, err := os.ReadFile(f)
 			if nil != err {
 			if nil != err {
-				LogErrorf("read font file [%s] failed: %s", f, err)
+				logging.LogErrorf("read font file [%s] failed: %s", f, err)
 				continue
 				continue
 			}
 			}
 			collection, err := ttc.ParseCollection(data)
 			collection, err := ttc.ParseCollection(data)

+ 0 - 340
kernel/util/log.go

@@ -1,340 +0,0 @@
-// SiYuan - Build Your Eternal Digital Garden
-// Copyright (c) 2020-present, b3log.org
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program.  If not, see <https://www.gnu.org/licenses/>.
-
-package util
-
-import (
-	"bytes"
-	"fmt"
-	"io"
-	stdlog "log"
-	"os"
-	"runtime"
-	"runtime/debug"
-	"strings"
-
-	"github.com/88250/gulu"
-	"github.com/getsentry/sentry-go"
-)
-
-func ShortStack() string {
-	output := string(debug.Stack())
-	lines := strings.Split(output, "\n")
-	if 5 < len(lines) {
-		lines = lines[5:]
-	}
-	buf := bytes.Buffer{}
-	for _, l := range lines {
-		if strings.Contains(l, "gin-gonic") {
-			break
-		}
-		buf.WriteString("    ")
-		buf.WriteString(l)
-		buf.WriteByte('\n')
-	}
-	return buf.String()
-}
-
-var (
-	logger  *Logger
-	logFile *os.File
-)
-
-func LogTracef(format string, v ...interface{}) {
-	if !logger.IsTraceEnabled() {
-		return
-	}
-
-	defer closeLogger()
-	openLogger()
-	logger.Tracef(format, v...)
-}
-
-func LogDebugf(format string, v ...interface{}) {
-	if !logger.IsDebugEnabled() {
-		return
-	}
-
-	defer closeLogger()
-	openLogger()
-	logger.Debugf(format, v...)
-}
-
-func LogInfof(format string, v ...interface{}) {
-	defer closeLogger()
-	openLogger()
-	logger.Infof(format, v...)
-}
-
-func LogErrorf(format string, v ...interface{}) {
-	defer closeLogger()
-	openLogger()
-	logger.Errorf(format, v...)
-}
-
-func LogWarnf(format string, v ...interface{}) {
-	if !logger.IsWarnEnabled() {
-		return
-	}
-
-	defer closeLogger()
-	openLogger()
-	logger.Warnf(format, v...)
-}
-
-func LogFatalf(format string, v ...interface{}) {
-	openLogger()
-	logger.Fatalf(format, v...)
-}
-
-func openLogger() {
-	if gulu.File.IsExist(LogPath) {
-		if size := gulu.File.GetFileSize(LogPath); 1024*1024*2 <= size {
-			// 日志文件大于 2M 的话删了重建
-			os.Remove(LogPath)
-		}
-	}
-
-	var err error
-	logFile, err = os.OpenFile(LogPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
-	if nil != err {
-		stdlog.Fatalf("create log file [%s] failed: %s", LogPath, err)
-	}
-	logger = NewLogger(io.MultiWriter(os.Stdout, logFile))
-}
-
-func closeLogger() {
-	logFile.Close()
-}
-
-func Recover() {
-	if e := recover(); nil != e {
-		stack := stack()
-		msg := fmt.Sprintf("PANIC RECOVERED: %v\n\t%s\n", e, stack)
-		LogErrorf(msg)
-	}
-}
-
-var (
-	dunno     = []byte("???")
-	centerDot = []byte("·")
-	dot       = []byte(".")
-	slash     = []byte("/")
-)
-
-// stack implements Stack, skipping 2 frames.
-func stack() []byte {
-	buf := &bytes.Buffer{} // the returned data
-	// As we loop, we open files and read them. These variables record the currently
-	// loaded file.
-	var lines [][]byte
-	var lastFile string
-	for i := 2; ; i++ { // Caller we care about is the user, 2 frames up
-		pc, file, line, ok := runtime.Caller(i)
-		if !ok {
-			break
-		}
-		// Print this much at least.  If we can't find the source, it won't show.
-		fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
-		if file != lastFile {
-			data, err := os.ReadFile(file)
-			if err != nil {
-				continue
-			}
-			lines = bytes.Split(data, []byte{'\n'})
-			lastFile = file
-		}
-		line-- // in stack trace, lines are 1-indexed but our array is 0-indexed
-		fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
-	}
-	return buf.Bytes()
-}
-
-// source returns a space-trimmed slice of the n'th line.
-func source(lines [][]byte, n int) []byte {
-	if n < 0 || n >= len(lines) {
-		return dunno
-	}
-	return bytes.Trim(lines[n], " \t")
-}
-
-// function returns, if possible, the name of the function containing the PC.
-func function(pc uintptr) []byte {
-	fn := runtime.FuncForPC(pc)
-	if fn == nil {
-		return dunno
-	}
-	name := []byte(fn.Name())
-	// The name includes the path name to the package, which is unnecessary
-	// since the file name is already included.  Plus, it has center dots.
-	// That is, we see
-	//	runtime/debug.*T·ptrmethod
-	// and want
-	//	*T.ptrmethod
-	// Since the package path might contains dots (e.g. code.google.com/...),
-	// we first remove the path prefix if there is one.
-	if lastslash := bytes.LastIndex(name, slash); lastslash >= 0 {
-		name = name[lastslash+1:]
-	}
-	if period := bytes.Index(name, dot); period >= 0 {
-		name = name[period+1:]
-	}
-	name = bytes.Replace(name, centerDot, dot, -1)
-	return name
-}
-
-// Logging level.
-const (
-	Off = iota
-	Trace
-	Debug
-	Info
-	Warn
-	Error
-	Fatal
-)
-
-// the global default logging level, it will be used for creating logger.
-var logLevel = Debug
-
-// Logger represents a simple logger with level.
-// The underlying logger is the standard Go logging "log".
-type Logger struct {
-	level  int
-	logger *stdlog.Logger
-}
-
-// NewLogger creates a logger.
-func NewLogger(out io.Writer) *Logger {
-	ret := &Logger{level: logLevel, logger: stdlog.New(out, "", stdlog.Ldate|stdlog.Ltime|stdlog.Lshortfile)}
-	return ret
-}
-
-// SetLogLevel sets the logging level of all loggers.
-func SetLogLevel(level string) {
-	logLevel = getLevel(level)
-}
-
-// getLevel gets logging level int value corresponding to the specified level.
-func getLevel(level string) int {
-	level = strings.ToLower(level)
-
-	switch level {
-	case "off":
-		return Off
-	case "trace":
-		return Trace
-	case "debug":
-		return Debug
-	case "info":
-		return Info
-	case "warn":
-		return Warn
-	case "error":
-		return Error
-	case "fatal":
-		return Fatal
-	default:
-		return Info
-	}
-}
-
-// SetLevel sets the logging level of a logger.
-func (l *Logger) SetLevel(level string) {
-	l.level = getLevel(level)
-}
-
-// IsTraceEnabled determines whether the trace level is enabled.
-func (l *Logger) IsTraceEnabled() bool {
-	return l.level <= Trace
-}
-
-// IsDebugEnabled determines whether the debug level is enabled.
-func (l *Logger) IsDebugEnabled() bool {
-	return l.level <= Debug
-}
-
-// IsWarnEnabled determines whether the debug level is enabled.
-func (l *Logger) IsWarnEnabled() bool {
-	return l.level <= Warn
-}
-
-// Tracef prints trace level message with format.
-func (l *Logger) Tracef(format string, v ...interface{}) {
-	if Trace < l.level {
-		return
-	}
-
-	l.logger.SetPrefix("T ")
-	l.logger.Output(3, fmt.Sprintf(format, v...))
-}
-
-// Debugf prints debug level message with format.
-func (l *Logger) Debugf(format string, v ...interface{}) {
-	if Debug < l.level {
-		return
-	}
-
-	l.logger.SetPrefix("D ")
-	l.logger.Output(3, fmt.Sprintf(format, v...))
-}
-
-// Infof prints info level message with format.
-func (l *Logger) Infof(format string, v ...interface{}) {
-	if Info < l.level {
-		return
-	}
-
-	l.logger.SetPrefix("I ")
-	l.logger.Output(3, fmt.Sprintf(format, v...))
-}
-
-// Warnf prints warning level message with format.
-func (l *Logger) Warnf(format string, v ...interface{}) {
-	if Warn < l.level {
-		return
-	}
-
-	l.logger.SetPrefix("W ")
-	msg := fmt.Sprintf(format, v...)
-	l.logger.Output(3, msg)
-}
-
-// Errorf prints error level message with format.
-func (l *Logger) Errorf(format string, v ...interface{}) {
-	if Error < l.level {
-		return
-	}
-
-	l.logger.SetPrefix("E ")
-	msg := fmt.Sprintf(format, v...)
-	l.logger.Output(3, msg)
-	sentry.CaptureMessage(msg)
-}
-
-// Fatalf prints fatal level message with format and exit process with code 1.
-func (l *Logger) Fatalf(format string, v ...interface{}) {
-	if Fatal < l.level {
-		return
-	}
-
-	l.logger.SetPrefix("F ")
-	msg := fmt.Sprintf(format, v...)
-	l.logger.Output(3, msg)
-	sentry.CaptureMessage(msg)
-	closeLogger()
-	os.Exit(ExitCodeFatal)
-}

+ 2 - 1
kernel/util/path.go

@@ -25,6 +25,7 @@ import (
 	"strings"
 	"strings"
 
 
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
+	"github.com/siyuan-note/logging"
 )
 )
 
 
 var (
 var (
@@ -96,7 +97,7 @@ func GetLocalIPs() (ret []string) {
 	ret = []string{}
 	ret = []string{}
 	addrs, err := net.InterfaceAddrs()
 	addrs, err := net.InterfaceAddrs()
 	if nil != err {
 	if nil != err {
-		LogWarnf("get interface addresses failed: %s", err)
+		logging.LogWarnf("get interface addresses failed: %s", err)
 		return
 		return
 	}
 	}
 	for _, addr := range addrs {
 	for _, addr := range addrs {

+ 5 - 2
kernel/util/result.go

@@ -16,7 +16,10 @@
 
 
 package util
 package util
 
 
-import "github.com/88250/gulu"
+import (
+	"github.com/88250/gulu"
+	"github.com/siyuan-note/logging"
+)
 
 
 type PushMode int
 type PushMode int
 
 
@@ -64,7 +67,7 @@ func NewCmdResult(cmdName string, cmdId float64, pushMode, reloadPushMode PushMo
 func (r *Result) Bytes() []byte {
 func (r *Result) Bytes() []byte {
 	ret, err := gulu.JSON.MarshalJSON(r)
 	ret, err := gulu.JSON.MarshalJSON(r)
 	if nil != err {
 	if nil != err {
-		LogErrorf("marshal result [%+v] failed [%s]", r, err)
+		logging.LogErrorf("marshal result [%+v] failed [%s]", r, err)
 	}
 	}
 	return ret
 	return ret
 }
 }

+ 2 - 1
kernel/util/rhy.go

@@ -21,6 +21,7 @@ import (
 	"time"
 	"time"
 
 
 	"github.com/siyuan-note/httpclient"
 	"github.com/siyuan-note/httpclient"
+	"github.com/siyuan-note/logging"
 )
 )
 
 
 var cachedRhyResult = map[string]interface{}{}
 var cachedRhyResult = map[string]interface{}{}
@@ -39,7 +40,7 @@ func GetRhyResult(force bool) (map[string]interface{}, error) {
 	request := httpclient.NewCloudRequest()
 	request := httpclient.NewCloudRequest()
 	_, err := request.SetResult(&cachedRhyResult).Get(AliyunServer + "/apis/siyuan/version?ver=" + Ver)
 	_, err := request.SetResult(&cachedRhyResult).Get(AliyunServer + "/apis/siyuan/version?ver=" + Ver)
 	if nil != err {
 	if nil != err {
-		LogErrorf("get version info failed: %s", err)
+		logging.LogErrorf("get version info failed: %s", err)
 		return nil, err
 		return nil, err
 	}
 	}
 	rhyResultCacheTime = now
 	rhyResultCacheTime = now

+ 5 - 4
kernel/util/runtime.go

@@ -26,6 +26,7 @@ import (
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/denisbrodbeck/machineid"
 	"github.com/denisbrodbeck/machineid"
 	"github.com/dustin/go-humanize"
 	"github.com/dustin/go-humanize"
+	"github.com/siyuan-note/logging"
 )
 )
 
 
 const DatabaseVer = "20220501" // 修改表结构的话需要修改这里
 const DatabaseVer = "20220501" // 修改表结构的话需要修改这里
@@ -43,7 +44,7 @@ func logBootInfo() {
 	s, _ := SizeOfDirectory(DataDir, true)
 	s, _ := SizeOfDirectory(DataDir, true)
 	dataDirSize := humanize.Bytes(uint64(s))
 	dataDirSize := humanize.Bytes(uint64(s))
 
 
-	LogInfof("kernel is booting:\n"+
+	logging.LogInfof("kernel is booting:\n"+
 		"    * ver [%s]\n"+
 		"    * ver [%s]\n"+
 		"    * arch [%s]\n"+
 		"    * arch [%s]\n"+
 		"    * runtime mode [%s]\n"+
 		"    * runtime mode [%s]\n"+
@@ -78,13 +79,13 @@ func GetDeviceID() string {
 
 
 func SetNetworkProxy(proxyURL string) {
 func SetNetworkProxy(proxyURL string) {
 	if err := os.Setenv("HTTPS_PROXY", proxyURL); nil != err {
 	if err := os.Setenv("HTTPS_PROXY", proxyURL); nil != err {
-		logger.Errorf("set env [HTTPS_PROXY] failed: %s", err)
+		logging.LogErrorf("set env [HTTPS_PROXY] failed: %s", err)
 	}
 	}
 	if err := os.Setenv("HTTP_PROXY", proxyURL); nil != err {
 	if err := os.Setenv("HTTP_PROXY", proxyURL); nil != err {
-		logger.Errorf("set env [HTTP_PROXY] failed: %s", err)
+		logging.LogErrorf("set env [HTTP_PROXY] failed: %s", err)
 	}
 	}
 
 
 	if "" != proxyURL {
 	if "" != proxyURL {
-		logger.Infof("use network proxy [%s]", proxyURL)
+		logging.LogInfof("use network proxy [%s]", proxyURL)
 	}
 	}
 }
 }

+ 3 - 2
kernel/util/web.go

@@ -24,6 +24,7 @@ import (
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/88250/melody"
 	"github.com/88250/melody"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
+	"github.com/siyuan-note/logging"
 )
 )
 
 
 func GetRemoteAddr(session *melody.Session) string {
 func GetRemoteAddr(session *melody.Session) string {
@@ -70,14 +71,14 @@ func tryToListenPort() bool {
 		time.Sleep(time.Second * 3)
 		time.Sleep(time.Second * 3)
 		listener, err = net.Listen("tcp", "127.0.0.1:"+ServerPort)
 		listener, err = net.Listen("tcp", "127.0.0.1:"+ServerPort)
 		if nil != err {
 		if nil != err {
-			LogErrorf("try to listen port [%s] failed: %s", ServerPort, err)
+			logging.LogErrorf("try to listen port [%s] failed: %s", ServerPort, err)
 			return false
 			return false
 		}
 		}
 	}
 	}
 	if err = listener.Close(); nil != err {
 	if err = listener.Close(); nil != err {
 		time.Sleep(time.Second * 1)
 		time.Sleep(time.Second * 1)
 		if err = listener.Close(); nil != err {
 		if err = listener.Close(); nil != err {
-			LogErrorf("close listen port [%s] failed: %s", ServerPort, err)
+			logging.LogErrorf("close listen port [%s] failed: %s", ServerPort, err)
 		}
 		}
 	}
 	}
 	return true
 	return true

+ 15 - 13
kernel/util/working.go

@@ -33,6 +33,7 @@ import (
 	figure "github.com/common-nighthawk/go-figure"
 	figure "github.com/common-nighthawk/go-figure"
 	goPS "github.com/mitchellh/go-ps"
 	goPS "github.com/mitchellh/go-ps"
 	"github.com/siyuan-note/httpclient"
 	"github.com/siyuan-note/httpclient"
+	"github.com/siyuan-note/logging"
 )
 )
 
 
 //var Mode = "dev"
 //var Mode = "dev"
@@ -87,6 +88,7 @@ func Boot() {
 
 
 	SSL = *ssl
 	SSL = *ssl
 	LogPath = filepath.Join(TempDir, "siyuan.log")
 	LogPath = filepath.Join(TempDir, "siyuan.log")
+	logging.SetLogPath(LogPath)
 	AppearancePath = filepath.Join(ConfDir, "appearance")
 	AppearancePath = filepath.Join(ConfDir, "appearance")
 	if "dev" == Mode {
 	if "dev" == Mode {
 		ThemesPath = filepath.Join(WorkingDir, "appearance", "themes")
 		ThemesPath = filepath.Join(WorkingDir, "appearance", "themes")
@@ -100,7 +102,7 @@ func Boot() {
 	checkPort()
 	checkPort()
 
 
 	bootBanner := figure.NewColorFigure("SiYuan", "isometric3", "green", true)
 	bootBanner := figure.NewColorFigure("SiYuan", "isometric3", "green", true)
-	LogInfof("\n" + bootBanner.String())
+	logging.LogInfof("\n" + bootBanner.String())
 	logBootInfo()
 	logBootInfo()
 
 
 	go cleanOld()
 	go cleanOld()
@@ -136,13 +138,13 @@ func GetBootProgress() float64 {
 func SetBooted() {
 func SetBooted() {
 	bootDetails = "Finishing boot..."
 	bootDetails = "Finishing boot..."
 	bootProgress = 100
 	bootProgress = 100
-	LogInfof("kernel booted")
+	logging.LogInfof("kernel booted")
 }
 }
 
 
 func GetHistoryDir(suffix string) (ret string, err error) {
 func GetHistoryDir(suffix string) (ret string, err error) {
 	ret = filepath.Join(HistoryDir, time.Now().Format("2006-01-02-150405")+"-"+suffix)
 	ret = filepath.Join(HistoryDir, time.Now().Format("2006-01-02-150405")+"-"+suffix)
 	if err = os.MkdirAll(ret, 0755); nil != err {
 	if err = os.MkdirAll(ret, 0755); nil != err {
-		LogErrorf("make history dir failed: %s", err)
+		logging.LogErrorf("make history dir failed: %s", err)
 		return
 		return
 	}
 	}
 	return
 	return
@@ -316,33 +318,33 @@ func checkPort() {
 		return
 		return
 	}
 	}
 
 
-	LogInfof("port [%s] is opened, try to check version of running kernel", ServerPort)
+	logging.LogInfof("port [%s] is opened, try to check version of running kernel", ServerPort)
 	result := NewResult()
 	result := NewResult()
 	_, err := httpclient.NewBrowserRequest().
 	_, err := httpclient.NewBrowserRequest().
 		SetResult(result).
 		SetResult(result).
 		SetHeader("User-Agent", UserAgent).
 		SetHeader("User-Agent", UserAgent).
 		Get("http://127.0.0.1:" + ServerPort + "/api/system/version")
 		Get("http://127.0.0.1:" + ServerPort + "/api/system/version")
 	if nil != err || 0 != result.Code {
 	if nil != err || 0 != result.Code {
-		LogErrorf("connect to port [%s] for checking running kernel failed", ServerPort)
+		logging.LogErrorf("connect to port [%s] for checking running kernel failed", ServerPort)
 		KillByPort(ServerPort)
 		KillByPort(ServerPort)
 		return
 		return
 	}
 	}
 
 
 	if nil == result.Data {
 	if nil == result.Data {
-		LogErrorf("connect ot port [%s] for checking running kernel failed", ServerPort)
+		logging.LogErrorf("connect ot port [%s] for checking running kernel failed", ServerPort)
 		os.Exit(ExitCodeUnavailablePort)
 		os.Exit(ExitCodeUnavailablePort)
 	}
 	}
 
 
 	runningVer := result.Data.(string)
 	runningVer := result.Data.(string)
 	if runningVer == Ver {
 	if runningVer == Ver {
-		LogInfof("version of the running kernel is the same as this boot [%s], exit this boot", runningVer)
+		logging.LogInfof("version of the running kernel is the same as this boot [%s], exit this boot", runningVer)
 		os.Exit(ExitCodeOk)
 		os.Exit(ExitCodeOk)
 	}
 	}
 
 
-	LogInfof("found kernel [%s] is running, try to exit it", runningVer)
+	logging.LogInfof("found kernel [%s] is running, try to exit it", runningVer)
 	processes, err := goPS.Processes()
 	processes, err := goPS.Processes()
 	if nil != err {
 	if nil != err {
-		LogErrorf("close kernel [%s] failed: %s", runningVer, err)
+		logging.LogErrorf("close kernel [%s] failed: %s", runningVer, err)
 		os.Exit(ExitCodeUnavailablePort)
 		os.Exit(ExitCodeUnavailablePort)
 	}
 	}
 
 
@@ -354,7 +356,7 @@ func checkPort() {
 			if currentPid != kernelPid {
 			if currentPid != kernelPid {
 				pid := strconv.Itoa(kernelPid)
 				pid := strconv.Itoa(kernelPid)
 				Kill(pid)
 				Kill(pid)
-				LogInfof("killed kernel [name=%s, pid=%s, ver=%s], continue to boot", name, pid, runningVer)
+				logging.LogInfof("killed kernel [name=%s, pid=%s, ver=%s], continue to boot", name, pid, runningVer)
 			}
 			}
 		}
 		}
 	}
 	}
@@ -383,7 +385,7 @@ func KillByPort(port string) {
 			name = proc.Executable()
 			name = proc.Executable()
 		}
 		}
 		Kill(pid)
 		Kill(pid)
-		LogInfof("killed process [name=%s, pid=%s]", name, pid)
+		logging.LogInfof("killed process [name=%s, pid=%s]", name, pid)
 	}
 	}
 }
 }
 
 
@@ -404,7 +406,7 @@ func PidByPort(port string) (ret string) {
 		CmdAttr(cmd)
 		CmdAttr(cmd)
 		data, err := cmd.CombinedOutput()
 		data, err := cmd.CombinedOutput()
 		if nil != err {
 		if nil != err {
-			LogErrorf("netstat failed: %s", err)
+			logging.LogErrorf("netstat failed: %s", err)
 			return
 			return
 		}
 		}
 		output := string(data)
 		output := string(data)
@@ -424,7 +426,7 @@ func PidByPort(port string) (ret string) {
 	CmdAttr(cmd)
 	CmdAttr(cmd)
 	data, err := cmd.CombinedOutput()
 	data, err := cmd.CombinedOutput()
 	if nil != err {
 	if nil != err {
-		LogErrorf("lsof failed: %s", err)
+		logging.LogErrorf("lsof failed: %s", err)
 		return
 		return
 	}
 	}
 	output := string(data)
 	output := string(data)

+ 3 - 1
kernel/util/working_mobile.go

@@ -24,6 +24,7 @@ import (
 
 
 	figure "github.com/common-nighthawk/go-figure"
 	figure "github.com/common-nighthawk/go-figure"
 	"github.com/siyuan-note/httpclient"
 	"github.com/siyuan-note/httpclient"
+	"github.com/siyuan-note/logging"
 )
 )
 
 
 func BootMobile(container, appDir, workspaceDir, nativeLibDir, privateDataDir, lang string) {
 func BootMobile(container, appDir, workspaceDir, nativeLibDir, privateDataDir, lang string) {
@@ -49,6 +50,7 @@ func BootMobile(container, appDir, workspaceDir, nativeLibDir, privateDataDir, l
 	AndroidNativeLibDir = nativeLibDir
 	AndroidNativeLibDir = nativeLibDir
 	AndroidPrivateDataDir = privateDataDir
 	AndroidPrivateDataDir = privateDataDir
 	LogPath = filepath.Join(TempDir, "siyuan.log")
 	LogPath = filepath.Join(TempDir, "siyuan.log")
+	logging.SetLogPath(LogPath)
 	AppearancePath = filepath.Join(ConfDir, "appearance")
 	AppearancePath = filepath.Join(ConfDir, "appearance")
 	ThemesPath = filepath.Join(AppearancePath, "themes")
 	ThemesPath = filepath.Join(AppearancePath, "themes")
 	IconsPath = filepath.Join(AppearancePath, "icons")
 	IconsPath = filepath.Join(AppearancePath, "icons")
@@ -57,6 +59,6 @@ func BootMobile(container, appDir, workspaceDir, nativeLibDir, privateDataDir, l
 	Lang = lang
 	Lang = lang
 	initPathDir()
 	initPathDir()
 	bootBanner := figure.NewFigure("SiYuan", "", true)
 	bootBanner := figure.NewFigure("SiYuan", "", true)
-	LogInfof("\n" + bootBanner.String())
+	logging.LogInfof("\n" + bootBanner.String())
 	logBootInfo()
 	logBootInfo()
 }
 }