detached b5e5ea3

feat: Enhance log level configuration with flexible environment and config support

- Add `LogLevel` to `GeneralConfig` for more granular logging control
- Implement log level configuration from environment variable `GORDON_LOG_LEVEL`
- Add default log level fallback to "info"
- Support log level configuration through YAML config file
- Improve log level parsing with case-insensitive matching
- Add debug logging for log level configuration changes
commit
b5e5ea3683f65c1373d790b77cca3edbc1578e71
author
bamen · · 2025-03-09 16:02 UTC
parent
2445c7c
signature
unsigned
1 file · +71 -7
M internal/common/init_config.go +71 -7
@@ -30,11 +30,33 @@ func init() {
3030 log.SetReportTimestamp(true)
3131 log.SetTimeFormat("15:04:05")
3232
33- // Check for debug environment variable
34- if os.Getenv("ENV") == "dev" {
35- // Set logger to debug level
33+ // First check for GORDON_LOG_LEVEL environment variable
34+ if logLevelEnv := os.Getenv("GORDON_LOG_LEVEL"); logLevelEnv != "" {
35+ // Convert string log level to charmbracelet/log level
36+ var logLevel log.Level
37+ switch strings.ToLower(logLevelEnv) {
38+ case "debug":
39+ logLevel = log.DebugLevel
40+ case "info":
41+ logLevel = log.InfoLevel
42+ case "warn", "warning":
43+ logLevel = log.WarnLevel
44+ case "error":
45+ logLevel = log.ErrorLevel
46+ case "fatal":
47+ logLevel = log.FatalLevel
48+ default:
49+ // Default to info level for unknown values
50+ logLevel = log.InfoLevel
51+ }
52+
53+ // Set the logger level
54+ logger.SetLevel(logLevel)
55+ logger.Debug("Log level set from environment variable", "level", logLevelEnv)
56+ } else if os.Getenv("ENV") == "dev" {
57+ // Fall back to ENV=dev behavior if GORDON_LOG_LEVEL is not set
3658 logger.SetLevel(log.DebugLevel)
37- logger.Debug("Debug logging enabled")
59+ logger.Debug("Debug logging enabled from ENV=dev")
3860 }
3961 }
4062
@@ -62,6 +84,7 @@ type AdminConfig struct {
6284 type GeneralConfig struct {
6385 StorageDir string `yaml:"storageDir"`
6486 Token string `yaml:"token"`
87+ LogLevel string `yaml:"logLevel"`
6588 }
6689 type HttpConfig struct {
6790 Port string `yaml:"port"`
@@ -99,9 +122,10 @@ var (
99122 certDir = "/certs"
100123 letsEncryptMode = "staging"
101124 autoRenew = true
102- renewBefore = 30 // days
103- cacheSize = 1000 // entries
104- gracePeriod = 30 // seconds
125+ renewBefore = 30 // days
126+ cacheSize = 1000 // entries
127+ gracePeriod = 30 // seconds
128+ defaultLogLevel = "info" // Default log level
105129 )
106130
107131 // applyDefaultsToConfig applies default values to any fields that have zero values
@@ -109,6 +133,13 @@ var (
109133 func applyDefaultsToConfig(config *Config) bool {
110134 defaultsApplied := false
111135
136+ // Apply defaults to GeneralConfig
137+ if config.General.LogLevel == "" {
138+ config.General.LogLevel = defaultLogLevel
139+ logger.Debug("Applied default value for General.LogLevel", "value", defaultLogLevel)
140+ defaultsApplied = true
141+ }
142+
112143 // Apply defaults to ReverseProxy config
113144 if config.ReverseProxy.Port == "" {
114145 config.ReverseProxy.Port = reverseProxyPort
@@ -353,6 +384,12 @@ func loadConfigFromEnv(config *Config, printLogs bool) {
353384 logger.Info("Using environment variable GORDON_TOKEN")
354385 }
355386 }
387+ if val := os.Getenv("GORDON_LOG_LEVEL"); val != "" {
388+ config.General.LogLevel = val
389+ if printLogs {
390+ logger.Info("Using environment variable GORDON_LOG_LEVEL", "value", val)
391+ }
392+ }
356393
357394 // HTTP Configuration
358395 if val := os.Getenv("GORDON_HTTP_PORT"); val != "" {
@@ -530,6 +567,7 @@ func (config *Config) LoadConfig() (*Config, error) {
530567 *config = Config{
531568 General: GeneralConfig{
532569 StorageDir: homeDir + "/.gordon",
570+ LogLevel: defaultLogLevel,
533571 },
534572 Http: HttpConfig{
535573 Port: "8080",
@@ -666,6 +704,7 @@ func (config *Config) LoadConfig() (*Config, error) {
666704 *config = Config{
667705 General: GeneralConfig{
668706 StorageDir: homeDir + "/.gordon",
707+ LogLevel: defaultLogLevel,
669708 },
670709 Http: HttpConfig{
671710 Port: "8080",
@@ -762,6 +801,31 @@ func (config *Config) LoadConfig() (*Config, error) {
762801 logger.Info("Loaded configuration from", "path", configFilePath)
763802 }
764803
804+ // Apply the log level from configuration
805+ if config.General.LogLevel != "" {
806+ // Convert string log level to charmbracelet/log level
807+ var logLevel log.Level
808+ switch strings.ToLower(config.General.LogLevel) {
809+ case "debug":
810+ logLevel = log.DebugLevel
811+ case "info":
812+ logLevel = log.InfoLevel
813+ case "warn", "warning":
814+ logLevel = log.WarnLevel
815+ case "error":
816+ logLevel = log.ErrorLevel
817+ case "fatal":
818+ logLevel = log.FatalLevel
819+ default:
820+ logger.Warn("Unknown log level specified, using default info level", "specified", config.General.LogLevel)
821+ logLevel = log.InfoLevel
822+ }
823+
824+ // Set the logger level
825+ logger.SetLevel(logLevel)
826+ logger.Debug("Log level set from configuration", "level", config.General.LogLevel)
827+ }
828+
765829 logger.Debug("LoadConfig: Completed LoadConfig function")
766830 return config, nil
767831 }
@@ -30,11 +30,33 @@ func init() {
30 log.SetReportTimestamp(true)30 log.SetReportTimestamp(true)
31 log.SetTimeFormat("15:04:05")31 log.SetTimeFormat("15:04:05")
32 32
33- // Check for debug environment variable33+ // First check for GORDON_LOG_LEVEL environment variable
34- if os.Getenv("ENV") == "dev" {34+ if logLevelEnv := os.Getenv("GORDON_LOG_LEVEL"); logLevelEnv != "" {
35- // Set logger to debug level35+ // Convert string log level to charmbracelet/log level
36+ var logLevel log.Level
37+ switch strings.ToLower(logLevelEnv) {
38+ case "debug":
39+ logLevel = log.DebugLevel
40+ case "info":
41+ logLevel = log.InfoLevel
42+ case "warn", "warning":
43+ logLevel = log.WarnLevel
44+ case "error":
45+ logLevel = log.ErrorLevel
46+ case "fatal":
47+ logLevel = log.FatalLevel
48+ default:
49+ // Default to info level for unknown values
50+ logLevel = log.InfoLevel
51+ }
52+
53+ // Set the logger level
54+ logger.SetLevel(logLevel)
55+ logger.Debug("Log level set from environment variable", "level", logLevelEnv)
56+ } else if os.Getenv("ENV") == "dev" {
57+ // Fall back to ENV=dev behavior if GORDON_LOG_LEVEL is not set
36 logger.SetLevel(log.DebugLevel)58 logger.SetLevel(log.DebugLevel)
37- logger.Debug("Debug logging enabled")59+ logger.Debug("Debug logging enabled from ENV=dev")
38 }60 }
39 }61 }
40 62
@@ -62,6 +84,7 @@ type AdminConfig struct {
62 type GeneralConfig struct {84 type GeneralConfig struct {
63 StorageDir string `yaml:"storageDir"`85 StorageDir string `yaml:"storageDir"`
64 Token string `yaml:"token"`86 Token string `yaml:"token"`
87+ LogLevel string `yaml:"logLevel"`
65 }88 }
66 type HttpConfig struct {89 type HttpConfig struct {
67 Port string `yaml:"port"`90 Port string `yaml:"port"`
@@ -99,9 +122,10 @@ var (
99 certDir = "/certs"122 certDir = "/certs"
100 letsEncryptMode = "staging"123 letsEncryptMode = "staging"
101 autoRenew = true124 autoRenew = true
102- renewBefore = 30 // days125+ renewBefore = 30 // days
103- cacheSize = 1000 // entries126+ cacheSize = 1000 // entries
104- gracePeriod = 30 // seconds127+ gracePeriod = 30 // seconds
128+ defaultLogLevel = "info" // Default log level
105 )129 )
106 130
107 // applyDefaultsToConfig applies default values to any fields that have zero values131 // applyDefaultsToConfig applies default values to any fields that have zero values
@@ -109,6 +133,13 @@ var (
109 func applyDefaultsToConfig(config *Config) bool {133 func applyDefaultsToConfig(config *Config) bool {
110 defaultsApplied := false134 defaultsApplied := false
111 135
136+ // Apply defaults to GeneralConfig
137+ if config.General.LogLevel == "" {
138+ config.General.LogLevel = defaultLogLevel
139+ logger.Debug("Applied default value for General.LogLevel", "value", defaultLogLevel)
140+ defaultsApplied = true
141+ }
142+
112 // Apply defaults to ReverseProxy config143 // Apply defaults to ReverseProxy config
113 if config.ReverseProxy.Port == "" {144 if config.ReverseProxy.Port == "" {
114 config.ReverseProxy.Port = reverseProxyPort145 config.ReverseProxy.Port = reverseProxyPort
@@ -353,6 +384,12 @@ func loadConfigFromEnv(config *Config, printLogs bool) {
353 logger.Info("Using environment variable GORDON_TOKEN")384 logger.Info("Using environment variable GORDON_TOKEN")
354 }385 }
355 }386 }
387+ if val := os.Getenv("GORDON_LOG_LEVEL"); val != "" {
388+ config.General.LogLevel = val
389+ if printLogs {
390+ logger.Info("Using environment variable GORDON_LOG_LEVEL", "value", val)
391+ }
392+ }
356 393
357 // HTTP Configuration394 // HTTP Configuration
358 if val := os.Getenv("GORDON_HTTP_PORT"); val != "" {395 if val := os.Getenv("GORDON_HTTP_PORT"); val != "" {
@@ -530,6 +567,7 @@ func (config *Config) LoadConfig() (*Config, error) {
530 *config = Config{567 *config = Config{
531 General: GeneralConfig{568 General: GeneralConfig{
532 StorageDir: homeDir + "/.gordon",569 StorageDir: homeDir + "/.gordon",
570+ LogLevel: defaultLogLevel,
533 },571 },
534 Http: HttpConfig{572 Http: HttpConfig{
535 Port: "8080",573 Port: "8080",
@@ -666,6 +704,7 @@ func (config *Config) LoadConfig() (*Config, error) {
666 *config = Config{704 *config = Config{
667 General: GeneralConfig{705 General: GeneralConfig{
668 StorageDir: homeDir + "/.gordon",706 StorageDir: homeDir + "/.gordon",
707+ LogLevel: defaultLogLevel,
669 },708 },
670 Http: HttpConfig{709 Http: HttpConfig{
671 Port: "8080",710 Port: "8080",
@@ -762,6 +801,31 @@ func (config *Config) LoadConfig() (*Config, error) {
762 logger.Info("Loaded configuration from", "path", configFilePath)801 logger.Info("Loaded configuration from", "path", configFilePath)
763 }802 }
764 803
804+ // Apply the log level from configuration
805+ if config.General.LogLevel != "" {
806+ // Convert string log level to charmbracelet/log level
807+ var logLevel log.Level
808+ switch strings.ToLower(config.General.LogLevel) {
809+ case "debug":
810+ logLevel = log.DebugLevel
811+ case "info":
812+ logLevel = log.InfoLevel
813+ case "warn", "warning":
814+ logLevel = log.WarnLevel
815+ case "error":
816+ logLevel = log.ErrorLevel
817+ case "fatal":
818+ logLevel = log.FatalLevel
819+ default:
820+ logger.Warn("Unknown log level specified, using default info level", "specified", config.General.LogLevel)
821+ logLevel = log.InfoLevel
822+ }
823+
824+ // Set the logger level
825+ logger.SetLevel(logLevel)
826+ logger.Debug("Log level set from configuration", "level", config.General.LogLevel)
827+ }
828+
765 logger.Debug("LoadConfig: Completed LoadConfig function")829 logger.Debug("LoadConfig: Completed LoadConfig function")
766 return config, nil830 return config, nil
767 }831 }

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 7

Tags 106

↑↓ moveenter openesc close