| 368 | } |
| 369 | |
| 370 | func createMultitenantAlertmanager(cfg *MultitenantAlertmanagerConfig, fallbackConfig []byte, peer *cluster.Peer, store alertstore.AlertStore, ringStore kv.Client, limits Limits, logger log.Logger, registerer prometheus.Registerer) (*MultitenantAlertmanager, error) { |
| 371 | am := &MultitenantAlertmanager{ |
| 372 | cfg: cfg, |
| 373 | fallbackConfig: string(fallbackConfig), |
| 374 | cfgs: map[string]alertspb.AlertConfigDesc{}, |
| 375 | alertmanagers: map[string]*Alertmanager{}, |
| 376 | alertmanagerMetrics: newAlertmanagerMetrics(), |
| 377 | multitenantMetrics: newMultitenantAlertmanagerMetrics(registerer), |
| 378 | peer: peer, |
| 379 | store: store, |
| 380 | userIndexUpdater: store.GetUserIndexUpdater(), |
| 381 | logger: log.With(logger, "component", "MultiTenantAlertmanager"), |
| 382 | registry: registerer, |
| 383 | limits: limits, |
| 384 | allowedTenants: users.NewAllowedTenants(cfg.EnabledTenants, cfg.DisabledTenants), |
| 385 | ringCheckErrors: promauto.With(registerer).NewCounter(prometheus.CounterOpts{ |
| 386 | Name: "cortex_alertmanager_ring_check_errors_total", |
| 387 | Help: "Number of errors that have occurred when checking the ring for ownership.", |
| 388 | }), |
| 389 | syncTotal: promauto.With(registerer).NewCounterVec(prometheus.CounterOpts{ |
| 390 | Name: "cortex_alertmanager_sync_configs_total", |
| 391 | Help: "Total number of times the alertmanager sync operation triggered.", |
| 392 | }, []string{"reason"}), |
| 393 | syncFailures: promauto.With(registerer).NewCounterVec(prometheus.CounterOpts{ |
| 394 | Name: "cortex_alertmanager_sync_configs_failed_total", |
| 395 | Help: "Total number of times the alertmanager sync operation failed.", |
| 396 | }, []string{"reason"}), |
| 397 | tenantsDiscovered: promauto.With(registerer).NewGauge(prometheus.GaugeOpts{ |
| 398 | Name: "cortex_alertmanager_tenants_discovered", |
| 399 | Help: "Number of tenants with an Alertmanager configuration discovered.", |
| 400 | }), |
| 401 | tenantsOwned: promauto.With(registerer).NewGauge(prometheus.GaugeOpts{ |
| 402 | Name: "cortex_alertmanager_tenants_owned", |
| 403 | Help: "Current number of tenants owned by the Alertmanager instance.", |
| 404 | }), |
| 405 | } |
| 406 | |
| 407 | // Initialize the top-level metrics. |
| 408 | for _, r := range []string{reasonInitial, reasonPeriodic, reasonRingChange} { |
| 409 | am.syncTotal.WithLabelValues(r) |
| 410 | am.syncFailures.WithLabelValues(r) |
| 411 | } |
| 412 | |
| 413 | if cfg.ShardingEnabled { |
| 414 | lifecyclerCfg, err := am.cfg.ShardingRing.ToLifecyclerConfig(am.logger) |
| 415 | if err != nil { |
| 416 | return nil, errors.Wrap(err, "failed to initialize Alertmanager's lifecycler config") |
| 417 | } |
| 418 | |
| 419 | // Define lifecycler delegates in reverse order (last to be called defined first because they're |
| 420 | // chained via "next delegate"). |
| 421 | delegate := ring.BasicLifecyclerDelegate(am) |
| 422 | delegate = ring.NewLeaveOnStoppingDelegate(delegate, am.logger) |
| 423 | delegate = ring.NewAutoForgetDelegate(am.cfg.ShardingRing.HeartbeatTimeout*ringAutoForgetUnhealthyPeriods, delegate, am.logger) |
| 424 | delegate = ring.NewTokensPersistencyDelegate(am.cfg.ShardingRing.TokensFilePath, ring.JOINING, delegate, am.logger) |
| 425 | |
| 426 | am.ringLifecycler, err = ring.NewBasicLifecycler(lifecyclerCfg, RingNameForServer, RingKey, ringStore, delegate, am.logger, prometheus.WrapRegistererWithPrefix("cortex_", am.registry)) |
| 427 | if err != nil { |