Quieter Integration Tests (#6513)
* Rename BaseLogger to WriterLogger to help the creation of other providers * Don't export ColorBytes and ResetBytes from ColoredValues * Make integration tests only print logs if they fail * check can color before coloring * I always forget about MSSQL * Oh and use LEVEL in sqlite.ini * Make the test logger log at info - as it means you see the router * Remove empty expected changes * Make the migrations quieter too * Don't display SQL on error - it can be looked at in the file logs if necessary * Fix skip when using onGiteaRun
This commit is contained in:
		
							parent
							
								
									7ed65a98e8
								
							
						
					
					
						commit
						5422f23ed8
					
				
					 23 changed files with 607 additions and 409 deletions
				
			
		| 
						 | 
					@ -357,10 +357,10 @@ attributes should be cached if this is a commonly used log message.
 | 
				
			||||||
of bytes representing the color.
 | 
					of bytes representing the color.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
These functions will not double wrap a `log.ColoredValue`. They will
 | 
					These functions will not double wrap a `log.ColoredValue`. They will
 | 
				
			||||||
also set the ResetBytes to the cached resetBytes.
 | 
					also set the `resetBytes` to the cached `resetBytes`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Be careful not to change the contents of resetBytes or boldBytes as this
 | 
					The `colorBytes` and `resetBytes` are not exported to prevent
 | 
				
			||||||
will break rendering of logging elsewhere. You have been warned.
 | 
					accidental overwriting of internal values.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Log Spoofing protection
 | 
					## Log Spoofing protection
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,7 +50,7 @@ func createSSHUrl(gitPath string, u *url.URL) *url.URL {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func onGiteaRun(t *testing.T, callback func(*testing.T, *url.URL)) {
 | 
					func onGiteaRun(t *testing.T, callback func(*testing.T, *url.URL)) {
 | 
				
			||||||
	prepareTestEnv(t)
 | 
						prepareTestEnv(t, 1)
 | 
				
			||||||
	s := http.Server{
 | 
						s := http.Server{
 | 
				
			||||||
		Handler: mac,
 | 
							Handler: mac,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,6 +38,7 @@ func testGit(t *testing.T, u *url.URL) {
 | 
				
			||||||
	u.Path = baseAPITestContext.GitPath()
 | 
						u.Path = baseAPITestContext.GitPath()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	t.Run("HTTP", func(t *testing.T) {
 | 
						t.Run("HTTP", func(t *testing.T) {
 | 
				
			||||||
 | 
							PrintCurrentTest(t)
 | 
				
			||||||
		httpContext := baseAPITestContext
 | 
							httpContext := baseAPITestContext
 | 
				
			||||||
		httpContext.Reponame = "repo-tmp-17"
 | 
							httpContext.Reponame = "repo-tmp-17"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,6 +48,7 @@ func testGit(t *testing.T, u *url.URL) {
 | 
				
			||||||
		assert.NoError(t, err)
 | 
							assert.NoError(t, err)
 | 
				
			||||||
		defer os.RemoveAll(dstPath)
 | 
							defer os.RemoveAll(dstPath)
 | 
				
			||||||
		t.Run("Standard", func(t *testing.T) {
 | 
							t.Run("Standard", func(t *testing.T) {
 | 
				
			||||||
 | 
								PrintCurrentTest(t)
 | 
				
			||||||
			ensureAnonymousClone(t, u)
 | 
								ensureAnonymousClone(t, u)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			t.Run("CreateRepo", doAPICreateRepository(httpContext, false))
 | 
								t.Run("CreateRepo", doAPICreateRepository(httpContext, false))
 | 
				
			||||||
| 
						 | 
					@ -57,16 +59,21 @@ func testGit(t *testing.T, u *url.URL) {
 | 
				
			||||||
			t.Run("Clone", doGitClone(dstPath, u))
 | 
								t.Run("Clone", doGitClone(dstPath, u))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			t.Run("PushCommit", func(t *testing.T) {
 | 
								t.Run("PushCommit", func(t *testing.T) {
 | 
				
			||||||
 | 
									PrintCurrentTest(t)
 | 
				
			||||||
				t.Run("Little", func(t *testing.T) {
 | 
									t.Run("Little", func(t *testing.T) {
 | 
				
			||||||
 | 
										PrintCurrentTest(t)
 | 
				
			||||||
					little = commitAndPush(t, littleSize, dstPath)
 | 
										little = commitAndPush(t, littleSize, dstPath)
 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
				t.Run("Big", func(t *testing.T) {
 | 
									t.Run("Big", func(t *testing.T) {
 | 
				
			||||||
 | 
										PrintCurrentTest(t)
 | 
				
			||||||
					big = commitAndPush(t, bigSize, dstPath)
 | 
										big = commitAndPush(t, bigSize, dstPath)
 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
		t.Run("LFS", func(t *testing.T) {
 | 
							t.Run("LFS", func(t *testing.T) {
 | 
				
			||||||
 | 
								PrintCurrentTest(t)
 | 
				
			||||||
			t.Run("PushCommit", func(t *testing.T) {
 | 
								t.Run("PushCommit", func(t *testing.T) {
 | 
				
			||||||
 | 
									PrintCurrentTest(t)
 | 
				
			||||||
				//Setup git LFS
 | 
									//Setup git LFS
 | 
				
			||||||
				_, err = git.NewCommand("lfs").AddArguments("install").RunInDir(dstPath)
 | 
									_, err = git.NewCommand("lfs").AddArguments("install").RunInDir(dstPath)
 | 
				
			||||||
				assert.NoError(t, err)
 | 
									assert.NoError(t, err)
 | 
				
			||||||
| 
						 | 
					@ -76,17 +83,21 @@ func testGit(t *testing.T, u *url.URL) {
 | 
				
			||||||
				assert.NoError(t, err)
 | 
									assert.NoError(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				t.Run("Little", func(t *testing.T) {
 | 
									t.Run("Little", func(t *testing.T) {
 | 
				
			||||||
 | 
										PrintCurrentTest(t)
 | 
				
			||||||
					littleLFS = commitAndPush(t, littleSize, dstPath)
 | 
										littleLFS = commitAndPush(t, littleSize, dstPath)
 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
				t.Run("Big", func(t *testing.T) {
 | 
									t.Run("Big", func(t *testing.T) {
 | 
				
			||||||
 | 
										PrintCurrentTest(t)
 | 
				
			||||||
					bigLFS = commitAndPush(t, bigSize, dstPath)
 | 
										bigLFS = commitAndPush(t, bigSize, dstPath)
 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
			t.Run("Locks", func(t *testing.T) {
 | 
								t.Run("Locks", func(t *testing.T) {
 | 
				
			||||||
 | 
									PrintCurrentTest(t)
 | 
				
			||||||
				lockTest(t, u.String(), dstPath)
 | 
									lockTest(t, u.String(), dstPath)
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
		t.Run("Raw", func(t *testing.T) {
 | 
							t.Run("Raw", func(t *testing.T) {
 | 
				
			||||||
 | 
								PrintCurrentTest(t)
 | 
				
			||||||
			session := loginUser(t, "user2")
 | 
								session := loginUser(t, "user2")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Request raw paths
 | 
								// Request raw paths
 | 
				
			||||||
| 
						 | 
					@ -110,6 +121,7 @@ func testGit(t *testing.T, u *url.URL) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
		t.Run("Media", func(t *testing.T) {
 | 
							t.Run("Media", func(t *testing.T) {
 | 
				
			||||||
 | 
								PrintCurrentTest(t)
 | 
				
			||||||
			session := loginUser(t, "user2")
 | 
								session := loginUser(t, "user2")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Request media paths
 | 
								// Request media paths
 | 
				
			||||||
| 
						 | 
					@ -132,12 +144,14 @@ func testGit(t *testing.T, u *url.URL) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	t.Run("SSH", func(t *testing.T) {
 | 
						t.Run("SSH", func(t *testing.T) {
 | 
				
			||||||
 | 
							PrintCurrentTest(t)
 | 
				
			||||||
		sshContext := baseAPITestContext
 | 
							sshContext := baseAPITestContext
 | 
				
			||||||
		sshContext.Reponame = "repo-tmp-18"
 | 
							sshContext.Reponame = "repo-tmp-18"
 | 
				
			||||||
		keyname := "my-testing-key"
 | 
							keyname := "my-testing-key"
 | 
				
			||||||
		//Setup key the user ssh key
 | 
							//Setup key the user ssh key
 | 
				
			||||||
		withKeyFile(t, keyname, func(keyFile string) {
 | 
							withKeyFile(t, keyname, func(keyFile string) {
 | 
				
			||||||
			t.Run("CreateUserKey", doAPICreateUserKey(sshContext, "test-key", keyFile))
 | 
								t.Run("CreateUserKey", doAPICreateUserKey(sshContext, "test-key", keyFile))
 | 
				
			||||||
 | 
								PrintCurrentTest(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			//Setup remote link
 | 
								//Setup remote link
 | 
				
			||||||
			sshURL := createSSHUrl(sshContext.GitPath(), u)
 | 
								sshURL := createSSHUrl(sshContext.GitPath(), u)
 | 
				
			||||||
| 
						 | 
					@ -149,6 +163,7 @@ func testGit(t *testing.T, u *url.URL) {
 | 
				
			||||||
			var little, big, littleLFS, bigLFS string
 | 
								var little, big, littleLFS, bigLFS string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			t.Run("Standard", func(t *testing.T) {
 | 
								t.Run("Standard", func(t *testing.T) {
 | 
				
			||||||
 | 
									PrintCurrentTest(t)
 | 
				
			||||||
				t.Run("CreateRepo", doAPICreateRepository(sshContext, false))
 | 
									t.Run("CreateRepo", doAPICreateRepository(sshContext, false))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				//TODO get url from api
 | 
									//TODO get url from api
 | 
				
			||||||
| 
						 | 
					@ -156,16 +171,21 @@ func testGit(t *testing.T, u *url.URL) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				//time.Sleep(5 * time.Minute)
 | 
									//time.Sleep(5 * time.Minute)
 | 
				
			||||||
				t.Run("PushCommit", func(t *testing.T) {
 | 
									t.Run("PushCommit", func(t *testing.T) {
 | 
				
			||||||
 | 
										PrintCurrentTest(t)
 | 
				
			||||||
					t.Run("Little", func(t *testing.T) {
 | 
										t.Run("Little", func(t *testing.T) {
 | 
				
			||||||
 | 
											PrintCurrentTest(t)
 | 
				
			||||||
						little = commitAndPush(t, littleSize, dstPath)
 | 
											little = commitAndPush(t, littleSize, dstPath)
 | 
				
			||||||
					})
 | 
										})
 | 
				
			||||||
					t.Run("Big", func(t *testing.T) {
 | 
										t.Run("Big", func(t *testing.T) {
 | 
				
			||||||
 | 
											PrintCurrentTest(t)
 | 
				
			||||||
						big = commitAndPush(t, bigSize, dstPath)
 | 
											big = commitAndPush(t, bigSize, dstPath)
 | 
				
			||||||
					})
 | 
										})
 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
			t.Run("LFS", func(t *testing.T) {
 | 
								t.Run("LFS", func(t *testing.T) {
 | 
				
			||||||
 | 
									PrintCurrentTest(t)
 | 
				
			||||||
				t.Run("PushCommit", func(t *testing.T) {
 | 
									t.Run("PushCommit", func(t *testing.T) {
 | 
				
			||||||
 | 
										PrintCurrentTest(t)
 | 
				
			||||||
					//Setup git LFS
 | 
										//Setup git LFS
 | 
				
			||||||
					_, err = git.NewCommand("lfs").AddArguments("install").RunInDir(dstPath)
 | 
										_, err = git.NewCommand("lfs").AddArguments("install").RunInDir(dstPath)
 | 
				
			||||||
					assert.NoError(t, err)
 | 
										assert.NoError(t, err)
 | 
				
			||||||
| 
						 | 
					@ -175,17 +195,21 @@ func testGit(t *testing.T, u *url.URL) {
 | 
				
			||||||
					assert.NoError(t, err)
 | 
										assert.NoError(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					t.Run("Little", func(t *testing.T) {
 | 
										t.Run("Little", func(t *testing.T) {
 | 
				
			||||||
 | 
											PrintCurrentTest(t)
 | 
				
			||||||
						littleLFS = commitAndPush(t, littleSize, dstPath)
 | 
											littleLFS = commitAndPush(t, littleSize, dstPath)
 | 
				
			||||||
					})
 | 
										})
 | 
				
			||||||
					t.Run("Big", func(t *testing.T) {
 | 
										t.Run("Big", func(t *testing.T) {
 | 
				
			||||||
 | 
											PrintCurrentTest(t)
 | 
				
			||||||
						bigLFS = commitAndPush(t, bigSize, dstPath)
 | 
											bigLFS = commitAndPush(t, bigSize, dstPath)
 | 
				
			||||||
					})
 | 
										})
 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
				t.Run("Locks", func(t *testing.T) {
 | 
									t.Run("Locks", func(t *testing.T) {
 | 
				
			||||||
 | 
										PrintCurrentTest(t)
 | 
				
			||||||
					lockTest(t, u.String(), dstPath)
 | 
										lockTest(t, u.String(), dstPath)
 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
			t.Run("Raw", func(t *testing.T) {
 | 
								t.Run("Raw", func(t *testing.T) {
 | 
				
			||||||
 | 
									PrintCurrentTest(t)
 | 
				
			||||||
				session := loginUser(t, "user2")
 | 
									session := loginUser(t, "user2")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// Request raw paths
 | 
									// Request raw paths
 | 
				
			||||||
| 
						 | 
					@ -209,6 +233,7 @@ func testGit(t *testing.T, u *url.URL) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
			t.Run("Media", func(t *testing.T) {
 | 
								t.Run("Media", func(t *testing.T) {
 | 
				
			||||||
 | 
									PrintCurrentTest(t)
 | 
				
			||||||
				session := loginUser(t, "user2")
 | 
									session := loginUser(t, "user2")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				// Request media paths
 | 
									// Request media paths
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -165,7 +165,12 @@ func initIntegrationTest() {
 | 
				
			||||||
	routers.GlobalInit()
 | 
						routers.GlobalInit()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func prepareTestEnv(t testing.TB) {
 | 
					func prepareTestEnv(t testing.TB, skip ...int) {
 | 
				
			||||||
 | 
						ourSkip := 2
 | 
				
			||||||
 | 
						if len(skip) > 0 {
 | 
				
			||||||
 | 
							ourSkip += skip[0]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						PrintCurrentTest(t, ourSkip)
 | 
				
			||||||
	assert.NoError(t, models.LoadFixtures())
 | 
						assert.NoError(t, models.LoadFixtures())
 | 
				
			||||||
	assert.NoError(t, os.RemoveAll(setting.RepoRootPath))
 | 
						assert.NoError(t, os.RemoveAll(setting.RepoRootPath))
 | 
				
			||||||
	assert.NoError(t, os.RemoveAll(models.LocalCopyPath()))
 | 
						assert.NoError(t, os.RemoveAll(models.LocalCopyPath()))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,13 +9,13 @@ import (
 | 
				
			||||||
	"database/sql"
 | 
						"database/sql"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"log"
 | 
					 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"path"
 | 
						"path"
 | 
				
			||||||
	"regexp"
 | 
						"regexp"
 | 
				
			||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/integrations"
 | 
				
			||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
	"code.gitea.io/gitea/models/migrations"
 | 
						"code.gitea.io/gitea/models/migrations"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/setting"
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
| 
						 | 
					@ -26,21 +26,22 @@ import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var currentEngine *xorm.Engine
 | 
					var currentEngine *xorm.Engine
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func initMigrationTest() {
 | 
					func initMigrationTest(t *testing.T) {
 | 
				
			||||||
 | 
						integrations.PrintCurrentTest(t, 2)
 | 
				
			||||||
	giteaRoot := os.Getenv("GITEA_ROOT")
 | 
						giteaRoot := os.Getenv("GITEA_ROOT")
 | 
				
			||||||
	if giteaRoot == "" {
 | 
						if giteaRoot == "" {
 | 
				
			||||||
		fmt.Println("Environment variable $GITEA_ROOT not set")
 | 
							integrations.Printf("Environment variable $GITEA_ROOT not set\n")
 | 
				
			||||||
		os.Exit(1)
 | 
							os.Exit(1)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	setting.AppPath = path.Join(giteaRoot, "gitea")
 | 
						setting.AppPath = path.Join(giteaRoot, "gitea")
 | 
				
			||||||
	if _, err := os.Stat(setting.AppPath); err != nil {
 | 
						if _, err := os.Stat(setting.AppPath); err != nil {
 | 
				
			||||||
		fmt.Printf("Could not find gitea binary at %s\n", setting.AppPath)
 | 
							integrations.Printf("Could not find gitea binary at %s\n", setting.AppPath)
 | 
				
			||||||
		os.Exit(1)
 | 
							os.Exit(1)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	giteaConf := os.Getenv("GITEA_CONF")
 | 
						giteaConf := os.Getenv("GITEA_CONF")
 | 
				
			||||||
	if giteaConf == "" {
 | 
						if giteaConf == "" {
 | 
				
			||||||
		fmt.Println("Environment variable $GITEA_CONF not set")
 | 
							integrations.Printf("Environment variable $GITEA_CONF not set\n")
 | 
				
			||||||
		os.Exit(1)
 | 
							os.Exit(1)
 | 
				
			||||||
	} else if !path.IsAbs(giteaConf) {
 | 
						} else if !path.IsAbs(giteaConf) {
 | 
				
			||||||
		setting.CustomConf = path.Join(giteaRoot, giteaConf)
 | 
							setting.CustomConf = path.Join(giteaRoot, giteaConf)
 | 
				
			||||||
| 
						 | 
					@ -51,6 +52,7 @@ func initMigrationTest() {
 | 
				
			||||||
	setting.NewContext()
 | 
						setting.NewContext()
 | 
				
			||||||
	setting.CheckLFSVersion()
 | 
						setting.CheckLFSVersion()
 | 
				
			||||||
	models.LoadConfigs()
 | 
						models.LoadConfigs()
 | 
				
			||||||
 | 
						setting.NewLogServices(true)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getDialect() string {
 | 
					func getDialect() string {
 | 
				
			||||||
| 
						 | 
					@ -125,7 +127,7 @@ func restoreOldDB(t *testing.T, version string) bool {
 | 
				
			||||||
	data, err := readSQLFromFile(version)
 | 
						data, err := readSQLFromFile(version)
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	if len(data) == 0 {
 | 
						if len(data) == 0 {
 | 
				
			||||||
		log.Printf("No db found to restore for %s version: %s\n", models.DbCfg.Type, version)
 | 
							integrations.Printf("No db found to restore for %s version: %s\n", models.DbCfg.Type, version)
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -212,7 +214,8 @@ func wrappedMigrate(x *xorm.Engine) error {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func doMigrationTest(t *testing.T, version string) {
 | 
					func doMigrationTest(t *testing.T, version string) {
 | 
				
			||||||
	log.Printf("Performing migration test for %s version: %s", models.DbCfg.Type, version)
 | 
						integrations.PrintCurrentTest(t)
 | 
				
			||||||
 | 
						integrations.Printf("Performing migration test for %s version: %s\n", models.DbCfg.Type, version)
 | 
				
			||||||
	if !restoreOldDB(t, version) {
 | 
						if !restoreOldDB(t, version) {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -227,19 +230,22 @@ func doMigrationTest(t *testing.T, version string) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestMigrations(t *testing.T) {
 | 
					func TestMigrations(t *testing.T) {
 | 
				
			||||||
	initMigrationTest()
 | 
						initMigrationTest(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dialect := models.DbCfg.Type
 | 
						dialect := models.DbCfg.Type
 | 
				
			||||||
	versions, err := availableVersions()
 | 
						versions, err := availableVersions()
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(versions) == 0 {
 | 
						if len(versions) == 0 {
 | 
				
			||||||
		log.Printf("No old database versions available to migration test for %s\n", dialect)
 | 
							integrations.Printf("No old database versions available to migration test for %s\n", dialect)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Printf("Preparing to test %d migrations for %s\n", len(versions), dialect)
 | 
						integrations.Printf("Preparing to test %d migrations for %s\n", len(versions), dialect)
 | 
				
			||||||
	for _, version := range versions {
 | 
						for _, version := range versions {
 | 
				
			||||||
		doMigrationTest(t, version)
 | 
							t.Run(fmt.Sprintf("Migrate-%s-%s", dialect, version), func(t *testing.T) {
 | 
				
			||||||
 | 
								doMigrationTest(t, version)
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,14 +60,19 @@ PROVIDER = file
 | 
				
			||||||
PROVIDER_CONFIG = data/sessions-mssql
 | 
					PROVIDER_CONFIG = data/sessions-mssql
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[log]
 | 
					[log]
 | 
				
			||||||
MODE      = console,file
 | 
					MODE                 = test,file
 | 
				
			||||||
ROOT_PATH = mssql-log
 | 
					ROOT_PATH            = sqlite-log
 | 
				
			||||||
 | 
					REDIRECT_MACARON_LOG = true
 | 
				
			||||||
 | 
					ROUTER               = ,
 | 
				
			||||||
 | 
					MACARON              = ,
 | 
				
			||||||
 | 
					XORM                 = file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[log.console]
 | 
					[log.test]
 | 
				
			||||||
LEVEL = Warn
 | 
					LEVEL                = Info
 | 
				
			||||||
 | 
					COLORIZE             = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[log.file]
 | 
					[log.file]
 | 
				
			||||||
LEVEL = Debug
 | 
					LEVEL                = Debug
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[security]
 | 
					[security]
 | 
				
			||||||
INSTALL_LOCK   = true
 | 
					INSTALL_LOCK   = true
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,14 +60,19 @@ PROVIDER = file
 | 
				
			||||||
PROVIDER_CONFIG = data/sessions-mysql
 | 
					PROVIDER_CONFIG = data/sessions-mysql
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[log]
 | 
					[log]
 | 
				
			||||||
MODE      = console,file
 | 
					MODE                 = test,file
 | 
				
			||||||
ROOT_PATH = mysql-log
 | 
					ROOT_PATH            = sqlite-log
 | 
				
			||||||
 | 
					REDIRECT_MACARON_LOG = true
 | 
				
			||||||
 | 
					ROUTER               = ,
 | 
				
			||||||
 | 
					MACARON              = ,
 | 
				
			||||||
 | 
					XORM                 = file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[log.console]
 | 
					[log.test]
 | 
				
			||||||
LEVEL = Warn
 | 
					LEVEL                = Info
 | 
				
			||||||
 | 
					COLORIZE             = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[log.file]
 | 
					[log.file]
 | 
				
			||||||
LEVEL = Debug
 | 
					LEVEL                = Debug
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[security]
 | 
					[security]
 | 
				
			||||||
INSTALL_LOCK   = true
 | 
					INSTALL_LOCK   = true
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,14 +57,20 @@ PROVIDER = file
 | 
				
			||||||
PROVIDER_CONFIG = data/sessions-mysql8
 | 
					PROVIDER_CONFIG = data/sessions-mysql8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[log]
 | 
					[log]
 | 
				
			||||||
MODE      = console,file
 | 
					MODE                 = test,file
 | 
				
			||||||
ROOT_PATH = mysql8-log
 | 
					ROOT_PATH            = sqlite-log
 | 
				
			||||||
 | 
					REDIRECT_MACARON_LOG = true
 | 
				
			||||||
 | 
					ROUTER               = ,
 | 
				
			||||||
 | 
					MACARON              = ,
 | 
				
			||||||
 | 
					XORM                 = file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[log.console]
 | 
					[log.test]
 | 
				
			||||||
LEVEL = Warn
 | 
					LEVEL                = Info
 | 
				
			||||||
 | 
					COLORIZE             = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[log.file]
 | 
					[log.file]
 | 
				
			||||||
LEVEL = Debug
 | 
					LEVEL                = Debug
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[security]
 | 
					[security]
 | 
				
			||||||
INSTALL_LOCK   = true
 | 
					INSTALL_LOCK   = true
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -60,14 +60,19 @@ PROVIDER = file
 | 
				
			||||||
PROVIDER_CONFIG = data/sessions-pgsql
 | 
					PROVIDER_CONFIG = data/sessions-pgsql
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[log]
 | 
					[log]
 | 
				
			||||||
MODE      = console,file
 | 
					MODE                 = test,file
 | 
				
			||||||
ROOT_PATH = pgsql-log
 | 
					ROOT_PATH            = sqlite-log
 | 
				
			||||||
 | 
					REDIRECT_MACARON_LOG = true
 | 
				
			||||||
 | 
					ROUTER               = ,
 | 
				
			||||||
 | 
					MACARON              = ,
 | 
				
			||||||
 | 
					XORM                 = file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[log.console]
 | 
					[log.test]
 | 
				
			||||||
LEVEL = Warn
 | 
					LEVEL                = Info
 | 
				
			||||||
 | 
					COLORIZE             = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[log.file]
 | 
					[log.file]
 | 
				
			||||||
LEVEL = Debug
 | 
					LEVEL                = Debug
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[security]
 | 
					[security]
 | 
				
			||||||
INSTALL_LOCK   = true
 | 
					INSTALL_LOCK   = true
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,18 +33,19 @@ APP_DATA_PATH    = integrations/gitea-integration-sqlite/data
 | 
				
			||||||
ENABLE_GZIP      = true
 | 
					ENABLE_GZIP      = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[mailer]
 | 
					[mailer]
 | 
				
			||||||
ENABLED = false
 | 
					ENABLED     = true
 | 
				
			||||||
 | 
					MAILER_TYPE = dummy
 | 
				
			||||||
 | 
					FROM        = sqlite-integration-test@gitea.io
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[service]
 | 
					[service]
 | 
				
			||||||
REGISTER_EMAIL_CONFIRM            = false
 | 
					REGISTER_EMAIL_CONFIRM            = false
 | 
				
			||||||
ENABLE_NOTIFY_MAIL                = false
 | 
					ENABLE_NOTIFY_MAIL                = true
 | 
				
			||||||
DISABLE_REGISTRATION              = false
 | 
					DISABLE_REGISTRATION              = false
 | 
				
			||||||
ENABLE_CAPTCHA                    = false
 | 
					ENABLE_CAPTCHA                    = false
 | 
				
			||||||
REQUIRE_SIGNIN_VIEW               = false
 | 
					REQUIRE_SIGNIN_VIEW               = false
 | 
				
			||||||
DEFAULT_KEEP_EMAIL_PRIVATE        = false
 | 
					DEFAULT_KEEP_EMAIL_PRIVATE        = false
 | 
				
			||||||
DEFAULT_ALLOW_CREATE_ORGANIZATION = true
 | 
					DEFAULT_ALLOW_CREATE_ORGANIZATION = true
 | 
				
			||||||
NO_REPLY_ADDRESS                  = noreply.example.org
 | 
					NO_REPLY_ADDRESS                  = noreply.example.org
 | 
				
			||||||
ENABLE_NOTIFY_MAIL                = true
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
[picture]
 | 
					[picture]
 | 
				
			||||||
DISABLE_GRAVATAR        = false
 | 
					DISABLE_GRAVATAR        = false
 | 
				
			||||||
| 
						 | 
					@ -54,21 +55,25 @@ ENABLE_FEDERATED_AVATAR = false
 | 
				
			||||||
PROVIDER = file
 | 
					PROVIDER = file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[log]
 | 
					[log]
 | 
				
			||||||
MODE      = console,file
 | 
					MODE                 = test,file
 | 
				
			||||||
ROOT_PATH = sqlite-log
 | 
					ROOT_PATH            = sqlite-log
 | 
				
			||||||
 | 
					REDIRECT_MACARON_LOG = true
 | 
				
			||||||
 | 
					ROUTER               = ,
 | 
				
			||||||
 | 
					MACARON              = ,
 | 
				
			||||||
 | 
					XORM                 = file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[log.console]
 | 
					[log.test]
 | 
				
			||||||
LEVEL = Warn
 | 
					LEVEL                = Info
 | 
				
			||||||
 | 
					COLORIZE             = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[log.file]
 | 
					[log.file]
 | 
				
			||||||
LEVEL = Debug
 | 
					LEVEL                = Debug
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[security]
 | 
					[security]
 | 
				
			||||||
INSTALL_LOCK   = true
 | 
					INSTALL_LOCK   = true
 | 
				
			||||||
SECRET_KEY     = 9pCviYTWSb
 | 
					SECRET_KEY     = 9pCviYTWSb
 | 
				
			||||||
INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTI3OTU5ODN9.OQkH5UmzID2XBdwQ9TAI6Jj2t1X-wElVTjbE7aoN4I8
 | 
					INTERNAL_TOKEN = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYmYiOjE0OTI3OTU5ODN9.OQkH5UmzID2XBdwQ9TAI6Jj2t1X-wElVTjbE7aoN4I8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[mailer]
 | 
					[oauth2]
 | 
				
			||||||
ENABLED = true
 | 
					JWT_SECRET = KZb_QLUd4fYVyxetjxC4eZkrBgWM2SndOOWDNtgUUko
 | 
				
			||||||
MAILER_TYPE = dummy
 | 
					
 | 
				
			||||||
FROM = sqlite-integration-test@gitea.io
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										104
									
								
								integrations/testlogger.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								integrations/testlogger.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,104 @@
 | 
				
			||||||
 | 
					// Copyright 2019 The Gitea Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a MIT-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package integrations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"runtime"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var prefix string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TestLogger is a logger which will write to the testing log
 | 
				
			||||||
 | 
					type TestLogger struct {
 | 
				
			||||||
 | 
						log.WriterLogger
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var writerCloser = &testLoggerWriterCloser{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type testLoggerWriterCloser struct {
 | 
				
			||||||
 | 
						t testing.TB
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (w *testLoggerWriterCloser) Write(p []byte) (int, error) {
 | 
				
			||||||
 | 
						if w.t != nil {
 | 
				
			||||||
 | 
							if len(p) > 0 && p[len(p)-1] == '\n' {
 | 
				
			||||||
 | 
								p = p[:len(p)-1]
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							w.t.Log(string(p))
 | 
				
			||||||
 | 
							return len(p), nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return len(p), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (w *testLoggerWriterCloser) Close() error {
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// PrintCurrentTest prints the current test to os.Stdout
 | 
				
			||||||
 | 
					func PrintCurrentTest(t testing.TB, skip ...int) {
 | 
				
			||||||
 | 
						actualSkip := 1
 | 
				
			||||||
 | 
						if len(skip) > 0 {
 | 
				
			||||||
 | 
							actualSkip = skip[0]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_, filename, line, _ := runtime.Caller(actualSkip)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if log.CanColorStdout {
 | 
				
			||||||
 | 
							fmt.Fprintf(os.Stdout, "=== %s (%s:%d)\n", log.NewColoredValue(t.Name()), strings.TrimPrefix(filename, prefix), line)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							fmt.Fprintf(os.Stdout, "=== %s (%s:%d)\n", t.Name(), strings.TrimPrefix(filename, prefix), line)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						writerCloser.t = t
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Printf takes a format and args and prints the string to os.Stdout
 | 
				
			||||||
 | 
					func Printf(format string, args ...interface{}) {
 | 
				
			||||||
 | 
						if log.CanColorStdout {
 | 
				
			||||||
 | 
							for i := 0; i < len(args); i++ {
 | 
				
			||||||
 | 
								args[i] = log.NewColoredValue(args[i])
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fmt.Fprintf(os.Stdout, "\t"+format, args...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewTestLogger creates a TestLogger as a log.LoggerProvider
 | 
				
			||||||
 | 
					func NewTestLogger() log.LoggerProvider {
 | 
				
			||||||
 | 
						logger := &TestLogger{}
 | 
				
			||||||
 | 
						logger.Colorize = log.CanColorStdout
 | 
				
			||||||
 | 
						logger.Level = log.TRACE
 | 
				
			||||||
 | 
						return logger
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Init inits connection writer with json config.
 | 
				
			||||||
 | 
					// json config only need key "level".
 | 
				
			||||||
 | 
					func (log *TestLogger) Init(config string) error {
 | 
				
			||||||
 | 
						err := json.Unmarshal([]byte(config), log)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						log.NewWriterLogger(writerCloser)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Flush when log should be flushed
 | 
				
			||||||
 | 
					func (log *TestLogger) Flush() {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetName returns the default name for this implementation
 | 
				
			||||||
 | 
					func (log *TestLogger) GetName() string {
 | 
				
			||||||
 | 
						return "test"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						log.Register("test", NewTestLogger)
 | 
				
			||||||
 | 
						_, filename, _, _ := runtime.Caller(0)
 | 
				
			||||||
 | 
						prefix = strings.TrimSuffix(filename, "integrations/testlogger.go")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,328 +0,0 @@
 | 
				
			||||||
// Copyright 2019 The Gitea Authors. All rights reserved.
 | 
					 | 
				
			||||||
// Use of this source code is governed by a MIT-style
 | 
					 | 
				
			||||||
// license that can be found in the LICENSE file.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
package log
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
	"regexp"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"sync"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// These flags define which text to prefix to each log entry generated
 | 
					 | 
				
			||||||
// by the Logger. Bits are or'ed together to control what's printed.
 | 
					 | 
				
			||||||
// There is no control over the order they appear (the order listed
 | 
					 | 
				
			||||||
// here) or the format they present (as described in the comments).
 | 
					 | 
				
			||||||
// The prefix is followed by a colon only if more than time is stated
 | 
					 | 
				
			||||||
// is specified. For example, flags Ldate | Ltime
 | 
					 | 
				
			||||||
// produce, 2009/01/23 01:23:23 message.
 | 
					 | 
				
			||||||
// The standard is:
 | 
					 | 
				
			||||||
// 2009/01/23 01:23:23 ...a/b/c/d.go:23:runtime.Caller() [I]: message
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	Ldate          = 1 << iota // the date in the local time zone: 2009/01/23
 | 
					 | 
				
			||||||
	Ltime                      // the time in the local time zone: 01:23:23
 | 
					 | 
				
			||||||
	Lmicroseconds              // microsecond resolution: 01:23:23.123123.  assumes Ltime.
 | 
					 | 
				
			||||||
	Llongfile                  // full file name and line number: /a/b/c/d.go:23
 | 
					 | 
				
			||||||
	Lshortfile                 // final file name element and line number: d.go:23. overrides Llongfile
 | 
					 | 
				
			||||||
	Lfuncname                  // function name of the caller: runtime.Caller()
 | 
					 | 
				
			||||||
	Lshortfuncname             // last part of the function name
 | 
					 | 
				
			||||||
	LUTC                       // if Ldate or Ltime is set, use UTC rather than the local time zone
 | 
					 | 
				
			||||||
	Llevelinitial              // Initial character of the provided level in brackets eg. [I] for info
 | 
					 | 
				
			||||||
	Llevel                     // Provided level in brackets [INFO]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Last 20 characters of the filename
 | 
					 | 
				
			||||||
	Lmedfile = Lshortfile | Llongfile
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// LstdFlags is the initial value for the standard logger
 | 
					 | 
				
			||||||
	LstdFlags = Ldate | Ltime | Lmedfile | Lshortfuncname | Llevelinitial
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var flagFromString = map[string]int{
 | 
					 | 
				
			||||||
	"none":          0,
 | 
					 | 
				
			||||||
	"date":          Ldate,
 | 
					 | 
				
			||||||
	"time":          Ltime,
 | 
					 | 
				
			||||||
	"microseconds":  Lmicroseconds,
 | 
					 | 
				
			||||||
	"longfile":      Llongfile,
 | 
					 | 
				
			||||||
	"shortfile":     Lshortfile,
 | 
					 | 
				
			||||||
	"funcname":      Lfuncname,
 | 
					 | 
				
			||||||
	"shortfuncname": Lshortfuncname,
 | 
					 | 
				
			||||||
	"utc":           LUTC,
 | 
					 | 
				
			||||||
	"levelinitial":  Llevelinitial,
 | 
					 | 
				
			||||||
	"level":         Llevel,
 | 
					 | 
				
			||||||
	"medfile":       Lmedfile,
 | 
					 | 
				
			||||||
	"stdflags":      LstdFlags,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// FlagsFromString takes a comma separated list of flags and returns
 | 
					 | 
				
			||||||
// the flags for this string
 | 
					 | 
				
			||||||
func FlagsFromString(from string) int {
 | 
					 | 
				
			||||||
	flags := 0
 | 
					 | 
				
			||||||
	for _, flag := range strings.Split(strings.ToLower(from), ",") {
 | 
					 | 
				
			||||||
		f, ok := flagFromString[strings.TrimSpace(flag)]
 | 
					 | 
				
			||||||
		if ok {
 | 
					 | 
				
			||||||
			flags = flags | f
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return flags
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type byteArrayWriter []byte
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *byteArrayWriter) Write(p []byte) (int, error) {
 | 
					 | 
				
			||||||
	*b = append(*b, p...)
 | 
					 | 
				
			||||||
	return len(p), nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// BaseLogger represent a basic logger for Gitea
 | 
					 | 
				
			||||||
type BaseLogger struct {
 | 
					 | 
				
			||||||
	out io.WriteCloser
 | 
					 | 
				
			||||||
	mu  sync.Mutex
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Level           Level  `json:"level"`
 | 
					 | 
				
			||||||
	StacktraceLevel Level  `json:"stacktraceLevel"`
 | 
					 | 
				
			||||||
	Flags           int    `json:"flags"`
 | 
					 | 
				
			||||||
	Prefix          string `json:"prefix"`
 | 
					 | 
				
			||||||
	Colorize        bool   `json:"colorize"`
 | 
					 | 
				
			||||||
	Expression      string `json:"expression"`
 | 
					 | 
				
			||||||
	regexp          *regexp.Regexp
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *BaseLogger) createLogger(out io.WriteCloser, level ...Level) {
 | 
					 | 
				
			||||||
	b.mu.Lock()
 | 
					 | 
				
			||||||
	defer b.mu.Unlock()
 | 
					 | 
				
			||||||
	b.out = out
 | 
					 | 
				
			||||||
	switch b.Flags {
 | 
					 | 
				
			||||||
	case 0:
 | 
					 | 
				
			||||||
		b.Flags = LstdFlags
 | 
					 | 
				
			||||||
	case -1:
 | 
					 | 
				
			||||||
		b.Flags = 0
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if len(level) > 0 {
 | 
					 | 
				
			||||||
		b.Level = level[0]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	b.createExpression()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *BaseLogger) createExpression() {
 | 
					 | 
				
			||||||
	if len(b.Expression) > 0 {
 | 
					 | 
				
			||||||
		var err error
 | 
					 | 
				
			||||||
		b.regexp, err = regexp.Compile(b.Expression)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			b.regexp = nil
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetLevel returns the logging level for this logger
 | 
					 | 
				
			||||||
func (b *BaseLogger) GetLevel() Level {
 | 
					 | 
				
			||||||
	return b.Level
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetStacktraceLevel returns the stacktrace logging level for this logger
 | 
					 | 
				
			||||||
func (b *BaseLogger) GetStacktraceLevel() Level {
 | 
					 | 
				
			||||||
	return b.StacktraceLevel
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Copy of cheap integer to fixed-width decimal to ascii from logger.
 | 
					 | 
				
			||||||
func itoa(buf *[]byte, i int, wid int) {
 | 
					 | 
				
			||||||
	var b [20]byte
 | 
					 | 
				
			||||||
	bp := len(b) - 1
 | 
					 | 
				
			||||||
	for i >= 10 || wid > 1 {
 | 
					 | 
				
			||||||
		wid--
 | 
					 | 
				
			||||||
		q := i / 10
 | 
					 | 
				
			||||||
		b[bp] = byte('0' + i - q*10)
 | 
					 | 
				
			||||||
		bp--
 | 
					 | 
				
			||||||
		i = q
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// i < 10
 | 
					 | 
				
			||||||
	b[bp] = byte('0' + i)
 | 
					 | 
				
			||||||
	*buf = append(*buf, b[bp:]...)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (b *BaseLogger) createMsg(buf *[]byte, event *Event) {
 | 
					 | 
				
			||||||
	*buf = append(*buf, b.Prefix...)
 | 
					 | 
				
			||||||
	t := event.time
 | 
					 | 
				
			||||||
	if b.Flags&(Ldate|Ltime|Lmicroseconds) != 0 {
 | 
					 | 
				
			||||||
		if b.Colorize {
 | 
					 | 
				
			||||||
			*buf = append(*buf, fgCyanBytes...)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if b.Flags&LUTC != 0 {
 | 
					 | 
				
			||||||
			t = t.UTC()
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if b.Flags&Ldate != 0 {
 | 
					 | 
				
			||||||
			year, month, day := t.Date()
 | 
					 | 
				
			||||||
			itoa(buf, year, 4)
 | 
					 | 
				
			||||||
			*buf = append(*buf, '/')
 | 
					 | 
				
			||||||
			itoa(buf, int(month), 2)
 | 
					 | 
				
			||||||
			*buf = append(*buf, '/')
 | 
					 | 
				
			||||||
			itoa(buf, day, 2)
 | 
					 | 
				
			||||||
			*buf = append(*buf, ' ')
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if b.Flags&(Ltime|Lmicroseconds) != 0 {
 | 
					 | 
				
			||||||
			hour, min, sec := t.Clock()
 | 
					 | 
				
			||||||
			itoa(buf, hour, 2)
 | 
					 | 
				
			||||||
			*buf = append(*buf, ':')
 | 
					 | 
				
			||||||
			itoa(buf, min, 2)
 | 
					 | 
				
			||||||
			*buf = append(*buf, ':')
 | 
					 | 
				
			||||||
			itoa(buf, sec, 2)
 | 
					 | 
				
			||||||
			if b.Flags&Lmicroseconds != 0 {
 | 
					 | 
				
			||||||
				*buf = append(*buf, '.')
 | 
					 | 
				
			||||||
				itoa(buf, t.Nanosecond()/1e3, 6)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			*buf = append(*buf, ' ')
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if b.Colorize {
 | 
					 | 
				
			||||||
			*buf = append(*buf, resetBytes...)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if b.Flags&(Lshortfile|Llongfile) != 0 {
 | 
					 | 
				
			||||||
		if b.Colorize {
 | 
					 | 
				
			||||||
			*buf = append(*buf, fgGreenBytes...)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		file := event.filename
 | 
					 | 
				
			||||||
		if b.Flags&Lmedfile == Lmedfile {
 | 
					 | 
				
			||||||
			startIndex := len(file) - 20
 | 
					 | 
				
			||||||
			if startIndex > 0 {
 | 
					 | 
				
			||||||
				file = "..." + file[startIndex:]
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else if b.Flags&Lshortfile != 0 {
 | 
					 | 
				
			||||||
			startIndex := strings.LastIndexByte(file, '/')
 | 
					 | 
				
			||||||
			if startIndex > 0 && startIndex < len(file) {
 | 
					 | 
				
			||||||
				file = file[startIndex+1:]
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		*buf = append(*buf, file...)
 | 
					 | 
				
			||||||
		*buf = append(*buf, ':')
 | 
					 | 
				
			||||||
		itoa(buf, event.line, -1)
 | 
					 | 
				
			||||||
		if b.Flags&(Lfuncname|Lshortfuncname) != 0 {
 | 
					 | 
				
			||||||
			*buf = append(*buf, ':')
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			if b.Colorize {
 | 
					 | 
				
			||||||
				*buf = append(*buf, resetBytes...)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			*buf = append(*buf, ' ')
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if b.Flags&(Lfuncname|Lshortfuncname) != 0 {
 | 
					 | 
				
			||||||
		if b.Colorize {
 | 
					 | 
				
			||||||
			*buf = append(*buf, fgGreenBytes...)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		funcname := event.caller
 | 
					 | 
				
			||||||
		if b.Flags&Lshortfuncname != 0 {
 | 
					 | 
				
			||||||
			lastIndex := strings.LastIndexByte(funcname, '.')
 | 
					 | 
				
			||||||
			if lastIndex > 0 && len(funcname) > lastIndex+1 {
 | 
					 | 
				
			||||||
				funcname = funcname[lastIndex+1:]
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		*buf = append(*buf, funcname...)
 | 
					 | 
				
			||||||
		if b.Colorize {
 | 
					 | 
				
			||||||
			*buf = append(*buf, resetBytes...)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		*buf = append(*buf, ' ')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if b.Flags&(Llevel|Llevelinitial) != 0 {
 | 
					 | 
				
			||||||
		level := strings.ToUpper(event.level.String())
 | 
					 | 
				
			||||||
		if b.Colorize {
 | 
					 | 
				
			||||||
			*buf = append(*buf, levelToColor[event.level]...)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		*buf = append(*buf, '[')
 | 
					 | 
				
			||||||
		if b.Flags&Llevelinitial != 0 {
 | 
					 | 
				
			||||||
			*buf = append(*buf, level[0])
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			*buf = append(*buf, level...)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		*buf = append(*buf, ']')
 | 
					 | 
				
			||||||
		if b.Colorize {
 | 
					 | 
				
			||||||
			*buf = append(*buf, resetBytes...)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		*buf = append(*buf, ' ')
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var msg = []byte(event.msg)
 | 
					 | 
				
			||||||
	if len(msg) > 0 && msg[len(msg)-1] == '\n' {
 | 
					 | 
				
			||||||
		msg = msg[:len(msg)-1]
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pawMode := allowColor
 | 
					 | 
				
			||||||
	if !b.Colorize {
 | 
					 | 
				
			||||||
		pawMode = removeColor
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	baw := byteArrayWriter(*buf)
 | 
					 | 
				
			||||||
	(&protectedANSIWriter{
 | 
					 | 
				
			||||||
		w:    &baw,
 | 
					 | 
				
			||||||
		mode: pawMode,
 | 
					 | 
				
			||||||
	}).Write([]byte(msg))
 | 
					 | 
				
			||||||
	*buf = baw
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if event.stacktrace != "" && b.StacktraceLevel <= event.level {
 | 
					 | 
				
			||||||
		lines := bytes.Split([]byte(event.stacktrace), []byte("\n"))
 | 
					 | 
				
			||||||
		if len(lines) > 1 {
 | 
					 | 
				
			||||||
			for _, line := range lines {
 | 
					 | 
				
			||||||
				*buf = append(*buf, "\n\t"...)
 | 
					 | 
				
			||||||
				*buf = append(*buf, line...)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		*buf = append(*buf, '\n')
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	*buf = append(*buf, '\n')
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// LogEvent logs the event to the internal writer
 | 
					 | 
				
			||||||
func (b *BaseLogger) LogEvent(event *Event) error {
 | 
					 | 
				
			||||||
	if b.Level > event.level {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	b.mu.Lock()
 | 
					 | 
				
			||||||
	defer b.mu.Unlock()
 | 
					 | 
				
			||||||
	if !b.Match(event) {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	var buf []byte
 | 
					 | 
				
			||||||
	b.createMsg(&buf, event)
 | 
					 | 
				
			||||||
	_, err := b.out.Write(buf)
 | 
					 | 
				
			||||||
	return err
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Match checks if the given event matches the logger's regexp expression
 | 
					 | 
				
			||||||
func (b *BaseLogger) Match(event *Event) bool {
 | 
					 | 
				
			||||||
	if b.regexp == nil {
 | 
					 | 
				
			||||||
		return true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if b.regexp.Match([]byte(fmt.Sprintf("%s:%d:%s", event.filename, event.line, event.caller))) {
 | 
					 | 
				
			||||||
		return true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	// Match on the non-colored msg - therefore strip out colors
 | 
					 | 
				
			||||||
	var msg []byte
 | 
					 | 
				
			||||||
	baw := byteArrayWriter(msg)
 | 
					 | 
				
			||||||
	(&protectedANSIWriter{
 | 
					 | 
				
			||||||
		w:    &baw,
 | 
					 | 
				
			||||||
		mode: removeColor,
 | 
					 | 
				
			||||||
	}).Write([]byte(event.msg))
 | 
					 | 
				
			||||||
	msg = baw
 | 
					 | 
				
			||||||
	if b.regexp.Match(msg) {
 | 
					 | 
				
			||||||
		return true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return false
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Close the base logger
 | 
					 | 
				
			||||||
func (b *BaseLogger) Close() {
 | 
					 | 
				
			||||||
	b.mu.Lock()
 | 
					 | 
				
			||||||
	defer b.mu.Unlock()
 | 
					 | 
				
			||||||
	if b.out != nil {
 | 
					 | 
				
			||||||
		b.out.Close()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// GetName returns empty for these provider loggers
 | 
					 | 
				
			||||||
func (b *BaseLogger) GetName() string {
 | 
					 | 
				
			||||||
	return ""
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					@ -268,8 +268,8 @@ normalLoop:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ColoredValue will Color the provided value
 | 
					// ColoredValue will Color the provided value
 | 
				
			||||||
type ColoredValue struct {
 | 
					type ColoredValue struct {
 | 
				
			||||||
	ColorBytes *[]byte
 | 
						colorBytes *[]byte
 | 
				
			||||||
	ResetBytes *[]byte
 | 
						resetBytes *[]byte
 | 
				
			||||||
	Value      *interface{}
 | 
						Value      *interface{}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -290,14 +290,14 @@ func NewColoredValuePointer(value *interface{}, color ...ColorAttribute) *Colore
 | 
				
			||||||
	if len(color) > 0 {
 | 
						if len(color) > 0 {
 | 
				
			||||||
		bytes := ColorBytes(color...)
 | 
							bytes := ColorBytes(color...)
 | 
				
			||||||
		return &ColoredValue{
 | 
							return &ColoredValue{
 | 
				
			||||||
			ColorBytes: &bytes,
 | 
								colorBytes: &bytes,
 | 
				
			||||||
			ResetBytes: &resetBytes,
 | 
								resetBytes: &resetBytes,
 | 
				
			||||||
			Value:      value,
 | 
								Value:      value,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return &ColoredValue{
 | 
						return &ColoredValue{
 | 
				
			||||||
		ColorBytes: &fgBoldBytes,
 | 
							colorBytes: &fgBoldBytes,
 | 
				
			||||||
		ResetBytes: &resetBytes,
 | 
							resetBytes: &resetBytes,
 | 
				
			||||||
		Value:      value,
 | 
							Value:      value,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -310,17 +310,37 @@ func NewColoredValueBytes(value interface{}, colorBytes *[]byte) *ColoredValue {
 | 
				
			||||||
		return val
 | 
							return val
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return &ColoredValue{
 | 
						return &ColoredValue{
 | 
				
			||||||
		ColorBytes: colorBytes,
 | 
							colorBytes: colorBytes,
 | 
				
			||||||
		ResetBytes: &resetBytes,
 | 
							resetBytes: &resetBytes,
 | 
				
			||||||
		Value:      &value,
 | 
							Value:      &value,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Format will format the provided value and protect against ANSI spoofing within the value
 | 
					// Format will format the provided value and protect against ANSI spoofing within the value
 | 
				
			||||||
func (cv *ColoredValue) Format(s fmt.State, c rune) {
 | 
					func (cv *ColoredValue) Format(s fmt.State, c rune) {
 | 
				
			||||||
	s.Write([]byte(*cv.ColorBytes))
 | 
						s.Write([]byte(*cv.colorBytes))
 | 
				
			||||||
	fmt.Fprintf(&protectedANSIWriter{w: s}, fmtString(s, c), *(cv.Value))
 | 
						fmt.Fprintf(&protectedANSIWriter{w: s}, fmtString(s, c), *(cv.Value))
 | 
				
			||||||
	s.Write([]byte(*cv.ResetBytes))
 | 
						s.Write([]byte(*cv.resetBytes))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SetColorBytes will allow a user to set the colorBytes of a colored value
 | 
				
			||||||
 | 
					func (cv *ColoredValue) SetColorBytes(colorBytes []byte) {
 | 
				
			||||||
 | 
						cv.colorBytes = &colorBytes
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SetColorBytesPointer will allow a user to set the colorBytes pointer of a colored value
 | 
				
			||||||
 | 
					func (cv *ColoredValue) SetColorBytesPointer(colorBytes *[]byte) {
 | 
				
			||||||
 | 
						cv.colorBytes = colorBytes
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SetResetBytes will allow a user to set the resetBytes pointer of a colored value
 | 
				
			||||||
 | 
					func (cv *ColoredValue) SetResetBytes(resetBytes []byte) {
 | 
				
			||||||
 | 
						cv.resetBytes = &resetBytes
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SetResetBytesPointer will allow a user to set the resetBytes pointer of a colored value
 | 
				
			||||||
 | 
					func (cv *ColoredValue) SetResetBytesPointer(resetBytes *[]byte) {
 | 
				
			||||||
 | 
						cv.resetBytes = resetBytes
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func fmtString(s fmt.State, c rune) string {
 | 
					func fmtString(s fmt.State, c rune) string {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -77,7 +77,7 @@ func (i *connWriter) connect() error {
 | 
				
			||||||
// ConnLogger implements LoggerProvider.
 | 
					// ConnLogger implements LoggerProvider.
 | 
				
			||||||
// it writes messages in keep-live tcp connection.
 | 
					// it writes messages in keep-live tcp connection.
 | 
				
			||||||
type ConnLogger struct {
 | 
					type ConnLogger struct {
 | 
				
			||||||
	BaseLogger
 | 
						WriterLogger
 | 
				
			||||||
	ReconnectOnMsg bool   `json:"reconnectOnMsg"`
 | 
						ReconnectOnMsg bool   `json:"reconnectOnMsg"`
 | 
				
			||||||
	Reconnect      bool   `json:"reconnect"`
 | 
						Reconnect      bool   `json:"reconnect"`
 | 
				
			||||||
	Net            string `json:"net"`
 | 
						Net            string `json:"net"`
 | 
				
			||||||
| 
						 | 
					@ -98,7 +98,7 @@ func (log *ConnLogger) Init(jsonconfig string) error {
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	log.createLogger(&connWriter{
 | 
						log.NewWriterLogger(&connWriter{
 | 
				
			||||||
		ReconnectOnMsg: log.ReconnectOnMsg,
 | 
							ReconnectOnMsg: log.ReconnectOnMsg,
 | 
				
			||||||
		Reconnect:      log.Reconnect,
 | 
							Reconnect:      log.Reconnect,
 | 
				
			||||||
		Net:            log.Net,
 | 
							Net:            log.Net,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,14 +34,14 @@ func (n *nopWriteCloser) Close() error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ConsoleLogger implements LoggerProvider and writes messages to terminal.
 | 
					// ConsoleLogger implements LoggerProvider and writes messages to terminal.
 | 
				
			||||||
type ConsoleLogger struct {
 | 
					type ConsoleLogger struct {
 | 
				
			||||||
	BaseLogger
 | 
						WriterLogger
 | 
				
			||||||
	Stderr bool `json:"stderr"`
 | 
						Stderr bool `json:"stderr"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewConsoleLogger create ConsoleLogger returning as LoggerProvider.
 | 
					// NewConsoleLogger create ConsoleLogger returning as LoggerProvider.
 | 
				
			||||||
func NewConsoleLogger() LoggerProvider {
 | 
					func NewConsoleLogger() LoggerProvider {
 | 
				
			||||||
	log := &ConsoleLogger{}
 | 
						log := &ConsoleLogger{}
 | 
				
			||||||
	log.createLogger(&nopWriteCloser{
 | 
						log.NewWriterLogger(&nopWriteCloser{
 | 
				
			||||||
		w: os.Stdout,
 | 
							w: os.Stdout,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	return log
 | 
						return log
 | 
				
			||||||
| 
						 | 
					@ -55,11 +55,11 @@ func (log *ConsoleLogger) Init(config string) error {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if log.Stderr {
 | 
						if log.Stderr {
 | 
				
			||||||
		log.createLogger(&nopWriteCloser{
 | 
							log.NewWriterLogger(&nopWriteCloser{
 | 
				
			||||||
			w: os.Stderr,
 | 
								w: os.Stderr,
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		log.createLogger(log.out)
 | 
							log.NewWriterLogger(log.out)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@ import (
 | 
				
			||||||
// FileLogger implements LoggerProvider.
 | 
					// FileLogger implements LoggerProvider.
 | 
				
			||||||
// It writes messages by lines limit, file size limit, or time frequency.
 | 
					// It writes messages by lines limit, file size limit, or time frequency.
 | 
				
			||||||
type FileLogger struct {
 | 
					type FileLogger struct {
 | 
				
			||||||
	BaseLogger
 | 
						WriterLogger
 | 
				
			||||||
	mw *MuxWriter
 | 
						mw *MuxWriter
 | 
				
			||||||
	// The opened file
 | 
						// The opened file
 | 
				
			||||||
	Filename string `json:"filename"`
 | 
						Filename string `json:"filename"`
 | 
				
			||||||
| 
						 | 
					@ -106,7 +106,7 @@ func (log *FileLogger) Init(config string) error {
 | 
				
			||||||
		return errors.New("config must have filename")
 | 
							return errors.New("config must have filename")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// set MuxWriter as Logger's io.Writer
 | 
						// set MuxWriter as Logger's io.Writer
 | 
				
			||||||
	log.createLogger(log.mw)
 | 
						log.NewWriterLogger(log.mw)
 | 
				
			||||||
	return log.StartLogger()
 | 
						return log.StartLogger()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -89,7 +89,6 @@ func TestFileLogger(t *testing.T) {
 | 
				
			||||||
	assert.Equal(t, expected, string(logData))
 | 
						assert.Equal(t, expected, string(logData))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	event.level = DEBUG
 | 
						event.level = DEBUG
 | 
				
			||||||
	expected = expected + ""
 | 
					 | 
				
			||||||
	fileLogger.LogEvent(&event)
 | 
						fileLogger.LogEvent(&event)
 | 
				
			||||||
	fileLogger.Flush()
 | 
						fileLogger.Flush()
 | 
				
			||||||
	logData, err = ioutil.ReadFile(filename)
 | 
						logData, err = ioutil.ReadFile(filename)
 | 
				
			||||||
| 
						 | 
					@ -97,7 +96,6 @@ func TestFileLogger(t *testing.T) {
 | 
				
			||||||
	assert.Equal(t, expected, string(logData))
 | 
						assert.Equal(t, expected, string(logData))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	event.level = TRACE
 | 
						event.level = TRACE
 | 
				
			||||||
	expected = expected + ""
 | 
					 | 
				
			||||||
	fileLogger.LogEvent(&event)
 | 
						fileLogger.LogEvent(&event)
 | 
				
			||||||
	fileLogger.Flush()
 | 
						fileLogger.Flush()
 | 
				
			||||||
	logData, err = ioutil.ReadFile(filename)
 | 
						logData, err = ioutil.ReadFile(filename)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										64
									
								
								modules/log/flags.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								modules/log/flags.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,64 @@
 | 
				
			||||||
 | 
					// Copyright 2019 The Gitea Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a MIT-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// These flags define which text to prefix to each log entry generated
 | 
				
			||||||
 | 
					// by the Logger. Bits are or'ed together to control what's printed.
 | 
				
			||||||
 | 
					// There is no control over the order they appear (the order listed
 | 
				
			||||||
 | 
					// here) or the format they present (as described in the comments).
 | 
				
			||||||
 | 
					// The prefix is followed by a colon only if more than time is stated
 | 
				
			||||||
 | 
					// is specified. For example, flags Ldate | Ltime
 | 
				
			||||||
 | 
					// produce, 2009/01/23 01:23:23 message.
 | 
				
			||||||
 | 
					// The standard is:
 | 
				
			||||||
 | 
					// 2009/01/23 01:23:23 ...a/logger/c/d.go:23:runtime.Caller() [I]: message
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						Ldate          = 1 << iota // the date in the local time zone: 2009/01/23
 | 
				
			||||||
 | 
						Ltime                      // the time in the local time zone: 01:23:23
 | 
				
			||||||
 | 
						Lmicroseconds              // microsecond resolution: 01:23:23.123123.  assumes Ltime.
 | 
				
			||||||
 | 
						Llongfile                  // full file name and line number: /a/logger/c/d.go:23
 | 
				
			||||||
 | 
						Lshortfile                 // final file name element and line number: d.go:23. overrides Llongfile
 | 
				
			||||||
 | 
						Lfuncname                  // function name of the caller: runtime.Caller()
 | 
				
			||||||
 | 
						Lshortfuncname             // last part of the function name
 | 
				
			||||||
 | 
						LUTC                       // if Ldate or Ltime is set, use UTC rather than the local time zone
 | 
				
			||||||
 | 
						Llevelinitial              // Initial character of the provided level in brackets eg. [I] for info
 | 
				
			||||||
 | 
						Llevel                     // Provided level in brackets [INFO]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Last 20 characters of the filename
 | 
				
			||||||
 | 
						Lmedfile = Lshortfile | Llongfile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// LstdFlags is the initial value for the standard logger
 | 
				
			||||||
 | 
						LstdFlags = Ldate | Ltime | Lmedfile | Lshortfuncname | Llevelinitial
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var flagFromString = map[string]int{
 | 
				
			||||||
 | 
						"none":          0,
 | 
				
			||||||
 | 
						"date":          Ldate,
 | 
				
			||||||
 | 
						"time":          Ltime,
 | 
				
			||||||
 | 
						"microseconds":  Lmicroseconds,
 | 
				
			||||||
 | 
						"longfile":      Llongfile,
 | 
				
			||||||
 | 
						"shortfile":     Lshortfile,
 | 
				
			||||||
 | 
						"funcname":      Lfuncname,
 | 
				
			||||||
 | 
						"shortfuncname": Lshortfuncname,
 | 
				
			||||||
 | 
						"utc":           LUTC,
 | 
				
			||||||
 | 
						"levelinitial":  Llevelinitial,
 | 
				
			||||||
 | 
						"level":         Llevel,
 | 
				
			||||||
 | 
						"medfile":       Lmedfile,
 | 
				
			||||||
 | 
						"stdflags":      LstdFlags,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// FlagsFromString takes a comma separated list of flags and returns
 | 
				
			||||||
 | 
					// the flags for this string
 | 
				
			||||||
 | 
					func FlagsFromString(from string) int {
 | 
				
			||||||
 | 
						flags := 0
 | 
				
			||||||
 | 
						for _, flag := range strings.Split(strings.ToLower(from), ",") {
 | 
				
			||||||
 | 
							f, ok := flagFromString[strings.TrimSpace(flag)]
 | 
				
			||||||
 | 
							if ok {
 | 
				
			||||||
 | 
								flags = flags | f
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return flags
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -31,7 +31,7 @@ func (s *smtpWriter) Close() error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SMTPLogger implements LoggerProvider and is used to send emails via given SMTP-server.
 | 
					// SMTPLogger implements LoggerProvider and is used to send emails via given SMTP-server.
 | 
				
			||||||
type SMTPLogger struct {
 | 
					type SMTPLogger struct {
 | 
				
			||||||
	BaseLogger
 | 
						WriterLogger
 | 
				
			||||||
	Username           string   `json:"Username"`
 | 
						Username           string   `json:"Username"`
 | 
				
			||||||
	Password           string   `json:"password"`
 | 
						Password           string   `json:"password"`
 | 
				
			||||||
	Host               string   `json:"host"`
 | 
						Host               string   `json:"host"`
 | 
				
			||||||
| 
						 | 
					@ -63,7 +63,7 @@ func (log *SMTPLogger) Init(jsonconfig string) error {
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	log.createLogger(&smtpWriter{
 | 
						log.NewWriterLogger(&smtpWriter{
 | 
				
			||||||
		owner: log,
 | 
							owner: log,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	log.sendMailFn = smtp.SendMail
 | 
						log.sendMailFn = smtp.SendMail
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										273
									
								
								modules/log/writer.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										273
									
								
								modules/log/writer.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,273 @@
 | 
				
			||||||
 | 
					// Copyright 2019 The Gitea Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a MIT-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package log
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"regexp"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type byteArrayWriter []byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (b *byteArrayWriter) Write(p []byte) (int, error) {
 | 
				
			||||||
 | 
						*b = append(*b, p...)
 | 
				
			||||||
 | 
						return len(p), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// WriterLogger represent a basic logger for Gitea
 | 
				
			||||||
 | 
					type WriterLogger struct {
 | 
				
			||||||
 | 
						out io.WriteCloser
 | 
				
			||||||
 | 
						mu  sync.Mutex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Level           Level  `json:"level"`
 | 
				
			||||||
 | 
						StacktraceLevel Level  `json:"stacktraceLevel"`
 | 
				
			||||||
 | 
						Flags           int    `json:"flags"`
 | 
				
			||||||
 | 
						Prefix          string `json:"prefix"`
 | 
				
			||||||
 | 
						Colorize        bool   `json:"colorize"`
 | 
				
			||||||
 | 
						Expression      string `json:"expression"`
 | 
				
			||||||
 | 
						regexp          *regexp.Regexp
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewWriterLogger creates a new WriterLogger from the provided WriteCloser.
 | 
				
			||||||
 | 
					// Optionally the level can be changed at the same time.
 | 
				
			||||||
 | 
					func (logger *WriterLogger) NewWriterLogger(out io.WriteCloser, level ...Level) {
 | 
				
			||||||
 | 
						logger.mu.Lock()
 | 
				
			||||||
 | 
						defer logger.mu.Unlock()
 | 
				
			||||||
 | 
						logger.out = out
 | 
				
			||||||
 | 
						switch logger.Flags {
 | 
				
			||||||
 | 
						case 0:
 | 
				
			||||||
 | 
							logger.Flags = LstdFlags
 | 
				
			||||||
 | 
						case -1:
 | 
				
			||||||
 | 
							logger.Flags = 0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if len(level) > 0 {
 | 
				
			||||||
 | 
							logger.Level = level[0]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						logger.createExpression()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (logger *WriterLogger) createExpression() {
 | 
				
			||||||
 | 
						if len(logger.Expression) > 0 {
 | 
				
			||||||
 | 
							var err error
 | 
				
			||||||
 | 
							logger.regexp, err = regexp.Compile(logger.Expression)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								logger.regexp = nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetLevel returns the logging level for this logger
 | 
				
			||||||
 | 
					func (logger *WriterLogger) GetLevel() Level {
 | 
				
			||||||
 | 
						return logger.Level
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetStacktraceLevel returns the stacktrace logging level for this logger
 | 
				
			||||||
 | 
					func (logger *WriterLogger) GetStacktraceLevel() Level {
 | 
				
			||||||
 | 
						return logger.StacktraceLevel
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Copy of cheap integer to fixed-width decimal to ascii from logger.
 | 
				
			||||||
 | 
					func itoa(buf *[]byte, i int, wid int) {
 | 
				
			||||||
 | 
						var logger [20]byte
 | 
				
			||||||
 | 
						bp := len(logger) - 1
 | 
				
			||||||
 | 
						for i >= 10 || wid > 1 {
 | 
				
			||||||
 | 
							wid--
 | 
				
			||||||
 | 
							q := i / 10
 | 
				
			||||||
 | 
							logger[bp] = byte('0' + i - q*10)
 | 
				
			||||||
 | 
							bp--
 | 
				
			||||||
 | 
							i = q
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// i < 10
 | 
				
			||||||
 | 
						logger[bp] = byte('0' + i)
 | 
				
			||||||
 | 
						*buf = append(*buf, logger[bp:]...)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (logger *WriterLogger) createMsg(buf *[]byte, event *Event) {
 | 
				
			||||||
 | 
						*buf = append(*buf, logger.Prefix...)
 | 
				
			||||||
 | 
						t := event.time
 | 
				
			||||||
 | 
						if logger.Flags&(Ldate|Ltime|Lmicroseconds) != 0 {
 | 
				
			||||||
 | 
							if logger.Colorize {
 | 
				
			||||||
 | 
								*buf = append(*buf, fgCyanBytes...)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if logger.Flags&LUTC != 0 {
 | 
				
			||||||
 | 
								t = t.UTC()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if logger.Flags&Ldate != 0 {
 | 
				
			||||||
 | 
								year, month, day := t.Date()
 | 
				
			||||||
 | 
								itoa(buf, year, 4)
 | 
				
			||||||
 | 
								*buf = append(*buf, '/')
 | 
				
			||||||
 | 
								itoa(buf, int(month), 2)
 | 
				
			||||||
 | 
								*buf = append(*buf, '/')
 | 
				
			||||||
 | 
								itoa(buf, day, 2)
 | 
				
			||||||
 | 
								*buf = append(*buf, ' ')
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if logger.Flags&(Ltime|Lmicroseconds) != 0 {
 | 
				
			||||||
 | 
								hour, min, sec := t.Clock()
 | 
				
			||||||
 | 
								itoa(buf, hour, 2)
 | 
				
			||||||
 | 
								*buf = append(*buf, ':')
 | 
				
			||||||
 | 
								itoa(buf, min, 2)
 | 
				
			||||||
 | 
								*buf = append(*buf, ':')
 | 
				
			||||||
 | 
								itoa(buf, sec, 2)
 | 
				
			||||||
 | 
								if logger.Flags&Lmicroseconds != 0 {
 | 
				
			||||||
 | 
									*buf = append(*buf, '.')
 | 
				
			||||||
 | 
									itoa(buf, t.Nanosecond()/1e3, 6)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								*buf = append(*buf, ' ')
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if logger.Colorize {
 | 
				
			||||||
 | 
								*buf = append(*buf, resetBytes...)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if logger.Flags&(Lshortfile|Llongfile) != 0 {
 | 
				
			||||||
 | 
							if logger.Colorize {
 | 
				
			||||||
 | 
								*buf = append(*buf, fgGreenBytes...)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							file := event.filename
 | 
				
			||||||
 | 
							if logger.Flags&Lmedfile == Lmedfile {
 | 
				
			||||||
 | 
								startIndex := len(file) - 20
 | 
				
			||||||
 | 
								if startIndex > 0 {
 | 
				
			||||||
 | 
									file = "..." + file[startIndex:]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if logger.Flags&Lshortfile != 0 {
 | 
				
			||||||
 | 
								startIndex := strings.LastIndexByte(file, '/')
 | 
				
			||||||
 | 
								if startIndex > 0 && startIndex < len(file) {
 | 
				
			||||||
 | 
									file = file[startIndex+1:]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							*buf = append(*buf, file...)
 | 
				
			||||||
 | 
							*buf = append(*buf, ':')
 | 
				
			||||||
 | 
							itoa(buf, event.line, -1)
 | 
				
			||||||
 | 
							if logger.Flags&(Lfuncname|Lshortfuncname) != 0 {
 | 
				
			||||||
 | 
								*buf = append(*buf, ':')
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if logger.Colorize {
 | 
				
			||||||
 | 
									*buf = append(*buf, resetBytes...)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								*buf = append(*buf, ' ')
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if logger.Flags&(Lfuncname|Lshortfuncname) != 0 {
 | 
				
			||||||
 | 
							if logger.Colorize {
 | 
				
			||||||
 | 
								*buf = append(*buf, fgGreenBytes...)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							funcname := event.caller
 | 
				
			||||||
 | 
							if logger.Flags&Lshortfuncname != 0 {
 | 
				
			||||||
 | 
								lastIndex := strings.LastIndexByte(funcname, '.')
 | 
				
			||||||
 | 
								if lastIndex > 0 && len(funcname) > lastIndex+1 {
 | 
				
			||||||
 | 
									funcname = funcname[lastIndex+1:]
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							*buf = append(*buf, funcname...)
 | 
				
			||||||
 | 
							if logger.Colorize {
 | 
				
			||||||
 | 
								*buf = append(*buf, resetBytes...)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							*buf = append(*buf, ' ')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if logger.Flags&(Llevel|Llevelinitial) != 0 {
 | 
				
			||||||
 | 
							level := strings.ToUpper(event.level.String())
 | 
				
			||||||
 | 
							if logger.Colorize {
 | 
				
			||||||
 | 
								*buf = append(*buf, levelToColor[event.level]...)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							*buf = append(*buf, '[')
 | 
				
			||||||
 | 
							if logger.Flags&Llevelinitial != 0 {
 | 
				
			||||||
 | 
								*buf = append(*buf, level[0])
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								*buf = append(*buf, level...)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							*buf = append(*buf, ']')
 | 
				
			||||||
 | 
							if logger.Colorize {
 | 
				
			||||||
 | 
								*buf = append(*buf, resetBytes...)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							*buf = append(*buf, ' ')
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var msg = []byte(event.msg)
 | 
				
			||||||
 | 
						if len(msg) > 0 && msg[len(msg)-1] == '\n' {
 | 
				
			||||||
 | 
							msg = msg[:len(msg)-1]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pawMode := allowColor
 | 
				
			||||||
 | 
						if !logger.Colorize {
 | 
				
			||||||
 | 
							pawMode = removeColor
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						baw := byteArrayWriter(*buf)
 | 
				
			||||||
 | 
						(&protectedANSIWriter{
 | 
				
			||||||
 | 
							w:    &baw,
 | 
				
			||||||
 | 
							mode: pawMode,
 | 
				
			||||||
 | 
						}).Write([]byte(msg))
 | 
				
			||||||
 | 
						*buf = baw
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if event.stacktrace != "" && logger.StacktraceLevel <= event.level {
 | 
				
			||||||
 | 
							lines := bytes.Split([]byte(event.stacktrace), []byte("\n"))
 | 
				
			||||||
 | 
							if len(lines) > 1 {
 | 
				
			||||||
 | 
								for _, line := range lines {
 | 
				
			||||||
 | 
									*buf = append(*buf, "\n\t"...)
 | 
				
			||||||
 | 
									*buf = append(*buf, line...)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							*buf = append(*buf, '\n')
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						*buf = append(*buf, '\n')
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// LogEvent logs the event to the internal writer
 | 
				
			||||||
 | 
					func (logger *WriterLogger) LogEvent(event *Event) error {
 | 
				
			||||||
 | 
						if logger.Level > event.level {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						logger.mu.Lock()
 | 
				
			||||||
 | 
						defer logger.mu.Unlock()
 | 
				
			||||||
 | 
						if !logger.Match(event) {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var buf []byte
 | 
				
			||||||
 | 
						logger.createMsg(&buf, event)
 | 
				
			||||||
 | 
						_, err := logger.out.Write(buf)
 | 
				
			||||||
 | 
						return err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Match checks if the given event matches the logger's regexp expression
 | 
				
			||||||
 | 
					func (logger *WriterLogger) Match(event *Event) bool {
 | 
				
			||||||
 | 
						if logger.regexp == nil {
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if logger.regexp.Match([]byte(fmt.Sprintf("%s:%d:%s", event.filename, event.line, event.caller))) {
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Match on the non-colored msg - therefore strip out colors
 | 
				
			||||||
 | 
						var msg []byte
 | 
				
			||||||
 | 
						baw := byteArrayWriter(msg)
 | 
				
			||||||
 | 
						(&protectedANSIWriter{
 | 
				
			||||||
 | 
							w:    &baw,
 | 
				
			||||||
 | 
							mode: removeColor,
 | 
				
			||||||
 | 
						}).Write([]byte(event.msg))
 | 
				
			||||||
 | 
						msg = baw
 | 
				
			||||||
 | 
						if logger.regexp.Match(msg) {
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Close the base logger
 | 
				
			||||||
 | 
					func (logger *WriterLogger) Close() {
 | 
				
			||||||
 | 
						logger.mu.Lock()
 | 
				
			||||||
 | 
						defer logger.mu.Unlock()
 | 
				
			||||||
 | 
						if logger.out != nil {
 | 
				
			||||||
 | 
							logger.out.Close()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetName returns empty for these provider loggers
 | 
				
			||||||
 | 
					func (logger *WriterLogger) GetName() string {
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -38,7 +38,7 @@ func TestBaseLogger(t *testing.T) {
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	prefix := "TestPrefix "
 | 
						prefix := "TestPrefix "
 | 
				
			||||||
	b := BaseLogger{
 | 
						b := WriterLogger{
 | 
				
			||||||
		out:    c,
 | 
							out:    c,
 | 
				
			||||||
		Level:  INFO,
 | 
							Level:  INFO,
 | 
				
			||||||
		Flags:  LstdFlags | LUTC,
 | 
							Flags:  LstdFlags | LUTC,
 | 
				
			||||||
| 
						 | 
					@ -115,7 +115,7 @@ func TestBaseLoggerDated(t *testing.T) {
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	prefix := ""
 | 
						prefix := ""
 | 
				
			||||||
	b := BaseLogger{
 | 
						b := WriterLogger{
 | 
				
			||||||
		out:    c,
 | 
							out:    c,
 | 
				
			||||||
		Level:  WARN,
 | 
							Level:  WARN,
 | 
				
			||||||
		Flags:  Ldate | Ltime | Lmicroseconds | Lshortfile | Llevel,
 | 
							Flags:  Ldate | Ltime | Lmicroseconds | Lshortfile | Llevel,
 | 
				
			||||||
| 
						 | 
					@ -195,14 +195,14 @@ func TestBaseLoggerMultiLineNoFlagsRegexp(t *testing.T) {
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	prefix := ""
 | 
						prefix := ""
 | 
				
			||||||
	b := BaseLogger{
 | 
						b := WriterLogger{
 | 
				
			||||||
		Level:           DEBUG,
 | 
							Level:           DEBUG,
 | 
				
			||||||
		StacktraceLevel: ERROR,
 | 
							StacktraceLevel: ERROR,
 | 
				
			||||||
		Flags:           -1,
 | 
							Flags:           -1,
 | 
				
			||||||
		Prefix:          prefix,
 | 
							Prefix:          prefix,
 | 
				
			||||||
		Expression:      "FILENAME",
 | 
							Expression:      "FILENAME",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	b.createLogger(c)
 | 
						b.NewWriterLogger(c)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	location, _ := time.LoadLocation("EST")
 | 
						location, _ := time.LoadLocation("EST")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -263,14 +263,14 @@ func TestBrokenRegexp(t *testing.T) {
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	b := BaseLogger{
 | 
						b := WriterLogger{
 | 
				
			||||||
		Level:           DEBUG,
 | 
							Level:           DEBUG,
 | 
				
			||||||
		StacktraceLevel: ERROR,
 | 
							StacktraceLevel: ERROR,
 | 
				
			||||||
		Flags:           -1,
 | 
							Flags:           -1,
 | 
				
			||||||
		Prefix:          prefix,
 | 
							Prefix:          prefix,
 | 
				
			||||||
		Expression:      "\\",
 | 
							Expression:      "\\",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	b.createLogger(c)
 | 
						b.NewWriterLogger(c)
 | 
				
			||||||
	assert.Empty(t, b.regexp)
 | 
						assert.Empty(t, b.regexp)
 | 
				
			||||||
	b.Close()
 | 
						b.Close()
 | 
				
			||||||
	assert.Equal(t, true, closed)
 | 
						assert.Equal(t, true, closed)
 | 
				
			||||||
| 
						 | 
					@ -273,6 +273,15 @@ func newLogService() {
 | 
				
			||||||
	golog.SetOutput(log.NewLoggerAsWriter("INFO", log.GetLogger(log.DEFAULT)))
 | 
						golog.SetOutput(log.NewLoggerAsWriter("INFO", log.GetLogger(log.DEFAULT)))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NewLogServices creates all the log services
 | 
				
			||||||
 | 
					func NewLogServices(disableConsole bool) {
 | 
				
			||||||
 | 
						newLogService()
 | 
				
			||||||
 | 
						newMacaronLogService()
 | 
				
			||||||
 | 
						newRouterLogService()
 | 
				
			||||||
 | 
						newAccessLogService()
 | 
				
			||||||
 | 
						NewXORMLogService(disableConsole)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewXORMLogService initializes xorm logger service
 | 
					// NewXORMLogService initializes xorm logger service
 | 
				
			||||||
func NewXORMLogService(disableConsole bool) {
 | 
					func NewXORMLogService(disableConsole bool) {
 | 
				
			||||||
	EnableXORMLog = Cfg.Section("log").Key("ENABLE_XORM_LOG").MustBool(true)
 | 
						EnableXORMLog = Cfg.Section("log").Key("ENABLE_XORM_LOG").MustBool(true)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -982,11 +982,7 @@ func loadOrGenerateInternalToken(sec *ini.Section) string {
 | 
				
			||||||
// NewServices initializes the services
 | 
					// NewServices initializes the services
 | 
				
			||||||
func NewServices() {
 | 
					func NewServices() {
 | 
				
			||||||
	newService()
 | 
						newService()
 | 
				
			||||||
	newLogService()
 | 
						NewLogServices(false)
 | 
				
			||||||
	newMacaronLogService()
 | 
					 | 
				
			||||||
	newAccessLogService()
 | 
					 | 
				
			||||||
	newRouterLogService()
 | 
					 | 
				
			||||||
	NewXORMLogService(false)
 | 
					 | 
				
			||||||
	newCacheService()
 | 
						newCacheService()
 | 
				
			||||||
	newSessionService()
 | 
						newSessionService()
 | 
				
			||||||
	newMailService()
 | 
						newMailService()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue