2 Commits

Author SHA1 Message Date
f0a699029a improve server startup 2025-03-07 17:19:42 -05:00
e178956eef improve grpc lifecycle 2025-03-07 17:04:46 -05:00
3 changed files with 55 additions and 17 deletions

View File

@ -2,6 +2,7 @@ package app
import (
"errors"
"sync"
"github.com/rs/zerolog"
"go.opentelemetry.io/otel/attribute"
@ -17,8 +18,6 @@ func (a *App) Done() <-chan any {
func (a *App) MustRun() {
if a.cfg != nil {
panic(errors.New("already ran app trying to run"))
} else if !a.cfg.HTTP.Enabled && !a.cfg.GRPC.Enabled {
panic(errors.New("neither http nor grpc enabled, nothing to do"))
}
// Set up app
@ -28,35 +27,53 @@ func (a *App) MustRun() {
a.appDone = make(chan any)
a.HTTP.HTTPDone = make(chan any)
if !a.cfg.HTTPEnabled() && !a.cfg.GRPCEnabled() {
panic(errors.New("neither http nor grpc enabled, nothing to do"))
}
if len(a.HTTP.Funcs) < 1 {
a.l.Warn().Msg("no http funcs provided, only serving health and metrics")
}
// Start OTEL
// Registers a NO-OP provider if not enabled
a.initOTEL()
ctx, initSpan := a.tracer.Start(a.AppContext, "init")
defer initSpan.End()
var serverWG sync.WaitGroup
// Start HTTP (does not block)
if a.cfg.HTTP.Enabled {
if err := a.initHTTP(ctx); err != nil {
initSpan.RecordError(err)
initSpan.SetStatus(codes.Error, err.Error())
}
initSpan.AddEvent("http server started")
initSpan.SetAttributes(attribute.Int("http.handlers", len(a.HTTP.Funcs)))
if a.cfg.HTTPEnabled() {
serverWG.Add(1)
go func() {
defer serverWG.Done()
if err := a.initHTTP(ctx); err != nil {
initSpan.RecordError(err)
initSpan.SetStatus(codes.Error, err.Error())
}
initSpan.AddEvent("http server started")
initSpan.SetAttributes(attribute.Int("http.handlers", len(a.HTTP.Funcs)))
}()
}
// Start GRPC (does not block)
if a.cfg.GRPC.Enabled {
if err := a.initGRPC(ctx); err != nil {
initSpan.RecordError(err)
initSpan.SetStatus(codes.Error, err.Error())
}
initSpan.AddEvent("grpc server started")
initSpan.SetAttributes(attribute.Int("grpc.services", len(a.GRPC.Services)))
if a.cfg.GRPCEnabled() {
serverWG.Add(1)
go func() {
defer serverWG.Done()
if err := a.initGRPC(ctx); err != nil {
initSpan.RecordError(err)
initSpan.SetStatus(codes.Error, err.Error())
}
initSpan.AddEvent("grpc server started")
initSpan.SetAttributes(attribute.Int("grpc.services", len(a.GRPC.Services)))
}()
}
serverWG.Wait()
// Monitor app lifecycle
go a.run()

View File

@ -22,3 +22,24 @@ type AppConfig struct {
OTEL *OTELConfig `yaml:"otel,omitempty"`
GRPC *GRPCConfig `yaml:"grpc,omitempty"`
}
func (ac *AppConfig) HTTPEnabled() bool {
if ac.HTTP != nil && ac.HTTP.Enabled {
return true
}
return false
}
func (ac *AppConfig) GRPCEnabled() bool {
if ac.GRPC != nil && ac.GRPC.Enabled {
return true
}
return false
}
func (ac *AppConfig) OTELEnabled() bool {
if ac.OTEL != nil && ac.OTEL.Enabled {
return true
}
return false
}

View File

@ -44,7 +44,7 @@ func Init(ctx context.Context) (context.Context, func(context.Context) error) {
cfg := config.MustFromCtx(ctx)
// Nothing to do here if not enabled
if !cfg.OTEL.Enabled {
if !cfg.OTELEnabled() {
opentelemetry.SetMeterProvider(noopMetric.NewMeterProvider())
opentelemetry.SetTracerProvider(noop.NewTracerProvider())
// Won't function with noop providers