Skip to content

Commit

Permalink
Reduced memory usage. Enviroment params: PGSCV_CPUPROFILE_FILE, PGSCV…
Browse files Browse the repository at this point in the history
…_MEMPROFILE_FILE, PGSCV_LOG_COLLECTOR (in yaml: cpu_profile, mem_profile, log_collector_statistics)
  • Loading branch information
dbulashev committed Jun 1, 2024
1 parent 060f4cb commit e7af102
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 28 deletions.
15 changes: 15 additions & 0 deletions cmd/pgscv.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"gopkg.in/alecthomas/kingpin.v2"
"os"
"os/signal"
"runtime/pprof"
"syscall"
)

Expand Down Expand Up @@ -38,6 +39,20 @@ func main() {
os.Exit(1)
}

if config.CpuProfile != "" {
f, err := os.Create(config.CpuProfile)
if err != nil {
log.Errorln(err)
os.Exit(1)
}
err = pprof.StartCPUProfile(f)
if err != nil {
log.Errorln(err)
os.Exit(1)
}
defer pprof.StopCPUProfile()
}

if err := config.Validate(); err != nil {
log.Errorln("validate config failed: ", err)
os.Exit(1)
Expand Down
41 changes: 35 additions & 6 deletions internal/collector/collector.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package collector

import (
"fmt"
"os"
"runtime"
"runtime/pprof"
"sync"
"time"

"github.com/cherts/pgscv/internal/filter"
"github.com/cherts/pgscv/internal/log"
Expand Down Expand Up @@ -201,13 +206,37 @@ func (n PgscvCollector) Collect(out chan<- prometheus.Metric) {
pipelineIn := make(chan prometheus.Metric)

// Run collectors.
wgCollector.Add(len(n.Collectors))
for name, c := range n.Collectors {
go func(name string, c Collector) {
wgCollector.Add(1)
go func(n PgscvCollector) {
defer wgCollector.Done()
for name, c := range n.Collectors {
var m runtime.MemStats
var start time.Time
if n.Config.LogCollectorStatistics {
start = time.Now()
runtime.ReadMemStats(&m)
log.Info(fmt.Sprintf("Start Collector: %s, Alloc = %v MiB", name, m.Alloc/1024/1024))
}
collect(name, n.Config, c, pipelineIn)
wgCollector.Done()
}(name, c)
}
runtime.GC()
if n.Config.LogCollectorStatistics {
runtime.ReadMemStats(&m)
log.Info(fmt.Sprintf("Stop Collector: %s, Alloc = %v MiB, duration = %s", name, m.Alloc/1024/1024, time.Since(start)))
}
}
if n.Config.MemProfile != "" {
f, err := os.Create(n.Config.MemProfile)
if err != nil {
log.Errorln(err)
os.Exit(1)
}
if pprof.WriteHeapProfile(f) != nil {
log.Errorln(err)
os.Exit(1)
}
_ = f.Close()
}
}(n)

// Run sender.
wgSender.Add(1)
Expand Down
4 changes: 4 additions & 0 deletions internal/collector/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ type Config struct {
DatabasesRE *regexp.Regexp
// Settings defines collectors settings propagated from main YAML configuration.
Settings model.CollectorsSettings
// path to store heap profile
MemProfile string
// logging: collecting duration, mem allocation
LogCollectorStatistics bool
}

// postgresServiceConfig defines Postgres-specific stuff required during collecting Postgres metrics.
Expand Down
50 changes: 41 additions & 9 deletions internal/pgscv/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,18 @@ const (

// Config defines application's configuration.
type Config struct {
NoTrackMode bool `yaml:"no_track_mode"` // controls tracking sensitive information (query texts, etc)
ListenAddress string `yaml:"listen_address"` // Network address and port where the application should listen on
ServicesConnsSettings service.ConnsSettings `yaml:"services"` // All connections settings for exact services
Defaults map[string]string `yaml:"defaults"` // Defaults
DisableCollectors []string `yaml:"disable_collectors"` // List of collectors which should be disabled. DEPRECATED in favor collectors settings
CollectorsSettings model.CollectorsSettings `yaml:"collectors"` // Collectors settings propagated from main YAML configuration
Databases string `yaml:"databases"` // Regular expression string specifies databases from which metrics should be collected
DatabasesRE *regexp.Regexp // Regular expression object compiled from Databases
AuthConfig http.AuthConfig `yaml:"authentication"` // TLS and Basic auth configuration
NoTrackMode bool `yaml:"no_track_mode"` // controls tracking sensitive information (query texts, etc)
ListenAddress string `yaml:"listen_address"` // Network address and port where the application should listen on
ServicesConnsSettings service.ConnsSettings `yaml:"services"` // All connections settings for exact services
Defaults map[string]string `yaml:"defaults"` // Defaults
DisableCollectors []string `yaml:"disable_collectors"` // List of collectors which should be disabled. DEPRECATED in favor collectors settings
CollectorsSettings model.CollectorsSettings `yaml:"collectors"` // Collectors settings propagated from main YAML configuration
Databases string `yaml:"databases"` // Regular expression string specifies databases from which metrics should be collected
DatabasesRE *regexp.Regexp // Regular expression object compiled from Databases
AuthConfig http.AuthConfig `yaml:"authentication"` // TLS and Basic auth configuration
CpuProfile string `yaml:"cpu_profile"` // path to store cpu profile
MemProfile string `yaml:"mem_profile"` // path to store heap profile
LogCollectorStatistics bool `yaml:"log_collector_statistics"` // logging: collecting duration, mem allocation
}

// NewConfig creates new config based on config file or return default config if config file is not specified.
Expand Down Expand Up @@ -94,6 +97,15 @@ func NewConfig(configFilePath string) (*Config, error) {
if configFromEnv.AuthConfig != (http.AuthConfig{}) {
configFromFile.AuthConfig = configFromEnv.AuthConfig
}
if configFromEnv.MemProfile != "" {
configFromFile.MemProfile = configFromEnv.MemProfile
}
if configFromEnv.CpuProfile != "" {
configFromFile.CpuProfile = configFromEnv.CpuProfile
}
if configFromEnv.LogCollectorStatistics {
configFromFile.LogCollectorStatistics = configFromEnv.LogCollectorStatistics
}
return configFromFile, nil
}

Expand Down Expand Up @@ -226,6 +238,15 @@ func (c *Config) Validate() error {
c.AuthConfig.EnableAuth = enableAuth
c.AuthConfig.EnableTLS = enableTLS

if c.LogCollectorStatistics {
log.Infoln("Enabled LogCollectorStatistics")
}
if c.MemProfile != "" {
log.Infoln("Enabled MemProfile")
}
if c.CpuProfile != "" {
log.Infoln("Enabled CpuProfile")
}
return nil
}

Expand Down Expand Up @@ -370,6 +391,17 @@ func newConfigFromEnv() (*Config, error) {
config.AuthConfig.Keyfile = value
case "PGSCV_AUTH_CERTFILE":
config.AuthConfig.Certfile = value
case "PGSCV_CPUPROFILE_FILE":
config.CpuProfile = value
case "PGSCV_MEMPROFILE_FILE":
config.MemProfile = value
case "PGSCV_LOG_COLLECTOR":
switch value {
case "y", "yes", "Yes", "YES", "t", "true", "True", "TRUE", "1", "on":
config.LogCollectorStatistics = true
default:
config.LogCollectorStatistics = false
}
}
}

Expand Down
15 changes: 8 additions & 7 deletions internal/pgscv/pgscv.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ func Start(ctx context.Context, config *Config) error {
log.Debug("start application")

serviceRepo := service.NewRepository()

serviceConfig := service.Config{
NoTrackMode: config.NoTrackMode,
ConnDefaults: config.Defaults,
ConnsSettings: config.ServicesConnsSettings,
DatabasesRE: config.DatabasesRE,
DisabledCollectors: config.DisableCollectors,
CollectorsSettings: config.CollectorsSettings,
NoTrackMode: config.NoTrackMode,
ConnDefaults: config.Defaults,
ConnsSettings: config.ServicesConnsSettings,
DatabasesRE: config.DatabasesRE,
DisabledCollectors: config.DisableCollectors,
CollectorsSettings: config.CollectorsSettings,
MemProfile: config.MemProfile,
LogCollectorStatistics: config.LogCollectorStatistics,
}

if len(config.ServicesConnsSettings) == 0 {
Expand Down
17 changes: 11 additions & 6 deletions internal/service/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ type Service struct {

// Config defines service's configuration.
type Config struct {
RuntimeMode int
NoTrackMode bool
ConnDefaults map[string]string `yaml:"defaults"` // Defaults
ConnsSettings ConnsSettings
Expand All @@ -42,6 +41,10 @@ type Config struct {
DisabledCollectors []string
// CollectorsSettings defines all collector settings propagated from main YAML configuration.
CollectorsSettings model.CollectorsSettings
// path to store heap profile
MemProfile string
// logging: collecting duration, mem allocation
LogCollectorStatistics bool
}

// Collector is an interface for prometheus.Collector.
Expand Down Expand Up @@ -184,11 +187,13 @@ func (repo *Repository) setupServices(config Config) error {
if service.Collector == nil {
factories := collector.Factories{}
collectorConfig := collector.Config{
NoTrackMode: config.NoTrackMode,
ServiceType: service.ConnSettings.ServiceType,
ConnString: service.ConnSettings.Conninfo,
Settings: config.CollectorsSettings,
DatabasesRE: config.DatabasesRE,
NoTrackMode: config.NoTrackMode,
ServiceType: service.ConnSettings.ServiceType,
ConnString: service.ConnSettings.Conninfo,
Settings: config.CollectorsSettings,
DatabasesRE: config.DatabasesRE,
MemProfile: config.MemProfile,
LogCollectorStatistics: config.LogCollectorStatistics,
}

switch service.ConnSettings.ServiceType {
Expand Down

0 comments on commit e7af102

Please sign in to comment.