update logging

This commit is contained in:
Fran Jurmanović
2025-05-29 00:21:32 +02:00
parent 3dfbe77219
commit 1f41f6003b
7 changed files with 238 additions and 56 deletions

View File

@@ -101,40 +101,53 @@ func ParseQueryFilter(c *fiber.Ctx, filter interface{}) error {
elem := val.Elem()
typ := elem.Type()
for i := 0; i < elem.NumField(); i++ {
field := elem.Field(i)
fieldType := typ.Field(i)
// Process all fields including embedded structs
var processFields func(reflect.Value, reflect.Type) error
processFields = func(val reflect.Value, typ reflect.Type) error {
for i := 0; i < val.NumField(); i++ {
field := val.Field(i)
fieldType := typ.Field(i)
// Skip if field cannot be set
if !field.CanSet() {
continue
}
// Check for param tag first (path parameters)
if paramName := fieldType.Tag.Get("param"); paramName != "" {
if err := parsePathParam(c, field, paramName); err != nil {
return fmt.Errorf("error parsing path parameter %s: %v", paramName, err)
// Handle embedded structs recursively
if fieldType.Anonymous {
if err := processFields(field, fieldType.Type); err != nil {
return err
}
continue
}
continue
}
// Then check for query tag
queryName := fieldType.Tag.Get("query")
if queryName == "" {
queryName = ToSnakeCase(fieldType.Name) // Default to snake_case of field name
}
// Skip if field cannot be set
if !field.CanSet() {
continue
}
queryVal := c.Query(queryName)
if queryVal == "" {
continue // Skip empty values
}
// Check for param tag first (path parameters)
if paramName := fieldType.Tag.Get("param"); paramName != "" {
if err := parsePathParam(c, field, paramName); err != nil {
return fmt.Errorf("error parsing path parameter %s: %v", paramName, err)
}
continue
}
if err := parseValue(field, queryVal, fieldType.Tag); err != nil {
return fmt.Errorf("error parsing query parameter %s: %v", queryName, err)
// Then check for query tag
queryName := fieldType.Tag.Get("query")
if queryName == "" {
queryName = ToSnakeCase(fieldType.Name) // Default to snake_case of field name
}
queryVal := c.Query(queryName)
if queryVal == "" {
continue // Skip empty values
}
if err := parseValue(field, queryVal, fieldType.Tag); err != nil {
return fmt.Errorf("error parsing query parameter %s: %v", queryName, err)
}
}
return nil
}
return nil
return processFields(elem, typ)
}
func parsePathParam(c *fiber.Ctx, field reflect.Value, paramName string) error {

View File

@@ -0,0 +1,78 @@
package tracking
import (
"bufio"
"os"
"time"
)
type LogTailer struct {
filePath string
handleLine func(string)
stopChan chan struct{}
isRunning bool
}
func NewLogTailer(filePath string, handleLine func(string)) *LogTailer {
return &LogTailer{
filePath: filePath,
handleLine: handleLine,
stopChan: make(chan struct{}),
}
}
func (t *LogTailer) Start() {
if t.isRunning {
return
}
t.isRunning = true
go func() {
var lastSize int64 = 0
for {
select {
case <-t.stopChan:
t.isRunning = false
return
default:
// Try to open and read the file
if file, err := os.Open(t.filePath); err == nil {
stat, err := file.Stat()
if err != nil {
file.Close()
time.Sleep(time.Second)
continue
}
// If file was truncated, start from beginning
if stat.Size() < lastSize {
lastSize = 0
}
// Seek to last read position
if lastSize > 0 {
file.Seek(lastSize, 0)
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
t.handleLine(scanner.Text())
lastSize, _ = file.Seek(0, 1) // Get current position
}
file.Close()
}
// Wait before next attempt
time.Sleep(time.Second)
}
}
}()
}
func (t *LogTailer) Stop() {
if !t.isRunning {
return
}
close(t.stopChan)
}