Implement custom logger with log levels

This commit is contained in:
Pijus Kamandulis 2024-02-27 22:38:59 +02:00
parent b9e38575bc
commit 6ccb7c4bdd
13 changed files with 108 additions and 51 deletions

View File

@ -51,6 +51,7 @@ To disable SSL and run Cosmium on HTTP instead, you can use the `-DisableTls` fl
* **-InitialData**: Path to JSON containing initial state * **-InitialData**: Path to JSON containing initial state
* **-Persist**: Saves data to the given path on application exit (When `-InitialData` argument is not supplied, it will try to load data from path supplied in `-Persist`) * **-Persist**: Saves data to the given path on application exit (When `-InitialData` argument is not supplied, it will try to load data from path supplied in `-Persist`)
* **-Port**: Listen port (default 8081) * **-Port**: Listen port (default 8081)
* **-Debug**: Runs application in debug mode, this provides additional logging
These arguments allow you to configure various aspects of Cosmium's behavior according to your requirements. These arguments allow you to configure various aspects of Cosmium's behavior according to your requirements.

View File

@ -22,6 +22,7 @@ func ParseFlags() {
disableAuthentication := flag.Bool("DisableAuth", false, "Disable authentication") disableAuthentication := flag.Bool("DisableAuth", false, "Disable authentication")
disableTls := flag.Bool("DisableTls", false, "Disable TLS, serve over HTTP") disableTls := flag.Bool("DisableTls", false, "Disable TLS, serve over HTTP")
persistDataPath := flag.String("Persist", "", "Saves data to given path on application exit") persistDataPath := flag.String("Persist", "", "Saves data to given path on application exit")
debug := flag.Bool("Debug", false, "Runs application in debug mode, this provides additional logging")
flag.Parse() flag.Parse()
@ -34,6 +35,7 @@ func ParseFlags() {
Config.PersistDataFilePath = *persistDataPath Config.PersistDataFilePath = *persistDataPath
Config.DisableAuth = *disableAuthentication Config.DisableAuth = *disableAuthentication
Config.DisableTls = *disableTls Config.DisableTls = *disableTls
Config.Debug = *debug
Config.DatabaseAccount = Config.Host Config.DatabaseAccount = Config.Host
Config.DatabaseDomain = Config.Host Config.DatabaseDomain = Config.Host

View File

@ -15,4 +15,5 @@ type ServerConfig struct {
PersistDataFilePath string PersistDataFilePath string
DisableAuth bool DisableAuth bool
DisableTls bool DisableTls bool
Debug bool
} }

View File

@ -1,13 +1,13 @@
package middleware package middleware
import ( import (
"fmt"
"net/url" "net/url"
"strings" "strings"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/pikami/cosmium/api/config" "github.com/pikami/cosmium/api/config"
"github.com/pikami/cosmium/internal/authentication" "github.com/pikami/cosmium/internal/authentication"
"github.com/pikami/cosmium/internal/logger"
) )
func Authentication() gin.HandlerFunc { func Authentication() gin.HandlerFunc {
@ -53,7 +53,7 @@ func Authentication() gin.HandlerFunc {
params, _ := url.ParseQuery(decoded) params, _ := url.ParseQuery(decoded)
clientSignature := strings.Replace(params.Get("sig"), " ", "+", -1) clientSignature := strings.Replace(params.Get("sig"), " ", "+", -1)
if clientSignature != expectedSignature { if clientSignature != expectedSignature {
fmt.Printf("Got wrong signature from client.\n- Expected: %s\n- Got: %s\n", expectedSignature, clientSignature) logger.Errorf("Got wrong signature from client.\n- Expected: %s\n- Got: %s\n", expectedSignature, clientSignature)
c.IndentedJSON(401, gin.H{ c.IndentedJSON(401, gin.H{
"code": "Unauthorized", "code": "Unauthorized",
"message": "Wrong signature.", "message": "Wrong signature.",

View File

@ -2,10 +2,10 @@ package middleware
import ( import (
"bytes" "bytes"
"fmt"
"io" "io"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/pikami/cosmium/internal/logger"
) )
func RequestLogger() gin.HandlerFunc { func RequestLogger() gin.HandlerFunc {
@ -16,7 +16,7 @@ func RequestLogger() gin.HandlerFunc {
bodyStr := readBody(rdr1) bodyStr := readBody(rdr1)
if bodyStr != "" { if bodyStr != "" {
fmt.Println(bodyStr) logger.Debug(bodyStr)
} }
c.Request.Body = rdr2 c.Request.Body = rdr2

View File

@ -8,12 +8,17 @@ import (
"github.com/pikami/cosmium/api/config" "github.com/pikami/cosmium/api/config"
"github.com/pikami/cosmium/api/handlers" "github.com/pikami/cosmium/api/handlers"
"github.com/pikami/cosmium/api/handlers/middleware" "github.com/pikami/cosmium/api/handlers/middleware"
"github.com/pikami/cosmium/internal/logger"
tlsprovider "github.com/pikami/cosmium/internal/tls_provider"
) )
func CreateRouter() *gin.Engine { func CreateRouter() *gin.Engine {
router := gin.Default() router := gin.Default()
if config.Config.Debug {
router.Use(middleware.RequestLogger()) router.Use(middleware.RequestLogger())
}
router.Use(middleware.Authentication()) router.Use(middleware.Authentication())
router.GET("/dbs/:databaseId/colls/:collId/pkranges", handlers.GetPartitionKeyRanges) router.GET("/dbs/:databaseId/colls/:collId/pkranges", handlers.GetPartitionKeyRanges)
@ -49,6 +54,10 @@ func CreateRouter() *gin.Engine {
} }
func StartAPI() { func StartAPI() {
if !config.Config.Debug {
gin.SetMode(gin.ReleaseMode)
}
router := CreateRouter() router := CreateRouter()
listenAddress := fmt.Sprintf(":%d", config.Config.Port) listenAddress := fmt.Sprintf(":%d", config.Config.Port)
@ -58,7 +67,7 @@ func StartAPI() {
config.Config.TLS_CertificatePath, config.Config.TLS_CertificatePath,
config.Config.TLS_CertificateKey) config.Config.TLS_CertificateKey)
if err != nil { if err != nil {
fmt.Println("Failed to start HTTPS server:", err) logger.Error("Failed to start HTTPS server:", err)
} }
return return
@ -68,17 +77,17 @@ func StartAPI() {
router.Run(listenAddress) router.Run(listenAddress)
} }
tlsConfig := config.GetDefaultTlsConfig() tlsConfig := tlsprovider.GetDefaultTlsConfig()
server := &http.Server{ server := &http.Server{
Addr: listenAddress, Addr: listenAddress,
Handler: router.Handler(), Handler: router.Handler(),
TLSConfig: tlsConfig, TLSConfig: tlsConfig,
} }
fmt.Printf("Listening and serving HTTPS on %s\n", server.Addr) logger.Infof("Listening and serving HTTPS on %s\n", server.Addr)
err := server.ListenAndServeTLS("", "") err := server.ListenAndServeTLS("", "")
if err != nil { if err != nil {
fmt.Println("Failed to start HTTPS server:", err) logger.Error("Failed to start HTTPS server:", err)
} }
router.Run() router.Run()

40
internal/logger/logger.go Normal file
View File

@ -0,0 +1,40 @@
package logger
import (
"log"
"os"
"github.com/pikami/cosmium/api/config"
)
var DebugLogger = log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lshortfile)
var InfoLogger = log.New(os.Stdout, "", log.Ldate|log.Ltime)
var ErrorLogger = log.New(os.Stderr, "", log.Ldate|log.Ltime|log.Lshortfile)
func Debug(v ...any) {
if config.Config.Debug {
DebugLogger.Println(v...)
}
}
func Debugf(format string, v ...any) {
if config.Config.Debug {
DebugLogger.Printf(format, v...)
}
}
func Info(v ...any) {
InfoLogger.Println(v...)
}
func Infof(format string, v ...any) {
InfoLogger.Printf(format, v...)
}
func Error(v ...any) {
ErrorLogger.Println(v...)
}
func Errorf(format string, v ...any) {
ErrorLogger.Printf(format, v...)
}

View File

@ -2,12 +2,12 @@ package repositories
import ( import (
"encoding/json" "encoding/json"
"fmt"
"log" "log"
"os" "os"
"reflect" "reflect"
"github.com/pikami/cosmium/api/config" "github.com/pikami/cosmium/api/config"
"github.com/pikami/cosmium/internal/logger"
repositorymodels "github.com/pikami/cosmium/internal/repository_models" repositorymodels "github.com/pikami/cosmium/internal/repository_models"
) )
@ -33,7 +33,7 @@ func InitializeRepository() {
} }
if stat.IsDir() { if stat.IsDir() {
fmt.Println("Argument '-Persist' must be a path to file, not a directory.") logger.Error("Argument '-Persist' must be a path to file, not a directory.")
os.Exit(1) os.Exit(1)
} }
@ -55,10 +55,10 @@ func LoadStateFS(filePath string) {
return return
} }
fmt.Println("Loaded state:") logger.Info("Loaded state:")
fmt.Printf("Databases: %d\n", getLength(state.Databases)) logger.Infof("Databases: %d\n", getLength(state.Databases))
fmt.Printf("Collections: %d\n", getLength(state.Collections)) logger.Infof("Collections: %d\n", getLength(state.Collections))
fmt.Printf("Documents: %d\n", getLength(state.Documents)) logger.Infof("Documents: %d\n", getLength(state.Documents))
storeState = state storeState = state
@ -68,16 +68,16 @@ func LoadStateFS(filePath string) {
func SaveStateFS(filePath string) { func SaveStateFS(filePath string) {
data, err := json.MarshalIndent(storeState, "", "\t") data, err := json.MarshalIndent(storeState, "", "\t")
if err != nil { if err != nil {
fmt.Printf("Failed to save state: %v\n", err) logger.Errorf("Failed to save state: %v\n", err)
return return
} }
os.WriteFile(filePath, data, os.ModePerm) os.WriteFile(filePath, data, os.ModePerm)
fmt.Println("Saved state:") logger.Info("Saved state:")
fmt.Printf("Databases: %d\n", getLength(storeState.Databases)) logger.Infof("Databases: %d\n", getLength(storeState.Databases))
fmt.Printf("Collections: %d\n", getLength(storeState.Collections)) logger.Infof("Collections: %d\n", getLength(storeState.Collections))
fmt.Printf("Documents: %d\n", getLength(storeState.Documents)) logger.Infof("Documents: %d\n", getLength(storeState.Documents))
} }
func GetState() repositorymodels.State { func GetState() repositorymodels.State {

View File

@ -1,9 +1,4 @@
package config package tlsprovider
import (
"crypto/tls"
"fmt"
)
const certificate = ` const certificate = `
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
@ -64,15 +59,3 @@ ilcZlmaCS9pqIXAFK9GQ89V/xa8OibOuJUiBgShnfSQqAwQrfX1vYjtKErnjoRFs
9+zaWugLCC47Hw6QlMDa 9+zaWugLCC47Hw6QlMDa
-----END PRIVATE KEY----- -----END PRIVATE KEY-----
` `
func GetDefaultTlsConfig() *tls.Config {
cert, err := tls.X509KeyPair([]byte(certificate), []byte(certificateKey))
if err != nil {
fmt.Println("Failed to parse certificate and key:", err)
return &tls.Config{}
}
return &tls.Config{
Certificates: []tls.Certificate{cert},
}
}

View File

@ -0,0 +1,19 @@
package tlsprovider
import (
"crypto/tls"
"github.com/pikami/cosmium/internal/logger"
)
func GetDefaultTlsConfig() *tls.Config {
cert, err := tls.X509KeyPair([]byte(certificate), []byte(certificateKey))
if err != nil {
logger.Error("Failed to parse certificate and key:", err)
return &tls.Config{}
}
return &tls.Config{
Certificates: []tls.Certificate{cert},
}
}

View File

@ -1,9 +1,9 @@
package memoryexecutor package memoryexecutor
import ( import (
"fmt"
"reflect" "reflect"
"github.com/pikami/cosmium/internal/logger"
"github.com/pikami/cosmium/parsers" "github.com/pikami/cosmium/parsers"
) )
@ -36,13 +36,13 @@ func (c memoryExecutorContext) array_Slice(arguments []interface{}, row RowType)
lengthEx := c.getFieldValue(arguments[2].(parsers.SelectItem), row) lengthEx := c.getFieldValue(arguments[2].(parsers.SelectItem), row)
if length, ok = lengthEx.(int); !ok { if length, ok = lengthEx.(int); !ok {
fmt.Println("array_Slice - got length parameters of wrong type") logger.Error("array_Slice - got length parameters of wrong type")
return []interface{}{} return []interface{}{}
} }
} }
if start, ok = startEx.(int); !ok { if start, ok = startEx.(int); !ok {
fmt.Println("array_Slice - got start parameters of wrong type") logger.Error("array_Slice - got start parameters of wrong type")
return []interface{}{} return []interface{}{}
} }
@ -117,7 +117,7 @@ func (c memoryExecutorContext) parseArray(argument interface{}, row RowType) []i
arrValue := reflect.ValueOf(ex) arrValue := reflect.ValueOf(ex)
if arrValue.Kind() != reflect.Slice { if arrValue.Kind() != reflect.Slice {
fmt.Println("parseArray got parameters of wrong type") logger.Error("parseArray got parameters of wrong type")
return nil return nil
} }

View File

@ -6,6 +6,7 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/pikami/cosmium/internal/logger"
"github.com/pikami/cosmium/parsers" "github.com/pikami/cosmium/parsers"
) )
@ -168,7 +169,7 @@ func (c memoryExecutorContext) getFieldValue(field parsers.SelectItem, row RowTy
var ok bool var ok bool
if typedValue, ok = field.Value.(parsers.Constant); !ok { if typedValue, ok = field.Value.(parsers.Constant); !ok {
// TODO: Handle error // TODO: Handle error
fmt.Println("parsers.Constant has incorrect Value type") logger.Error("parsers.Constant has incorrect Value type")
} }
if typedValue.Type == parsers.ConstantTypeParameterConstant && if typedValue.Type == parsers.ConstantTypeParameterConstant &&
@ -186,7 +187,7 @@ func (c memoryExecutorContext) getFieldValue(field parsers.SelectItem, row RowTy
var ok bool var ok bool
if typedValue, ok = field.Value.(parsers.FunctionCall); !ok { if typedValue, ok = field.Value.(parsers.FunctionCall); !ok {
// TODO: Handle error // TODO: Handle error
fmt.Println("parsers.Constant has incorrect Value type") logger.Error("parsers.Constant has incorrect Value type")
} }
switch typedValue.Type { switch typedValue.Type {
@ -288,7 +289,7 @@ func (c memoryExecutorContext) getExpressionParameterValue(
return c.getFieldValue(typedParameter, row) return c.getFieldValue(typedParameter, row)
} }
fmt.Println("getExpressionParameterValue - got incorrect parameter type") logger.Error("getExpressionParameterValue - got incorrect parameter type")
return nil return nil
} }

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/pikami/cosmium/internal/logger"
"github.com/pikami/cosmium/parsers" "github.com/pikami/cosmium/parsers"
) )
@ -118,7 +119,7 @@ func (c memoryExecutorContext) strings_Left(arguments []interface{}, row RowType
lengthEx := c.getFieldValue(arguments[1].(parsers.SelectItem), row) lengthEx := c.getFieldValue(arguments[1].(parsers.SelectItem), row)
if length, ok = lengthEx.(int); !ok { if length, ok = lengthEx.(int); !ok {
fmt.Println("strings_Left - got parameters of wrong type") logger.Error("strings_Left - got parameters of wrong type")
return "" return ""
} }
@ -157,7 +158,7 @@ func (c memoryExecutorContext) strings_Replicate(arguments []interface{}, row Ro
timesEx := c.getFieldValue(arguments[1].(parsers.SelectItem), row) timesEx := c.getFieldValue(arguments[1].(parsers.SelectItem), row)
if times, ok = timesEx.(int); !ok { if times, ok = timesEx.(int); !ok {
fmt.Println("strings_Replicate - got parameters of wrong type") logger.Error("strings_Replicate - got parameters of wrong type")
return "" return ""
} }
@ -190,7 +191,7 @@ func (c memoryExecutorContext) strings_Right(arguments []interface{}, row RowTyp
lengthEx := c.getFieldValue(arguments[1].(parsers.SelectItem), row) lengthEx := c.getFieldValue(arguments[1].(parsers.SelectItem), row)
if length, ok = lengthEx.(int); !ok { if length, ok = lengthEx.(int); !ok {
fmt.Println("strings_Right - got parameters of wrong type") logger.Error("strings_Right - got parameters of wrong type")
return "" return ""
} }
@ -219,11 +220,11 @@ func (c memoryExecutorContext) strings_Substring(arguments []interface{}, row Ro
lengthEx := c.getFieldValue(arguments[2].(parsers.SelectItem), row) lengthEx := c.getFieldValue(arguments[2].(parsers.SelectItem), row)
if startPos, ok = startPosEx.(int); !ok { if startPos, ok = startPosEx.(int); !ok {
fmt.Println("strings_Substring - got start parameters of wrong type") logger.Error("strings_Substring - got start parameters of wrong type")
return "" return ""
} }
if length, ok = lengthEx.(int); !ok { if length, ok = lengthEx.(int); !ok {
fmt.Println("strings_Substring - got length parameters of wrong type") logger.Error("strings_Substring - got length parameters of wrong type")
return "" return ""
} }
@ -263,7 +264,7 @@ func (c memoryExecutorContext) parseString(argument interface{}, row RowType) st
return str1 return str1
} }
fmt.Println("StringEquals got parameters of wrong type") logger.Error("StringEquals got parameters of wrong type")
return "" return ""
} }