-
-
Notifications
You must be signed in to change notification settings - Fork 70
refactor: decoupled registry #36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
3feb8dd
8cd42aa
979e37e
952600e
7910fb0
759b53d
8afb10f
c76dfa5
8efbfd4
239bea7
9f4ec63
4f7a4a7
c2cb2c8
d00f43a
d385eba
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,28 +3,23 @@ package main | |
|
|
||
| import ( | ||
| "context" | ||
| "errors" | ||
| "flag" | ||
| "fmt" | ||
| "log/slog" | ||
| "net/http" | ||
| "os" | ||
| "os/signal" | ||
| "syscall" | ||
| "time" | ||
|
|
||
| "gomodel/config" | ||
| "gomodel/internal/auditlog" | ||
| "gomodel/internal/app" | ||
| "gomodel/internal/observability" | ||
| "gomodel/internal/providers" | ||
|
|
||
| // Import provider packages to trigger their init() registration | ||
| _ "gomodel/internal/providers/anthropic" | ||
| _ "gomodel/internal/providers/gemini" | ||
| _ "gomodel/internal/providers/groq" | ||
| _ "gomodel/internal/providers/openai" | ||
| _ "gomodel/internal/providers/xai" | ||
| "gomodel/internal/server" | ||
| "gomodel/internal/providers/anthropic" | ||
| "gomodel/internal/providers/gemini" | ||
| "gomodel/internal/providers/groq" | ||
| "gomodel/internal/providers/openai" | ||
| "gomodel/internal/providers/xai" | ||
| "gomodel/internal/version" | ||
| ) | ||
|
|
||
|
|
@@ -62,88 +57,49 @@ func main() { | |
| os.Exit(1) | ||
| } | ||
|
|
||
| // Setup observability hooks for metrics collection (if enabled) | ||
| // This must be done BEFORE creating providers so they can use the hooks | ||
| // Create provider factory and register all providers explicitly | ||
| factory := providers.NewProviderFactory() | ||
|
|
||
| // Set observability hooks before registering providers | ||
| if cfg.Metrics.Enabled { | ||
| metricsHooks := observability.NewPrometheusHooks() | ||
| providers.SetGlobalHooks(metricsHooks) | ||
| slog.Info("prometheus metrics enabled", "endpoint", cfg.Metrics.Endpoint) | ||
| } else { | ||
| slog.Info("prometheus metrics disabled") | ||
| factory.SetHooks(observability.NewPrometheusHooks()) | ||
| } | ||
|
|
||
| // Initialize provider infrastructure (cache, registry, router) | ||
| providerResult, err := providers.Init(context.Background(), cfg) | ||
| // Register all providers with the factory | ||
| factory.Register(openai.Registration) | ||
| factory.Register(anthropic.Registration) | ||
| factory.Register(gemini.Registration) | ||
| factory.Register(groq.Registration) | ||
| factory.Register(xai.Registration) | ||
|
|
||
| // Create the application | ||
| application, err := app.New(context.Background(), app.Config{ | ||
| AppConfig: cfg, | ||
| Factory: factory, | ||
| }) | ||
| if err != nil { | ||
| slog.Error("failed to initialize providers", "error", err) | ||
| slog.Error("failed to initialize application", "error", err) | ||
| os.Exit(1) | ||
| } | ||
|
Comment on lines
+76
to
83
|
||
| defer providerResult.Close() | ||
|
|
||
| // Security check: warn if no master key is configured | ||
| if cfg.Server.MasterKey == "" { | ||
| slog.Warn("SECURITY WARNING: GOMODEL_MASTER_KEY not set - server running in UNSAFE MODE", | ||
| "security_risk", "unauthenticated access allowed", | ||
| "recommendation", "set GOMODEL_MASTER_KEY environment variable to secure this gateway") | ||
| } else { | ||
| slog.Info("authentication enabled", "mode", "master_key") | ||
| } | ||
|
|
||
| // Initialize audit logging | ||
| auditResult, err := auditlog.New(context.Background(), cfg) | ||
| if err != nil { | ||
| slog.Error("failed to initialize audit logging", "error", err) | ||
| os.Exit(1) | ||
| } | ||
| defer auditResult.Close() | ||
|
|
||
| if cfg.Logging.Enabled { | ||
| slog.Info("audit logging enabled", | ||
| "storage_type", cfg.Logging.StorageType, | ||
| "log_bodies", cfg.Logging.LogBodies, | ||
| "log_headers", cfg.Logging.LogHeaders, | ||
| "retention_days", cfg.Logging.RetentionDays, | ||
| ) | ||
| } else { | ||
| slog.Info("audit logging disabled") | ||
| } | ||
|
|
||
| // Create and start server | ||
| serverCfg := &server.Config{ | ||
| MasterKey: cfg.Server.MasterKey, | ||
| MetricsEnabled: cfg.Metrics.Enabled, | ||
| MetricsEndpoint: cfg.Metrics.Endpoint, | ||
| BodySizeLimit: cfg.Server.BodySizeLimit, | ||
| AuditLogger: auditResult.Logger, | ||
| LogOnlyModelInteractions: cfg.Logging.OnlyModelInteractions, | ||
| } | ||
| srv := server.New(providerResult.Router, serverCfg) | ||
|
|
||
| // Handle graceful shutdown | ||
| go func() { | ||
| quit := make(chan os.Signal, 1) | ||
| signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) | ||
| <-quit | ||
|
|
||
| slog.Info("shutting down server...") | ||
|
|
||
| ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) | ||
| defer cancel() | ||
|
|
||
| if err := srv.Shutdown(ctx); err != nil { | ||
| slog.Error("server shutdown error", "error", err) | ||
| if err := application.Shutdown(ctx); err != nil { | ||
| slog.Error("application shutdown error", "error", err) | ||
| } | ||
| }() | ||
|
|
||
| // Start the server (blocking) | ||
| addr := ":" + cfg.Server.Port | ||
| slog.Info("starting server", "address", addr) | ||
|
|
||
| if err := srv.Start(addr); err != nil { | ||
| if errors.Is(err, http.ErrServerClosed) { | ||
| slog.Info("server stopped gracefully") | ||
| } else { | ||
| slog.Error("server failed to start", "error", err) | ||
| os.Exit(1) | ||
| } | ||
| if err := application.Start(addr); err != nil { | ||
| slog.Error("application failed", "error", err) | ||
| os.Exit(1) | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.