* feat(backend): try a new approach for logs formatting (http) * feat(backend): added logger module * feat(backend): added project/session info to /i endpoint * feat(backend): found a solution for correct caller information * feat(backend): finished logs for http handlers * feat(backend): finished logs for mobile http handlers * feat(backend): finished ender * feat(backend): finished assets * feat(backend): finished heuristics * feat(backend): finished image-storage * feat(backend): finished sink * feat(backend): finished storage * feat(backend): formatted logs in all services * feat(backend): finished foss part * feat(backend): added missed foss part * feat(backend): fixed panic in memory manager and sink service * feat(backend): connectors
120 lines
2.9 KiB
Go
120 lines
2.9 KiB
Go
package configurator
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/sethvargo/go-envconfig"
|
|
|
|
"openreplay/backend/internal/config/common"
|
|
"openreplay/backend/pkg/logger"
|
|
)
|
|
|
|
func readFile(path string) (map[string]string, error) {
|
|
file, err := os.Open(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("can't open file: %s", err)
|
|
}
|
|
defer file.Close()
|
|
data, err := io.ReadAll(file)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("can't read file: %s", err)
|
|
}
|
|
|
|
res := make(map[string]string)
|
|
lines := strings.Split(string(data), "\n")
|
|
for _, line := range lines {
|
|
if len(line) == 0 {
|
|
continue
|
|
}
|
|
env := strings.Split(line, "=")
|
|
if len(env) < 2 {
|
|
continue
|
|
}
|
|
res[env[0]] = env[1]
|
|
}
|
|
return res, nil
|
|
}
|
|
|
|
func parseFile(log logger.Logger, a interface{}, path string) {
|
|
ctx := context.Background()
|
|
// Skip parsing process without logs if we don't have path to config file
|
|
if path == "" {
|
|
return
|
|
}
|
|
envs, err := readFile(path)
|
|
if err != nil {
|
|
log.Error(ctx, "can't read config file, err: %s", err)
|
|
return
|
|
}
|
|
|
|
val := reflect.ValueOf(a).Elem()
|
|
for i := 0; i < val.NumField(); i++ {
|
|
envName := val.Type().Field(i).Tag.Get("env")
|
|
if envName == "" {
|
|
continue
|
|
}
|
|
envName = strings.Split(envName, ",")[0]
|
|
if envName == "" {
|
|
continue
|
|
}
|
|
fmt.Println(envName, val.Type().Field(i).Type.String())
|
|
if value, ok := envs[envName]; ok {
|
|
switch val.Type().Field(i).Type.String() {
|
|
case "string":
|
|
val.Field(i).SetString(value)
|
|
case "int", "int8", "int16", "int32", "int64":
|
|
intValue, err := strconv.Atoi(value)
|
|
if err != nil {
|
|
log.Error(ctx, "can't parse int value: %s", err)
|
|
continue
|
|
}
|
|
val.Field(i).SetInt(int64(intValue))
|
|
case "uint", "uint8", "uint16", "uint32", "uint64":
|
|
uintValue, err := strconv.Atoi(value)
|
|
if err != nil {
|
|
log.Error(ctx, "can't parse uint value: %s", err)
|
|
continue
|
|
}
|
|
val.Field(i).SetUint(uint64(uintValue))
|
|
case "bool":
|
|
boolValue, err := strconv.ParseBool(value)
|
|
if err != nil {
|
|
log.Error(ctx, "can't parse bool value: %s", err)
|
|
continue
|
|
}
|
|
val.Field(i).SetBool(boolValue)
|
|
case "time.Duration":
|
|
d, err := time.ParseDuration(value)
|
|
if err != nil {
|
|
log.Error(ctx, "can't parse time.Duration value: %s", err)
|
|
continue
|
|
}
|
|
val.Field(i).SetInt(int64(d))
|
|
case "map[string]string":
|
|
var stringMap map[string]string
|
|
if err := json.Unmarshal([]byte(value), &stringMap); err != nil {
|
|
log.Error(ctx, "can't parse map[string]string value: %s", err)
|
|
continue
|
|
}
|
|
val.Field(i).Set(reflect.ValueOf(stringMap))
|
|
default:
|
|
log.Error(ctx, "unknown config type: ", val.Type().Field(i).Type.String())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func Process(log logger.Logger, cfg common.Configer) {
|
|
if err := envconfig.Process(context.Background(), cfg); err != nil {
|
|
log.Fatal(context.Background(), "error while processing env vars, err: %s", err)
|
|
}
|
|
parseFile(log, cfg, cfg.GetConfigPath())
|
|
}
|