From 6e1ec0b5c16cead91bc24a45d16cbf124dd58b3f Mon Sep 17 00:00:00 2001 From: Ryan McGuire Date: Sat, 22 Mar 2025 14:29:24 -0400 Subject: [PATCH] implement redis and noop recorders --- contrib/schema.json | 6 ++++++ pkg/ambient/ambient.go | 7 ++++--- pkg/ambient/config/config_recorder.go | 6 +++--- pkg/weather/recorder/recorder.go | 13 ++++++++++--- .../recorder/recorders/memory/memory.go | 9 +++++++-- pkg/weather/recorder/recorders/noop/noop.go | 2 ++ pkg/weather/recorder/recorders/recorders.go | 1 + pkg/weather/recorder/recorders/redis/redis.go | 18 ++++++++++++------ 8 files changed, 45 insertions(+), 17 deletions(-) diff --git a/contrib/schema.json b/contrib/schema.json index eb2a7e6..c1f8ffc 100644 --- a/contrib/schema.json +++ b/contrib/schema.json @@ -86,12 +86,18 @@ "ConfigRecorderConfig": { "properties": { "keepLast": { + "default": 120, "type": "integer" }, "redisConfig": { "$ref": "#/definitions/ConfigRedisConfig" }, "type": { + "enum": [ + "memory", + "redis", + "noop" + ], "type": "string" } }, diff --git a/pkg/ambient/ambient.go b/pkg/ambient/ambient.go index 364c22a..8289e4e 100644 --- a/pkg/ambient/ambient.go +++ b/pkg/ambient/ambient.go @@ -91,9 +91,10 @@ func (aw *AmbientWeather) Init() *AmbientWeather { } aw.weatherRecorder = recorder.MustNewWeatherRecorder(&recorder.Opts{ - Ctx: aw.appCtx, - KeepLast: updatesToKeep, - Recorder: r, + AppConfig: aw.Config, + Ctx: aw.appCtx, + KeepLast: updatesToKeep, + Recorder: r, }) aw.l.Trace().Any("awConfig", aw.Config).Send() diff --git a/pkg/ambient/config/config_recorder.go b/pkg/ambient/config/config_recorder.go index d638600..f647da4 100644 --- a/pkg/ambient/config/config_recorder.go +++ b/pkg/ambient/config/config_recorder.go @@ -9,9 +9,9 @@ const ( ) type RecorderConfig struct { - Type RecorderType `yaml:"type" env:"RECORDER_TYPE" json:"type,omitempty"` // memory|redis - KeepLast int `yaml:"keepLast" env:"RECORDER_KEEP_LAST" json:"keepLast,omitempty"` - RedisConfig *RedisConfig `json:"redisConfig,omitempty"` + Type RecorderType `yaml:"type" env:"RECORDER_TYPE" json:"type,omitempty" enum:"memory,redis,noop"` + KeepLast int `yaml:"keepLast" env:"RECORDER_KEEP_LAST" json:"keepLast,omitempty" default:"120"` + RedisConfig *RedisConfig `yaml:"redisConfig,omitempty" json:"redisConfig,omitempty"` } type RedisConfig struct { diff --git a/pkg/weather/recorder/recorder.go b/pkg/weather/recorder/recorder.go index 0aed4f6..f818b9e 100644 --- a/pkg/weather/recorder/recorder.go +++ b/pkg/weather/recorder/recorder.go @@ -4,11 +4,13 @@ import ( "context" "sync" + "github.com/rs/zerolog" "go.opentelemetry.io/otel/metric" "go.opentelemetry.io/otel/trace" "gitea.libretechconsulting.com/rmcguire/go-app/pkg/otel" + "gitea.libretechconsulting.com/rmcguire/ambient-local-exporter/pkg/ambient/config" "gitea.libretechconsulting.com/rmcguire/ambient-local-exporter/pkg/weather/recorder/recorders" ) @@ -21,9 +23,10 @@ type WeatherRecorder struct { } type Opts struct { - Ctx context.Context - Recorder recorders.Recorder // If nil, will use memory recorder - KeepLast int + AppConfig *config.AmbientLocalExporterConfig + Ctx context.Context + Recorder recorders.Recorder // If nil, will use memory recorder + KeepLast int } func MustNewWeatherRecorder(opts *Opts) *WeatherRecorder { @@ -36,10 +39,14 @@ func MustNewWeatherRecorder(opts *Opts) *WeatherRecorder { } opts.Recorder.Init(opts.Ctx, &recorders.RecorderOpts{ + AppConfig: opts.AppConfig, RetainLast: opts.KeepLast, BaseCtx: opts.Ctx, }) + zerolog.Ctx(opts.Ctx).Info().Str("recorderType", opts.Recorder.Name()). + Msg("weather update recorder ready") + return &WeatherRecorder{ ctx: opts.Ctx, recorder: opts.Recorder, diff --git a/pkg/weather/recorder/recorders/memory/memory.go b/pkg/weather/recorder/recorders/memory/memory.go index 217c9f0..9c733c8 100644 --- a/pkg/weather/recorder/recorders/memory/memory.go +++ b/pkg/weather/recorder/recorders/memory/memory.go @@ -12,7 +12,10 @@ import ( "gitea.libretechconsulting.com/rmcguire/ambient-local-exporter/pkg/weather/recorder/recorders" ) -const defRetainLast = 120 +const ( + DEF_RETAIN_LAST = 120 + NAME = "memory recorder" +) type MemoryRecorder struct { baseCtx context.Context @@ -24,7 +27,7 @@ type MemoryRecorder struct { func (r *MemoryRecorder) Init(ctx context.Context, opts *recorders.RecorderOpts) { if opts.RetainLast < 1 { - opts.RetainLast = defRetainLast + opts.RetainLast = DEF_RETAIN_LAST } r.updates = make([]*weather.WeatherUpdate, 0, opts.RetainLast) @@ -33,3 +36,5 @@ func (r *MemoryRecorder) Init(ctx context.Context, opts *recorders.RecorderOpts) r.RWMutex = &sync.RWMutex{} r.tracer = otel.GetTracer(r.baseCtx, "memoryRecorder") } + +func (r *MemoryRecorder) Name() string { return NAME } diff --git a/pkg/weather/recorder/recorders/noop/noop.go b/pkg/weather/recorder/recorders/noop/noop.go index 2e04106..a3758b3 100644 --- a/pkg/weather/recorder/recorders/noop/noop.go +++ b/pkg/weather/recorder/recorders/noop/noop.go @@ -19,3 +19,5 @@ func (n *NoopRecorder) Get(context.Context, *pb.GetWeatherRequest) ([]*weather.W } func (n *NoopRecorder) Count(context.Context) int { return 0 } + +func (r *NoopRecorder) Name() string { return "no-op recorder" } diff --git a/pkg/weather/recorder/recorders/recorders.go b/pkg/weather/recorder/recorders/recorders.go index d2d870e..36bf50e 100644 --- a/pkg/weather/recorder/recorders/recorders.go +++ b/pkg/weather/recorder/recorders/recorders.go @@ -19,4 +19,5 @@ type Recorder interface { Set(context.Context, *weather.WeatherUpdate) error Get(context.Context, *pb.GetWeatherRequest) ([]*weather.WeatherUpdate, error) Count(context.Context) int // Best Effort + Name() string } diff --git a/pkg/weather/recorder/recorders/redis/redis.go b/pkg/weather/recorder/recorders/redis/redis.go index b112ab2..13b4414 100644 --- a/pkg/weather/recorder/recorders/redis/redis.go +++ b/pkg/weather/recorder/recorders/redis/redis.go @@ -22,6 +22,7 @@ import ( const ( DEF_RETAIN = 120 UPDATES_KEY = "weatherUpdates" + NAME = "redis recorder" ) type RedisRecorder struct { @@ -36,11 +37,19 @@ type RedisRecorder struct { } func (r *RedisRecorder) Init(ctx context.Context, opts *recorders.RecorderOpts) { + if opts.AppConfig.RecorderConfig.RedisConfig == nil { + panic("refusing to init redis recorder with no redisConfig") + } + if opts.RetainLast < 1 { opts.RetainLast = DEF_RETAIN } - r.log = zerolog.Ctx(opts.BaseCtx) + r.config = opts.AppConfig + r.keep = opts.RetainLast + r.RWMutex = &sync.RWMutex{} + r.baseCtx = opts.BaseCtx + r.log = zerolog.Ctx(r.baseCtx) r.tracer = otel.GetTracer(r.baseCtx, "redisRecorder") ctx, span := r.tracer.Start(ctx, "redisRecorder.init", trace.WithAttributes( @@ -51,11 +60,6 @@ func (r *RedisRecorder) Init(ctx context.Context, opts *recorders.RecorderOpts) )) defer span.End() - r.config = opts.AppConfig - r.keep = opts.RetainLast - r.baseCtx = opts.BaseCtx - r.RWMutex = &sync.RWMutex{} - // Unique key prefix for this version/env/name of exporter // will be consistent across replicas, but resets on upgrade // as it is using version @@ -106,3 +110,5 @@ func (r *RedisRecorder) MustInitRedis(ctx context.Context) { func (r *RedisRecorder) Key() string { return fmt.Sprintf("%s:%s", r.appKey, UPDATES_KEY) } + +func (r *RedisRecorder) Name() string { return NAME }