From 55d0b5a9e748933ba27de3aa6bd69c8b51e777f9 Mon Sep 17 00:00:00 2001 From: Naeel Date: Sun, 26 Apr 2026 16:24:29 +0300 Subject: [PATCH] layer1: log namespace watcher startup summary --- .../2026-04-26-namespace-manager-step51.md | 15 +++++++ pkg/utils/namespace_manager.go | 1 + pkg/utils/namespace_manager_test.go | 39 +++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/doc/thinking/2026-04-26-namespace-manager-step51.md b/doc/thinking/2026-04-26-namespace-manager-step51.md index ed7b5e8b..1cbabb58 100644 --- a/doc/thinking/2026-04-26-namespace-manager-step51.md +++ b/doc/thinking/2026-04-26-namespace-manager-step51.md @@ -2,6 +2,21 @@ ## Цель шага +Закрыть observability gap между `prepared namespace manager` и runtime transition logs. + +## Что изменено + +1. `RunManagedNamespaceWatcher()` теперь пишет единый summary log после старта watcher-а. +2. Добавлен unit test на startup logging path. + +## Почему это полезно + +- buildermgr, router и executor получают одинаковый startup debug signal без копипасты; +- видно состояние manager-а в момент, когда watcher уже реально подключён; +- runtime semantics не меняется.# 2026-04-26 — NamespaceManager rewrite, step 51 + +## Цель шага + Убрать из call sites повторение стандартного config для managed namespace watcher-а. ## Что меняем diff --git a/pkg/utils/namespace_manager.go b/pkg/utils/namespace_manager.go index 1d595bbc..a538dd66 100644 --- a/pkg/utils/namespace_manager.go +++ b/pkg/utils/namespace_manager.go @@ -133,6 +133,7 @@ func PrepareManagedNamespaceWatcher(ctx context.Context, logger *zap.Logger, con func RunManagedNamespaceWatcher(ctx context.Context, logger *zap.Logger, kubeClient kubernetes.Interface, mgr managerPkg.Interface, config ManagedNamespaceWatcherConfig) (NamespaceManager, error) { manager, handlers, err := PrepareManagedNamespaceWatcher(ctx, logger, config) StartManagedNamespaceWatcher(ctx, logger, config.Component, kubeClient, mgr, handlers) + LogNamespaceManagerSummary(logger, config.Component+": started namespace watcher", manager.Summary()) return manager, err } diff --git a/pkg/utils/namespace_manager_test.go b/pkg/utils/namespace_manager_test.go index 90c2c6dc..5a2835bc 100644 --- a/pkg/utils/namespace_manager_test.go +++ b/pkg/utils/namespace_manager_test.go @@ -515,6 +515,45 @@ func TestRunManagedNamespaceWatcher(t *testing.T) { } } +func TestRunManagedNamespaceWatcherLogsStartedSummary(t *testing.T) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + router := &testNamespaceSubscriber{name: "router"} + core, logs := observer.New(zap.InfoLevel) + logger := zap.New(core) + + _, err := RunManagedNamespaceWatcher(ctx, logger, k8sfake.NewSimpleClientset(), managerPkg.New(), ManagedNamespaceWatcherConfig{ + Component: "router.NSWatcher", + Namespaces: []string{"tenant-a"}, + RemovalStrategy: NamespaceRemovalStrategyTrackOnly, + Subscriber: router, + }) + if err != nil { + t.Fatalf("expected managed namespace watcher run success: %v", err) + } + + entries := logs.FilterMessage("router.NSWatcher: started namespace watcher").AllUntimed() + if len(entries) != 1 { + t.Fatalf("expected one started-summary log entry, got %d", len(entries)) + } + fields := entries[0].ContextMap() + if live, ok := fields["live_namespaces"].(int64); !ok || live != 1 { + t.Fatalf("expected started summary to report one live namespace, got %v", fields["live_namespaces"]) + } + if active, ok := fields["has_active_namespaces"].(bool); !ok || !active { + t.Fatalf("expected started summary to report active namespaces") + } + if total, ok := fields["total_namespaces"].(int64); !ok || total != 1 { + t.Fatalf("expected started summary to report one total namespace, got %v", fields["total_namespaces"]) + } + if got := fields["subscribers"]; got == nil || !reflect.DeepEqual(got, []interface{}{"router"}) && !reflect.DeepEqual(got, []string{"router"}) { + t.Fatalf("expected started summary to report router subscriber, got %v", got) + } + if got := fields["phase_counts"]; got == nil { + t.Fatalf("expected started summary to report phase counts") + } +} + func TestNewDefaultManagedNamespaceWatcherConfig(t *testing.T) { resolver := DefaultNSResolver() original := resolver.FissionResourceNS