From cbb9e50ab61392c403de71ffd2023ff4ffc29e19 Mon Sep 17 00:00:00 2001 From: Levi Schoen Date: Thu, 26 Oct 2023 12:51:37 -0700 Subject: [PATCH] add config and routine init logic for metric pruning --- .env | 14 +++ config/config.go | 180 ++++++++++++++++++++----------------- main.go | 38 ++++++++ routines/metric_pruning.go | 65 ++++++++++++++ 4 files changed, 214 insertions(+), 83 deletions(-) create mode 100644 routines/metric_pruning.go diff --git a/.env b/.env index c470985..222b31d 100644 --- a/.env +++ b/.env @@ -102,6 +102,20 @@ METRIC_PARTITIONING_ROUTINE_DELAY_FIRST_RUN_SECONDS=10 METRIC_PARTITIONINING_PREFILL_PERIOD_DAYS=7 # Used by `ready` script to ensure metric partitions have been created. MINIMUM_REQUIRED_PARTITIONS=30 +# Whether metric pruning routines should run on the configured interval, defaults to true +METRIC_PRUNING_ENABLED=true +# How frequenlty metric pruning routines should run +# defaults to 1 day +METRIC_PRUNING_ROUTINE_INTERVAL_SECONDS=10 +# how long (after the proxy service starts) it will wait +# to run the first iteration of the metric pruning routine +METRIC_PRUNING_ROUTINE_DELAY_FIRST_RUN_SECONDS=5 +# The maximum number of days of request metrics that should +# be preserved starting from +# the end of the current day each time +# the pruning routine runs +# all metrics for earlier days will be truncated +METRIC_PRUNING_MAX_REQUEST_METRICS_HISTORY_DAYS=1 # CACHE_ENABLED specifies if cache should be enabled. By default cache is disabled. CACHE_ENABLED=true # REDIS_ENDPOINT_URL is an url of redis diff --git a/config/config.go b/config/config.go index d55fb08..5d5ce18 100644 --- a/config/config.go +++ b/config/config.go @@ -13,39 +13,42 @@ import ( ) type Config struct { - ProxyServicePort string - LogLevel string - ProxyBackendHostURLMapRaw string - ProxyBackendHostURLMapParsed map[string]url.URL - EnableHeightBasedRouting bool - ProxyPruningBackendHostURLMapRaw string - ProxyPruningBackendHostURLMap map[string]url.URL - EvmQueryServiceURL string - DatabaseName string - DatabaseEndpointURL string - DatabaseUserName string - DatabasePassword string - DatabaseReadTimeoutSeconds int64 - DatabaseWriteTimeoutSeconds int64 - DatabaseSSLEnabled bool - DatabaseQueryLoggingEnabled bool - DatabaseMaxIdleConnections int64 - DatabaseConnectionMaxIdleSeconds int64 - DatabaseMaxOpenConnections int64 - RunDatabaseMigrations bool - HTTPReadTimeoutSeconds int64 - HTTPWriteTimeoutSeconds int64 - MetricCompactionRoutineInterval time.Duration - MetricCollectionEnabled bool - MetricPartitioningRoutineInterval time.Duration - MetricPartitioningRoutineDelayFirstRun time.Duration - MetricPartitioningPrefillPeriodDays int - CacheEnabled bool - RedisEndpointURL string - RedisPassword string - CacheTTL time.Duration - CacheIndefinitely bool - CachePrefix string + ProxyServicePort string + LogLevel string + ProxyBackendHostURLMapRaw string + ProxyBackendHostURLMapParsed map[string]url.URL + EnableHeightBasedRouting bool + ProxyPruningBackendHostURLMapRaw string + ProxyPruningBackendHostURLMap map[string]url.URL + EvmQueryServiceURL string + DatabaseName string + DatabaseEndpointURL string + DatabaseUserName string + DatabasePassword string + DatabaseReadTimeoutSeconds int64 + DatabaseWriteTimeoutSeconds int64 + DatabaseSSLEnabled bool + DatabaseQueryLoggingEnabled bool + DatabaseMaxIdleConnections int64 + DatabaseConnectionMaxIdleSeconds int64 + DatabaseMaxOpenConnections int64 + RunDatabaseMigrations bool + HTTPReadTimeoutSeconds int64 + HTTPWriteTimeoutSeconds int64 + MetricCompactionRoutineInterval time.Duration + MetricCollectionEnabled bool + MetricPartitioningRoutineInterval time.Duration + MetricPartitioningRoutineDelayFirstRun time.Duration + MetricPartitioningPrefillPeriodDays int + MetricPruningEnabled bool + MetricPruningRoutineInterval time.Duration + MetricPruningRoutineDelayFirstRun time.Duration + MetricPruningMaxRequestMetricsHistoryDays int + CacheEnabled bool + RedisEndpointURL string + RedisPassword string + CacheTTL time.Duration + CachePrefix string } const ( @@ -79,23 +82,31 @@ const ( DEFAULT_METRIC_PARTITIONING_ROUTINE_DELAY_FIRST_RUN_SECONDS = 10 METRIC_PARTITIONING_PREFILL_PERIOD_DAYS_ENVIRONMENT_KEY = "METRIC_PARTITIONING_PREFILL_PERIOD_DAYS" DEFAULT_METRIC_PARTITIONING_PREFILL_PERIOD_DAYS = 7 - EVM_QUERY_SERVICE_ENVIRONMENT_KEY = "EVM_QUERY_SERVICE_URL" - DATABASE_MAX_IDLE_CONNECTIONS_ENVIRONMENT_KEY = "DATABASE_MAX_IDLE_CONNECTIONS" - DEFAULT_DATABASE_MAX_IDLE_CONNECTIONS = 20 - DATABASE_CONNECTION_MAX_IDLE_SECONDS_ENVIRONMENT_KEY = "DATABASE_CONNECTION_MAX_IDLE_SECONDS" - DEFAULT_DATABASE_CONNECTION_MAX_IDLE_SECONDS = 5 - DATABASE_MAX_OPEN_CONNECTIONS_ENVIRONMENT_KEY = "DATABASE_MAX_OPEN_CONNECTIONS" - DEFAULT_DATABASE_MAX_OPEN_CONNECTIONS = 100 - DATABASE_READ_TIMEOUT_SECONDS_ENVIRONMENT_KEY = "DATABASE_READ_TIMEOUT_SECONDS" - DEFAULT_DATABASE_READ_TIMEOUT_SECONDS = 60 - DATABASE_WRITE_TIMEOUT_SECONDS_ENVIRONMENT_KEY = "DATABASE_WRITE_TIMEOUT_SECONDS" - DEFAULT_DATABASE_WRITE_TIMEOUT_SECONDS = 10 - CACHE_ENABLED_ENVIRONMENT_KEY = "CACHE_ENABLED" - REDIS_ENDPOINT_URL_ENVIRONMENT_KEY = "REDIS_ENDPOINT_URL" - REDIS_PASSWORD_ENVIRONMENT_KEY = "REDIS_PASSWORD" - CACHE_TTL_ENVIRONMENT_KEY = "CACHE_TTL_SECONDS" - CACHE_INDEFINITELY_KEY = "CACHE_INDEFINITELY" - CACHE_PREFIX_ENVIRONMENT_KEY = "CACHE_PREFIX" + METRIC_PRUNING_ENABLED_ENVIRONMENT_KEY = "METRIC_PRUNING_ENABLED" + DEFAULT_METRIC_PRUNING_ENABLED = true + METRIC_PRUNING_ROUTINE_INTERVAL_SECONDS_ENVIRONMENT_KEY = "METRIC_PRUNING_ROUTINE_INTERVAL_SECONDS" + // 60 seconds * 60 minutes * 24 hours = 1 day + DEFAULT_METRIC_PRUNING_ROUTINE_INTERVAL_SECONDS = 86400 + METRIC_PRUNING_ROUTINE_DELAY_FIRST_RUN_SECONDS_ENVIRONMENT_KEY = "METRIC_PRUNING_ROUTINE_DELAY_FIRST_RUN_SECONDS" + DEFAULT_METRIC_PRUNING_ROUTINE_DELAY_FIRST_RUN_SECONDS = 10 + METRIC_PRUNING_MAX_REQUEST_METRICS_HISTORY_DAYS_ENVIRONMENT_KEY = "METRIC_PRUNING_MAX_REQUEST_METRICS_HISTORY_DAYS" + DEFAULT_METRIC_PRUNING_MAX_REQUEST_METRICS_HISTORY_DAYS = 1 + EVM_QUERY_SERVICE_ENVIRONMENT_KEY = "EVM_QUERY_SERVICE_URL" + DATABASE_MAX_IDLE_CONNECTIONS_ENVIRONMENT_KEY = "DATABASE_MAX_IDLE_CONNECTIONS" + DEFAULT_DATABASE_MAX_IDLE_CONNECTIONS = 20 + DATABASE_CONNECTION_MAX_IDLE_SECONDS_ENVIRONMENT_KEY = "DATABASE_CONNECTION_MAX_IDLE_SECONDS" + DEFAULT_DATABASE_CONNECTION_MAX_IDLE_SECONDS = 5 + DATABASE_MAX_OPEN_CONNECTIONS_ENVIRONMENT_KEY = "DATABASE_MAX_OPEN_CONNECTIONS" + DEFAULT_DATABASE_MAX_OPEN_CONNECTIONS = 100 + DATABASE_READ_TIMEOUT_SECONDS_ENVIRONMENT_KEY = "DATABASE_READ_TIMEOUT_SECONDS" + DEFAULT_DATABASE_READ_TIMEOUT_SECONDS = 60 + DATABASE_WRITE_TIMEOUT_SECONDS_ENVIRONMENT_KEY = "DATABASE_WRITE_TIMEOUT_SECONDS" + DEFAULT_DATABASE_WRITE_TIMEOUT_SECONDS = 10 + CACHE_ENABLED_ENVIRONMENT_KEY = "CACHE_ENABLED" + REDIS_ENDPOINT_URL_ENVIRONMENT_KEY = "REDIS_ENDPOINT_URL" + REDIS_PASSWORD_ENVIRONMENT_KEY = "REDIS_PASSWORD" + CACHE_TTL_ENVIRONMENT_KEY = "CACHE_TTL_SECONDS" + CACHE_PREFIX_ENVIRONMENT_KEY = "CACHE_PREFIX" ) var ErrEmptyHostMap = errors.New("backend host url map is empty") @@ -202,38 +213,41 @@ func ReadConfig() Config { parsedProxyPruningBackendHostURLMap, _ := ParseRawProxyBackendHostURLMap(rawProxyPruningBackendHostURLMap) return Config{ - ProxyServicePort: os.Getenv(PROXY_SERVICE_PORT_ENVIRONMENT_KEY), - LogLevel: EnvOrDefault(LOG_LEVEL_ENVIRONMENT_KEY, DEFAULT_LOG_LEVEL), - ProxyBackendHostURLMapRaw: rawProxyBackendHostURLMap, - ProxyBackendHostURLMapParsed: parsedProxyBackendHostURLMap, - EnableHeightBasedRouting: EnvOrDefaultBool(PROXY_HEIGHT_BASED_ROUTING_ENABLED_KEY, false), - ProxyPruningBackendHostURLMapRaw: rawProxyPruningBackendHostURLMap, - ProxyPruningBackendHostURLMap: parsedProxyPruningBackendHostURLMap, - DatabaseName: os.Getenv(DATABASE_NAME_ENVIRONMENT_KEY), - DatabaseEndpointURL: os.Getenv(DATABASE_ENDPOINT_URL_ENVIRONMENT_KEY), - DatabaseUserName: os.Getenv(DATABASE_USERNAME_ENVIRONMENT_KEY), - DatabasePassword: os.Getenv(DATABASE_PASSWORD_ENVIRONMENT_KEY), - DatabaseSSLEnabled: EnvOrDefaultBool(DATABASE_SSL_ENABLED_ENVIRONMENT_KEY, false), - DatabaseReadTimeoutSeconds: EnvOrDefaultInt64(DATABASE_READ_TIMEOUT_SECONDS_ENVIRONMENT_KEY, DEFAULT_DATABASE_READ_TIMEOUT_SECONDS), - DatabaseWriteTimeoutSeconds: EnvOrDefaultInt64(DATABASE_WRITE_TIMEOUT_SECONDS_ENVIRONMENT_KEY, DEFAULT_DATABASE_WRITE_TIMEOUT_SECONDS), - DatabaseQueryLoggingEnabled: EnvOrDefaultBool(DATABASE_QUERY_LOGGING_ENABLED_ENVIRONMENT_KEY, true), - RunDatabaseMigrations: EnvOrDefaultBool(RUN_DATABASE_MIGRATIONS_ENVIRONMENT_KEY, false), - DatabaseMaxIdleConnections: EnvOrDefaultInt64(DATABASE_MAX_IDLE_CONNECTIONS_ENVIRONMENT_KEY, DEFAULT_DATABASE_MAX_IDLE_CONNECTIONS), - DatabaseConnectionMaxIdleSeconds: EnvOrDefaultInt64(DATABASE_CONNECTION_MAX_IDLE_SECONDS_ENVIRONMENT_KEY, DEFAULT_DATABASE_CONNECTION_MAX_IDLE_SECONDS), - DatabaseMaxOpenConnections: EnvOrDefaultInt64(DATABASE_MAX_OPEN_CONNECTIONS_ENVIRONMENT_KEY, DEFAULT_DATABASE_MAX_OPEN_CONNECTIONS), - HTTPReadTimeoutSeconds: EnvOrDefaultInt64(HTTP_READ_TIMEOUT_ENVIRONMENT_KEY, DEFAULT_HTTP_READ_TIMEOUT), - HTTPWriteTimeoutSeconds: EnvOrDefaultInt64(HTTP_WRITE_TIMEOUT_ENVIRONMENT_KEY, DEFAULT_HTTP_WRITE_TIMEOUT), - MetricCompactionRoutineInterval: time.Duration(time.Duration(EnvOrDefaultInt(METRIC_COMPACTION_ROUTINE_INTERVAL_ENVIRONMENT_KEY, DEFAULT_METRIC_COMPACTION_ROUTINE_INTERVAL_SECONDS)) * time.Second), - EvmQueryServiceURL: os.Getenv(EVM_QUERY_SERVICE_ENVIRONMENT_KEY), - MetricCollectionEnabled: EnvOrDefaultBool(METRIC_COLLECTION_ENABLED_ENVIRONMENT_KEY, DEFAULT_METRIC_COLLECTION_ENABLED), - MetricPartitioningRoutineInterval: time.Duration(time.Duration(EnvOrDefaultInt(METRIC_PARTITIONING_ROUTINE_INTERVAL_SECONDS_ENVIRONMENT_KEY, DEFAULT_METRIC_PARTITIONING_ROUTINE_INTERVAL_SECONDS)) * time.Second), - MetricPartitioningRoutineDelayFirstRun: time.Duration(time.Duration(EnvOrDefaultInt(METRIC_PARTITIONING_ROUTINE_DELAY_FIRST_RUN_SECONDS_ENVIRONMENT_KEY, DEFAULT_METRIC_PARTITIONING_ROUTINE_DELAY_FIRST_RUN_SECONDS)) * time.Second), - MetricPartitioningPrefillPeriodDays: EnvOrDefaultInt(METRIC_PARTITIONING_PREFILL_PERIOD_DAYS_ENVIRONMENT_KEY, DEFAULT_METRIC_PARTITIONING_PREFILL_PERIOD_DAYS), - CacheEnabled: EnvOrDefaultBool(CACHE_ENABLED_ENVIRONMENT_KEY, false), - RedisEndpointURL: os.Getenv(REDIS_ENDPOINT_URL_ENVIRONMENT_KEY), - RedisPassword: os.Getenv(REDIS_PASSWORD_ENVIRONMENT_KEY), - CacheTTL: time.Duration(EnvOrDefaultInt(CACHE_TTL_ENVIRONMENT_KEY, 0)) * time.Second, - CacheIndefinitely: EnvOrDefaultBool(CACHE_INDEFINITELY_KEY, false), - CachePrefix: os.Getenv(CACHE_PREFIX_ENVIRONMENT_KEY), + ProxyServicePort: os.Getenv(PROXY_SERVICE_PORT_ENVIRONMENT_KEY), + LogLevel: EnvOrDefault(LOG_LEVEL_ENVIRONMENT_KEY, DEFAULT_LOG_LEVEL), + ProxyBackendHostURLMapRaw: rawProxyBackendHostURLMap, + ProxyBackendHostURLMapParsed: parsedProxyBackendHostURLMap, + EnableHeightBasedRouting: EnvOrDefaultBool(PROXY_HEIGHT_BASED_ROUTING_ENABLED_KEY, false), + ProxyPruningBackendHostURLMapRaw: rawProxyPruningBackendHostURLMap, + ProxyPruningBackendHostURLMap: parsedProxyPruningBackendHostURLMap, + DatabaseName: os.Getenv(DATABASE_NAME_ENVIRONMENT_KEY), + DatabaseEndpointURL: os.Getenv(DATABASE_ENDPOINT_URL_ENVIRONMENT_KEY), + DatabaseUserName: os.Getenv(DATABASE_USERNAME_ENVIRONMENT_KEY), + DatabasePassword: os.Getenv(DATABASE_PASSWORD_ENVIRONMENT_KEY), + DatabaseSSLEnabled: EnvOrDefaultBool(DATABASE_SSL_ENABLED_ENVIRONMENT_KEY, false), + DatabaseReadTimeoutSeconds: EnvOrDefaultInt64(DATABASE_READ_TIMEOUT_SECONDS_ENVIRONMENT_KEY, DEFAULT_DATABASE_READ_TIMEOUT_SECONDS), + DatabaseWriteTimeoutSeconds: EnvOrDefaultInt64(DATABASE_WRITE_TIMEOUT_SECONDS_ENVIRONMENT_KEY, DEFAULT_DATABASE_WRITE_TIMEOUT_SECONDS), + DatabaseQueryLoggingEnabled: EnvOrDefaultBool(DATABASE_QUERY_LOGGING_ENABLED_ENVIRONMENT_KEY, true), + RunDatabaseMigrations: EnvOrDefaultBool(RUN_DATABASE_MIGRATIONS_ENVIRONMENT_KEY, false), + DatabaseMaxIdleConnections: EnvOrDefaultInt64(DATABASE_MAX_IDLE_CONNECTIONS_ENVIRONMENT_KEY, DEFAULT_DATABASE_MAX_IDLE_CONNECTIONS), + DatabaseConnectionMaxIdleSeconds: EnvOrDefaultInt64(DATABASE_CONNECTION_MAX_IDLE_SECONDS_ENVIRONMENT_KEY, DEFAULT_DATABASE_CONNECTION_MAX_IDLE_SECONDS), + DatabaseMaxOpenConnections: EnvOrDefaultInt64(DATABASE_MAX_OPEN_CONNECTIONS_ENVIRONMENT_KEY, DEFAULT_DATABASE_MAX_OPEN_CONNECTIONS), + HTTPReadTimeoutSeconds: EnvOrDefaultInt64(HTTP_READ_TIMEOUT_ENVIRONMENT_KEY, DEFAULT_HTTP_READ_TIMEOUT), + HTTPWriteTimeoutSeconds: EnvOrDefaultInt64(HTTP_WRITE_TIMEOUT_ENVIRONMENT_KEY, DEFAULT_HTTP_WRITE_TIMEOUT), + MetricCompactionRoutineInterval: time.Duration(time.Duration(EnvOrDefaultInt(METRIC_COMPACTION_ROUTINE_INTERVAL_ENVIRONMENT_KEY, DEFAULT_METRIC_COMPACTION_ROUTINE_INTERVAL_SECONDS)) * time.Second), + EvmQueryServiceURL: os.Getenv(EVM_QUERY_SERVICE_ENVIRONMENT_KEY), + MetricCollectionEnabled: EnvOrDefaultBool(METRIC_COLLECTION_ENABLED_ENVIRONMENT_KEY, DEFAULT_METRIC_COLLECTION_ENABLED), + MetricPartitioningRoutineInterval: time.Duration(time.Duration(EnvOrDefaultInt(METRIC_PARTITIONING_ROUTINE_INTERVAL_SECONDS_ENVIRONMENT_KEY, DEFAULT_METRIC_PARTITIONING_ROUTINE_INTERVAL_SECONDS)) * time.Second), + MetricPartitioningRoutineDelayFirstRun: time.Duration(time.Duration(EnvOrDefaultInt(METRIC_PARTITIONING_ROUTINE_DELAY_FIRST_RUN_SECONDS_ENVIRONMENT_KEY, DEFAULT_METRIC_PARTITIONING_ROUTINE_DELAY_FIRST_RUN_SECONDS)) * time.Second), + MetricPartitioningPrefillPeriodDays: EnvOrDefaultInt(METRIC_PARTITIONING_PREFILL_PERIOD_DAYS_ENVIRONMENT_KEY, DEFAULT_METRIC_PARTITIONING_PREFILL_PERIOD_DAYS), + MetricPruningEnabled: EnvOrDefaultBool(METRIC_PRUNING_ENABLED_ENVIRONMENT_KEY, DEFAULT_METRIC_PRUNING_ENABLED), + MetricPruningRoutineInterval: time.Duration(time.Duration(EnvOrDefaultInt(METRIC_PRUNING_ROUTINE_INTERVAL_SECONDS_ENVIRONMENT_KEY, DEFAULT_METRIC_PRUNING_ROUTINE_INTERVAL_SECONDS)) * time.Second), + MetricPruningRoutineDelayFirstRun: time.Duration(time.Duration(EnvOrDefaultInt(METRIC_PRUNING_ROUTINE_DELAY_FIRST_RUN_SECONDS_ENVIRONMENT_KEY, DEFAULT_METRIC_PRUNING_ROUTINE_DELAY_FIRST_RUN_SECONDS)) * time.Second), + MetricPruningMaxRequestMetricsHistoryDays: EnvOrDefaultInt(METRIC_PRUNING_MAX_REQUEST_METRICS_HISTORY_DAYS_ENVIRONMENT_KEY, DEFAULT_METRIC_PRUNING_MAX_REQUEST_METRICS_HISTORY_DAYS), + CacheEnabled: EnvOrDefaultBool(CACHE_ENABLED_ENVIRONMENT_KEY, false), + RedisEndpointURL: os.Getenv(REDIS_ENDPOINT_URL_ENVIRONMENT_KEY), + RedisPassword: os.Getenv(REDIS_PASSWORD_ENVIRONMENT_KEY), + CacheTTL: time.Duration(EnvOrDefaultInt(CACHE_TTL_ENVIRONMENT_KEY, 0)) * time.Second, + CachePrefix: os.Getenv(CACHE_PREFIX_ENVIRONMENT_KEY), } } diff --git a/main.go b/main.go index f82c9e4..c61b1b4 100644 --- a/main.go +++ b/main.go @@ -94,6 +94,35 @@ func startMetricCompactionRoutine(serviceConfig config.Config, service service.P return errChan } +func startMetricPruningRoutine(serviceConfig config.Config, service service.ProxyService, serviceLogger logging.ServiceLogger) <-chan error { + metricPruningRoutineConfig := routines.MetricPruningRoutineConfig{ + Interval: serviceConfig.MetricPruningRoutineInterval, + StartDelay: serviceConfig.MetricPartitioningRoutineDelayFirstRun, + Database: service.Database, + Logger: serviceLogger, + } + + metricPruningRoutine, err := routines.NewMetricPruningRoutine(metricPruningRoutineConfig) + + if err != nil { + serviceLogger.Error().Msg(fmt.Sprintf("error %s creating metric pruning routine with config %+v", err, metricPruningRoutineConfig)) + + return nil + } + + errChan, err := metricPruningRoutine.Run() + + if err != nil { + serviceLogger.Error().Msg(fmt.Sprintf("error %s starting metric pruning routine with config %+v", err, metricPruningRoutineConfig)) + + return nil + } + + serviceLogger.Debug().Msg(fmt.Sprintf("started metric pruning routine with config %+v", metricPruningRoutineConfig)) + + return errChan +} + func main() { serviceLogger.Debug().Msg(fmt.Sprintf("initial config: %+v", serviceConfig)) @@ -123,6 +152,15 @@ func main() { } }() + // metric pruning routine + go func() { + metricPruningErrs := startMetricPruningRoutine(serviceConfig, service, serviceLogger) + + for routineErr := range metricPruningErrs { + serviceLogger.Error().Msg(fmt.Sprintf("metric pruning routine encountered error %s", routineErr)) + } + }() + // run the proxy service finalErr := service.Run() diff --git a/routines/metric_pruning.go b/routines/metric_pruning.go new file mode 100644 index 0000000..ec67360 --- /dev/null +++ b/routines/metric_pruning.go @@ -0,0 +1,65 @@ +// package routines provides configuration and logic +// for running background routines such as metric Pruning +// for aggregating and pruning proxied request metrics +package routines + +import ( + "fmt" + "time" + + "github.com/google/uuid" + "github.com/kava-labs/kava-proxy-service/clients/database" + "github.com/kava-labs/kava-proxy-service/logging" +) + +// MetricPruningRoutineConfig wraps values used +// for creating a new metric Pruning routine +type MetricPruningRoutineConfig struct { + Interval time.Duration + StartDelay time.Duration + Database *database.PostgresClient + Logger logging.ServiceLogger +} + +// MetricPruningRoutine can be used to +// run a background routine on a configurable interval +// to aggregate and prune historical request metrics +type MetricPruningRoutine struct { + id string + interval time.Duration + startDelay time.Duration + *database.PostgresClient + logging.ServiceLogger +} + +// Run runs the metric Pruning routine for aggregating +// and pruning historical request metrics, returning error (if any) +// from starting the routine and an error channel which any errors +// encountered during running will be sent on +func (mpr *MetricPruningRoutine) Run() (<-chan error, error) { + errorChannel := make(chan error) + + time.Sleep(mpr.startDelay) + + timer := time.Tick(mpr.interval) + + go func() { + for tick := range timer { + mpr.Trace().Msg(fmt.Sprintf("%s tick at %+v", mpr.id, tick)) + } + }() + + return errorChannel, nil +} + +// NewMetricPruningRoutine creates a new metric Pruning routine +// using the provided config, returning the routine and error (if any) +func NewMetricPruningRoutine(config MetricPruningRoutineConfig) (*MetricPruningRoutine, error) { + return &MetricPruningRoutine{ + id: uuid.New().String(), + interval: config.Interval, + startDelay: config.StartDelay, + PostgresClient: config.Database, + ServiceLogger: config.Logger, + }, nil +}