@@ -379,39 +379,11 @@ func startupCommand(ctx context.Context, inPgadmin *v1beta1.PGAdmin) []string {
379379 // configDatabaseURIPath is the path for mounting the database URI connection string
380380 configDatabaseURIPathAbsolutePath = configMountPath + "/" + configDatabaseURIPath
381381 )
382- var (
383- maxBackupRetentionNumber = "1"
384- // One day in minutes for pgadmin rotation
385- pgAdminRetentionPeriod = "24 * 60"
386- // Daily rotation for gunicorn rotation
387- gunicornRetentionPeriod = "D"
388- )
389-
390- // If the OpenTelemetryLogs Feature is enabled and the user has set a retention period,
391- // we will use those values for pgAdmin log rotation, which is otherwise managed by python.
392- if feature .Enabled (ctx , feature .OpenTelemetryLogs ) &&
393- inPgadmin .Spec .Instrumentation != nil &&
394- inPgadmin .Spec .Instrumentation .Logs != nil &&
395- inPgadmin .Spec .Instrumentation .Logs .RetentionPeriod != nil {
396-
397- retentionNumber , period := collector .ParseDurationForLogrotate (inPgadmin .Spec .Instrumentation .Logs .RetentionPeriod )
398- // `LOG_ROTATION_MAX_LOG_FILES`` in pgadmin refers to the already rotated logs.
399- // `backupCount` for gunicorn is similar.
400- // Our retention unit is for total number of log files, so subtract 1 to account
401- // for the currently-used log file.
402- maxBackupRetentionNumber = strconv .Itoa (retentionNumber - 1 )
403- if period == "hourly" {
404- // If the period is hourly, set the pgadmin
405- // and gunicorn retention periods to hourly.
406- pgAdminRetentionPeriod = "60"
407- gunicornRetentionPeriod = "H"
408- }
409- }
410382
411383 // The constants set in configSystem will not be overridden through
412384 // spec.config.settings.
413385 var configSystem = `
414- import glob, json, re, os, logging
386+ import glob, json, re, os
415387DEFAULT_BINARY_PATHS = {'pg': sorted([''] + glob.glob('/usr/pgsql-*/bin')).pop()}
416388with open('` + configMountPath + `/` + configFilePath + `') as _f:
417389 _conf, _data = re.compile(r'[A-Z_0-9]+'), json.load(_f)
@@ -423,18 +395,8 @@ if os.path.isfile('` + ldapPasswordAbsolutePath + `'):
423395if os.path.isfile('` + configDatabaseURIPathAbsolutePath + `'):
424396 with open('` + configDatabaseURIPathAbsolutePath + `') as _f:
425397 CONFIG_DATABASE_URI = _f.read()
426-
427- DATA_DIR = '` + dataMountPath + `'
428- LOG_FILE = '` + LogFileAbsolutePath + `'
429- LOG_ROTATION_AGE = ` + pgAdminRetentionPeriod + ` # minutes
430- LOG_ROTATION_SIZE = 5 # MiB
431- LOG_ROTATION_MAX_LOG_FILES = ` + maxBackupRetentionNumber + `
432-
433- JSON_LOGGER = True
434- CONSOLE_LOG_LEVEL = logging.WARNING
435- FILE_LOG_LEVEL = logging.INFO
436- FILE_LOG_FORMAT_JSON = {'time': 'created', 'name': 'name', 'level': 'levelname', 'message': 'message'}
437398`
399+
438400 // Gunicorn reads from the `/etc/pgadmin/gunicorn_config.py` file during startup
439401 // after all other config files.
440402 // - https://docs.gunicorn.org/en/latest/configure.html#configuration-file
@@ -450,12 +412,59 @@ FILE_LOG_FORMAT_JSON = {'time': 'created', 'name': 'name', 'level': 'levelname',
450412 // https://docs.python.org/3/library/logging.html#logrecord-attributes.
451413 // JsonFormatter is used to format the log: https://pypi.org/project/jsonformatter/
452414 var gunicornConfig = `
453- import json, re, collections, copy, gunicorn, gunicorn.glogging
415+ import json, re
454416with open('` + configMountPath + `/` + gunicornConfigFilePath + `') as _f:
455417 _conf, _data = re.compile(r'[a-z_]+'), json.load(_f)
456418 if type(_data) is dict:
457419 globals().update({k: v for k, v in _data.items() if _conf.fullmatch(k)})
420+ `
421+
422+ // If OTel logs feature gate is enabled, we want to change the pgAdmin/gunicorn logging
423+ if feature .Enabled (ctx , feature .OpenTelemetryLogs ) && inPgadmin .Spec .Instrumentation != nil {
424+
425+ var (
426+ maxBackupRetentionNumber = "1"
427+ // One day in minutes for pgadmin rotation
428+ pgAdminRetentionPeriod = "24 * 60"
429+ // Daily rotation for gunicorn rotation
430+ gunicornRetentionPeriod = "D"
431+ )
432+
433+ // If the user has set a retention period, we will use those values for log rotation,
434+ // which is otherwise managed by python.
435+ if inPgadmin .Spec .Instrumentation .Logs != nil &&
436+ inPgadmin .Spec .Instrumentation .Logs .RetentionPeriod != nil {
437+
438+ retentionNumber , period := collector .ParseDurationForLogrotate (inPgadmin .Spec .Instrumentation .Logs .RetentionPeriod )
439+ // `LOG_ROTATION_MAX_LOG_FILES`` in pgadmin refers to the already rotated logs.
440+ // `backupCount` for gunicorn is similar.
441+ // Our retention unit is for total number of log files, so subtract 1 to account
442+ // for the currently-used log file.
443+ maxBackupRetentionNumber = strconv .Itoa (retentionNumber - 1 )
444+ if period == "hourly" {
445+ // If the period is hourly, set the pgadmin
446+ // and gunicorn retention periods to hourly.
447+ pgAdminRetentionPeriod = "60"
448+ gunicornRetentionPeriod = "H"
449+ }
450+ }
451+
452+ configSystem = configSystem + `
453+ import logging
454+ DATA_DIR = '` + dataMountPath + `'
455+ LOG_FILE = '` + LogFileAbsolutePath + `'
456+ LOG_ROTATION_AGE = ` + pgAdminRetentionPeriod + ` # minutes
457+ LOG_ROTATION_SIZE = 5 # MiB
458+ LOG_ROTATION_MAX_LOG_FILES = ` + maxBackupRetentionNumber + `
459+
460+ JSON_LOGGER = True
461+ CONSOLE_LOG_LEVEL = logging.WARNING
462+ FILE_LOG_LEVEL = logging.INFO
463+ FILE_LOG_FORMAT_JSON = {'time': 'created', 'name': 'name', 'level': 'levelname', 'message': 'message'}
464+ `
458465
466+ gunicornConfig = gunicornConfig + `
467+ import collections, copy, gunicorn, gunicorn.glogging
459468gunicorn.SERVER_SOFTWARE = 'Python'
460469logconfig_dict = copy.deepcopy(gunicorn.glogging.CONFIG_DEFAULTS)
461470logconfig_dict['loggers']['gunicorn.access']['handlers'] = ['file']
@@ -479,6 +488,7 @@ logconfig_dict['formatters']['json'] = {
479488 ])
480489}
481490`
491+ }
482492
483493 args := []string {strings .TrimLeft (configSystem , "\n " ), strings .TrimLeft (gunicornConfig , "\n " )}
484494
0 commit comments