diff --git a/client/README.md b/client/README.md index 7bdbf13..999908a 100644 --- a/client/README.md +++ b/client/README.md @@ -1,8 +1,6 @@ # Bark Client -## IMPORTANT: It is not Yet Built - -## What does the client do? +## What does the client do? The Bark client (just _client_ henceforth) is the _library_ side of the bark. It is the piece that takes in the logs from any golang program and sends it to the server which is configured against the client. It is supposed to have the utility functions to help users log to bark directly from go code without having to worry about network calls and such. ## Levels of Logs @@ -19,7 +17,7 @@ The client defines 7 levels of logs: Any single character in the place of error level in a parsable single log message would indicate the level of **INFO**. ## Simple usecase -The client can be initialized and used as follows (we explain the options below code sample): +The client can be initialized and used as follows (we explain the options below code sample): ```go barkClient := client.NewClient("", "", "", "", @@ -41,12 +39,12 @@ The options that are used for initializing the client are as follows: - **bark_server_url**: This is the URL of a running bark server. It must end in `/`. For example `http://bark.example.com/` or `http://127.0.0.1:8080/` - **default_log_level**: When you use `Println` or `Default`, the log message is parsed (rules for prasing are described [here](../_nocode/docs/log-string-parsing-in-bark.md)) and if it does not contain any indication for what the log level is, then the value supplied in this field is used as the log level for sent log message. When using dedicated methods for error levels (e.g. `Panic`, `Error` etc.), the parsed error level is overwritten. - **default_service_name**: This is the name of the service which is sending the log - so it has to be the name of the program or service which is calling it. In case a blank string is sent, the value against `constants.DefaultLogServiceName` (currently set to `def_svc`) is used. -- **session_name**: This is the name of the calling app's session. This value is supposed to indicate which instance among possibly multiple instances of a service sent a log message. For example, in case of the service being deployed within Kubernetes, it might indicate the service's pod's name. If the value is sent as a blank string, client will try to use the machine's hostname. If it fails to fetch the hostname, a random string will be used instead. +- **session_name**: This is the name of the calling app's session. This value is supposed to indicate which instance among possibly multiple instances of a service sent a log message. For example, in case of the service being deployed within Kubernetes, it might indicate the service's pod's name. If the value is sent as a blank string, client will try to use the machine's hostname. If it fails to fetch the hostname, a random string will be used instead. - **enable_slog**: This enables [slog](https://go.dev/blog/slog) for the client. When this option is enabled, all logs in addition to being sent to the bark server is also printed on STDOUT of the service. - **enable_bulk_dispatch**: Setting this to true would enable the client to push all the requests being received in a channel and start using it. It improves the overall performance of the client sending log entries to the server. ### Simplest usecase (without any server) -The simplest usecase of any logging library is to print to STDOUT. While the primary usecase of bark is to be able to dispatch log messages to a remote server, when we start off with a new project, we often just want to start logging things to STDOUT. Maybe even later, that is how we want to use logs. For such usecases, the client library offers `NewSloggerClient` which uses the built in [slog](https://go.dev/blog/slog) package in go (version 1.21+) to log your messages to STDOUT with levels. Example: +The simplest usecase of any logging library is to print to STDOUT. While the primary usecase of bark is to be able to dispatch log messages to a remote server, when we start off with a new project, we often just want to start logging things to STDOUT. Maybe even later, that is how we want to use logs. For such usecases, the client library offers `NewSloggerClient` which uses the built in [slog](https://go.dev/blog/slog) package in go (version 1.21+) to log your messages to STDOUT with levels. Example: ```go log := client.NewSloggerClient("INFO") @@ -60,7 +58,7 @@ log.Info("Info message") log.Debug("Debug message") log.Println("Println message") ``` -The above piece of code will end up printing something like the following (the dates in the beginning of each line will vary): +The above piece of code will end up printing something like the following (the dates in the beginning of each line will vary): ``` 2023/10/15 21:57:41 PANIC Panic message @@ -74,7 +72,7 @@ The above piece of code will end up printing something like the following (the d ``` ## Printing logs to a file -Bark client, as shown above, is capable of sending logs to a server as well as printing them to the standard output as well. It can also do both of those things simultaneously. The architecture in very simple representation looks like this: +Bark client, as shown above, is capable of sending logs to a server as well as printing them to the standard output as well. It can also do both of those things simultaneously. The architecture in very simple representation looks like this: ![barkslogger.svg](../_nocode/images/barkslogger.svg) @@ -100,7 +98,7 @@ The above code will write the output to `random.txt` file. You can expect the fi 2023/10/18 19:27:51 INFO Some Message that'll be sent to random.txt file ``` -### Slog and writing to a file +### Slog and writing to a file Bark client uses [slog](https://go.dev/blog/slog) internally to handle the printing of the logs. Slog is a simple and structured logging library that comes with Go (version 1.21+). @@ -153,7 +151,7 @@ If you add a nil options, the log labels will appear as described in the [slog d > LevelDebug Level = -4 \ > LevelInfo Level = 0 \ > LevelWarn Level = 4 \ -> LevelError Level = 8 \ +> LevelError Level = 8 The custom log levels defined by bark client have the following values: diff --git a/models/barklog.go b/models/barklog.go index d3d6e8f..42bd4cb 100644 --- a/models/barklog.go +++ b/models/barklog.go @@ -113,12 +113,12 @@ func (bld *BarkLogDao) InsertServerStartedLog() error { } // InsertBatch sends a batch of logs to the DB. -func (bld *BarkLogDao) InsertBatch(l []BarkLog) error { - batchOfBarkLog := [][]any{} - for i := 0; i < len(l); i++ { - batchElement := []any{l[i].LogTime, l[i].LogLevel, l[i].ServiceName, l[i].SessionName, - l[i].Code, l[i].Message, l[i].MoreData} - batchOfBarkLog = append(batchOfBarkLog, batchElement) +func (bld *BarkLogDao) InsertBatch(l *[]BarkLog) error { + batchOfBarkLog := make([][]any, len(*l)) + for i := 0; i < len(*l); i++ { + batchElement := []any{(*l)[i].LogTime, (*l)[i].LogLevel, (*l)[i].ServiceName, (*l)[i].SessionName, + (*l)[i].Code, (*l)[i].Message, (*l)[i].MoreData} + batchOfBarkLog[i] = batchElement } _, err := resources.BarkDb.Client.CopyFrom(context.Background(), pgx.Identifier{"app_log"}, diff --git a/services/dbLogWriter/db_log_writer.go b/services/dbLogWriter/db_log_writer.go index 099830c..3c0bd5a 100644 --- a/services/dbLogWriter/db_log_writer.go +++ b/services/dbLogWriter/db_log_writer.go @@ -17,6 +17,35 @@ func init() { BarkLogDao = models.NewBarkLogDao() } +var smallLogBatch = make([]models.BarkLog, constants.ServerLogInsertionBatchSizeSmall) +var mediumLogBatch = make([]models.BarkLog, constants.ServerLogInsertionBatchSizeMedium) +var largeLogBatch = make([]models.BarkLog, constants.ServerLogInsertionBatchSizeLarge) + +// insertBatchOfSize saves logs of the specified size to bark database. +func insertBatchOfSize(size int, logBatch *[]models.BarkLog) { + for i := 0; i < size; i++ { + elem, ok := <-channels.LogChannel + if !ok { + fmt.Println("E#1LVMFC - Error occured while getting batch from channel") + break // Something went wrong + } + (*logBatch)[i] = elem + } + + go func() { + defer resources.ServerDbSaverWg.Add(-size) + err := BarkLogDao.InsertBatch(logBatch) + if err != nil { + fmt.Println("E#1LVMIR - Batch insertion failed. Error: " + err.Error() + "\n") + for _, logEntry := range *logBatch { + fmt.Printf("E#1LVMJG - Log message: | %v\n", logEntry) + } + return + } + fmt.Printf("L#1LVM50 - Batch inserted at %s of size %d", time.Now().Format("2006-01-02 15:04:05"), size) + }() +} + // KeepSavingLogs is a go routine to check channel length and commit to DB // The routine decides whether a batch or single insert DB call of the logs is needed to be made. // Further bifurcation of the batch sizes is done based on the incoming traffic and LogChannel capacity. @@ -26,79 +55,18 @@ func KeepSavingLogs() { for { logChannelLength = len(channels.LogChannel) //fmt.Println("ChanLen: ", logChannelLength) - var logBatch = []models.BarkLog{} if logChannelLength >= constants.ServerLogInsertionBatchSizeLarge { //fmt.Println("Sending Large Batch") // Bulk insert - for i := 0; i < constants.ServerLogInsertionBatchSizeLarge; i++ { - elem, ok := <-channels.LogChannel - if !ok { - fmt.Println("E#1LVMFC - Error occured while getting batch from channel") - break // Something went wrong - } - logBatch = append(logBatch, elem) - } - - go func() { - defer resources.ServerDbSaverWg.Add(-(len(logBatch))) - err := BarkLogDao.InsertBatch(logBatch) - if err != nil { - fmt.Println("E#1LVMIR - Large Batch insertion failed. Error: " + err.Error() + "\n") - for _, logEntry := range logBatch { - fmt.Printf("E#1LVMJG - Log message: | %v\n", logEntry) - } - return - } - fmt.Println("L#1LVM50 - Large Batch inserted at ", time.Now().Format("2006-01-02 15:04:05")) - }() + insertBatchOfSize(constants.ServerLogInsertionBatchSizeLarge, &largeLogBatch) } else if logChannelLength >= constants.ServerLogInsertionBatchSizeMedium && logChannelLength < constants.ServerLogInsertionBatchSizeLarge { //fmt.Println("Sending Medium Batch") // Bulk insert - for i := 0; i < constants.ServerLogInsertionBatchSizeMedium; i++ { - elem, ok := <-channels.LogChannel - if !ok { - fmt.Println("E#1LVMFF - Error occured while getting batch from channel") - break // Something went wrong - } - logBatch = append(logBatch, elem) - } - - go func() { - defer resources.ServerDbSaverWg.Add(-(len(logBatch))) - err := BarkLogDao.InsertBatch(logBatch) - if err != nil { - fmt.Println("E#1LVMKR - Medium Batch insertion failed. Error: " + err.Error() + "\n") - for _, logEntry := range logBatch { - fmt.Printf("E#1LVMKU - Log message: | %v\n", logEntry) - } - return - } - fmt.Println("L#1LVMKM - Medium Batch inserted at ", time.Now().Format("2006-01-02 15:04:05")) - }() + insertBatchOfSize(constants.ServerLogInsertionBatchSizeMedium, &mediumLogBatch) } else if logChannelLength >= constants.ServerLogInsertionBatchSizeSmall && logChannelLength < constants.ServerLogInsertionBatchSizeMedium { //fmt.Println("Sending Small Batch") // Bulk insert - for i := 0; i < constants.ServerLogInsertionBatchSizeSmall; i++ { - elem, ok := <-channels.LogChannel - if !ok { - fmt.Println("E#1LVMFL - Error occured while getting batch from channel") - break // Something went wrong - } - logBatch = append(logBatch, elem) - } - - go func() { - defer resources.ServerDbSaverWg.Add(-(len(logBatch))) - err := BarkLogDao.InsertBatch(logBatch) - if err != nil { - fmt.Println("E#1LVMLE - Small Batch insertion failed. Error: " + err.Error() + "\n") - for _, logEntry := range logBatch { - fmt.Printf("E#1LVMLI - Log message: | %v\n", logEntry) - } - return - } - fmt.Println("L#1LVMFR - Small Batch inserted at ", time.Now().Format("2006-01-02 15:04:05")) - }() + insertBatchOfSize(constants.ServerLogInsertionBatchSizeMedium, &smallLogBatch) } else if logChannelLength > 0 && logChannelLength < constants.ServerLogInsertionBatchSizeSmall { //fmt.Println("Sending Single Log") // Commit one at a time @@ -112,6 +80,7 @@ func KeepSavingLogs() { fmt.Printf("E#1LVMML - Log message: | %v\n", singleLog) } } else { + logBatch := make([]models.BarkLog, logChannelLength) if appRuntime.ShutdownRequested.Load() == true { if len(channels.LogChannel) == 0 { return @@ -124,7 +93,7 @@ func KeepSavingLogs() { } logBatch = append(logBatch, elem) } - err := BarkLogDao.InsertBatch(logBatch) + err := BarkLogDao.InsertBatch(&logBatch) if err != nil { fmt.Println("E#1LVMN5 - Remaining Batch insertion failed. Error: " + err.Error() + "\n") for _, logEntry := range logBatch {