From c1e62062d4a1972a2a39f03be5eb9528366b2f42 Mon Sep 17 00:00:00 2001 From: Siavash Safi Date: Tue, 28 Jul 2026 16:57:40 +0200 Subject: [PATCH] feat(eventrecorder): replace event output schema Replace the original event recorder schema with events/v2. Alert labels, alert annotations, group labels, silence annotations, and muted-alert labels are now encoded as maps instead of nested ordered label pairs. This is a breaking change for every event recorder output. JSON consumers must handle the new map-based fields, and protobuf consumers must regenerate their bindings from proto/eventrecorder/events/v2/events.proto. Remove the legacy eventrecorderpb schema and generated bindings. Register the new schema as the event recorder Buf module and use it directly for all file, webhook, Kafka, and stdout outputs without version selection or conversion. Event producers now construct opaque eventrecorder.Event values through snapshotting constructors instead of depending on protobuf types. Destinations receive the typed Event and serialize it as JSON or protobuf. Event metadata is attached without mutating the constructed payload. Also include silence annotations in recorded events. BREAKING CHANGE: Event recorder outputs now use the events/v2 schema and map-based label and annotation fields. The legacy eventrecorderpb wire format is no longer supported. Signed-off-by: Siavash Safi --- CHANGELOG.md | 2 + app/app.go | 20 +- buf.yaml | 4 +- dispatch/dispatch.go | 19 +- docs/configuration.md | 13 +- .../eventrecorderpb/eventrecorder.pb.go | 2106 ----------------- .../eventrecorderpb/eventrecorder.proto | 392 --- eventrecorder/events.go | 556 +++-- eventrecorder/events/v2/events.pb.go | 1899 +++++++++++++++ eventrecorder/events_test.go | 202 +- eventrecorder/file.go | 7 +- eventrecorder/kafka.go | 9 +- eventrecorder/kafka_test.go | 26 +- eventrecorder/recorder.go | 65 +- eventrecorder/recorder_test.go | 59 +- eventrecorder/stdout.go | 8 +- eventrecorder/webhook.go | 6 +- eventrecorder/webhook_test.go | 2 +- inhibit/inhibit.go | 5 +- notify/event.go | 105 +- notify/retry_stage.go | 3 +- proto/eventrecorder/events/v2/events.proto | 186 ++ provider/mem/mem.go | 3 +- silence/silence.go | 17 +- 24 files changed, 2715 insertions(+), 2999 deletions(-) delete mode 100644 eventrecorder/eventrecorderpb/eventrecorder.pb.go delete mode 100644 eventrecorder/eventrecorderpb/eventrecorder.proto create mode 100644 eventrecorder/events/v2/events.pb.go create mode 100644 proto/eventrecorder/events/v2/events.proto diff --git a/CHANGELOG.md b/CHANGELOG.md index a5182671a2..2bb89f90f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## main / (unreleased) +* [CHANGE] eventrecorder: The output data format now uses the new `events/v2` schema. This is a breaking change: alert labels, alert annotations, group labels, silence annotations, and muted-alert labels are JSON maps, and protobuf consumers must use the new schema. + ## 0.34.0 / 2026-08-16 * [CHANGE] notify: The `reason` label on `alertmanager_notifications_failed_total` now distinguishes `authError` (HTTP 401/403) and `rateLimited` (HTTP 429) from the generic `clientError`. Dashboards/alerts matching `reason="clientError"` for these codes must be updated. #5332 diff --git a/app/app.go b/app/app.go index cb1c4c6790..68382fb01f 100644 --- a/app/app.go +++ b/app/app.go @@ -39,7 +39,6 @@ import ( "github.com/prometheus/alertmanager/config" "github.com/prometheus/alertmanager/dispatch" "github.com/prometheus/alertmanager/eventrecorder" - "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" "github.com/prometheus/alertmanager/httpserver" "github.com/prometheus/alertmanager/marker" "github.com/prometheus/alertmanager/nflog" @@ -265,23 +264,12 @@ func (a *App) setup() error { a.onStop("event recorder", eventRec.Close) recordCtx := eventrecorder.WithEventRecording(context.Background()) - eventRec.RecordEvent(recordCtx, func() *eventrecorderpb.EventData { - return &eventrecorderpb.EventData{ - EventType: &eventrecorderpb.EventData_AlertmanagerStartupEvent{ - AlertmanagerStartupEvent: &eventrecorderpb.AlertmanagerStartupEvent{ - Version: version.Version, - BuildContext: version.BuildContext(), - }, - }, - } + eventRec.RecordEvent(recordCtx, func() eventrecorder.EventData { + return eventrecorder.NewAlertmanagerStartupEvent(version.Version, version.BuildContext()) }) a.onStop("shutdown event", func() error { - eventRec.RecordEvent(recordCtx, func() *eventrecorderpb.EventData { - return &eventrecorderpb.EventData{ - EventType: &eventrecorderpb.EventData_AlertmanagerShutdownEvent{ - AlertmanagerShutdownEvent: &eventrecorderpb.AlertmanagerShutdownEvent{}, - }, - } + eventRec.RecordEvent(recordCtx, func() eventrecorder.EventData { + return eventrecorder.NewAlertmanagerShutdownEvent() }) return nil }) diff --git a/buf.yaml b/buf.yaml index 225e01263f..1fb8793125 100644 --- a/buf.yaml +++ b/buf.yaml @@ -3,11 +3,11 @@ version: v2 modules: - path: cluster/clusterpb name: prometheus/alertmanager/cluster - - path: eventrecorder/eventrecorderpb - name: prometheus/alertmanager/eventrecorder - path: nflog/nflogpb name: prometheus/alertmanager/nflog - path: proto/api name: prometheus/alertmanager/api + - path: proto/eventrecorder + name: prometheus/alertmanager/eventrecorder - path: silence/silencepb name: prometheus/alertmanager/silence diff --git a/dispatch/dispatch.go b/dispatch/dispatch.go index 47e45151d7..2e3da19970 100644 --- a/dispatch/dispatch.go +++ b/dispatch/dispatch.go @@ -34,7 +34,6 @@ import ( "github.com/prometheus/alertmanager/alert" "github.com/prometheus/alertmanager/eventrecorder" - "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" "github.com/prometheus/alertmanager/marker" "github.com/prometheus/alertmanager/notify" "github.com/prometheus/alertmanager/pkg/labels" @@ -890,7 +889,7 @@ func (ag *aggrGroup) insert(ctx context.Context, alert *alert.Alert) bool { span.RecordError(err) ag.logger.Error(message, "err", err) } else { - ag.recorder.RecordEvent(ctx, func() *eventrecorderpb.EventData { + ag.recorder.RecordEvent(ctx, func() eventrecorder.EventData { return notify.NewAlertGroupedEvent(ag.alertGroupInfo(), alert) }) // The alert set changed; the alert is already visible via ag.alerts. @@ -965,21 +964,17 @@ func (ag *aggrGroup) recordResolvedEvents(resolved types.AlertSlice) { if len(resolved) == 0 { return } - groupInfo := ag.alertGroupInfo() for _, a := range resolved { - ag.recorder.RecordEvent(ag.ctx, func() *eventrecorderpb.EventData { - return notify.NewAlertResolvedEvent(groupInfo, a) + ag.recorder.RecordEvent(ag.ctx, func() eventrecorder.EventData { + return notify.NewAlertResolvedEvent(ag.alertGroupInfo(), a) }) } } -func (ag *aggrGroup) alertGroupInfo() *eventrecorderpb.AlertGroupInfo { - return &eventrecorderpb.AlertGroupInfo{ - GroupKey: ag.GroupKey(), - GroupLabels: eventrecorder.LabelSetAsProto(ag.labels), - GroupId: notify.Key(ag.GroupKey()).Hash(), - ReceiverName: ag.opts.Receiver, - } +func (ag *aggrGroup) alertGroupInfo() eventrecorder.AlertGroup { + return eventrecorder.NewAlertGroup( + ag.GroupKey(), ag.labels, notify.Key(ag.GroupKey()).Hash(), ag.opts.Receiver, nil, "", + ) } type nilLimits struct{} diff --git a/docs/configuration.md b/docs/configuration.md index 92cf0e04d8..eec8781b57 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -2175,6 +2175,12 @@ stdout_outputs: [ - ... ] ``` +Every output uses the schema in `proto/eventrecorder/events/v2/events.proto`. +Alert labels, alert annotations, group labels, silence annotations, and +muted-alert labels are encoded as maps. Protobuf consumers must use the Go +package `github.com/prometheus/alertmanager/eventrecorder/events/v2` or bindings +generated from that schema. + #### `` Writes each event as a single JSON line to a file. The file is reopened @@ -2234,7 +2240,10 @@ url: For example, [Cloudflare Pipelines streams](https://developers.cloudflare.com/pipelines/streams/writing-to-streams/) accept JSON arrays through their HTTP ingestion endpoints and can be configured -as a batched webhook output: +as a batched webhook output. Because the event timestamp field is named +`@timestamp`, quote it when referencing it from the pipeline SQL. A complete +fan-out example is available under +[`doc/examples/cloudflare-pipelines`](https://github.com/prometheus/alertmanager/blob/main/doc/examples/cloudflare-pipelines/README.md). ```yaml event_recorder: @@ -2277,7 +2286,7 @@ topic: # On-the-wire encoding for each record value: "json" (protojson) or # "protobuf" (binary proto). JSON is the default for symmetry with the # file and webhook outputs; consumers that already use the -# eventrecorder.proto schema may prefer protobuf for compactness. +# selected event recorder protobuf schema may prefer protobuf for compactness. [ format: <"json" | "protobuf"> | default = "json" ] # Producer acknowledgement level. "leader" matches the franz-go default diff --git a/eventrecorder/eventrecorderpb/eventrecorder.pb.go b/eventrecorder/eventrecorderpb/eventrecorder.pb.go deleted file mode 100644 index 3926cfb61f..0000000000 --- a/eventrecorder/eventrecorderpb/eventrecorder.pb.go +++ /dev/null @@ -1,2106 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.36.12 -// protoc (unknown) -// source: eventrecorder.proto - -package eventrecorderpb - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - durationpb "google.golang.org/protobuf/types/known/durationpb" - timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" - unsafe "unsafe" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -// NotifyReason describes why a notification was sent for an aggregation -// group. -type NotifyReason int32 - -const ( - // Default / unknown reason. - NotifyReason_NOTIFY_REASON_UNSPECIFIED NotifyReason = 0 - // The group has never been notified before and contains at least one - // firing alert. - NotifyReason_NOTIFY_REASON_FIRST_NOTIFICATION NotifyReason = 1 - // New firing alerts have been added to the group since the last - // notification. - NotifyReason_NOTIFY_REASON_NEW_ALERTS_IN_GROUP NotifyReason = 2 - // Some alerts in the group have resolved since the last notification. - NotifyReason_NOTIFY_REASON_NEW_RESOLVED_ALERTS NotifyReason = 3 - // All alerts in the group have resolved. - NotifyReason_NOTIFY_REASON_ALL_ALERTS_RESOLVED NotifyReason = 4 - // The configured repeat interval has elapsed since the last - // notification. - NotifyReason_NOTIFY_REASON_REPEAT_INTERVAL_ELAPSED NotifyReason = 5 -) - -// Enum value maps for NotifyReason. -var ( - NotifyReason_name = map[int32]string{ - 0: "NOTIFY_REASON_UNSPECIFIED", - 1: "NOTIFY_REASON_FIRST_NOTIFICATION", - 2: "NOTIFY_REASON_NEW_ALERTS_IN_GROUP", - 3: "NOTIFY_REASON_NEW_RESOLVED_ALERTS", - 4: "NOTIFY_REASON_ALL_ALERTS_RESOLVED", - 5: "NOTIFY_REASON_REPEAT_INTERVAL_ELAPSED", - } - NotifyReason_value = map[string]int32{ - "NOTIFY_REASON_UNSPECIFIED": 0, - "NOTIFY_REASON_FIRST_NOTIFICATION": 1, - "NOTIFY_REASON_NEW_ALERTS_IN_GROUP": 2, - "NOTIFY_REASON_NEW_RESOLVED_ALERTS": 3, - "NOTIFY_REASON_ALL_ALERTS_RESOLVED": 4, - "NOTIFY_REASON_REPEAT_INTERVAL_ELAPSED": 5, - } -) - -func (x NotifyReason) Enum() *NotifyReason { - p := new(NotifyReason) - *p = x - return p -} - -func (x NotifyReason) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (NotifyReason) Descriptor() protoreflect.EnumDescriptor { - return file_eventrecorder_proto_enumTypes[0].Descriptor() -} - -func (NotifyReason) Type() protoreflect.EnumType { - return &file_eventrecorder_proto_enumTypes[0] -} - -func (x NotifyReason) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use NotifyReason.Descriptor instead. -func (NotifyReason) EnumDescriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{0} -} - -// Type enumerates the supported matching operators. -type Matcher_Type int32 - -const ( - // Unspecified / unknown match type. - Matcher_TYPE_UNSPECIFIED Matcher_Type = 0 - // Exact string equality (=). - Matcher_TYPE_EQUAL Matcher_Type = 1 - // Regular expression match (=~). - Matcher_TYPE_REGEXP Matcher_Type = 2 - // Negated exact string equality (!=). - Matcher_TYPE_NOT_EQUAL Matcher_Type = 3 - // Negated regular expression match (!~). - Matcher_TYPE_NOT_REGEXP Matcher_Type = 4 -) - -// Enum value maps for Matcher_Type. -var ( - Matcher_Type_name = map[int32]string{ - 0: "TYPE_UNSPECIFIED", - 1: "TYPE_EQUAL", - 2: "TYPE_REGEXP", - 3: "TYPE_NOT_EQUAL", - 4: "TYPE_NOT_REGEXP", - } - Matcher_Type_value = map[string]int32{ - "TYPE_UNSPECIFIED": 0, - "TYPE_EQUAL": 1, - "TYPE_REGEXP": 2, - "TYPE_NOT_EQUAL": 3, - "TYPE_NOT_REGEXP": 4, - } -) - -func (x Matcher_Type) Enum() *Matcher_Type { - p := new(Matcher_Type) - *p = x - return p -} - -func (x Matcher_Type) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Matcher_Type) Descriptor() protoreflect.EnumDescriptor { - return file_eventrecorder_proto_enumTypes[1].Descriptor() -} - -func (Matcher_Type) Type() protoreflect.EnumType { - return &file_eventrecorder_proto_enumTypes[1] -} - -func (x Matcher_Type) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Matcher_Type.Descriptor instead. -func (Matcher_Type) EnumDescriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{15, 0} -} - -// Event is the top-level envelope written to each event recorder output. -// It wraps the specific event data with metadata about when and where -// the event was produced. -type Event struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The wall-clock time at which the event was recorded. - Timestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=timestamp,json=@timestamp,proto3" json:"timestamp,omitempty"` - // The hostname or address of the Alertmanager instance that produced - // the event. - Instance string `protobuf:"bytes,2,opt,name=instance,proto3" json:"instance,omitempty"` - // The event payload. Exactly one of the oneof fields inside EventData - // will be set. - Data *EventData `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` - // The ordinal position of this instance among its HA cluster peers. - // Zero when clustering is disabled. - ClusterPosition uint32 `protobuf:"varint,4,opt,name=cluster_position,json=clusterPosition,proto3" json:"cluster_position,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Event) Reset() { - *x = Event{} - mi := &file_eventrecorder_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Event) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Event) ProtoMessage() {} - -func (x *Event) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[0] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Event.ProtoReflect.Descriptor instead. -func (*Event) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{0} -} - -func (x *Event) GetTimestamp() *timestamppb.Timestamp { - if x != nil { - return x.Timestamp - } - return nil -} - -func (x *Event) GetInstance() string { - if x != nil { - return x.Instance - } - return "" -} - -func (x *Event) GetData() *EventData { - if x != nil { - return x.Data - } - return nil -} - -func (x *Event) GetClusterPosition() uint32 { - if x != nil { - return x.ClusterPosition - } - return 0 -} - -// EventData carries the payload for a single event recorder entry. -// Exactly one of the oneof fields will be populated. -type EventData struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Types that are valid to be assigned to EventType: - // - // *EventData_AlertmanagerStartupEvent - // *EventData_AlertmanagerShutdownEvent - // *EventData_AlertCreated - // *EventData_AlertResolved - // *EventData_AlertGrouped - // *EventData_Notification - // *EventData_SilenceCreated - // *EventData_SilenceUpdated - // *EventData_SilenceMutedAlert - // *EventData_InhibitionMutedAlert - EventType isEventData_EventType `protobuf_oneof:"event_type"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *EventData) Reset() { - *x = EventData{} - mi := &file_eventrecorder_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *EventData) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*EventData) ProtoMessage() {} - -func (x *EventData) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[1] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use EventData.ProtoReflect.Descriptor instead. -func (*EventData) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{1} -} - -func (x *EventData) GetEventType() isEventData_EventType { - if x != nil { - return x.EventType - } - return nil -} - -func (x *EventData) GetAlertmanagerStartupEvent() *AlertmanagerStartupEvent { - if x != nil { - if x, ok := x.EventType.(*EventData_AlertmanagerStartupEvent); ok { - return x.AlertmanagerStartupEvent - } - } - return nil -} - -func (x *EventData) GetAlertmanagerShutdownEvent() *AlertmanagerShutdownEvent { - if x != nil { - if x, ok := x.EventType.(*EventData_AlertmanagerShutdownEvent); ok { - return x.AlertmanagerShutdownEvent - } - } - return nil -} - -func (x *EventData) GetAlertCreated() *AlertCreatedEvent { - if x != nil { - if x, ok := x.EventType.(*EventData_AlertCreated); ok { - return x.AlertCreated - } - } - return nil -} - -func (x *EventData) GetAlertResolved() *AlertResolvedEvent { - if x != nil { - if x, ok := x.EventType.(*EventData_AlertResolved); ok { - return x.AlertResolved - } - } - return nil -} - -func (x *EventData) GetAlertGrouped() *AlertGroupedEvent { - if x != nil { - if x, ok := x.EventType.(*EventData_AlertGrouped); ok { - return x.AlertGrouped - } - } - return nil -} - -func (x *EventData) GetNotification() *NotificationEvent { - if x != nil { - if x, ok := x.EventType.(*EventData_Notification); ok { - return x.Notification - } - } - return nil -} - -func (x *EventData) GetSilenceCreated() *SilenceCreatedEvent { - if x != nil { - if x, ok := x.EventType.(*EventData_SilenceCreated); ok { - return x.SilenceCreated - } - } - return nil -} - -func (x *EventData) GetSilenceUpdated() *SilenceUpdatedEvent { - if x != nil { - if x, ok := x.EventType.(*EventData_SilenceUpdated); ok { - return x.SilenceUpdated - } - } - return nil -} - -func (x *EventData) GetSilenceMutedAlert() *SilenceMutedAlertEvent { - if x != nil { - if x, ok := x.EventType.(*EventData_SilenceMutedAlert); ok { - return x.SilenceMutedAlert - } - } - return nil -} - -func (x *EventData) GetInhibitionMutedAlert() *InhibitionMutedAlertEvent { - if x != nil { - if x, ok := x.EventType.(*EventData_InhibitionMutedAlert); ok { - return x.InhibitionMutedAlert - } - } - return nil -} - -type isEventData_EventType interface { - isEventData_EventType() -} - -type EventData_AlertmanagerStartupEvent struct { - // Recorded when the Alertmanager process starts. - AlertmanagerStartupEvent *AlertmanagerStartupEvent `protobuf:"bytes,1,opt,name=alertmanager_startup_event,json=alertmanagerStartupEvent,proto3,oneof"` -} - -type EventData_AlertmanagerShutdownEvent struct { - // Recorded when the Alertmanager process shuts down gracefully. - AlertmanagerShutdownEvent *AlertmanagerShutdownEvent `protobuf:"bytes,2,opt,name=alertmanager_shutdown_event,json=alertmanagerShutdownEvent,proto3,oneof"` -} - -type EventData_AlertCreated struct { - // Recorded when a new alert is first inserted into the alert store. - AlertCreated *AlertCreatedEvent `protobuf:"bytes,3,opt,name=alert_created,json=alertCreated,proto3,oneof"` -} - -type EventData_AlertResolved struct { - // Recorded when an alert transitions to the resolved state and is - // removed from its aggregation group after successful notification. - AlertResolved *AlertResolvedEvent `protobuf:"bytes,4,opt,name=alert_resolved,json=alertResolved,proto3,oneof"` -} - -type EventData_AlertGrouped struct { - // Recorded when an alert is inserted into an aggregation group for - // the first time. - AlertGrouped *AlertGroupedEvent `protobuf:"bytes,5,opt,name=alert_grouped,json=alertGrouped,proto3,oneof"` -} - -type EventData_Notification struct { - // Recorded after a notification is successfully delivered to an - // integration (e.g., webhook, email, PagerDuty). - Notification *NotificationEvent `protobuf:"bytes,6,opt,name=notification,proto3,oneof"` -} - -type EventData_SilenceCreated struct { - // Recorded when a new silence is created. - SilenceCreated *SilenceCreatedEvent `protobuf:"bytes,7,opt,name=silence_created,json=silenceCreated,proto3,oneof"` -} - -type EventData_SilenceUpdated struct { - // Recorded when an existing silence is updated (e.g., extended or - // re-commented). - SilenceUpdated *SilenceUpdatedEvent `protobuf:"bytes,8,opt,name=silence_updated,json=silenceUpdated,proto3,oneof"` -} - -type EventData_SilenceMutedAlert struct { - // Recorded each time a silence actively suppresses an alert during - // the muting evaluation pass. - SilenceMutedAlert *SilenceMutedAlertEvent `protobuf:"bytes,9,opt,name=silence_muted_alert,json=silenceMutedAlert,proto3,oneof"` -} - -type EventData_InhibitionMutedAlert struct { - // Recorded each time one or more inhibition rules suppress an alert - // during the muting evaluation pass. - InhibitionMutedAlert *InhibitionMutedAlertEvent `protobuf:"bytes,10,opt,name=inhibition_muted_alert,json=inhibitionMutedAlert,proto3,oneof"` -} - -func (*EventData_AlertmanagerStartupEvent) isEventData_EventType() {} - -func (*EventData_AlertmanagerShutdownEvent) isEventData_EventType() {} - -func (*EventData_AlertCreated) isEventData_EventType() {} - -func (*EventData_AlertResolved) isEventData_EventType() {} - -func (*EventData_AlertGrouped) isEventData_EventType() {} - -func (*EventData_Notification) isEventData_EventType() {} - -func (*EventData_SilenceCreated) isEventData_EventType() {} - -func (*EventData_SilenceUpdated) isEventData_EventType() {} - -func (*EventData_SilenceMutedAlert) isEventData_EventType() {} - -func (*EventData_InhibitionMutedAlert) isEventData_EventType() {} - -// AlertmanagerStartupEvent is emitted once when the process starts. -type AlertmanagerStartupEvent struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The semantic version of the Alertmanager binary (e.g., "0.28.0"). - Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` - // Free-form build metadata such as Go version, branch, and revision. - BuildContext string `protobuf:"bytes,2,opt,name=build_context,json=buildContext,proto3" json:"build_context,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AlertmanagerStartupEvent) Reset() { - *x = AlertmanagerStartupEvent{} - mi := &file_eventrecorder_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AlertmanagerStartupEvent) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AlertmanagerStartupEvent) ProtoMessage() {} - -func (x *AlertmanagerStartupEvent) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[2] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AlertmanagerStartupEvent.ProtoReflect.Descriptor instead. -func (*AlertmanagerStartupEvent) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{2} -} - -func (x *AlertmanagerStartupEvent) GetVersion() string { - if x != nil { - return x.Version - } - return "" -} - -func (x *AlertmanagerStartupEvent) GetBuildContext() string { - if x != nil { - return x.BuildContext - } - return "" -} - -// AlertmanagerShutdownEvent is emitted when the process shuts down -// gracefully. It carries no additional data. -type AlertmanagerShutdownEvent struct { - state protoimpl.MessageState `protogen:"open.v1"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AlertmanagerShutdownEvent) Reset() { - *x = AlertmanagerShutdownEvent{} - mi := &file_eventrecorder_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AlertmanagerShutdownEvent) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AlertmanagerShutdownEvent) ProtoMessage() {} - -func (x *AlertmanagerShutdownEvent) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[3] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AlertmanagerShutdownEvent.ProtoReflect.Descriptor instead. -func (*AlertmanagerShutdownEvent) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{3} -} - -// LabelPair is a single key-value label. -type LabelPair struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The label name (e.g., "alertname"). - Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` - // The label value (e.g., "HighMemoryUsage"). - Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *LabelPair) Reset() { - *x = LabelPair{} - mi := &file_eventrecorder_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *LabelPair) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LabelPair) ProtoMessage() {} - -func (x *LabelPair) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[4] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LabelPair.ProtoReflect.Descriptor instead. -func (*LabelPair) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{4} -} - -func (x *LabelPair) GetKey() string { - if x != nil { - return x.Key - } - return "" -} - -func (x *LabelPair) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -// LabelSet is an ordered collection of label pairs. -type LabelSet struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The label pairs that make up this set. - Labels []*LabelPair `protobuf:"bytes,1,rep,name=labels,proto3" json:"labels,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *LabelSet) Reset() { - *x = LabelSet{} - mi := &file_eventrecorder_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *LabelSet) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LabelSet) ProtoMessage() {} - -func (x *LabelSet) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[5] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use LabelSet.ProtoReflect.Descriptor instead. -func (*LabelSet) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{5} -} - -func (x *LabelSet) GetLabels() []*LabelPair { - if x != nil { - return x.Labels - } - return nil -} - -// Alert represents a snapshot of an alert at the time the event was -// recorded. -type Alert struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The unique fingerprint derived from the alert's label set. - Fingerprint uint64 `protobuf:"varint,1,opt,name=fingerprint,proto3" json:"fingerprint,omitempty"` - // The value of the "alertname" label, provided for convenience. - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - // The full label set that identifies this alert. - Labels *LabelSet `protobuf:"bytes,3,opt,name=labels,proto3" json:"labels,omitempty"` - // Informational annotations attached to the alert (e.g., summary, - // description). - Annotations *LabelSet `protobuf:"bytes,4,opt,name=annotations,proto3" json:"annotations,omitempty"` - // The time at which the alert started firing. - StartsAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=starts_at,json=startsAt,proto3" json:"starts_at,omitempty"` - // The time at which the alert is considered resolved. For firing - // alerts this is typically set to a time in the future. - EndsAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=ends_at,json=endsAt,proto3" json:"ends_at,omitempty"` - // Whether the alert was resolved at the time the event was recorded. - Resolved bool `protobuf:"varint,7,opt,name=resolved,proto3" json:"resolved,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Alert) Reset() { - *x = Alert{} - mi := &file_eventrecorder_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Alert) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Alert) ProtoMessage() {} - -func (x *Alert) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[6] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Alert.ProtoReflect.Descriptor instead. -func (*Alert) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{6} -} - -func (x *Alert) GetFingerprint() uint64 { - if x != nil { - return x.Fingerprint - } - return 0 -} - -func (x *Alert) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *Alert) GetLabels() *LabelSet { - if x != nil { - return x.Labels - } - return nil -} - -func (x *Alert) GetAnnotations() *LabelSet { - if x != nil { - return x.Annotations - } - return nil -} - -func (x *Alert) GetStartsAt() *timestamppb.Timestamp { - if x != nil { - return x.StartsAt - } - return nil -} - -func (x *Alert) GetEndsAt() *timestamppb.Timestamp { - if x != nil { - return x.EndsAt - } - return nil -} - -func (x *Alert) GetResolved() bool { - if x != nil { - return x.Resolved - } - return false -} - -// GroupedAlert is a reference to an alert within an aggregation group. -// It always carries the content hash; the full alert details are -// included when available. -type GroupedAlert struct { - state protoimpl.MessageState `protogen:"open.v1"` - // A hash of the alert's label set, used for deduplication within the - // notification pipeline. - Hash uint64 `protobuf:"varint,1,opt,name=hash,proto3" json:"hash,omitempty"` - // The full alert details. May be absent when only the hash is needed - // (e.g., in firing/resolved lists on NotificationEvent). - Details *Alert `protobuf:"bytes,2,opt,name=details,proto3,oneof" json:"details,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GroupedAlert) Reset() { - *x = GroupedAlert{} - mi := &file_eventrecorder_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GroupedAlert) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GroupedAlert) ProtoMessage() {} - -func (x *GroupedAlert) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[7] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use GroupedAlert.ProtoReflect.Descriptor instead. -func (*GroupedAlert) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{7} -} - -func (x *GroupedAlert) GetHash() uint64 { - if x != nil { - return x.Hash - } - return 0 -} - -func (x *GroupedAlert) GetDetails() *Alert { - if x != nil { - return x.Details - } - return nil -} - -// AlertGroupInfo describes the aggregation group context in which an -// alert is being processed. -type AlertGroupInfo struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The composite key that uniquely identifies this aggregation group - // (encodes route and group label values). - GroupKey string `protobuf:"bytes,1,opt,name=group_key,json=groupKey,proto3" json:"group_key,omitempty"` - // The label set used to group alerts together within this route. - GroupLabels *LabelSet `protobuf:"bytes,2,opt,name=group_labels,json=groupLabels,proto3" json:"group_labels,omitempty"` - // A stable, shortened identifier derived from the group key (SHA-256 - // hex). - GroupId string `protobuf:"bytes,3,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` - // The name of the receiver that this group routes to. - ReceiverName string `protobuf:"bytes,4,opt,name=receiver_name,json=receiverName,proto3" json:"receiver_name,omitempty"` - // The set of matchers defined on the route that matched these alerts. - Matchers []*Matcher `protobuf:"bytes,5,rep,name=matchers,proto3" json:"matchers,omitempty"` - // A UUID that uniquely identifies this aggregation group instance. - GroupUuid string `protobuf:"bytes,6,opt,name=group_uuid,json=groupUuid,proto3" json:"group_uuid,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AlertGroupInfo) Reset() { - *x = AlertGroupInfo{} - mi := &file_eventrecorder_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AlertGroupInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AlertGroupInfo) ProtoMessage() {} - -func (x *AlertGroupInfo) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[8] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AlertGroupInfo.ProtoReflect.Descriptor instead. -func (*AlertGroupInfo) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{8} -} - -func (x *AlertGroupInfo) GetGroupKey() string { - if x != nil { - return x.GroupKey - } - return "" -} - -func (x *AlertGroupInfo) GetGroupLabels() *LabelSet { - if x != nil { - return x.GroupLabels - } - return nil -} - -func (x *AlertGroupInfo) GetGroupId() string { - if x != nil { - return x.GroupId - } - return "" -} - -func (x *AlertGroupInfo) GetReceiverName() string { - if x != nil { - return x.ReceiverName - } - return "" -} - -func (x *AlertGroupInfo) GetMatchers() []*Matcher { - if x != nil { - return x.Matchers - } - return nil -} - -func (x *AlertGroupInfo) GetGroupUuid() string { - if x != nil { - return x.GroupUuid - } - return "" -} - -// AlertCreatedEvent is emitted when a brand-new alert is inserted into -// the in-memory alert store. -type AlertCreatedEvent struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The newly created alert. - Alert *Alert `protobuf:"bytes,1,opt,name=alert,proto3" json:"alert,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AlertCreatedEvent) Reset() { - *x = AlertCreatedEvent{} - mi := &file_eventrecorder_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AlertCreatedEvent) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AlertCreatedEvent) ProtoMessage() {} - -func (x *AlertCreatedEvent) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[9] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AlertCreatedEvent.ProtoReflect.Descriptor instead. -func (*AlertCreatedEvent) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{9} -} - -func (x *AlertCreatedEvent) GetAlert() *Alert { - if x != nil { - return x.Alert - } - return nil -} - -// AlertResolvedEvent is emitted when an alert is removed from its -// aggregation group after a successful notification that included the -// resolution. -type AlertResolvedEvent struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The resolved alert, including its hash and full details. - Alert *GroupedAlert `protobuf:"bytes,1,opt,name=alert,proto3" json:"alert,omitempty"` - // The aggregation group from which the alert was resolved. - GroupInfo *AlertGroupInfo `protobuf:"bytes,2,opt,name=group_info,json=groupInfo,proto3" json:"group_info,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AlertResolvedEvent) Reset() { - *x = AlertResolvedEvent{} - mi := &file_eventrecorder_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AlertResolvedEvent) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AlertResolvedEvent) ProtoMessage() {} - -func (x *AlertResolvedEvent) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[10] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AlertResolvedEvent.ProtoReflect.Descriptor instead. -func (*AlertResolvedEvent) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{10} -} - -func (x *AlertResolvedEvent) GetAlert() *GroupedAlert { - if x != nil { - return x.Alert - } - return nil -} - -func (x *AlertResolvedEvent) GetGroupInfo() *AlertGroupInfo { - if x != nil { - return x.GroupInfo - } - return nil -} - -// AlertGroupedEvent is emitted the first time an alert is inserted into -// an aggregation group. -type AlertGroupedEvent struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The alert being grouped, including its hash and full details. - Alert *GroupedAlert `protobuf:"bytes,1,opt,name=alert,proto3" json:"alert,omitempty"` - // The aggregation group the alert was added to. - GroupInfo *AlertGroupInfo `protobuf:"bytes,2,opt,name=group_info,json=groupInfo,proto3" json:"group_info,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AlertGroupedEvent) Reset() { - *x = AlertGroupedEvent{} - mi := &file_eventrecorder_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AlertGroupedEvent) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AlertGroupedEvent) ProtoMessage() {} - -func (x *AlertGroupedEvent) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[11] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use AlertGroupedEvent.ProtoReflect.Descriptor instead. -func (*AlertGroupedEvent) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{11} -} - -func (x *AlertGroupedEvent) GetAlert() *GroupedAlert { - if x != nil { - return x.Alert - } - return nil -} - -func (x *AlertGroupedEvent) GetGroupInfo() *AlertGroupInfo { - if x != nil { - return x.GroupInfo - } - return nil -} - -// Integration identifies a specific notification integration (e.g., -// the second PagerDuty receiver in a receiver definition). -type Integration struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The type of the integration (e.g., "webhook", "pagerduty"). - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - // The zero-based index of this integration within its receiver. - Index int64 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Integration) Reset() { - *x = Integration{} - mi := &file_eventrecorder_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Integration) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Integration) ProtoMessage() {} - -func (x *Integration) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[12] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Integration.ProtoReflect.Descriptor instead. -func (*Integration) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{12} -} - -func (x *Integration) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *Integration) GetIndex() int64 { - if x != nil { - return x.Index - } - return 0 -} - -// NotificationEvent is emitted after a notification is successfully -// delivered to an integration. -type NotificationEvent struct { - state protoimpl.MessageState `protogen:"open.v1"` - // All alerts that were included in the notification. - Alerts []*GroupedAlert `protobuf:"bytes,1,rep,name=alerts,proto3" json:"alerts,omitempty"` - // The subset of alerts that are currently firing. - FiringAlerts []*GroupedAlert `protobuf:"bytes,2,rep,name=firing_alerts,json=firingAlerts,proto3" json:"firing_alerts,omitempty"` - // The subset of alerts that are resolved. - ResolvedAlerts []*GroupedAlert `protobuf:"bytes,3,rep,name=resolved_alerts,json=resolvedAlerts,proto3" json:"resolved_alerts,omitempty"` - // Alerts that were muted (silenced or inhibited) during this flush - // cycle. - MutedAlerts []*GroupedAlert `protobuf:"bytes,4,rep,name=muted_alerts,json=mutedAlerts,proto3" json:"muted_alerts,omitempty"` - // The aggregation group context for this notification. - GroupInfo *AlertGroupInfo `protobuf:"bytes,5,opt,name=group_info,json=groupInfo,proto3" json:"group_info,omitempty"` - // The configured repeat interval for the aggregation group's route. - RepeatInterval *durationpb.Duration `protobuf:"bytes,6,opt,name=repeat_interval,json=repeatInterval,proto3" json:"repeat_interval,omitempty"` - // The reason the notification was triggered. - Reason NotifyReason `protobuf:"varint,7,opt,name=reason,proto3,enum=eventrecorderpb.NotifyReason" json:"reason,omitempty"` - // A monotonically increasing identifier for each flush cycle of the - // aggregation group. - FlushId uint64 `protobuf:"varint,8,opt,name=flush_id,json=flushId,proto3" json:"flush_id,omitempty"` - // The integration that delivered the notification. - Integration *Integration `protobuf:"bytes,9,opt,name=integration,proto3" json:"integration,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *NotificationEvent) Reset() { - *x = NotificationEvent{} - mi := &file_eventrecorder_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *NotificationEvent) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NotificationEvent) ProtoMessage() {} - -func (x *NotificationEvent) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[13] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use NotificationEvent.ProtoReflect.Descriptor instead. -func (*NotificationEvent) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{13} -} - -func (x *NotificationEvent) GetAlerts() []*GroupedAlert { - if x != nil { - return x.Alerts - } - return nil -} - -func (x *NotificationEvent) GetFiringAlerts() []*GroupedAlert { - if x != nil { - return x.FiringAlerts - } - return nil -} - -func (x *NotificationEvent) GetResolvedAlerts() []*GroupedAlert { - if x != nil { - return x.ResolvedAlerts - } - return nil -} - -func (x *NotificationEvent) GetMutedAlerts() []*GroupedAlert { - if x != nil { - return x.MutedAlerts - } - return nil -} - -func (x *NotificationEvent) GetGroupInfo() *AlertGroupInfo { - if x != nil { - return x.GroupInfo - } - return nil -} - -func (x *NotificationEvent) GetRepeatInterval() *durationpb.Duration { - if x != nil { - return x.RepeatInterval - } - return nil -} - -func (x *NotificationEvent) GetReason() NotifyReason { - if x != nil { - return x.Reason - } - return NotifyReason_NOTIFY_REASON_UNSPECIFIED -} - -func (x *NotificationEvent) GetFlushId() uint64 { - if x != nil { - return x.FlushId - } - return 0 -} - -func (x *NotificationEvent) GetIntegration() *Integration { - if x != nil { - return x.Integration - } - return nil -} - -// Silence is a snapshot of a silence definition at the time the event -// was recorded. -type Silence struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The globally unique silence identifier (UUID). - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - // The matchers that define which alerts this silence suppresses. - // For silences with multiple matcher sets, this is the first set. - Matchers []*Matcher `protobuf:"bytes,2,rep,name=matchers,proto3" json:"matchers,omitempty"` - // Optional structured annotations on the silence (key-value pairs). - Annotations *LabelSet `protobuf:"bytes,3,opt,name=annotations,proto3" json:"annotations,omitempty"` - // The time at which the silence becomes active. - StartsAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=starts_at,json=startsAt,proto3" json:"starts_at,omitempty"` - // The time at which the silence expires. - EndsAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=ends_at,json=endsAt,proto3" json:"ends_at,omitempty"` - // The last time the silence was created or updated. - UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` - // The author who created the silence. - CreatedBy string `protobuf:"bytes,7,opt,name=created_by,json=createdBy,proto3" json:"created_by,omitempty"` - // A human-readable comment explaining the silence. - Comment string `protobuf:"bytes,8,opt,name=comment,proto3" json:"comment,omitempty"` - // Additional matcher sets evaluated with OR logic. At least one - // matcher set must match for the silence to apply. - MatcherSets []*MatcherSet `protobuf:"bytes,9,rep,name=matcher_sets,json=matcherSets,proto3" json:"matcher_sets,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Silence) Reset() { - *x = Silence{} - mi := &file_eventrecorder_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Silence) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Silence) ProtoMessage() {} - -func (x *Silence) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[14] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Silence.ProtoReflect.Descriptor instead. -func (*Silence) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{14} -} - -func (x *Silence) GetId() string { - if x != nil { - return x.Id - } - return "" -} - -func (x *Silence) GetMatchers() []*Matcher { - if x != nil { - return x.Matchers - } - return nil -} - -func (x *Silence) GetAnnotations() *LabelSet { - if x != nil { - return x.Annotations - } - return nil -} - -func (x *Silence) GetStartsAt() *timestamppb.Timestamp { - if x != nil { - return x.StartsAt - } - return nil -} - -func (x *Silence) GetEndsAt() *timestamppb.Timestamp { - if x != nil { - return x.EndsAt - } - return nil -} - -func (x *Silence) GetUpdatedAt() *timestamppb.Timestamp { - if x != nil { - return x.UpdatedAt - } - return nil -} - -func (x *Silence) GetCreatedBy() string { - if x != nil { - return x.CreatedBy - } - return "" -} - -func (x *Silence) GetComment() string { - if x != nil { - return x.Comment - } - return "" -} - -func (x *Silence) GetMatcherSets() []*MatcherSet { - if x != nil { - return x.MatcherSets - } - return nil -} - -// Matcher defines a single label matching rule. -type Matcher struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The matching operator to apply. - Type Matcher_Type `protobuf:"varint,1,opt,name=type,proto3,enum=eventrecorderpb.Matcher_Type" json:"type,omitempty"` - // The label name to match against. - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - // The value or pattern to match, interpreted according to type. - Pattern string `protobuf:"bytes,3,opt,name=pattern,proto3" json:"pattern,omitempty"` - // Human-readable string representation (e.g., "env=~prod.*"). - Rendered string `protobuf:"bytes,4,opt,name=rendered,proto3" json:"rendered,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Matcher) Reset() { - *x = Matcher{} - mi := &file_eventrecorder_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Matcher) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Matcher) ProtoMessage() {} - -func (x *Matcher) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[15] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Matcher.ProtoReflect.Descriptor instead. -func (*Matcher) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{15} -} - -func (x *Matcher) GetType() Matcher_Type { - if x != nil { - return x.Type - } - return Matcher_TYPE_UNSPECIFIED -} - -func (x *Matcher) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *Matcher) GetPattern() string { - if x != nil { - return x.Pattern - } - return "" -} - -func (x *Matcher) GetRendered() string { - if x != nil { - return x.Rendered - } - return "" -} - -// MatcherSet is a conjunction of matchers: all matchers in the set must -// match for the set to match. -type MatcherSet struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The matchers that make up this set (evaluated with AND logic). - Matchers []*Matcher `protobuf:"bytes,1,rep,name=matchers,proto3" json:"matchers,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *MatcherSet) Reset() { - *x = MatcherSet{} - mi := &file_eventrecorder_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *MatcherSet) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MatcherSet) ProtoMessage() {} - -func (x *MatcherSet) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[16] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MatcherSet.ProtoReflect.Descriptor instead. -func (*MatcherSet) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{16} -} - -func (x *MatcherSet) GetMatchers() []*Matcher { - if x != nil { - return x.Matchers - } - return nil -} - -// SilenceCreatedEvent is emitted when a new silence is created. -type SilenceCreatedEvent struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The newly created silence. - Silence *Silence `protobuf:"bytes,1,opt,name=silence,proto3" json:"silence,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SilenceCreatedEvent) Reset() { - *x = SilenceCreatedEvent{} - mi := &file_eventrecorder_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SilenceCreatedEvent) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SilenceCreatedEvent) ProtoMessage() {} - -func (x *SilenceCreatedEvent) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[17] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SilenceCreatedEvent.ProtoReflect.Descriptor instead. -func (*SilenceCreatedEvent) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{17} -} - -func (x *SilenceCreatedEvent) GetSilence() *Silence { - if x != nil { - return x.Silence - } - return nil -} - -// SilenceUpdatedEvent is emitted when an existing silence is modified. -type SilenceUpdatedEvent struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The silence after the update. - Silence *Silence `protobuf:"bytes,1,opt,name=silence,proto3" json:"silence,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SilenceUpdatedEvent) Reset() { - *x = SilenceUpdatedEvent{} - mi := &file_eventrecorder_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SilenceUpdatedEvent) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SilenceUpdatedEvent) ProtoMessage() {} - -func (x *SilenceUpdatedEvent) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[18] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SilenceUpdatedEvent.ProtoReflect.Descriptor instead. -func (*SilenceUpdatedEvent) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{18} -} - -func (x *SilenceUpdatedEvent) GetSilence() *Silence { - if x != nil { - return x.Silence - } - return nil -} - -// MutedAlert identifies an alert that was suppressed by a silence or -// inhibition rule. -type MutedAlert struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The label set of the muted alert. - Labels *LabelSet `protobuf:"bytes,1,opt,name=labels,proto3" json:"labels,omitempty"` - // The fingerprint of the muted alert. - Fingerprint uint64 `protobuf:"varint,2,opt,name=fingerprint,proto3" json:"fingerprint,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *MutedAlert) Reset() { - *x = MutedAlert{} - mi := &file_eventrecorder_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *MutedAlert) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MutedAlert) ProtoMessage() {} - -func (x *MutedAlert) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[19] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use MutedAlert.ProtoReflect.Descriptor instead. -func (*MutedAlert) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{19} -} - -func (x *MutedAlert) GetLabels() *LabelSet { - if x != nil { - return x.Labels - } - return nil -} - -func (x *MutedAlert) GetFingerprint() uint64 { - if x != nil { - return x.Fingerprint - } - return 0 -} - -// SilenceMutedAlertEvent is emitted each time a silence suppresses an -// alert during the muting evaluation pass. -type SilenceMutedAlertEvent struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The silence that suppressed the alert. - Silence *Silence `protobuf:"bytes,1,opt,name=silence,proto3" json:"silence,omitempty"` - // The alert that was suppressed. - MutedAlert *MutedAlert `protobuf:"bytes,2,opt,name=muted_alert,json=mutedAlert,proto3" json:"muted_alert,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SilenceMutedAlertEvent) Reset() { - *x = SilenceMutedAlertEvent{} - mi := &file_eventrecorder_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SilenceMutedAlertEvent) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SilenceMutedAlertEvent) ProtoMessage() {} - -func (x *SilenceMutedAlertEvent) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[20] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SilenceMutedAlertEvent.ProtoReflect.Descriptor instead. -func (*SilenceMutedAlertEvent) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{20} -} - -func (x *SilenceMutedAlertEvent) GetSilence() *Silence { - if x != nil { - return x.Silence - } - return nil -} - -func (x *SilenceMutedAlertEvent) GetMutedAlert() *MutedAlert { - if x != nil { - return x.MutedAlert - } - return nil -} - -// InhibitRule is a snapshot of an inhibition rule definition. -type InhibitRule struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Matchers that identify source alerts (those that do the inhibiting). - SourceMatchers []*Matcher `protobuf:"bytes,1,rep,name=source_matchers,json=sourceMatchers,proto3" json:"source_matchers,omitempty"` - // Matchers that identify target alerts (those that get inhibited). - TargetMatchers []*Matcher `protobuf:"bytes,2,rep,name=target_matchers,json=targetMatchers,proto3" json:"target_matchers,omitempty"` - // Label names whose values must be equal between source and target - // alerts for the inhibition to take effect. - EqualLabels []string `protobuf:"bytes,3,rep,name=equal_labels,json=equalLabels,proto3" json:"equal_labels,omitempty"` - // Name is the optional name of the inhibition rule. - Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *InhibitRule) Reset() { - *x = InhibitRule{} - mi := &file_eventrecorder_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *InhibitRule) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InhibitRule) ProtoMessage() {} - -func (x *InhibitRule) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[21] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use InhibitRule.ProtoReflect.Descriptor instead. -func (*InhibitRule) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{21} -} - -func (x *InhibitRule) GetSourceMatchers() []*Matcher { - if x != nil { - return x.SourceMatchers - } - return nil -} - -func (x *InhibitRule) GetTargetMatchers() []*Matcher { - if x != nil { - return x.TargetMatchers - } - return nil -} - -func (x *InhibitRule) GetEqualLabels() []string { - if x != nil { - return x.EqualLabels - } - return nil -} - -func (x *InhibitRule) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -// InhibitionMutedAlertEvent is emitted when one or more inhibition -// rules suppress an alert. -type InhibitionMutedAlertEvent struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The inhibition rules that matched. - InhibitRules []*InhibitRule `protobuf:"bytes,1,rep,name=inhibit_rules,json=inhibitRules,proto3" json:"inhibit_rules,omitempty"` - // The alert that was suppressed. - MutedAlert *MutedAlert `protobuf:"bytes,2,opt,name=muted_alert,json=mutedAlert,proto3" json:"muted_alert,omitempty"` - // The fingerprints of the source alerts that caused the inhibition. - InhibitingFingerprints []uint64 `protobuf:"varint,3,rep,packed,name=inhibiting_fingerprints,json=inhibitingFingerprints,proto3" json:"inhibiting_fingerprints,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *InhibitionMutedAlertEvent) Reset() { - *x = InhibitionMutedAlertEvent{} - mi := &file_eventrecorder_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *InhibitionMutedAlertEvent) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*InhibitionMutedAlertEvent) ProtoMessage() {} - -func (x *InhibitionMutedAlertEvent) ProtoReflect() protoreflect.Message { - mi := &file_eventrecorder_proto_msgTypes[22] - if x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use InhibitionMutedAlertEvent.ProtoReflect.Descriptor instead. -func (*InhibitionMutedAlertEvent) Descriptor() ([]byte, []int) { - return file_eventrecorder_proto_rawDescGZIP(), []int{22} -} - -func (x *InhibitionMutedAlertEvent) GetInhibitRules() []*InhibitRule { - if x != nil { - return x.InhibitRules - } - return nil -} - -func (x *InhibitionMutedAlertEvent) GetMutedAlert() *MutedAlert { - if x != nil { - return x.MutedAlert - } - return nil -} - -func (x *InhibitionMutedAlertEvent) GetInhibitingFingerprints() []uint64 { - if x != nil { - return x.InhibitingFingerprints - } - return nil -} - -var File_eventrecorder_proto protoreflect.FileDescriptor - -const file_eventrecorder_proto_rawDesc = "" + - "\n" + - "\x13eventrecorder.proto\x12\x0feventrecorderpb\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xb9\x01\n" + - "\x05Event\x129\n" + - "\ttimestamp\x18\x01 \x01(\v2\x1a.google.protobuf.TimestampR\n" + - "@timestamp\x12\x1a\n" + - "\binstance\x18\x02 \x01(\tR\binstance\x12.\n" + - "\x04data\x18\x03 \x01(\v2\x1a.eventrecorderpb.EventDataR\x04data\x12)\n" + - "\x10cluster_position\x18\x04 \x01(\rR\x0fclusterPosition\"\x81\a\n" + - "\tEventData\x12i\n" + - "\x1aalertmanager_startup_event\x18\x01 \x01(\v2).eventrecorderpb.AlertmanagerStartupEventH\x00R\x18alertmanagerStartupEvent\x12l\n" + - "\x1balertmanager_shutdown_event\x18\x02 \x01(\v2*.eventrecorderpb.AlertmanagerShutdownEventH\x00R\x19alertmanagerShutdownEvent\x12I\n" + - "\ralert_created\x18\x03 \x01(\v2\".eventrecorderpb.AlertCreatedEventH\x00R\falertCreated\x12L\n" + - "\x0ealert_resolved\x18\x04 \x01(\v2#.eventrecorderpb.AlertResolvedEventH\x00R\ralertResolved\x12I\n" + - "\ralert_grouped\x18\x05 \x01(\v2\".eventrecorderpb.AlertGroupedEventH\x00R\falertGrouped\x12H\n" + - "\fnotification\x18\x06 \x01(\v2\".eventrecorderpb.NotificationEventH\x00R\fnotification\x12O\n" + - "\x0fsilence_created\x18\a \x01(\v2$.eventrecorderpb.SilenceCreatedEventH\x00R\x0esilenceCreated\x12O\n" + - "\x0fsilence_updated\x18\b \x01(\v2$.eventrecorderpb.SilenceUpdatedEventH\x00R\x0esilenceUpdated\x12Y\n" + - "\x13silence_muted_alert\x18\t \x01(\v2'.eventrecorderpb.SilenceMutedAlertEventH\x00R\x11silenceMutedAlert\x12b\n" + - "\x16inhibition_muted_alert\x18\n" + - " \x01(\v2*.eventrecorderpb.InhibitionMutedAlertEventH\x00R\x14inhibitionMutedAlertB\f\n" + - "\n" + - "event_type\"Y\n" + - "\x18AlertmanagerStartupEvent\x12\x18\n" + - "\aversion\x18\x01 \x01(\tR\aversion\x12#\n" + - "\rbuild_context\x18\x02 \x01(\tR\fbuildContext\"\x1b\n" + - "\x19AlertmanagerShutdownEvent\"3\n" + - "\tLabelPair\x12\x10\n" + - "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + - "\x05value\x18\x02 \x01(\tR\x05value\">\n" + - "\bLabelSet\x122\n" + - "\x06labels\x18\x01 \x03(\v2\x1a.eventrecorderpb.LabelPairR\x06labels\"\xb7\x02\n" + - "\x05Alert\x12 \n" + - "\vfingerprint\x18\x01 \x01(\x04R\vfingerprint\x12\x12\n" + - "\x04name\x18\x02 \x01(\tR\x04name\x121\n" + - "\x06labels\x18\x03 \x01(\v2\x19.eventrecorderpb.LabelSetR\x06labels\x12;\n" + - "\vannotations\x18\x04 \x01(\v2\x19.eventrecorderpb.LabelSetR\vannotations\x127\n" + - "\tstarts_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\bstartsAt\x123\n" + - "\aends_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\x06endsAt\x12\x1a\n" + - "\bresolved\x18\a \x01(\bR\bresolved\"e\n" + - "\fGroupedAlert\x12\x12\n" + - "\x04hash\x18\x01 \x01(\x04R\x04hash\x125\n" + - "\adetails\x18\x02 \x01(\v2\x16.eventrecorderpb.AlertH\x00R\adetails\x88\x01\x01B\n" + - "\n" + - "\b_details\"\x80\x02\n" + - "\x0eAlertGroupInfo\x12\x1b\n" + - "\tgroup_key\x18\x01 \x01(\tR\bgroupKey\x12<\n" + - "\fgroup_labels\x18\x02 \x01(\v2\x19.eventrecorderpb.LabelSetR\vgroupLabels\x12\x19\n" + - "\bgroup_id\x18\x03 \x01(\tR\agroupId\x12#\n" + - "\rreceiver_name\x18\x04 \x01(\tR\freceiverName\x124\n" + - "\bmatchers\x18\x05 \x03(\v2\x18.eventrecorderpb.MatcherR\bmatchers\x12\x1d\n" + - "\n" + - "group_uuid\x18\x06 \x01(\tR\tgroupUuid\"A\n" + - "\x11AlertCreatedEvent\x12,\n" + - "\x05alert\x18\x01 \x01(\v2\x16.eventrecorderpb.AlertR\x05alert\"\x89\x01\n" + - "\x12AlertResolvedEvent\x123\n" + - "\x05alert\x18\x01 \x01(\v2\x1d.eventrecorderpb.GroupedAlertR\x05alert\x12>\n" + - "\n" + - "group_info\x18\x02 \x01(\v2\x1f.eventrecorderpb.AlertGroupInfoR\tgroupInfo\"\x88\x01\n" + - "\x11AlertGroupedEvent\x123\n" + - "\x05alert\x18\x01 \x01(\v2\x1d.eventrecorderpb.GroupedAlertR\x05alert\x12>\n" + - "\n" + - "group_info\x18\x02 \x01(\v2\x1f.eventrecorderpb.AlertGroupInfoR\tgroupInfo\"7\n" + - "\vIntegration\x12\x12\n" + - "\x04name\x18\x01 \x01(\tR\x04name\x12\x14\n" + - "\x05index\x18\x02 \x01(\x03R\x05index\"\xae\x04\n" + - "\x11NotificationEvent\x125\n" + - "\x06alerts\x18\x01 \x03(\v2\x1d.eventrecorderpb.GroupedAlertR\x06alerts\x12B\n" + - "\rfiring_alerts\x18\x02 \x03(\v2\x1d.eventrecorderpb.GroupedAlertR\ffiringAlerts\x12F\n" + - "\x0fresolved_alerts\x18\x03 \x03(\v2\x1d.eventrecorderpb.GroupedAlertR\x0eresolvedAlerts\x12@\n" + - "\fmuted_alerts\x18\x04 \x03(\v2\x1d.eventrecorderpb.GroupedAlertR\vmutedAlerts\x12>\n" + - "\n" + - "group_info\x18\x05 \x01(\v2\x1f.eventrecorderpb.AlertGroupInfoR\tgroupInfo\x12B\n" + - "\x0frepeat_interval\x18\x06 \x01(\v2\x19.google.protobuf.DurationR\x0erepeatInterval\x125\n" + - "\x06reason\x18\a \x01(\x0e2\x1d.eventrecorderpb.NotifyReasonR\x06reason\x12\x19\n" + - "\bflush_id\x18\b \x01(\x04R\aflushId\x12>\n" + - "\vintegration\x18\t \x01(\v2\x1c.eventrecorderpb.IntegrationR\vintegration\"\xae\x03\n" + - "\aSilence\x12\x0e\n" + - "\x02id\x18\x01 \x01(\tR\x02id\x124\n" + - "\bmatchers\x18\x02 \x03(\v2\x18.eventrecorderpb.MatcherR\bmatchers\x12;\n" + - "\vannotations\x18\x03 \x01(\v2\x19.eventrecorderpb.LabelSetR\vannotations\x127\n" + - "\tstarts_at\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\bstartsAt\x123\n" + - "\aends_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\x06endsAt\x129\n" + - "\n" + - "updated_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAt\x12\x1d\n" + - "\n" + - "created_by\x18\a \x01(\tR\tcreatedBy\x12\x18\n" + - "\acomment\x18\b \x01(\tR\acomment\x12>\n" + - "\fmatcher_sets\x18\t \x03(\v2\x1b.eventrecorderpb.MatcherSetR\vmatcherSets\"\xee\x01\n" + - "\aMatcher\x121\n" + - "\x04type\x18\x01 \x01(\x0e2\x1d.eventrecorderpb.Matcher.TypeR\x04type\x12\x12\n" + - "\x04name\x18\x02 \x01(\tR\x04name\x12\x18\n" + - "\apattern\x18\x03 \x01(\tR\apattern\x12\x1a\n" + - "\brendered\x18\x04 \x01(\tR\brendered\"f\n" + - "\x04Type\x12\x14\n" + - "\x10TYPE_UNSPECIFIED\x10\x00\x12\x0e\n" + - "\n" + - "TYPE_EQUAL\x10\x01\x12\x0f\n" + - "\vTYPE_REGEXP\x10\x02\x12\x12\n" + - "\x0eTYPE_NOT_EQUAL\x10\x03\x12\x13\n" + - "\x0fTYPE_NOT_REGEXP\x10\x04\"B\n" + - "\n" + - "MatcherSet\x124\n" + - "\bmatchers\x18\x01 \x03(\v2\x18.eventrecorderpb.MatcherR\bmatchers\"I\n" + - "\x13SilenceCreatedEvent\x122\n" + - "\asilence\x18\x01 \x01(\v2\x18.eventrecorderpb.SilenceR\asilence\"I\n" + - "\x13SilenceUpdatedEvent\x122\n" + - "\asilence\x18\x01 \x01(\v2\x18.eventrecorderpb.SilenceR\asilence\"a\n" + - "\n" + - "MutedAlert\x121\n" + - "\x06labels\x18\x01 \x01(\v2\x19.eventrecorderpb.LabelSetR\x06labels\x12 \n" + - "\vfingerprint\x18\x02 \x01(\x04R\vfingerprint\"\x8a\x01\n" + - "\x16SilenceMutedAlertEvent\x122\n" + - "\asilence\x18\x01 \x01(\v2\x18.eventrecorderpb.SilenceR\asilence\x12<\n" + - "\vmuted_alert\x18\x02 \x01(\v2\x1b.eventrecorderpb.MutedAlertR\n" + - "mutedAlert\"\xca\x01\n" + - "\vInhibitRule\x12A\n" + - "\x0fsource_matchers\x18\x01 \x03(\v2\x18.eventrecorderpb.MatcherR\x0esourceMatchers\x12A\n" + - "\x0ftarget_matchers\x18\x02 \x03(\v2\x18.eventrecorderpb.MatcherR\x0etargetMatchers\x12!\n" + - "\fequal_labels\x18\x03 \x03(\tR\vequalLabels\x12\x12\n" + - "\x04name\x18\x04 \x01(\tR\x04name\"\xd5\x01\n" + - "\x19InhibitionMutedAlertEvent\x12A\n" + - "\rinhibit_rules\x18\x01 \x03(\v2\x1c.eventrecorderpb.InhibitRuleR\finhibitRules\x12<\n" + - "\vmuted_alert\x18\x02 \x01(\v2\x1b.eventrecorderpb.MutedAlertR\n" + - "mutedAlert\x127\n" + - "\x17inhibiting_fingerprints\x18\x03 \x03(\x04R\x16inhibitingFingerprints*\xf3\x01\n" + - "\fNotifyReason\x12\x1d\n" + - "\x19NOTIFY_REASON_UNSPECIFIED\x10\x00\x12$\n" + - " NOTIFY_REASON_FIRST_NOTIFICATION\x10\x01\x12%\n" + - "!NOTIFY_REASON_NEW_ALERTS_IN_GROUP\x10\x02\x12%\n" + - "!NOTIFY_REASON_NEW_RESOLVED_ALERTS\x10\x03\x12%\n" + - "!NOTIFY_REASON_ALL_ALERTS_RESOLVED\x10\x04\x12)\n" + - "%NOTIFY_REASON_REPEAT_INTERVAL_ELAPSED\x10\x05BBZ@github.com/prometheus/alertmanager/eventrecorder/eventrecorderpbb\x06proto3" - -var ( - file_eventrecorder_proto_rawDescOnce sync.Once - file_eventrecorder_proto_rawDescData []byte -) - -func file_eventrecorder_proto_rawDescGZIP() []byte { - file_eventrecorder_proto_rawDescOnce.Do(func() { - file_eventrecorder_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_eventrecorder_proto_rawDesc), len(file_eventrecorder_proto_rawDesc))) - }) - return file_eventrecorder_proto_rawDescData -} - -var file_eventrecorder_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_eventrecorder_proto_msgTypes = make([]protoimpl.MessageInfo, 23) -var file_eventrecorder_proto_goTypes = []any{ - (NotifyReason)(0), // 0: eventrecorderpb.NotifyReason - (Matcher_Type)(0), // 1: eventrecorderpb.Matcher.Type - (*Event)(nil), // 2: eventrecorderpb.Event - (*EventData)(nil), // 3: eventrecorderpb.EventData - (*AlertmanagerStartupEvent)(nil), // 4: eventrecorderpb.AlertmanagerStartupEvent - (*AlertmanagerShutdownEvent)(nil), // 5: eventrecorderpb.AlertmanagerShutdownEvent - (*LabelPair)(nil), // 6: eventrecorderpb.LabelPair - (*LabelSet)(nil), // 7: eventrecorderpb.LabelSet - (*Alert)(nil), // 8: eventrecorderpb.Alert - (*GroupedAlert)(nil), // 9: eventrecorderpb.GroupedAlert - (*AlertGroupInfo)(nil), // 10: eventrecorderpb.AlertGroupInfo - (*AlertCreatedEvent)(nil), // 11: eventrecorderpb.AlertCreatedEvent - (*AlertResolvedEvent)(nil), // 12: eventrecorderpb.AlertResolvedEvent - (*AlertGroupedEvent)(nil), // 13: eventrecorderpb.AlertGroupedEvent - (*Integration)(nil), // 14: eventrecorderpb.Integration - (*NotificationEvent)(nil), // 15: eventrecorderpb.NotificationEvent - (*Silence)(nil), // 16: eventrecorderpb.Silence - (*Matcher)(nil), // 17: eventrecorderpb.Matcher - (*MatcherSet)(nil), // 18: eventrecorderpb.MatcherSet - (*SilenceCreatedEvent)(nil), // 19: eventrecorderpb.SilenceCreatedEvent - (*SilenceUpdatedEvent)(nil), // 20: eventrecorderpb.SilenceUpdatedEvent - (*MutedAlert)(nil), // 21: eventrecorderpb.MutedAlert - (*SilenceMutedAlertEvent)(nil), // 22: eventrecorderpb.SilenceMutedAlertEvent - (*InhibitRule)(nil), // 23: eventrecorderpb.InhibitRule - (*InhibitionMutedAlertEvent)(nil), // 24: eventrecorderpb.InhibitionMutedAlertEvent - (*timestamppb.Timestamp)(nil), // 25: google.protobuf.Timestamp - (*durationpb.Duration)(nil), // 26: google.protobuf.Duration -} -var file_eventrecorder_proto_depIdxs = []int32{ - 25, // 0: eventrecorderpb.Event.timestamp:type_name -> google.protobuf.Timestamp - 3, // 1: eventrecorderpb.Event.data:type_name -> eventrecorderpb.EventData - 4, // 2: eventrecorderpb.EventData.alertmanager_startup_event:type_name -> eventrecorderpb.AlertmanagerStartupEvent - 5, // 3: eventrecorderpb.EventData.alertmanager_shutdown_event:type_name -> eventrecorderpb.AlertmanagerShutdownEvent - 11, // 4: eventrecorderpb.EventData.alert_created:type_name -> eventrecorderpb.AlertCreatedEvent - 12, // 5: eventrecorderpb.EventData.alert_resolved:type_name -> eventrecorderpb.AlertResolvedEvent - 13, // 6: eventrecorderpb.EventData.alert_grouped:type_name -> eventrecorderpb.AlertGroupedEvent - 15, // 7: eventrecorderpb.EventData.notification:type_name -> eventrecorderpb.NotificationEvent - 19, // 8: eventrecorderpb.EventData.silence_created:type_name -> eventrecorderpb.SilenceCreatedEvent - 20, // 9: eventrecorderpb.EventData.silence_updated:type_name -> eventrecorderpb.SilenceUpdatedEvent - 22, // 10: eventrecorderpb.EventData.silence_muted_alert:type_name -> eventrecorderpb.SilenceMutedAlertEvent - 24, // 11: eventrecorderpb.EventData.inhibition_muted_alert:type_name -> eventrecorderpb.InhibitionMutedAlertEvent - 6, // 12: eventrecorderpb.LabelSet.labels:type_name -> eventrecorderpb.LabelPair - 7, // 13: eventrecorderpb.Alert.labels:type_name -> eventrecorderpb.LabelSet - 7, // 14: eventrecorderpb.Alert.annotations:type_name -> eventrecorderpb.LabelSet - 25, // 15: eventrecorderpb.Alert.starts_at:type_name -> google.protobuf.Timestamp - 25, // 16: eventrecorderpb.Alert.ends_at:type_name -> google.protobuf.Timestamp - 8, // 17: eventrecorderpb.GroupedAlert.details:type_name -> eventrecorderpb.Alert - 7, // 18: eventrecorderpb.AlertGroupInfo.group_labels:type_name -> eventrecorderpb.LabelSet - 17, // 19: eventrecorderpb.AlertGroupInfo.matchers:type_name -> eventrecorderpb.Matcher - 8, // 20: eventrecorderpb.AlertCreatedEvent.alert:type_name -> eventrecorderpb.Alert - 9, // 21: eventrecorderpb.AlertResolvedEvent.alert:type_name -> eventrecorderpb.GroupedAlert - 10, // 22: eventrecorderpb.AlertResolvedEvent.group_info:type_name -> eventrecorderpb.AlertGroupInfo - 9, // 23: eventrecorderpb.AlertGroupedEvent.alert:type_name -> eventrecorderpb.GroupedAlert - 10, // 24: eventrecorderpb.AlertGroupedEvent.group_info:type_name -> eventrecorderpb.AlertGroupInfo - 9, // 25: eventrecorderpb.NotificationEvent.alerts:type_name -> eventrecorderpb.GroupedAlert - 9, // 26: eventrecorderpb.NotificationEvent.firing_alerts:type_name -> eventrecorderpb.GroupedAlert - 9, // 27: eventrecorderpb.NotificationEvent.resolved_alerts:type_name -> eventrecorderpb.GroupedAlert - 9, // 28: eventrecorderpb.NotificationEvent.muted_alerts:type_name -> eventrecorderpb.GroupedAlert - 10, // 29: eventrecorderpb.NotificationEvent.group_info:type_name -> eventrecorderpb.AlertGroupInfo - 26, // 30: eventrecorderpb.NotificationEvent.repeat_interval:type_name -> google.protobuf.Duration - 0, // 31: eventrecorderpb.NotificationEvent.reason:type_name -> eventrecorderpb.NotifyReason - 14, // 32: eventrecorderpb.NotificationEvent.integration:type_name -> eventrecorderpb.Integration - 17, // 33: eventrecorderpb.Silence.matchers:type_name -> eventrecorderpb.Matcher - 7, // 34: eventrecorderpb.Silence.annotations:type_name -> eventrecorderpb.LabelSet - 25, // 35: eventrecorderpb.Silence.starts_at:type_name -> google.protobuf.Timestamp - 25, // 36: eventrecorderpb.Silence.ends_at:type_name -> google.protobuf.Timestamp - 25, // 37: eventrecorderpb.Silence.updated_at:type_name -> google.protobuf.Timestamp - 18, // 38: eventrecorderpb.Silence.matcher_sets:type_name -> eventrecorderpb.MatcherSet - 1, // 39: eventrecorderpb.Matcher.type:type_name -> eventrecorderpb.Matcher.Type - 17, // 40: eventrecorderpb.MatcherSet.matchers:type_name -> eventrecorderpb.Matcher - 16, // 41: eventrecorderpb.SilenceCreatedEvent.silence:type_name -> eventrecorderpb.Silence - 16, // 42: eventrecorderpb.SilenceUpdatedEvent.silence:type_name -> eventrecorderpb.Silence - 7, // 43: eventrecorderpb.MutedAlert.labels:type_name -> eventrecorderpb.LabelSet - 16, // 44: eventrecorderpb.SilenceMutedAlertEvent.silence:type_name -> eventrecorderpb.Silence - 21, // 45: eventrecorderpb.SilenceMutedAlertEvent.muted_alert:type_name -> eventrecorderpb.MutedAlert - 17, // 46: eventrecorderpb.InhibitRule.source_matchers:type_name -> eventrecorderpb.Matcher - 17, // 47: eventrecorderpb.InhibitRule.target_matchers:type_name -> eventrecorderpb.Matcher - 23, // 48: eventrecorderpb.InhibitionMutedAlertEvent.inhibit_rules:type_name -> eventrecorderpb.InhibitRule - 21, // 49: eventrecorderpb.InhibitionMutedAlertEvent.muted_alert:type_name -> eventrecorderpb.MutedAlert - 50, // [50:50] is the sub-list for method output_type - 50, // [50:50] is the sub-list for method input_type - 50, // [50:50] is the sub-list for extension type_name - 50, // [50:50] is the sub-list for extension extendee - 0, // [0:50] is the sub-list for field type_name -} - -func init() { file_eventrecorder_proto_init() } -func file_eventrecorder_proto_init() { - if File_eventrecorder_proto != nil { - return - } - file_eventrecorder_proto_msgTypes[1].OneofWrappers = []any{ - (*EventData_AlertmanagerStartupEvent)(nil), - (*EventData_AlertmanagerShutdownEvent)(nil), - (*EventData_AlertCreated)(nil), - (*EventData_AlertResolved)(nil), - (*EventData_AlertGrouped)(nil), - (*EventData_Notification)(nil), - (*EventData_SilenceCreated)(nil), - (*EventData_SilenceUpdated)(nil), - (*EventData_SilenceMutedAlert)(nil), - (*EventData_InhibitionMutedAlert)(nil), - } - file_eventrecorder_proto_msgTypes[7].OneofWrappers = []any{} - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_eventrecorder_proto_rawDesc), len(file_eventrecorder_proto_rawDesc)), - NumEnums: 2, - NumMessages: 23, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_eventrecorder_proto_goTypes, - DependencyIndexes: file_eventrecorder_proto_depIdxs, - EnumInfos: file_eventrecorder_proto_enumTypes, - MessageInfos: file_eventrecorder_proto_msgTypes, - }.Build() - File_eventrecorder_proto = out.File - file_eventrecorder_proto_goTypes = nil - file_eventrecorder_proto_depIdxs = nil -} diff --git a/eventrecorder/eventrecorderpb/eventrecorder.proto b/eventrecorder/eventrecorderpb/eventrecorder.proto deleted file mode 100644 index 3de19298cd..0000000000 --- a/eventrecorder/eventrecorderpb/eventrecorder.proto +++ /dev/null @@ -1,392 +0,0 @@ -syntax = "proto3"; - -package eventrecorderpb; - -import "google/protobuf/duration.proto"; -import "google/protobuf/timestamp.proto"; - -option go_package = "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb"; - -// Event is the top-level envelope written to each event recorder output. -// It wraps the specific event data with metadata about when and where -// the event was produced. -message Event { - // The wall-clock time at which the event was recorded. - google.protobuf.Timestamp timestamp = 1 [json_name = "@timestamp"]; - - // The hostname or address of the Alertmanager instance that produced - // the event. - string instance = 2; - - // The event payload. Exactly one of the oneof fields inside EventData - // will be set. - EventData data = 3; - - // The ordinal position of this instance among its HA cluster peers. - // Zero when clustering is disabled. - uint32 cluster_position = 4; -} - -// EventData carries the payload for a single event recorder entry. -// Exactly one of the oneof fields will be populated. -message EventData { - oneof event_type { - // Recorded when the Alertmanager process starts. - AlertmanagerStartupEvent alertmanager_startup_event = 1; - - // Recorded when the Alertmanager process shuts down gracefully. - AlertmanagerShutdownEvent alertmanager_shutdown_event = 2; - - // Recorded when a new alert is first inserted into the alert store. - AlertCreatedEvent alert_created = 3; - - // Recorded when an alert transitions to the resolved state and is - // removed from its aggregation group after successful notification. - AlertResolvedEvent alert_resolved = 4; - - // Recorded when an alert is inserted into an aggregation group for - // the first time. - AlertGroupedEvent alert_grouped = 5; - - // Recorded after a notification is successfully delivered to an - // integration (e.g., webhook, email, PagerDuty). - NotificationEvent notification = 6; - - // Recorded when a new silence is created. - SilenceCreatedEvent silence_created = 7; - - // Recorded when an existing silence is updated (e.g., extended or - // re-commented). - SilenceUpdatedEvent silence_updated = 8; - - // Recorded each time a silence actively suppresses an alert during - // the muting evaluation pass. - SilenceMutedAlertEvent silence_muted_alert = 9; - - // Recorded each time one or more inhibition rules suppress an alert - // during the muting evaluation pass. - InhibitionMutedAlertEvent inhibition_muted_alert = 10; - } -} - -// AlertmanagerStartupEvent is emitted once when the process starts. -message AlertmanagerStartupEvent { - // The semantic version of the Alertmanager binary (e.g., "0.28.0"). - string version = 1; - - // Free-form build metadata such as Go version, branch, and revision. - string build_context = 2; -} - -// AlertmanagerShutdownEvent is emitted when the process shuts down -// gracefully. It carries no additional data. -message AlertmanagerShutdownEvent {} - -// LabelPair is a single key-value label. -message LabelPair { - // The label name (e.g., "alertname"). - string key = 1; - - // The label value (e.g., "HighMemoryUsage"). - string value = 2; -} - -// LabelSet is an ordered collection of label pairs. -message LabelSet { - // The label pairs that make up this set. - repeated LabelPair labels = 1; -} - -// Alert represents a snapshot of an alert at the time the event was -// recorded. -message Alert { - // The unique fingerprint derived from the alert's label set. - uint64 fingerprint = 1; - - // The value of the "alertname" label, provided for convenience. - string name = 2; - - // The full label set that identifies this alert. - LabelSet labels = 3; - - // Informational annotations attached to the alert (e.g., summary, - // description). - LabelSet annotations = 4; - - // The time at which the alert started firing. - google.protobuf.Timestamp starts_at = 5; - - // The time at which the alert is considered resolved. For firing - // alerts this is typically set to a time in the future. - google.protobuf.Timestamp ends_at = 6; - - // Whether the alert was resolved at the time the event was recorded. - bool resolved = 7; -} - -// GroupedAlert is a reference to an alert within an aggregation group. -// It always carries the content hash; the full alert details are -// included when available. -message GroupedAlert { - // A hash of the alert's label set, used for deduplication within the - // notification pipeline. - uint64 hash = 1; - - // The full alert details. May be absent when only the hash is needed - // (e.g., in firing/resolved lists on NotificationEvent). - optional Alert details = 2; -} - -// AlertGroupInfo describes the aggregation group context in which an -// alert is being processed. -message AlertGroupInfo { - // The composite key that uniquely identifies this aggregation group - // (encodes route and group label values). - string group_key = 1; - - // The label set used to group alerts together within this route. - LabelSet group_labels = 2; - - // A stable, shortened identifier derived from the group key (SHA-256 - // hex). - string group_id = 3; - - // The name of the receiver that this group routes to. - string receiver_name = 4; - - // The set of matchers defined on the route that matched these alerts. - repeated Matcher matchers = 5; - - // A UUID that uniquely identifies this aggregation group instance. - string group_uuid = 6; -} - -// AlertCreatedEvent is emitted when a brand-new alert is inserted into -// the in-memory alert store. -message AlertCreatedEvent { - // The newly created alert. - Alert alert = 1; -} - -// AlertResolvedEvent is emitted when an alert is removed from its -// aggregation group after a successful notification that included the -// resolution. -message AlertResolvedEvent { - // The resolved alert, including its hash and full details. - GroupedAlert alert = 1; - - // The aggregation group from which the alert was resolved. - AlertGroupInfo group_info = 2; -} - -// AlertGroupedEvent is emitted the first time an alert is inserted into -// an aggregation group. -message AlertGroupedEvent { - // The alert being grouped, including its hash and full details. - GroupedAlert alert = 1; - - // The aggregation group the alert was added to. - AlertGroupInfo group_info = 2; -} - -// NotifyReason describes why a notification was sent for an aggregation -// group. -enum NotifyReason { - // Default / unknown reason. - NOTIFY_REASON_UNSPECIFIED = 0; - - // The group has never been notified before and contains at least one - // firing alert. - NOTIFY_REASON_FIRST_NOTIFICATION = 1; - - // New firing alerts have been added to the group since the last - // notification. - NOTIFY_REASON_NEW_ALERTS_IN_GROUP = 2; - - // Some alerts in the group have resolved since the last notification. - NOTIFY_REASON_NEW_RESOLVED_ALERTS = 3; - - // All alerts in the group have resolved. - NOTIFY_REASON_ALL_ALERTS_RESOLVED = 4; - - // The configured repeat interval has elapsed since the last - // notification. - NOTIFY_REASON_REPEAT_INTERVAL_ELAPSED = 5; -} - -// Integration identifies a specific notification integration (e.g., -// the second PagerDuty receiver in a receiver definition). -message Integration { - // The type of the integration (e.g., "webhook", "pagerduty"). - string name = 1; - - // The zero-based index of this integration within its receiver. - int64 index = 2; -} - -// NotificationEvent is emitted after a notification is successfully -// delivered to an integration. -message NotificationEvent { - // All alerts that were included in the notification. - repeated GroupedAlert alerts = 1; - - // The subset of alerts that are currently firing. - repeated GroupedAlert firing_alerts = 2; - - // The subset of alerts that are resolved. - repeated GroupedAlert resolved_alerts = 3; - - // Alerts that were muted (silenced or inhibited) during this flush - // cycle. - repeated GroupedAlert muted_alerts = 4; - - // The aggregation group context for this notification. - AlertGroupInfo group_info = 5; - - // The configured repeat interval for the aggregation group's route. - google.protobuf.Duration repeat_interval = 6; - - // The reason the notification was triggered. - NotifyReason reason = 7; - - // A monotonically increasing identifier for each flush cycle of the - // aggregation group. - uint64 flush_id = 8; - - // The integration that delivered the notification. - Integration integration = 9; -} - -// Silence is a snapshot of a silence definition at the time the event -// was recorded. -message Silence { - // The globally unique silence identifier (UUID). - string id = 1; - - // The matchers that define which alerts this silence suppresses. - // For silences with multiple matcher sets, this is the first set. - repeated Matcher matchers = 2; - - // Optional structured annotations on the silence (key-value pairs). - LabelSet annotations = 3; - - // The time at which the silence becomes active. - google.protobuf.Timestamp starts_at = 4; - - // The time at which the silence expires. - google.protobuf.Timestamp ends_at = 5; - - // The last time the silence was created or updated. - google.protobuf.Timestamp updated_at = 6; - - // The author who created the silence. - string created_by = 7; - - // A human-readable comment explaining the silence. - string comment = 8; - - // Additional matcher sets evaluated with OR logic. At least one - // matcher set must match for the silence to apply. - repeated MatcherSet matcher_sets = 9; -} - -// Matcher defines a single label matching rule. -message Matcher { - // Type enumerates the supported matching operators. - enum Type { - // Unspecified / unknown match type. - TYPE_UNSPECIFIED = 0; - - // Exact string equality (=). - TYPE_EQUAL = 1; - - // Regular expression match (=~). - TYPE_REGEXP = 2; - - // Negated exact string equality (!=). - TYPE_NOT_EQUAL = 3; - - // Negated regular expression match (!~). - TYPE_NOT_REGEXP = 4; - } - - // The matching operator to apply. - Type type = 1; - - // The label name to match against. - string name = 2; - - // The value or pattern to match, interpreted according to type. - string pattern = 3; - - // Human-readable string representation (e.g., "env=~prod.*"). - string rendered = 4; -} - -// MatcherSet is a conjunction of matchers: all matchers in the set must -// match for the set to match. -message MatcherSet { - // The matchers that make up this set (evaluated with AND logic). - repeated Matcher matchers = 1; -} - -// SilenceCreatedEvent is emitted when a new silence is created. -message SilenceCreatedEvent { - // The newly created silence. - Silence silence = 1; -} - -// SilenceUpdatedEvent is emitted when an existing silence is modified. -message SilenceUpdatedEvent { - // The silence after the update. - Silence silence = 1; -} - -// MutedAlert identifies an alert that was suppressed by a silence or -// inhibition rule. -message MutedAlert { - // The label set of the muted alert. - LabelSet labels = 1; - - // The fingerprint of the muted alert. - uint64 fingerprint = 2; -} - -// SilenceMutedAlertEvent is emitted each time a silence suppresses an -// alert during the muting evaluation pass. -message SilenceMutedAlertEvent { - // The silence that suppressed the alert. - Silence silence = 1; - - // The alert that was suppressed. - MutedAlert muted_alert = 2; -} - -// InhibitRule is a snapshot of an inhibition rule definition. -message InhibitRule { - // Matchers that identify source alerts (those that do the inhibiting). - repeated Matcher source_matchers = 1; - - // Matchers that identify target alerts (those that get inhibited). - repeated Matcher target_matchers = 2; - - // Label names whose values must be equal between source and target - // alerts for the inhibition to take effect. - repeated string equal_labels = 3; - - // Name is the optional name of the inhibition rule. - string name = 4; -} - -// InhibitionMutedAlertEvent is emitted when one or more inhibition -// rules suppress an alert. -message InhibitionMutedAlertEvent { - // The inhibition rules that matched. - repeated InhibitRule inhibit_rules = 1; - - // The alert that was suppressed. - MutedAlert muted_alert = 2; - - // The fingerprints of the source alerts that caused the inhibition. - repeated uint64 inhibiting_fingerprints = 3; -} diff --git a/eventrecorder/events.go b/eventrecorder/events.go index 4b5e5d5891..929cade8eb 100644 --- a/eventrecorder/events.go +++ b/eventrecorder/events.go @@ -11,282 +11,402 @@ // See the License for the specific language governing permissions and // limitations under the License. -// This file contains pure-functional helpers that convert internal -// Alertmanager types into eventrecorderpb messages, plus convenience -// constructors for the EventData oneof variants. None of these -// functions touch the Recorder; they are imported and called by the -// dispatch, silence, inhibit, and provider packages to build event -// payloads that are then handed to Recorder.RecordEvent. - package eventrecorder import ( + "maps" "slices" - "strings" + "time" "github.com/prometheus/common/model" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/timestamppb" - "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" + "github.com/prometheus/alertmanager/alert" + events "github.com/prometheus/alertmanager/eventrecorder/events/v2" "github.com/prometheus/alertmanager/pkg/labels" silencepb "github.com/prometheus/alertmanager/silence/silencepb" - "github.com/prometheus/alertmanager/types" ) -// LabelSetAsProto converts a model.LabelSet to an eventrecorderpb.LabelSet. -// Labels are sorted by name for deterministic output. -func LabelSetAsProto(ls model.LabelSet) *eventrecorderpb.LabelSet { - names := make([]model.LabelName, 0, len(ls)) - for k := range ls { - names = append(names, k) +// EventData is an immutable event recorder payload without envelope metadata. +// Its protobuf representation is private so producers cannot construct invalid +// output events. +type EventData struct { + message *events.EventData + eventType string +} + +// Event is an immutable event recorder output with envelope metadata. Its +// protobuf representation is private so destinations cannot be passed arbitrary +// protobuf messages. +type Event struct { + message *events.Event + eventType string +} + +// MarshalJSON serializes the event using its protobuf schema. +func (e Event) MarshalJSON() ([]byte, error) { + return protojson.Marshal(e.message) +} + +// MarshalProtobuf serializes the event using its protobuf schema. +func (e Event) MarshalProtobuf() ([]byte, error) { + return proto.Marshal(e.message) +} + +func (d EventData) typeName() string { + return eventTypeName(d.eventType) +} + +func (e Event) typeName() string { + return eventTypeName(e.eventType) +} + +func eventTypeName(eventType string) string { + if eventType == "" { + return "unknown" } - slices.SortFunc(names, func(a, b model.LabelName) int { - return strings.Compare(string(a), string(b)) - }) - pairs := make([]*eventrecorderpb.LabelPair, 0, len(ls)) - for _, k := range names { - pairs = append(pairs, &eventrecorderpb.LabelPair{Key: string(k), Value: string(ls[k])}) + return eventType +} + +func (e Event) protoMessage() proto.Message { + return e.message +} + +func (d EventData) withMetadata(timestamp *timestamppb.Timestamp, instance string, clusterPosition uint64) Event { + return Event{ + message: &events.Event{ + Timestamp: timestamp, Instance: instance, Data: d.message, ClusterPosition: clusterPosition, + }, + eventType: d.eventType, } - return &eventrecorderpb.LabelSet{Labels: pairs} -} - -// AlertAsProto converts a types.Alert to an eventrecorderpb.Alert. -func AlertAsProto(alert *types.Alert) *eventrecorderpb.Alert { - return &eventrecorderpb.Alert{ - Fingerprint: uint64(alert.Fingerprint()), - Name: alert.Name(), - Labels: LabelSetAsProto(alert.Labels), - Annotations: LabelSetAsProto(alert.Annotations), - StartsAt: timestamppb.New(alert.StartsAt), - EndsAt: timestamppb.New(alert.EndsAt), - Resolved: alert.Resolved(), +} + +// AlertGroup is an immutable aggregation-group snapshot. +type AlertGroup struct { + message *events.AlertGroupInfo +} + +// GroupedAlert is an immutable grouped-alert snapshot. +type GroupedAlert struct { + message *events.GroupedAlert +} + +// InhibitRule is an immutable inhibition-rule snapshot. +type InhibitRule struct { + message *events.InhibitRule +} + +// NotificationReason describes why a notification was sent. +type NotificationReason int + +const ( + NotificationReasonUnspecified NotificationReason = iota + NotificationReasonFirstNotification + NotificationReasonNewAlertsInGroup + NotificationReasonNewResolvedAlerts + NotificationReasonAllAlertsResolved + NotificationReasonRepeatIntervalElapsed +) + +// Notification contains the snapshots used to construct a notification event. +type Notification struct { + Alerts []GroupedAlert + FiringAlerts []GroupedAlert + ResolvedAlerts []GroupedAlert + MutedAlerts []GroupedAlert + Group AlertGroup + RepeatInterval time.Duration + Reason NotificationReason + FlushID uint64 + Integration string + IntegrationIdx int64 +} + +// NewAlertGroup snapshots aggregation-group metadata. +func NewAlertGroup(groupKey string, groupLabels model.LabelSet, groupID, receiverName string, matchers labels.Matchers, groupUUID string) AlertGroup { + return AlertGroup{message: &events.AlertGroupInfo{ + GroupKey: groupKey, GroupLabels: labelSetMap(groupLabels), GroupId: groupID, + ReceiverName: receiverName, Matchers: matchersToEvents(matchers), GroupUuid: groupUUID, + }} +} + +// NewGroupedAlert snapshots an alert and its notification-pipeline hash. +func NewGroupedAlert(hash uint64, a *alert.Alert) GroupedAlert { + return GroupedAlert{message: &events.GroupedAlert{Hash: hash, Details: alertToEvents(a)}} +} + +// NewGroupedAlertReference snapshots a hash-only grouped-alert reference. +func NewGroupedAlertReference(hash uint64) GroupedAlert { + return GroupedAlert{message: &events.GroupedAlert{Hash: hash}} +} + +// NewAlertmanagerStartupEvent constructs startup event data. +func NewAlertmanagerStartupEvent(version, buildContext string) EventData { + return newEventData("alertmanager_startup_event", &events.EventData{EventType: &events.EventData_AlertmanagerStartupEvent{ + AlertmanagerStartupEvent: &events.AlertmanagerStartupEvent{Version: version, BuildContext: buildContext}, + }}) +} + +// NewAlertmanagerShutdownEvent constructs shutdown event data. +func NewAlertmanagerShutdownEvent() EventData { + return newEventData("alertmanager_shutdown_event", &events.EventData{EventType: &events.EventData_AlertmanagerShutdownEvent{ + AlertmanagerShutdownEvent: &events.AlertmanagerShutdownEvent{}, + }}) +} + +// NewAlertCreatedEvent constructs alert-created event data. +func NewAlertCreatedEvent(a *alert.Alert) EventData { + return newEventData("alert_created", &events.EventData{EventType: &events.EventData_AlertCreated{ + AlertCreated: &events.AlertCreatedEvent{Alert: alertToEvents(a)}, + }}) +} + +// NewAlertGroupedEvent constructs alert-grouped event data. +func NewAlertGroupedEvent(group AlertGroup, groupedAlert GroupedAlert) EventData { + return newEventData("alert_grouped", &events.EventData{EventType: &events.EventData_AlertGrouped{ + AlertGrouped: &events.AlertGroupedEvent{Alert: groupedAlert.message, GroupInfo: group.message}, + }}) +} + +// NewAlertResolvedEvent constructs alert-resolved event data. +func NewAlertResolvedEvent(group AlertGroup, groupedAlert GroupedAlert) EventData { + return newEventData("alert_resolved", &events.EventData{EventType: &events.EventData_AlertResolved{ + AlertResolved: &events.AlertResolvedEvent{Alert: groupedAlert.message, GroupInfo: group.message}, + }}) +} + +// NewNotificationEvent constructs notification event data. +func NewNotificationEvent(notification Notification) EventData { + return newEventData("notification", &events.EventData{EventType: &events.EventData_Notification{ + Notification: &events.NotificationEvent{ + Alerts: groupedAlertsToEvents(notification.Alerts), FiringAlerts: groupedAlertsToEvents(notification.FiringAlerts), + ResolvedAlerts: groupedAlertsToEvents(notification.ResolvedAlerts), MutedAlerts: groupedAlertsToEvents(notification.MutedAlerts), + GroupInfo: notification.Group.message, RepeatInterval: durationpb.New(notification.RepeatInterval), + Reason: notificationReasonToEvents(notification.Reason), FlushId: notification.FlushID, + Integration: &events.Integration{Name: notification.Integration, Index: notification.IntegrationIdx}, + }, + }}) +} + +// NewSilenceMutedAlertEvent constructs silence-muted-alert event data. +func NewSilenceMutedAlertEvent(silence *silencepb.Silence, fp model.Fingerprint, labelSet model.LabelSet) EventData { + return newEventData("silence_muted_alert", &events.EventData{EventType: &events.EventData_SilenceMutedAlert{ + SilenceMutedAlert: &events.SilenceMutedAlertEvent{Silence: silenceToEvents(silence), MutedAlert: &events.MutedAlert{ + Fingerprint: uint64(fp), Labels: labelSetMap(labelSet), + }}, + }}) +} + +// NewSilenceCreatedEvent constructs silence-created event data. +func NewSilenceCreatedEvent(silence *silencepb.Silence) EventData { + return newEventData("silence_created", &events.EventData{EventType: &events.EventData_SilenceCreated{ + SilenceCreated: &events.SilenceCreatedEvent{Silence: silenceToEvents(silence)}, + }}) +} + +// NewSilenceUpdatedEvent constructs silence-updated event data. +func NewSilenceUpdatedEvent(silence *silencepb.Silence) EventData { + return newEventData("silence_updated", &events.EventData{EventType: &events.EventData_SilenceUpdated{ + SilenceUpdated: &events.SilenceUpdatedEvent{Silence: silenceToEvents(silence)}, + }}) +} + +// NewInhibitRule snapshots an inhibition rule. +func NewInhibitRule(name string, sourceMatchers, targetMatchers labels.Matchers, equal map[model.LabelName]struct{}) InhibitRule { + equalLabels := make([]string, 0, len(equal)) + for label := range equal { + equalLabels = append(equalLabels, string(label)) } + slices.Sort(equalLabels) + return InhibitRule{message: &events.InhibitRule{ + Name: name, SourceMatchers: matchersToEvents(sourceMatchers), TargetMatchers: matchersToEvents(targetMatchers), EqualLabels: equalLabels, + }} } -// MatcherAsProto converts a single *labels.Matcher to its protobuf -// representation. -func MatcherAsProto(m *labels.Matcher) *eventrecorderpb.Matcher { - var matcherType eventrecorderpb.Matcher_Type - switch m.Type { - case labels.MatchEqual: - matcherType = eventrecorderpb.Matcher_TYPE_EQUAL - case labels.MatchNotEqual: - matcherType = eventrecorderpb.Matcher_TYPE_NOT_EQUAL - case labels.MatchRegexp: - matcherType = eventrecorderpb.Matcher_TYPE_REGEXP - case labels.MatchNotRegexp: - matcherType = eventrecorderpb.Matcher_TYPE_NOT_REGEXP - default: - matcherType = eventrecorderpb.Matcher_TYPE_UNSPECIFIED +// NewInhibitionMutedAlertEvent constructs inhibition-muted-alert event data. +func NewInhibitionMutedAlertEvent(rules []InhibitRule, fp model.Fingerprint, labelSet model.LabelSet, inhibitingFPs []model.Fingerprint) EventData { + fps := make([]uint64, len(inhibitingFPs)) + for i, fingerprint := range inhibitingFPs { + fps[i] = uint64(fingerprint) } - return &eventrecorderpb.Matcher{ - Type: matcherType, - Name: m.Name, - Pattern: m.Value, - Rendered: m.String(), + eventRules := make([]*events.InhibitRule, len(rules)) + for i, rule := range rules { + eventRules[i] = rule.message } + return newEventData("inhibition_muted_alert", &events.EventData{EventType: &events.EventData_InhibitionMutedAlert{ + InhibitionMutedAlert: &events.InhibitionMutedAlertEvent{ + InhibitRules: eventRules, MutedAlert: &events.MutedAlert{Fingerprint: uint64(fp), Labels: labelSetMap(labelSet)}, + InhibitingFingerprints: fps, + }, + }}) +} + +func newEventData(eventType string, message *events.EventData) EventData { + return EventData{message: message, eventType: eventType} } -// MatchersAsProto converts a slice of matchers to their protobuf -// representations. -func MatchersAsProto(matchers labels.Matchers) []*eventrecorderpb.Matcher { - result := make([]*eventrecorderpb.Matcher, len(matchers)) - for i, m := range matchers { - result[i] = MatcherAsProto(m) +func labelSetMap(labelSet model.LabelSet) map[string]string { + result := make(map[string]string, len(labelSet)) + for name, value := range labelSet { + result[string(name)] = string(value) } return result } -// SilenceMatcherAsProto converts a silencepb.Matcher to an -// eventrecorderpb.Matcher. -func SilenceMatcherAsProto(m *silencepb.Matcher) *eventrecorderpb.Matcher { - var matcherType eventrecorderpb.Matcher_Type - switch m.Type { - case silencepb.Matcher_EQUAL: - matcherType = eventrecorderpb.Matcher_TYPE_EQUAL - case silencepb.Matcher_REGEXP: - matcherType = eventrecorderpb.Matcher_TYPE_REGEXP - case silencepb.Matcher_NOT_EQUAL: - matcherType = eventrecorderpb.Matcher_TYPE_NOT_EQUAL - case silencepb.Matcher_NOT_REGEXP: - matcherType = eventrecorderpb.Matcher_TYPE_NOT_REGEXP - default: - matcherType = eventrecorderpb.Matcher_TYPE_UNSPECIFIED +func stringMap(values map[string]string) map[string]string { + if len(values) == 0 { + return nil } + result := make(map[string]string, len(values)) + maps.Copy(result, values) + return result +} - var rendered string - var matchType labels.MatchType - switch m.Type { - case silencepb.Matcher_EQUAL: - matchType = labels.MatchEqual - case silencepb.Matcher_NOT_EQUAL: - matchType = labels.MatchNotEqual - case silencepb.Matcher_REGEXP: - matchType = labels.MatchRegexp - case silencepb.Matcher_NOT_REGEXP: - matchType = labels.MatchNotRegexp - default: - matchType = labels.MatchEqual +func alertToEvents(a *alert.Alert) *events.Alert { + if a == nil { + return nil } - if lm, err := labels.NewMatcher(matchType, m.Name, m.Pattern); err == nil { - rendered = lm.String() + return &events.Alert{ + Fingerprint: uint64(a.Fingerprint()), Name: a.Name(), Labels: labelSetMap(a.Labels), Annotations: labelSetMap(a.Annotations), + StartsAt: timestamppb.New(a.StartsAt), EndsAt: timestamppb.New(a.EndsAt), Resolved: a.Resolved(), } +} - return &eventrecorderpb.Matcher{ - Type: matcherType, - Name: m.Name, - Pattern: m.Pattern, - Rendered: rendered, +func matchersToEvents(matchers labels.Matchers) []*events.Matcher { + result := make([]*events.Matcher, 0, len(matchers)) + for _, matcher := range matchers { + if matcher == nil { + continue + } + result = append(result, &events.Matcher{Type: matcherTypeToEvents(matcher.Type), Name: matcher.Name, Pattern: matcher.Value, Rendered: matcher.String()}) } + return result } -// SilenceAsProto converts a silencepb.Silence to an -// eventrecorderpb.Silence. -func SilenceAsProto(sil *silencepb.Silence) *eventrecorderpb.Silence { - matcherSets := make([]*eventrecorderpb.MatcherSet, len(sil.MatcherSets)) - for i, ms := range sil.MatcherSets { - matcherSet := &eventrecorderpb.MatcherSet{ - Matchers: make([]*eventrecorderpb.Matcher, len(ms.Matchers)), - } - for j, m := range ms.Matchers { - matcherSet.Matchers[j] = SilenceMatcherAsProto(m) - } - matcherSets[i] = matcherSet +func matcherTypeToEvents(matcherType labels.MatchType) events.Matcher_Type { + switch matcherType { + case labels.MatchEqual: + return events.Matcher_TYPE_EQUAL + case labels.MatchNotEqual: + return events.Matcher_TYPE_NOT_EQUAL + case labels.MatchRegexp: + return events.Matcher_TYPE_REGEXP + case labels.MatchNotRegexp: + return events.Matcher_TYPE_NOT_REGEXP + default: + return events.Matcher_TYPE_UNSPECIFIED } +} - var matchers []*eventrecorderpb.Matcher - if len(matcherSets) > 0 { +func silenceToEvents(silence *silencepb.Silence) *events.Silence { + if silence == nil { + return nil + } + matcherSets := silenceMatcherSetsToEvents(silence.MatcherSets) + receiverMatcherSets := silenceMatcherSetsToEvents(silence.ReceiverMatcherSets) + matchers := silenceMatchersToEvents(silence.Matchers) + if len(matchers) == 0 && len(matcherSets) > 0 { matchers = matcherSets[0].Matchers } - - return &eventrecorderpb.Silence{ - Id: sil.Id, - Matchers: matchers, - MatcherSets: matcherSets, - StartsAt: sil.StartsAt, - EndsAt: sil.EndsAt, - UpdatedAt: sil.UpdatedAt, - CreatedBy: sil.CreatedBy, - Comment: sil.Comment, + return &events.Silence{ + Id: silence.Id, Matchers: matchers, Annotations: stringMap(silence.Annotations), StartsAt: cloneTimestamp(silence.StartsAt), + EndsAt: cloneTimestamp(silence.EndsAt), UpdatedAt: cloneTimestamp(silence.UpdatedAt), CreatedBy: silence.CreatedBy, + Comment: silence.Comment, MatcherSets: matcherSets, ReceiverMatcherSets: receiverMatcherSets, } } -// InhibitRuleAsProto converts inhibit rule fields to an -// eventrecorderpb.InhibitRule. It accepts the individual fields rather -// than the InhibitRule struct to avoid an import cycle. -func InhibitRuleAsProto(name string, sourceMatchers, targetMatchers labels.Matchers, equal map[model.LabelName]struct{}) *eventrecorderpb.InhibitRule { - equalLabels := make([]string, 0, len(equal)) - for label := range equal { - equalLabels = append(equalLabels, string(label)) - } - slices.Sort(equalLabels) - return &eventrecorderpb.InhibitRule{ - Name: name, - SourceMatchers: MatchersAsProto(sourceMatchers), - TargetMatchers: MatchersAsProto(targetMatchers), - EqualLabels: equalLabels, +func silenceMatcherSetsToEvents(sets []*silencepb.MatcherSet) []*events.MatcherSet { + result := make([]*events.MatcherSet, 0, len(sets)) + for _, set := range sets { + if set == nil { + continue + } + result = append(result, &events.MatcherSet{Matchers: silenceMatchersToEvents(set.Matchers)}) } + return result } -// NewAlertCreatedEvent constructs an AlertCreated event. -func NewAlertCreatedEvent(alert *types.Alert) *eventrecorderpb.EventData { - return &eventrecorderpb.EventData{ - EventType: &eventrecorderpb.EventData_AlertCreated{ - AlertCreated: &eventrecorderpb.AlertCreatedEvent{ - Alert: AlertAsProto(alert), - }, - }, +func silenceMatchersToEvents(matchers []*silencepb.Matcher) []*events.Matcher { + result := make([]*events.Matcher, 0, len(matchers)) + for _, matcher := range matchers { + if matcher == nil { + continue + } + result = append(result, silenceMatcherToEvents(matcher)) } + return result } -// NewSilenceMutedAlertEvent constructs a SilenceMutedAlert event. -func NewSilenceMutedAlertEvent(silence *eventrecorderpb.Silence, fp model.Fingerprint, lset model.LabelSet) *eventrecorderpb.EventData { - return &eventrecorderpb.EventData{ - EventType: &eventrecorderpb.EventData_SilenceMutedAlert{ - SilenceMutedAlert: &eventrecorderpb.SilenceMutedAlertEvent{ - Silence: silence, - MutedAlert: &eventrecorderpb.MutedAlert{ - Fingerprint: uint64(fp), - Labels: LabelSetAsProto(lset), - }, - }, - }, +func silenceMatcherToEvents(matcher *silencepb.Matcher) *events.Matcher { + if matcher == nil { + return nil + } + eventType := events.Matcher_TYPE_UNSPECIFIED + switch matcher.Type { + case silencepb.Matcher_EQUAL: + eventType = events.Matcher_TYPE_EQUAL + case silencepb.Matcher_REGEXP: + eventType = events.Matcher_TYPE_REGEXP + case silencepb.Matcher_NOT_EQUAL: + eventType = events.Matcher_TYPE_NOT_EQUAL + case silencepb.Matcher_NOT_REGEXP: + eventType = events.Matcher_TYPE_NOT_REGEXP } + return &events.Matcher{Type: eventType, Name: matcher.Name, Pattern: matcher.Pattern, Rendered: silenceMatcherRendered(matcher)} } -// NewSilenceCreatedEvent constructs a SilenceCreated event. -func NewSilenceCreatedEvent(silence *eventrecorderpb.Silence) *eventrecorderpb.EventData { - return &eventrecorderpb.EventData{ - EventType: &eventrecorderpb.EventData_SilenceCreated{ - SilenceCreated: &eventrecorderpb.SilenceCreatedEvent{ - Silence: silence, - }, - }, +func silenceMatcherRendered(matcher *silencepb.Matcher) string { + var matcherType labels.MatchType + switch matcher.Type { + case silencepb.Matcher_EQUAL: + matcherType = labels.MatchEqual + case silencepb.Matcher_REGEXP: + matcherType = labels.MatchRegexp + case silencepb.Matcher_NOT_EQUAL: + matcherType = labels.MatchNotEqual + case silencepb.Matcher_NOT_REGEXP: + matcherType = labels.MatchNotRegexp + default: + return "" } + rendered := "" + if parsed, err := labels.NewMatcher(matcherType, matcher.Name, matcher.Pattern); err == nil { + rendered = parsed.String() + } + return rendered } -// NewSilenceUpdatedEvent constructs a SilenceUpdated event. -func NewSilenceUpdatedEvent(silence *eventrecorderpb.Silence) *eventrecorderpb.EventData { - return &eventrecorderpb.EventData{ - EventType: &eventrecorderpb.EventData_SilenceUpdated{ - SilenceUpdated: &eventrecorderpb.SilenceUpdatedEvent{ - Silence: silence, - }, - }, +func cloneTimestamp(timestamp *timestamppb.Timestamp) *timestamppb.Timestamp { + if timestamp == nil { + return nil } + return timestamppb.New(timestamp.AsTime()) } -// NewInhibitionMutedAlertEvent constructs an InhibitionMutedAlert event. -func NewInhibitionMutedAlertEvent(rules []*eventrecorderpb.InhibitRule, fp model.Fingerprint, lset model.LabelSet, inhibitingFPs []model.Fingerprint) *eventrecorderpb.EventData { - fps := make([]uint64, len(inhibitingFPs)) - for i, f := range inhibitingFPs { - fps[i] = uint64(f) - } - return &eventrecorderpb.EventData{ - EventType: &eventrecorderpb.EventData_InhibitionMutedAlert{ - InhibitionMutedAlert: &eventrecorderpb.InhibitionMutedAlertEvent{ - InhibitRules: rules, - MutedAlert: &eventrecorderpb.MutedAlert{ - Fingerprint: uint64(fp), - Labels: LabelSetAsProto(lset), - }, - InhibitingFingerprints: fps, - }, - }, +func groupedAlertsToEvents(alerts []GroupedAlert) []*events.GroupedAlert { + result := make([]*events.GroupedAlert, len(alerts)) + for i, groupedAlert := range alerts { + result[i] = groupedAlert.message } + return result } -// extractEventType returns the proto oneof field name for the event -// type (e.g. "alert_created", "notification"). It uses a type switch -// on the generated oneof wrapper types, avoiding proto reflection. -// A nil input is reported as "unknown" so logging and metric paths -// stay panic-free. -func extractEventType(event *eventrecorderpb.EventData) string { - if event == nil { - return "unknown" - } - switch event.EventType.(type) { - case *eventrecorderpb.EventData_AlertmanagerStartupEvent: - return "alertmanager_startup_event" - case *eventrecorderpb.EventData_AlertmanagerShutdownEvent: - return "alertmanager_shutdown_event" - case *eventrecorderpb.EventData_AlertCreated: - return "alert_created" - case *eventrecorderpb.EventData_AlertResolved: - return "alert_resolved" - case *eventrecorderpb.EventData_AlertGrouped: - return "alert_grouped" - case *eventrecorderpb.EventData_Notification: - return "notification" - case *eventrecorderpb.EventData_SilenceCreated: - return "silence_created" - case *eventrecorderpb.EventData_SilenceUpdated: - return "silence_updated" - case *eventrecorderpb.EventData_SilenceMutedAlert: - return "silence_muted_alert" - case *eventrecorderpb.EventData_InhibitionMutedAlert: - return "inhibition_muted_alert" +func notificationReasonToEvents(reason NotificationReason) events.NotifyReason { + switch reason { + case NotificationReasonFirstNotification: + return events.NotifyReason_NOTIFY_REASON_FIRST_NOTIFICATION + case NotificationReasonNewAlertsInGroup: + return events.NotifyReason_NOTIFY_REASON_NEW_ALERTS_IN_GROUP + case NotificationReasonNewResolvedAlerts: + return events.NotifyReason_NOTIFY_REASON_NEW_RESOLVED_ALERTS + case NotificationReasonAllAlertsResolved: + return events.NotifyReason_NOTIFY_REASON_ALL_ALERTS_RESOLVED + case NotificationReasonRepeatIntervalElapsed: + return events.NotifyReason_NOTIFY_REASON_REPEAT_INTERVAL_ELAPSED default: - return "unknown" + return events.NotifyReason_NOTIFY_REASON_UNSPECIFIED } } diff --git a/eventrecorder/events/v2/events.pb.go b/eventrecorder/events/v2/events.pb.go new file mode 100644 index 0000000000..374d5776e2 --- /dev/null +++ b/eventrecorder/events/v2/events.pb.go @@ -0,0 +1,1899 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc (unknown) +// source: events/v2/events.proto + +package eventsv2 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + durationpb "google.golang.org/protobuf/types/known/durationpb" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// NotifyReason describes why a notification was sent. +type NotifyReason int32 + +const ( + NotifyReason_NOTIFY_REASON_UNSPECIFIED NotifyReason = 0 + NotifyReason_NOTIFY_REASON_FIRST_NOTIFICATION NotifyReason = 1 + NotifyReason_NOTIFY_REASON_NEW_ALERTS_IN_GROUP NotifyReason = 2 + NotifyReason_NOTIFY_REASON_NEW_RESOLVED_ALERTS NotifyReason = 3 + NotifyReason_NOTIFY_REASON_ALL_ALERTS_RESOLVED NotifyReason = 4 + NotifyReason_NOTIFY_REASON_REPEAT_INTERVAL_ELAPSED NotifyReason = 5 +) + +// Enum value maps for NotifyReason. +var ( + NotifyReason_name = map[int32]string{ + 0: "NOTIFY_REASON_UNSPECIFIED", + 1: "NOTIFY_REASON_FIRST_NOTIFICATION", + 2: "NOTIFY_REASON_NEW_ALERTS_IN_GROUP", + 3: "NOTIFY_REASON_NEW_RESOLVED_ALERTS", + 4: "NOTIFY_REASON_ALL_ALERTS_RESOLVED", + 5: "NOTIFY_REASON_REPEAT_INTERVAL_ELAPSED", + } + NotifyReason_value = map[string]int32{ + "NOTIFY_REASON_UNSPECIFIED": 0, + "NOTIFY_REASON_FIRST_NOTIFICATION": 1, + "NOTIFY_REASON_NEW_ALERTS_IN_GROUP": 2, + "NOTIFY_REASON_NEW_RESOLVED_ALERTS": 3, + "NOTIFY_REASON_ALL_ALERTS_RESOLVED": 4, + "NOTIFY_REASON_REPEAT_INTERVAL_ELAPSED": 5, + } +) + +func (x NotifyReason) Enum() *NotifyReason { + p := new(NotifyReason) + *p = x + return p +} + +func (x NotifyReason) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (NotifyReason) Descriptor() protoreflect.EnumDescriptor { + return file_events_v2_events_proto_enumTypes[0].Descriptor() +} + +func (NotifyReason) Type() protoreflect.EnumType { + return &file_events_v2_events_proto_enumTypes[0] +} + +func (x NotifyReason) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use NotifyReason.Descriptor instead. +func (NotifyReason) EnumDescriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{0} +} + +type Matcher_Type int32 + +const ( + Matcher_TYPE_UNSPECIFIED Matcher_Type = 0 + Matcher_TYPE_EQUAL Matcher_Type = 1 + Matcher_TYPE_REGEXP Matcher_Type = 2 + Matcher_TYPE_NOT_EQUAL Matcher_Type = 3 + Matcher_TYPE_NOT_REGEXP Matcher_Type = 4 +) + +// Enum value maps for Matcher_Type. +var ( + Matcher_Type_name = map[int32]string{ + 0: "TYPE_UNSPECIFIED", + 1: "TYPE_EQUAL", + 2: "TYPE_REGEXP", + 3: "TYPE_NOT_EQUAL", + 4: "TYPE_NOT_REGEXP", + } + Matcher_Type_value = map[string]int32{ + "TYPE_UNSPECIFIED": 0, + "TYPE_EQUAL": 1, + "TYPE_REGEXP": 2, + "TYPE_NOT_EQUAL": 3, + "TYPE_NOT_REGEXP": 4, + } +) + +func (x Matcher_Type) Enum() *Matcher_Type { + p := new(Matcher_Type) + *p = x + return p +} + +func (x Matcher_Type) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Matcher_Type) Descriptor() protoreflect.EnumDescriptor { + return file_events_v2_events_proto_enumTypes[1].Descriptor() +} + +func (Matcher_Type) Type() protoreflect.EnumType { + return &file_events_v2_events_proto_enumTypes[1] +} + +func (x Matcher_Type) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Matcher_Type.Descriptor instead. +func (Matcher_Type) EnumDescriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{13, 0} +} + +// Event is the top-level envelope written to each event recorder output. +type Event struct { + state protoimpl.MessageState `protogen:"open.v1"` + Timestamp *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=timestamp,json=@timestamp,proto3" json:"timestamp,omitempty"` + Instance string `protobuf:"bytes,2,opt,name=instance,proto3" json:"instance,omitempty"` + Data *EventData `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"` + ClusterPosition uint64 `protobuf:"varint,4,opt,name=cluster_position,json=clusterPosition,proto3" json:"cluster_position,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Event) Reset() { + *x = Event{} + mi := &file_events_v2_events_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Event) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Event) ProtoMessage() {} + +func (x *Event) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Event.ProtoReflect.Descriptor instead. +func (*Event) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{0} +} + +func (x *Event) GetTimestamp() *timestamppb.Timestamp { + if x != nil { + return x.Timestamp + } + return nil +} + +func (x *Event) GetInstance() string { + if x != nil { + return x.Instance + } + return "" +} + +func (x *Event) GetData() *EventData { + if x != nil { + return x.Data + } + return nil +} + +func (x *Event) GetClusterPosition() uint64 { + if x != nil { + return x.ClusterPosition + } + return 0 +} + +// EventData carries the payload for a single event recorder entry. +type EventData struct { + state protoimpl.MessageState `protogen:"open.v1"` + // Types that are valid to be assigned to EventType: + // + // *EventData_AlertmanagerStartupEvent + // *EventData_AlertmanagerShutdownEvent + // *EventData_AlertCreated + // *EventData_AlertResolved + // *EventData_AlertGrouped + // *EventData_Notification + // *EventData_SilenceCreated + // *EventData_SilenceUpdated + // *EventData_SilenceMutedAlert + // *EventData_InhibitionMutedAlert + EventType isEventData_EventType `protobuf_oneof:"event_type"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *EventData) Reset() { + *x = EventData{} + mi := &file_events_v2_events_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *EventData) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EventData) ProtoMessage() {} + +func (x *EventData) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EventData.ProtoReflect.Descriptor instead. +func (*EventData) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{1} +} + +func (x *EventData) GetEventType() isEventData_EventType { + if x != nil { + return x.EventType + } + return nil +} + +func (x *EventData) GetAlertmanagerStartupEvent() *AlertmanagerStartupEvent { + if x != nil { + if x, ok := x.EventType.(*EventData_AlertmanagerStartupEvent); ok { + return x.AlertmanagerStartupEvent + } + } + return nil +} + +func (x *EventData) GetAlertmanagerShutdownEvent() *AlertmanagerShutdownEvent { + if x != nil { + if x, ok := x.EventType.(*EventData_AlertmanagerShutdownEvent); ok { + return x.AlertmanagerShutdownEvent + } + } + return nil +} + +func (x *EventData) GetAlertCreated() *AlertCreatedEvent { + if x != nil { + if x, ok := x.EventType.(*EventData_AlertCreated); ok { + return x.AlertCreated + } + } + return nil +} + +func (x *EventData) GetAlertResolved() *AlertResolvedEvent { + if x != nil { + if x, ok := x.EventType.(*EventData_AlertResolved); ok { + return x.AlertResolved + } + } + return nil +} + +func (x *EventData) GetAlertGrouped() *AlertGroupedEvent { + if x != nil { + if x, ok := x.EventType.(*EventData_AlertGrouped); ok { + return x.AlertGrouped + } + } + return nil +} + +func (x *EventData) GetNotification() *NotificationEvent { + if x != nil { + if x, ok := x.EventType.(*EventData_Notification); ok { + return x.Notification + } + } + return nil +} + +func (x *EventData) GetSilenceCreated() *SilenceCreatedEvent { + if x != nil { + if x, ok := x.EventType.(*EventData_SilenceCreated); ok { + return x.SilenceCreated + } + } + return nil +} + +func (x *EventData) GetSilenceUpdated() *SilenceUpdatedEvent { + if x != nil { + if x, ok := x.EventType.(*EventData_SilenceUpdated); ok { + return x.SilenceUpdated + } + } + return nil +} + +func (x *EventData) GetSilenceMutedAlert() *SilenceMutedAlertEvent { + if x != nil { + if x, ok := x.EventType.(*EventData_SilenceMutedAlert); ok { + return x.SilenceMutedAlert + } + } + return nil +} + +func (x *EventData) GetInhibitionMutedAlert() *InhibitionMutedAlertEvent { + if x != nil { + if x, ok := x.EventType.(*EventData_InhibitionMutedAlert); ok { + return x.InhibitionMutedAlert + } + } + return nil +} + +type isEventData_EventType interface { + isEventData_EventType() +} + +type EventData_AlertmanagerStartupEvent struct { + AlertmanagerStartupEvent *AlertmanagerStartupEvent `protobuf:"bytes,1,opt,name=alertmanager_startup_event,json=alertmanagerStartupEvent,proto3,oneof"` +} + +type EventData_AlertmanagerShutdownEvent struct { + AlertmanagerShutdownEvent *AlertmanagerShutdownEvent `protobuf:"bytes,2,opt,name=alertmanager_shutdown_event,json=alertmanagerShutdownEvent,proto3,oneof"` +} + +type EventData_AlertCreated struct { + AlertCreated *AlertCreatedEvent `protobuf:"bytes,3,opt,name=alert_created,json=alertCreated,proto3,oneof"` +} + +type EventData_AlertResolved struct { + AlertResolved *AlertResolvedEvent `protobuf:"bytes,4,opt,name=alert_resolved,json=alertResolved,proto3,oneof"` +} + +type EventData_AlertGrouped struct { + AlertGrouped *AlertGroupedEvent `protobuf:"bytes,5,opt,name=alert_grouped,json=alertGrouped,proto3,oneof"` +} + +type EventData_Notification struct { + Notification *NotificationEvent `protobuf:"bytes,6,opt,name=notification,proto3,oneof"` +} + +type EventData_SilenceCreated struct { + SilenceCreated *SilenceCreatedEvent `protobuf:"bytes,7,opt,name=silence_created,json=silenceCreated,proto3,oneof"` +} + +type EventData_SilenceUpdated struct { + SilenceUpdated *SilenceUpdatedEvent `protobuf:"bytes,8,opt,name=silence_updated,json=silenceUpdated,proto3,oneof"` +} + +type EventData_SilenceMutedAlert struct { + SilenceMutedAlert *SilenceMutedAlertEvent `protobuf:"bytes,9,opt,name=silence_muted_alert,json=silenceMutedAlert,proto3,oneof"` +} + +type EventData_InhibitionMutedAlert struct { + InhibitionMutedAlert *InhibitionMutedAlertEvent `protobuf:"bytes,10,opt,name=inhibition_muted_alert,json=inhibitionMutedAlert,proto3,oneof"` +} + +func (*EventData_AlertmanagerStartupEvent) isEventData_EventType() {} + +func (*EventData_AlertmanagerShutdownEvent) isEventData_EventType() {} + +func (*EventData_AlertCreated) isEventData_EventType() {} + +func (*EventData_AlertResolved) isEventData_EventType() {} + +func (*EventData_AlertGrouped) isEventData_EventType() {} + +func (*EventData_Notification) isEventData_EventType() {} + +func (*EventData_SilenceCreated) isEventData_EventType() {} + +func (*EventData_SilenceUpdated) isEventData_EventType() {} + +func (*EventData_SilenceMutedAlert) isEventData_EventType() {} + +func (*EventData_InhibitionMutedAlert) isEventData_EventType() {} + +// AlertmanagerStartupEvent is emitted once when the process starts. +type AlertmanagerStartupEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` + BuildContext string `protobuf:"bytes,2,opt,name=build_context,json=buildContext,proto3" json:"build_context,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AlertmanagerStartupEvent) Reset() { + *x = AlertmanagerStartupEvent{} + mi := &file_events_v2_events_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AlertmanagerStartupEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AlertmanagerStartupEvent) ProtoMessage() {} + +func (x *AlertmanagerStartupEvent) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AlertmanagerStartupEvent.ProtoReflect.Descriptor instead. +func (*AlertmanagerStartupEvent) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{2} +} + +func (x *AlertmanagerStartupEvent) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *AlertmanagerStartupEvent) GetBuildContext() string { + if x != nil { + return x.BuildContext + } + return "" +} + +// AlertmanagerShutdownEvent is emitted when the process shuts down gracefully. +type AlertmanagerShutdownEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AlertmanagerShutdownEvent) Reset() { + *x = AlertmanagerShutdownEvent{} + mi := &file_events_v2_events_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AlertmanagerShutdownEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AlertmanagerShutdownEvent) ProtoMessage() {} + +func (x *AlertmanagerShutdownEvent) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AlertmanagerShutdownEvent.ProtoReflect.Descriptor instead. +func (*AlertmanagerShutdownEvent) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{3} +} + +// Alert represents a snapshot of an alert at the time the event was recorded. +type Alert struct { + state protoimpl.MessageState `protogen:"open.v1"` + Fingerprint uint64 `protobuf:"varint,1,opt,name=fingerprint,proto3" json:"fingerprint,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Labels map[string]string `protobuf:"bytes,3,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Annotations map[string]string `protobuf:"bytes,4,rep,name=annotations,proto3" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + StartsAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=starts_at,json=startsAt,proto3" json:"starts_at,omitempty"` + EndsAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=ends_at,json=endsAt,proto3" json:"ends_at,omitempty"` + Resolved bool `protobuf:"varint,7,opt,name=resolved,proto3" json:"resolved,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Alert) Reset() { + *x = Alert{} + mi := &file_events_v2_events_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Alert) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Alert) ProtoMessage() {} + +func (x *Alert) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Alert.ProtoReflect.Descriptor instead. +func (*Alert) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{4} +} + +func (x *Alert) GetFingerprint() uint64 { + if x != nil { + return x.Fingerprint + } + return 0 +} + +func (x *Alert) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Alert) GetLabels() map[string]string { + if x != nil { + return x.Labels + } + return nil +} + +func (x *Alert) GetAnnotations() map[string]string { + if x != nil { + return x.Annotations + } + return nil +} + +func (x *Alert) GetStartsAt() *timestamppb.Timestamp { + if x != nil { + return x.StartsAt + } + return nil +} + +func (x *Alert) GetEndsAt() *timestamppb.Timestamp { + if x != nil { + return x.EndsAt + } + return nil +} + +func (x *Alert) GetResolved() bool { + if x != nil { + return x.Resolved + } + return false +} + +// GroupedAlert is a reference to an alert within an aggregation group. +type GroupedAlert struct { + state protoimpl.MessageState `protogen:"open.v1"` + Hash uint64 `protobuf:"varint,1,opt,name=hash,proto3" json:"hash,omitempty"` + Details *Alert `protobuf:"bytes,2,opt,name=details,proto3,oneof" json:"details,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GroupedAlert) Reset() { + *x = GroupedAlert{} + mi := &file_events_v2_events_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GroupedAlert) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GroupedAlert) ProtoMessage() {} + +func (x *GroupedAlert) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GroupedAlert.ProtoReflect.Descriptor instead. +func (*GroupedAlert) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{5} +} + +func (x *GroupedAlert) GetHash() uint64 { + if x != nil { + return x.Hash + } + return 0 +} + +func (x *GroupedAlert) GetDetails() *Alert { + if x != nil { + return x.Details + } + return nil +} + +// AlertGroupInfo describes an alert's aggregation group context. +type AlertGroupInfo struct { + state protoimpl.MessageState `protogen:"open.v1"` + GroupKey string `protobuf:"bytes,1,opt,name=group_key,json=groupKey,proto3" json:"group_key,omitempty"` + GroupLabels map[string]string `protobuf:"bytes,2,rep,name=group_labels,json=groupLabels,proto3" json:"group_labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + GroupId string `protobuf:"bytes,3,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"` + ReceiverName string `protobuf:"bytes,4,opt,name=receiver_name,json=receiverName,proto3" json:"receiver_name,omitempty"` + Matchers []*Matcher `protobuf:"bytes,5,rep,name=matchers,proto3" json:"matchers,omitempty"` + GroupUuid string `protobuf:"bytes,6,opt,name=group_uuid,json=groupUuid,proto3" json:"group_uuid,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AlertGroupInfo) Reset() { + *x = AlertGroupInfo{} + mi := &file_events_v2_events_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AlertGroupInfo) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AlertGroupInfo) ProtoMessage() {} + +func (x *AlertGroupInfo) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AlertGroupInfo.ProtoReflect.Descriptor instead. +func (*AlertGroupInfo) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{6} +} + +func (x *AlertGroupInfo) GetGroupKey() string { + if x != nil { + return x.GroupKey + } + return "" +} + +func (x *AlertGroupInfo) GetGroupLabels() map[string]string { + if x != nil { + return x.GroupLabels + } + return nil +} + +func (x *AlertGroupInfo) GetGroupId() string { + if x != nil { + return x.GroupId + } + return "" +} + +func (x *AlertGroupInfo) GetReceiverName() string { + if x != nil { + return x.ReceiverName + } + return "" +} + +func (x *AlertGroupInfo) GetMatchers() []*Matcher { + if x != nil { + return x.Matchers + } + return nil +} + +func (x *AlertGroupInfo) GetGroupUuid() string { + if x != nil { + return x.GroupUuid + } + return "" +} + +// AlertCreatedEvent is emitted when a new alert is inserted. +type AlertCreatedEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + Alert *Alert `protobuf:"bytes,1,opt,name=alert,proto3" json:"alert,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AlertCreatedEvent) Reset() { + *x = AlertCreatedEvent{} + mi := &file_events_v2_events_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AlertCreatedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AlertCreatedEvent) ProtoMessage() {} + +func (x *AlertCreatedEvent) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AlertCreatedEvent.ProtoReflect.Descriptor instead. +func (*AlertCreatedEvent) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{7} +} + +func (x *AlertCreatedEvent) GetAlert() *Alert { + if x != nil { + return x.Alert + } + return nil +} + +// AlertResolvedEvent is emitted when a resolved alert leaves its group. +type AlertResolvedEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + Alert *GroupedAlert `protobuf:"bytes,1,opt,name=alert,proto3" json:"alert,omitempty"` + GroupInfo *AlertGroupInfo `protobuf:"bytes,2,opt,name=group_info,json=groupInfo,proto3" json:"group_info,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AlertResolvedEvent) Reset() { + *x = AlertResolvedEvent{} + mi := &file_events_v2_events_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AlertResolvedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AlertResolvedEvent) ProtoMessage() {} + +func (x *AlertResolvedEvent) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AlertResolvedEvent.ProtoReflect.Descriptor instead. +func (*AlertResolvedEvent) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{8} +} + +func (x *AlertResolvedEvent) GetAlert() *GroupedAlert { + if x != nil { + return x.Alert + } + return nil +} + +func (x *AlertResolvedEvent) GetGroupInfo() *AlertGroupInfo { + if x != nil { + return x.GroupInfo + } + return nil +} + +// AlertGroupedEvent is emitted when an alert first enters a group. +type AlertGroupedEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + Alert *GroupedAlert `protobuf:"bytes,1,opt,name=alert,proto3" json:"alert,omitempty"` + GroupInfo *AlertGroupInfo `protobuf:"bytes,2,opt,name=group_info,json=groupInfo,proto3" json:"group_info,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *AlertGroupedEvent) Reset() { + *x = AlertGroupedEvent{} + mi := &file_events_v2_events_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *AlertGroupedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AlertGroupedEvent) ProtoMessage() {} + +func (x *AlertGroupedEvent) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AlertGroupedEvent.ProtoReflect.Descriptor instead. +func (*AlertGroupedEvent) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{9} +} + +func (x *AlertGroupedEvent) GetAlert() *GroupedAlert { + if x != nil { + return x.Alert + } + return nil +} + +func (x *AlertGroupedEvent) GetGroupInfo() *AlertGroupInfo { + if x != nil { + return x.GroupInfo + } + return nil +} + +// Integration identifies a notification integration. +type Integration struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Index int64 `protobuf:"varint,2,opt,name=index,proto3" json:"index,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Integration) Reset() { + *x = Integration{} + mi := &file_events_v2_events_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Integration) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Integration) ProtoMessage() {} + +func (x *Integration) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Integration.ProtoReflect.Descriptor instead. +func (*Integration) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{10} +} + +func (x *Integration) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Integration) GetIndex() int64 { + if x != nil { + return x.Index + } + return 0 +} + +// NotificationEvent is emitted after a notification is delivered. +type NotificationEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + Alerts []*GroupedAlert `protobuf:"bytes,1,rep,name=alerts,proto3" json:"alerts,omitempty"` + FiringAlerts []*GroupedAlert `protobuf:"bytes,2,rep,name=firing_alerts,json=firingAlerts,proto3" json:"firing_alerts,omitempty"` + ResolvedAlerts []*GroupedAlert `protobuf:"bytes,3,rep,name=resolved_alerts,json=resolvedAlerts,proto3" json:"resolved_alerts,omitempty"` + MutedAlerts []*GroupedAlert `protobuf:"bytes,4,rep,name=muted_alerts,json=mutedAlerts,proto3" json:"muted_alerts,omitempty"` + GroupInfo *AlertGroupInfo `protobuf:"bytes,5,opt,name=group_info,json=groupInfo,proto3" json:"group_info,omitempty"` + RepeatInterval *durationpb.Duration `protobuf:"bytes,6,opt,name=repeat_interval,json=repeatInterval,proto3" json:"repeat_interval,omitempty"` + Reason NotifyReason `protobuf:"varint,7,opt,name=reason,proto3,enum=events.v2.NotifyReason" json:"reason,omitempty"` + FlushId uint64 `protobuf:"varint,8,opt,name=flush_id,json=flushId,proto3" json:"flush_id,omitempty"` + Integration *Integration `protobuf:"bytes,9,opt,name=integration,proto3" json:"integration,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *NotificationEvent) Reset() { + *x = NotificationEvent{} + mi := &file_events_v2_events_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *NotificationEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NotificationEvent) ProtoMessage() {} + +func (x *NotificationEvent) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[11] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NotificationEvent.ProtoReflect.Descriptor instead. +func (*NotificationEvent) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{11} +} + +func (x *NotificationEvent) GetAlerts() []*GroupedAlert { + if x != nil { + return x.Alerts + } + return nil +} + +func (x *NotificationEvent) GetFiringAlerts() []*GroupedAlert { + if x != nil { + return x.FiringAlerts + } + return nil +} + +func (x *NotificationEvent) GetResolvedAlerts() []*GroupedAlert { + if x != nil { + return x.ResolvedAlerts + } + return nil +} + +func (x *NotificationEvent) GetMutedAlerts() []*GroupedAlert { + if x != nil { + return x.MutedAlerts + } + return nil +} + +func (x *NotificationEvent) GetGroupInfo() *AlertGroupInfo { + if x != nil { + return x.GroupInfo + } + return nil +} + +func (x *NotificationEvent) GetRepeatInterval() *durationpb.Duration { + if x != nil { + return x.RepeatInterval + } + return nil +} + +func (x *NotificationEvent) GetReason() NotifyReason { + if x != nil { + return x.Reason + } + return NotifyReason_NOTIFY_REASON_UNSPECIFIED +} + +func (x *NotificationEvent) GetFlushId() uint64 { + if x != nil { + return x.FlushId + } + return 0 +} + +func (x *NotificationEvent) GetIntegration() *Integration { + if x != nil { + return x.Integration + } + return nil +} + +// Silence is a snapshot of a silence definition. +type Silence struct { + state protoimpl.MessageState `protogen:"open.v1"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Matchers []*Matcher `protobuf:"bytes,2,rep,name=matchers,proto3" json:"matchers,omitempty"` + Annotations map[string]string `protobuf:"bytes,3,rep,name=annotations,proto3" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + StartsAt *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=starts_at,json=startsAt,proto3" json:"starts_at,omitempty"` + EndsAt *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=ends_at,json=endsAt,proto3" json:"ends_at,omitempty"` + UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` + CreatedBy string `protobuf:"bytes,7,opt,name=created_by,json=createdBy,proto3" json:"created_by,omitempty"` + Comment string `protobuf:"bytes,8,opt,name=comment,proto3" json:"comment,omitempty"` + MatcherSets []*MatcherSet `protobuf:"bytes,9,rep,name=matcher_sets,json=matcherSets,proto3" json:"matcher_sets,omitempty"` + ReceiverMatcherSets []*MatcherSet `protobuf:"bytes,10,rep,name=receiver_matcher_sets,json=receiverMatcherSets,proto3" json:"receiver_matcher_sets,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Silence) Reset() { + *x = Silence{} + mi := &file_events_v2_events_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Silence) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Silence) ProtoMessage() {} + +func (x *Silence) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[12] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Silence.ProtoReflect.Descriptor instead. +func (*Silence) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{12} +} + +func (x *Silence) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Silence) GetMatchers() []*Matcher { + if x != nil { + return x.Matchers + } + return nil +} + +func (x *Silence) GetAnnotations() map[string]string { + if x != nil { + return x.Annotations + } + return nil +} + +func (x *Silence) GetStartsAt() *timestamppb.Timestamp { + if x != nil { + return x.StartsAt + } + return nil +} + +func (x *Silence) GetEndsAt() *timestamppb.Timestamp { + if x != nil { + return x.EndsAt + } + return nil +} + +func (x *Silence) GetUpdatedAt() *timestamppb.Timestamp { + if x != nil { + return x.UpdatedAt + } + return nil +} + +func (x *Silence) GetCreatedBy() string { + if x != nil { + return x.CreatedBy + } + return "" +} + +func (x *Silence) GetComment() string { + if x != nil { + return x.Comment + } + return "" +} + +func (x *Silence) GetMatcherSets() []*MatcherSet { + if x != nil { + return x.MatcherSets + } + return nil +} + +func (x *Silence) GetReceiverMatcherSets() []*MatcherSet { + if x != nil { + return x.ReceiverMatcherSets + } + return nil +} + +// Matcher defines a single label matching rule. +type Matcher struct { + state protoimpl.MessageState `protogen:"open.v1"` + Type Matcher_Type `protobuf:"varint,1,opt,name=type,proto3,enum=events.v2.Matcher_Type" json:"type,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Pattern string `protobuf:"bytes,3,opt,name=pattern,proto3" json:"pattern,omitempty"` + Rendered string `protobuf:"bytes,4,opt,name=rendered,proto3" json:"rendered,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Matcher) Reset() { + *x = Matcher{} + mi := &file_events_v2_events_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Matcher) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Matcher) ProtoMessage() {} + +func (x *Matcher) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[13] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Matcher.ProtoReflect.Descriptor instead. +func (*Matcher) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{13} +} + +func (x *Matcher) GetType() Matcher_Type { + if x != nil { + return x.Type + } + return Matcher_TYPE_UNSPECIFIED +} + +func (x *Matcher) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Matcher) GetPattern() string { + if x != nil { + return x.Pattern + } + return "" +} + +func (x *Matcher) GetRendered() string { + if x != nil { + return x.Rendered + } + return "" +} + +// MatcherSet is a conjunction of matchers. +type MatcherSet struct { + state protoimpl.MessageState `protogen:"open.v1"` + Matchers []*Matcher `protobuf:"bytes,1,rep,name=matchers,proto3" json:"matchers,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MatcherSet) Reset() { + *x = MatcherSet{} + mi := &file_events_v2_events_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MatcherSet) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MatcherSet) ProtoMessage() {} + +func (x *MatcherSet) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[14] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MatcherSet.ProtoReflect.Descriptor instead. +func (*MatcherSet) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{14} +} + +func (x *MatcherSet) GetMatchers() []*Matcher { + if x != nil { + return x.Matchers + } + return nil +} + +// SilenceCreatedEvent is emitted when a silence is created. +type SilenceCreatedEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + Silence *Silence `protobuf:"bytes,1,opt,name=silence,proto3" json:"silence,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SilenceCreatedEvent) Reset() { + *x = SilenceCreatedEvent{} + mi := &file_events_v2_events_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SilenceCreatedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SilenceCreatedEvent) ProtoMessage() {} + +func (x *SilenceCreatedEvent) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[15] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SilenceCreatedEvent.ProtoReflect.Descriptor instead. +func (*SilenceCreatedEvent) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{15} +} + +func (x *SilenceCreatedEvent) GetSilence() *Silence { + if x != nil { + return x.Silence + } + return nil +} + +// SilenceUpdatedEvent is emitted when a silence is modified. +type SilenceUpdatedEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + Silence *Silence `protobuf:"bytes,1,opt,name=silence,proto3" json:"silence,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SilenceUpdatedEvent) Reset() { + *x = SilenceUpdatedEvent{} + mi := &file_events_v2_events_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SilenceUpdatedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SilenceUpdatedEvent) ProtoMessage() {} + +func (x *SilenceUpdatedEvent) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[16] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SilenceUpdatedEvent.ProtoReflect.Descriptor instead. +func (*SilenceUpdatedEvent) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{16} +} + +func (x *SilenceUpdatedEvent) GetSilence() *Silence { + if x != nil { + return x.Silence + } + return nil +} + +// MutedAlert identifies an alert suppressed by a silence or inhibition rule. +type MutedAlert struct { + state protoimpl.MessageState `protogen:"open.v1"` + Labels map[string]string `protobuf:"bytes,1,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` + Fingerprint uint64 `protobuf:"varint,2,opt,name=fingerprint,proto3" json:"fingerprint,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *MutedAlert) Reset() { + *x = MutedAlert{} + mi := &file_events_v2_events_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *MutedAlert) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MutedAlert) ProtoMessage() {} + +func (x *MutedAlert) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[17] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MutedAlert.ProtoReflect.Descriptor instead. +func (*MutedAlert) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{17} +} + +func (x *MutedAlert) GetLabels() map[string]string { + if x != nil { + return x.Labels + } + return nil +} + +func (x *MutedAlert) GetFingerprint() uint64 { + if x != nil { + return x.Fingerprint + } + return 0 +} + +// SilenceMutedAlertEvent is emitted when a silence suppresses an alert. +type SilenceMutedAlertEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + Silence *Silence `protobuf:"bytes,1,opt,name=silence,proto3" json:"silence,omitempty"` + MutedAlert *MutedAlert `protobuf:"bytes,2,opt,name=muted_alert,json=mutedAlert,proto3" json:"muted_alert,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *SilenceMutedAlertEvent) Reset() { + *x = SilenceMutedAlertEvent{} + mi := &file_events_v2_events_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SilenceMutedAlertEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SilenceMutedAlertEvent) ProtoMessage() {} + +func (x *SilenceMutedAlertEvent) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[18] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SilenceMutedAlertEvent.ProtoReflect.Descriptor instead. +func (*SilenceMutedAlertEvent) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{18} +} + +func (x *SilenceMutedAlertEvent) GetSilence() *Silence { + if x != nil { + return x.Silence + } + return nil +} + +func (x *SilenceMutedAlertEvent) GetMutedAlert() *MutedAlert { + if x != nil { + return x.MutedAlert + } + return nil +} + +// InhibitRule is a snapshot of an inhibition rule definition. +type InhibitRule struct { + state protoimpl.MessageState `protogen:"open.v1"` + SourceMatchers []*Matcher `protobuf:"bytes,1,rep,name=source_matchers,json=sourceMatchers,proto3" json:"source_matchers,omitempty"` + TargetMatchers []*Matcher `protobuf:"bytes,2,rep,name=target_matchers,json=targetMatchers,proto3" json:"target_matchers,omitempty"` + EqualLabels []string `protobuf:"bytes,3,rep,name=equal_labels,json=equalLabels,proto3" json:"equal_labels,omitempty"` + Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InhibitRule) Reset() { + *x = InhibitRule{} + mi := &file_events_v2_events_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InhibitRule) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InhibitRule) ProtoMessage() {} + +func (x *InhibitRule) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InhibitRule.ProtoReflect.Descriptor instead. +func (*InhibitRule) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{19} +} + +func (x *InhibitRule) GetSourceMatchers() []*Matcher { + if x != nil { + return x.SourceMatchers + } + return nil +} + +func (x *InhibitRule) GetTargetMatchers() []*Matcher { + if x != nil { + return x.TargetMatchers + } + return nil +} + +func (x *InhibitRule) GetEqualLabels() []string { + if x != nil { + return x.EqualLabels + } + return nil +} + +func (x *InhibitRule) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +// InhibitionMutedAlertEvent is emitted when inhibition suppresses an alert. +type InhibitionMutedAlertEvent struct { + state protoimpl.MessageState `protogen:"open.v1"` + InhibitRules []*InhibitRule `protobuf:"bytes,1,rep,name=inhibit_rules,json=inhibitRules,proto3" json:"inhibit_rules,omitempty"` + MutedAlert *MutedAlert `protobuf:"bytes,2,opt,name=muted_alert,json=mutedAlert,proto3" json:"muted_alert,omitempty"` + InhibitingFingerprints []uint64 `protobuf:"varint,3,rep,packed,name=inhibiting_fingerprints,json=inhibitingFingerprints,proto3" json:"inhibiting_fingerprints,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InhibitionMutedAlertEvent) Reset() { + *x = InhibitionMutedAlertEvent{} + mi := &file_events_v2_events_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InhibitionMutedAlertEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InhibitionMutedAlertEvent) ProtoMessage() {} + +func (x *InhibitionMutedAlertEvent) ProtoReflect() protoreflect.Message { + mi := &file_events_v2_events_proto_msgTypes[20] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InhibitionMutedAlertEvent.ProtoReflect.Descriptor instead. +func (*InhibitionMutedAlertEvent) Descriptor() ([]byte, []int) { + return file_events_v2_events_proto_rawDescGZIP(), []int{20} +} + +func (x *InhibitionMutedAlertEvent) GetInhibitRules() []*InhibitRule { + if x != nil { + return x.InhibitRules + } + return nil +} + +func (x *InhibitionMutedAlertEvent) GetMutedAlert() *MutedAlert { + if x != nil { + return x.MutedAlert + } + return nil +} + +func (x *InhibitionMutedAlertEvent) GetInhibitingFingerprints() []uint64 { + if x != nil { + return x.InhibitingFingerprints + } + return nil +} + +var File_events_v2_events_proto protoreflect.FileDescriptor + +const file_events_v2_events_proto_rawDesc = "" + + "\n" + + "\x16events/v2/events.proto\x12\tevents.v2\x1a\x1egoogle/protobuf/duration.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xb3\x01\n" + + "\x05Event\x129\n" + + "\ttimestamp\x18\x01 \x01(\v2\x1a.google.protobuf.TimestampR\n" + + "@timestamp\x12\x1a\n" + + "\binstance\x18\x02 \x01(\tR\binstance\x12(\n" + + "\x04data\x18\x03 \x01(\v2\x14.events.v2.EventDataR\x04data\x12)\n" + + "\x10cluster_position\x18\x04 \x01(\x04R\x0fclusterPosition\"\xc5\x06\n" + + "\tEventData\x12c\n" + + "\x1aalertmanager_startup_event\x18\x01 \x01(\v2#.events.v2.AlertmanagerStartupEventH\x00R\x18alertmanagerStartupEvent\x12f\n" + + "\x1balertmanager_shutdown_event\x18\x02 \x01(\v2$.events.v2.AlertmanagerShutdownEventH\x00R\x19alertmanagerShutdownEvent\x12C\n" + + "\ralert_created\x18\x03 \x01(\v2\x1c.events.v2.AlertCreatedEventH\x00R\falertCreated\x12F\n" + + "\x0ealert_resolved\x18\x04 \x01(\v2\x1d.events.v2.AlertResolvedEventH\x00R\ralertResolved\x12C\n" + + "\ralert_grouped\x18\x05 \x01(\v2\x1c.events.v2.AlertGroupedEventH\x00R\falertGrouped\x12B\n" + + "\fnotification\x18\x06 \x01(\v2\x1c.events.v2.NotificationEventH\x00R\fnotification\x12I\n" + + "\x0fsilence_created\x18\a \x01(\v2\x1e.events.v2.SilenceCreatedEventH\x00R\x0esilenceCreated\x12I\n" + + "\x0fsilence_updated\x18\b \x01(\v2\x1e.events.v2.SilenceUpdatedEventH\x00R\x0esilenceUpdated\x12S\n" + + "\x13silence_muted_alert\x18\t \x01(\v2!.events.v2.SilenceMutedAlertEventH\x00R\x11silenceMutedAlert\x12\\\n" + + "\x16inhibition_muted_alert\x18\n" + + " \x01(\v2$.events.v2.InhibitionMutedAlertEventH\x00R\x14inhibitionMutedAlertB\f\n" + + "\n" + + "event_type\"Y\n" + + "\x18AlertmanagerStartupEvent\x12\x18\n" + + "\aversion\x18\x01 \x01(\tR\aversion\x12#\n" + + "\rbuild_context\x18\x02 \x01(\tR\fbuildContext\"\x1b\n" + + "\x19AlertmanagerShutdownEvent\"\xbd\x03\n" + + "\x05Alert\x12 \n" + + "\vfingerprint\x18\x01 \x01(\x04R\vfingerprint\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\x124\n" + + "\x06labels\x18\x03 \x03(\v2\x1c.events.v2.Alert.LabelsEntryR\x06labels\x12C\n" + + "\vannotations\x18\x04 \x03(\v2!.events.v2.Alert.AnnotationsEntryR\vannotations\x127\n" + + "\tstarts_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\bstartsAt\x123\n" + + "\aends_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\x06endsAt\x12\x1a\n" + + "\bresolved\x18\a \x01(\bR\bresolved\x1a9\n" + + "\vLabelsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\x1a>\n" + + "\x10AnnotationsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"_\n" + + "\fGroupedAlert\x12\x12\n" + + "\x04hash\x18\x01 \x01(\x04R\x04hash\x12/\n" + + "\adetails\x18\x02 \x01(\v2\x10.events.v2.AlertH\x00R\adetails\x88\x01\x01B\n" + + "\n" + + "\b_details\"\xcb\x02\n" + + "\x0eAlertGroupInfo\x12\x1b\n" + + "\tgroup_key\x18\x01 \x01(\tR\bgroupKey\x12M\n" + + "\fgroup_labels\x18\x02 \x03(\v2*.events.v2.AlertGroupInfo.GroupLabelsEntryR\vgroupLabels\x12\x19\n" + + "\bgroup_id\x18\x03 \x01(\tR\agroupId\x12#\n" + + "\rreceiver_name\x18\x04 \x01(\tR\freceiverName\x12.\n" + + "\bmatchers\x18\x05 \x03(\v2\x12.events.v2.MatcherR\bmatchers\x12\x1d\n" + + "\n" + + "group_uuid\x18\x06 \x01(\tR\tgroupUuid\x1a>\n" + + "\x10GroupLabelsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\";\n" + + "\x11AlertCreatedEvent\x12&\n" + + "\x05alert\x18\x01 \x01(\v2\x10.events.v2.AlertR\x05alert\"}\n" + + "\x12AlertResolvedEvent\x12-\n" + + "\x05alert\x18\x01 \x01(\v2\x17.events.v2.GroupedAlertR\x05alert\x128\n" + + "\n" + + "group_info\x18\x02 \x01(\v2\x19.events.v2.AlertGroupInfoR\tgroupInfo\"|\n" + + "\x11AlertGroupedEvent\x12-\n" + + "\x05alert\x18\x01 \x01(\v2\x17.events.v2.GroupedAlertR\x05alert\x128\n" + + "\n" + + "group_info\x18\x02 \x01(\v2\x19.events.v2.AlertGroupInfoR\tgroupInfo\"7\n" + + "\vIntegration\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12\x14\n" + + "\x05index\x18\x02 \x01(\x03R\x05index\"\x84\x04\n" + + "\x11NotificationEvent\x12/\n" + + "\x06alerts\x18\x01 \x03(\v2\x17.events.v2.GroupedAlertR\x06alerts\x12<\n" + + "\rfiring_alerts\x18\x02 \x03(\v2\x17.events.v2.GroupedAlertR\ffiringAlerts\x12@\n" + + "\x0fresolved_alerts\x18\x03 \x03(\v2\x17.events.v2.GroupedAlertR\x0eresolvedAlerts\x12:\n" + + "\fmuted_alerts\x18\x04 \x03(\v2\x17.events.v2.GroupedAlertR\vmutedAlerts\x128\n" + + "\n" + + "group_info\x18\x05 \x01(\v2\x19.events.v2.AlertGroupInfoR\tgroupInfo\x12B\n" + + "\x0frepeat_interval\x18\x06 \x01(\v2\x19.google.protobuf.DurationR\x0erepeatInterval\x12/\n" + + "\x06reason\x18\a \x01(\x0e2\x17.events.v2.NotifyReasonR\x06reason\x12\x19\n" + + "\bflush_id\x18\b \x01(\x04R\aflushId\x128\n" + + "\vintegration\x18\t \x01(\v2\x16.events.v2.IntegrationR\vintegration\"\xb7\x04\n" + + "\aSilence\x12\x0e\n" + + "\x02id\x18\x01 \x01(\tR\x02id\x12.\n" + + "\bmatchers\x18\x02 \x03(\v2\x12.events.v2.MatcherR\bmatchers\x12E\n" + + "\vannotations\x18\x03 \x03(\v2#.events.v2.Silence.AnnotationsEntryR\vannotations\x127\n" + + "\tstarts_at\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampR\bstartsAt\x123\n" + + "\aends_at\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampR\x06endsAt\x129\n" + + "\n" + + "updated_at\x18\x06 \x01(\v2\x1a.google.protobuf.TimestampR\tupdatedAt\x12\x1d\n" + + "\n" + + "created_by\x18\a \x01(\tR\tcreatedBy\x12\x18\n" + + "\acomment\x18\b \x01(\tR\acomment\x128\n" + + "\fmatcher_sets\x18\t \x03(\v2\x15.events.v2.MatcherSetR\vmatcherSets\x12I\n" + + "\x15receiver_matcher_sets\x18\n" + + " \x03(\v2\x15.events.v2.MatcherSetR\x13receiverMatcherSets\x1a>\n" + + "\x10AnnotationsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\xe8\x01\n" + + "\aMatcher\x12+\n" + + "\x04type\x18\x01 \x01(\x0e2\x17.events.v2.Matcher.TypeR\x04type\x12\x12\n" + + "\x04name\x18\x02 \x01(\tR\x04name\x12\x18\n" + + "\apattern\x18\x03 \x01(\tR\apattern\x12\x1a\n" + + "\brendered\x18\x04 \x01(\tR\brendered\"f\n" + + "\x04Type\x12\x14\n" + + "\x10TYPE_UNSPECIFIED\x10\x00\x12\x0e\n" + + "\n" + + "TYPE_EQUAL\x10\x01\x12\x0f\n" + + "\vTYPE_REGEXP\x10\x02\x12\x12\n" + + "\x0eTYPE_NOT_EQUAL\x10\x03\x12\x13\n" + + "\x0fTYPE_NOT_REGEXP\x10\x04\"<\n" + + "\n" + + "MatcherSet\x12.\n" + + "\bmatchers\x18\x01 \x03(\v2\x12.events.v2.MatcherR\bmatchers\"C\n" + + "\x13SilenceCreatedEvent\x12,\n" + + "\asilence\x18\x01 \x01(\v2\x12.events.v2.SilenceR\asilence\"C\n" + + "\x13SilenceUpdatedEvent\x12,\n" + + "\asilence\x18\x01 \x01(\v2\x12.events.v2.SilenceR\asilence\"\xa4\x01\n" + + "\n" + + "MutedAlert\x129\n" + + "\x06labels\x18\x01 \x03(\v2!.events.v2.MutedAlert.LabelsEntryR\x06labels\x12 \n" + + "\vfingerprint\x18\x02 \x01(\x04R\vfingerprint\x1a9\n" + + "\vLabelsEntry\x12\x10\n" + + "\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" + + "\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"~\n" + + "\x16SilenceMutedAlertEvent\x12,\n" + + "\asilence\x18\x01 \x01(\v2\x12.events.v2.SilenceR\asilence\x126\n" + + "\vmuted_alert\x18\x02 \x01(\v2\x15.events.v2.MutedAlertR\n" + + "mutedAlert\"\xbe\x01\n" + + "\vInhibitRule\x12;\n" + + "\x0fsource_matchers\x18\x01 \x03(\v2\x12.events.v2.MatcherR\x0esourceMatchers\x12;\n" + + "\x0ftarget_matchers\x18\x02 \x03(\v2\x12.events.v2.MatcherR\x0etargetMatchers\x12!\n" + + "\fequal_labels\x18\x03 \x03(\tR\vequalLabels\x12\x12\n" + + "\x04name\x18\x04 \x01(\tR\x04name\"\xc9\x01\n" + + "\x19InhibitionMutedAlertEvent\x12;\n" + + "\rinhibit_rules\x18\x01 \x03(\v2\x16.events.v2.InhibitRuleR\finhibitRules\x126\n" + + "\vmuted_alert\x18\x02 \x01(\v2\x15.events.v2.MutedAlertR\n" + + "mutedAlert\x127\n" + + "\x17inhibiting_fingerprints\x18\x03 \x03(\x04R\x16inhibitingFingerprints*\xf3\x01\n" + + "\fNotifyReason\x12\x1d\n" + + "\x19NOTIFY_REASON_UNSPECIFIED\x10\x00\x12$\n" + + " NOTIFY_REASON_FIRST_NOTIFICATION\x10\x01\x12%\n" + + "!NOTIFY_REASON_NEW_ALERTS_IN_GROUP\x10\x02\x12%\n" + + "!NOTIFY_REASON_NEW_RESOLVED_ALERTS\x10\x03\x12%\n" + + "!NOTIFY_REASON_ALL_ALERTS_RESOLVED\x10\x04\x12)\n" + + "%NOTIFY_REASON_REPEAT_INTERVAL_ELAPSED\x10\x05BEZCgithub.com/prometheus/alertmanager/eventrecorder/events/v2;eventsv2b\x06proto3" + +var ( + file_events_v2_events_proto_rawDescOnce sync.Once + file_events_v2_events_proto_rawDescData []byte +) + +func file_events_v2_events_proto_rawDescGZIP() []byte { + file_events_v2_events_proto_rawDescOnce.Do(func() { + file_events_v2_events_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_events_v2_events_proto_rawDesc), len(file_events_v2_events_proto_rawDesc))) + }) + return file_events_v2_events_proto_rawDescData +} + +var file_events_v2_events_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_events_v2_events_proto_msgTypes = make([]protoimpl.MessageInfo, 26) +var file_events_v2_events_proto_goTypes = []any{ + (NotifyReason)(0), // 0: events.v2.NotifyReason + (Matcher_Type)(0), // 1: events.v2.Matcher.Type + (*Event)(nil), // 2: events.v2.Event + (*EventData)(nil), // 3: events.v2.EventData + (*AlertmanagerStartupEvent)(nil), // 4: events.v2.AlertmanagerStartupEvent + (*AlertmanagerShutdownEvent)(nil), // 5: events.v2.AlertmanagerShutdownEvent + (*Alert)(nil), // 6: events.v2.Alert + (*GroupedAlert)(nil), // 7: events.v2.GroupedAlert + (*AlertGroupInfo)(nil), // 8: events.v2.AlertGroupInfo + (*AlertCreatedEvent)(nil), // 9: events.v2.AlertCreatedEvent + (*AlertResolvedEvent)(nil), // 10: events.v2.AlertResolvedEvent + (*AlertGroupedEvent)(nil), // 11: events.v2.AlertGroupedEvent + (*Integration)(nil), // 12: events.v2.Integration + (*NotificationEvent)(nil), // 13: events.v2.NotificationEvent + (*Silence)(nil), // 14: events.v2.Silence + (*Matcher)(nil), // 15: events.v2.Matcher + (*MatcherSet)(nil), // 16: events.v2.MatcherSet + (*SilenceCreatedEvent)(nil), // 17: events.v2.SilenceCreatedEvent + (*SilenceUpdatedEvent)(nil), // 18: events.v2.SilenceUpdatedEvent + (*MutedAlert)(nil), // 19: events.v2.MutedAlert + (*SilenceMutedAlertEvent)(nil), // 20: events.v2.SilenceMutedAlertEvent + (*InhibitRule)(nil), // 21: events.v2.InhibitRule + (*InhibitionMutedAlertEvent)(nil), // 22: events.v2.InhibitionMutedAlertEvent + nil, // 23: events.v2.Alert.LabelsEntry + nil, // 24: events.v2.Alert.AnnotationsEntry + nil, // 25: events.v2.AlertGroupInfo.GroupLabelsEntry + nil, // 26: events.v2.Silence.AnnotationsEntry + nil, // 27: events.v2.MutedAlert.LabelsEntry + (*timestamppb.Timestamp)(nil), // 28: google.protobuf.Timestamp + (*durationpb.Duration)(nil), // 29: google.protobuf.Duration +} +var file_events_v2_events_proto_depIdxs = []int32{ + 28, // 0: events.v2.Event.timestamp:type_name -> google.protobuf.Timestamp + 3, // 1: events.v2.Event.data:type_name -> events.v2.EventData + 4, // 2: events.v2.EventData.alertmanager_startup_event:type_name -> events.v2.AlertmanagerStartupEvent + 5, // 3: events.v2.EventData.alertmanager_shutdown_event:type_name -> events.v2.AlertmanagerShutdownEvent + 9, // 4: events.v2.EventData.alert_created:type_name -> events.v2.AlertCreatedEvent + 10, // 5: events.v2.EventData.alert_resolved:type_name -> events.v2.AlertResolvedEvent + 11, // 6: events.v2.EventData.alert_grouped:type_name -> events.v2.AlertGroupedEvent + 13, // 7: events.v2.EventData.notification:type_name -> events.v2.NotificationEvent + 17, // 8: events.v2.EventData.silence_created:type_name -> events.v2.SilenceCreatedEvent + 18, // 9: events.v2.EventData.silence_updated:type_name -> events.v2.SilenceUpdatedEvent + 20, // 10: events.v2.EventData.silence_muted_alert:type_name -> events.v2.SilenceMutedAlertEvent + 22, // 11: events.v2.EventData.inhibition_muted_alert:type_name -> events.v2.InhibitionMutedAlertEvent + 23, // 12: events.v2.Alert.labels:type_name -> events.v2.Alert.LabelsEntry + 24, // 13: events.v2.Alert.annotations:type_name -> events.v2.Alert.AnnotationsEntry + 28, // 14: events.v2.Alert.starts_at:type_name -> google.protobuf.Timestamp + 28, // 15: events.v2.Alert.ends_at:type_name -> google.protobuf.Timestamp + 6, // 16: events.v2.GroupedAlert.details:type_name -> events.v2.Alert + 25, // 17: events.v2.AlertGroupInfo.group_labels:type_name -> events.v2.AlertGroupInfo.GroupLabelsEntry + 15, // 18: events.v2.AlertGroupInfo.matchers:type_name -> events.v2.Matcher + 6, // 19: events.v2.AlertCreatedEvent.alert:type_name -> events.v2.Alert + 7, // 20: events.v2.AlertResolvedEvent.alert:type_name -> events.v2.GroupedAlert + 8, // 21: events.v2.AlertResolvedEvent.group_info:type_name -> events.v2.AlertGroupInfo + 7, // 22: events.v2.AlertGroupedEvent.alert:type_name -> events.v2.GroupedAlert + 8, // 23: events.v2.AlertGroupedEvent.group_info:type_name -> events.v2.AlertGroupInfo + 7, // 24: events.v2.NotificationEvent.alerts:type_name -> events.v2.GroupedAlert + 7, // 25: events.v2.NotificationEvent.firing_alerts:type_name -> events.v2.GroupedAlert + 7, // 26: events.v2.NotificationEvent.resolved_alerts:type_name -> events.v2.GroupedAlert + 7, // 27: events.v2.NotificationEvent.muted_alerts:type_name -> events.v2.GroupedAlert + 8, // 28: events.v2.NotificationEvent.group_info:type_name -> events.v2.AlertGroupInfo + 29, // 29: events.v2.NotificationEvent.repeat_interval:type_name -> google.protobuf.Duration + 0, // 30: events.v2.NotificationEvent.reason:type_name -> events.v2.NotifyReason + 12, // 31: events.v2.NotificationEvent.integration:type_name -> events.v2.Integration + 15, // 32: events.v2.Silence.matchers:type_name -> events.v2.Matcher + 26, // 33: events.v2.Silence.annotations:type_name -> events.v2.Silence.AnnotationsEntry + 28, // 34: events.v2.Silence.starts_at:type_name -> google.protobuf.Timestamp + 28, // 35: events.v2.Silence.ends_at:type_name -> google.protobuf.Timestamp + 28, // 36: events.v2.Silence.updated_at:type_name -> google.protobuf.Timestamp + 16, // 37: events.v2.Silence.matcher_sets:type_name -> events.v2.MatcherSet + 16, // 38: events.v2.Silence.receiver_matcher_sets:type_name -> events.v2.MatcherSet + 1, // 39: events.v2.Matcher.type:type_name -> events.v2.Matcher.Type + 15, // 40: events.v2.MatcherSet.matchers:type_name -> events.v2.Matcher + 14, // 41: events.v2.SilenceCreatedEvent.silence:type_name -> events.v2.Silence + 14, // 42: events.v2.SilenceUpdatedEvent.silence:type_name -> events.v2.Silence + 27, // 43: events.v2.MutedAlert.labels:type_name -> events.v2.MutedAlert.LabelsEntry + 14, // 44: events.v2.SilenceMutedAlertEvent.silence:type_name -> events.v2.Silence + 19, // 45: events.v2.SilenceMutedAlertEvent.muted_alert:type_name -> events.v2.MutedAlert + 15, // 46: events.v2.InhibitRule.source_matchers:type_name -> events.v2.Matcher + 15, // 47: events.v2.InhibitRule.target_matchers:type_name -> events.v2.Matcher + 21, // 48: events.v2.InhibitionMutedAlertEvent.inhibit_rules:type_name -> events.v2.InhibitRule + 19, // 49: events.v2.InhibitionMutedAlertEvent.muted_alert:type_name -> events.v2.MutedAlert + 50, // [50:50] is the sub-list for method output_type + 50, // [50:50] is the sub-list for method input_type + 50, // [50:50] is the sub-list for extension type_name + 50, // [50:50] is the sub-list for extension extendee + 0, // [0:50] is the sub-list for field type_name +} + +func init() { file_events_v2_events_proto_init() } +func file_events_v2_events_proto_init() { + if File_events_v2_events_proto != nil { + return + } + file_events_v2_events_proto_msgTypes[1].OneofWrappers = []any{ + (*EventData_AlertmanagerStartupEvent)(nil), + (*EventData_AlertmanagerShutdownEvent)(nil), + (*EventData_AlertCreated)(nil), + (*EventData_AlertResolved)(nil), + (*EventData_AlertGrouped)(nil), + (*EventData_Notification)(nil), + (*EventData_SilenceCreated)(nil), + (*EventData_SilenceUpdated)(nil), + (*EventData_SilenceMutedAlert)(nil), + (*EventData_InhibitionMutedAlert)(nil), + } + file_events_v2_events_proto_msgTypes[5].OneofWrappers = []any{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_events_v2_events_proto_rawDesc), len(file_events_v2_events_proto_rawDesc)), + NumEnums: 2, + NumMessages: 26, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_events_v2_events_proto_goTypes, + DependencyIndexes: file_events_v2_events_proto_depIdxs, + EnumInfos: file_events_v2_events_proto_enumTypes, + MessageInfos: file_events_v2_events_proto_msgTypes, + }.Build() + File_events_v2_events_proto = out.File + file_events_v2_events_proto_goTypes = nil + file_events_v2_events_proto_depIdxs = nil +} diff --git a/eventrecorder/events_test.go b/eventrecorder/events_test.go index 01983f2fb9..57f36180ad 100644 --- a/eventrecorder/events_test.go +++ b/eventrecorder/events_test.go @@ -14,107 +14,149 @@ package eventrecorder import ( + "encoding/json" "testing" + "time" "github.com/prometheus/common/model" "github.com/stretchr/testify/require" - "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" + "github.com/prometheus/alertmanager/alert" + events "github.com/prometheus/alertmanager/eventrecorder/events/v2" "github.com/prometheus/alertmanager/pkg/labels" + "github.com/prometheus/alertmanager/silence/silencepb" ) -func TestExtractEventType(t *testing.T) { - tests := []struct { - name string - event *eventrecorderpb.EventData - expected string - }{ - { - name: "startup", - event: startupEvent(), - expected: "alertmanager_startup_event", - }, - { - name: "shutdown", - event: &eventrecorderpb.EventData{ - EventType: &eventrecorderpb.EventData_AlertmanagerShutdownEvent{}, - }, - expected: "alertmanager_shutdown_event", - }, - { - name: "alert_created", - event: &eventrecorderpb.EventData{ - EventType: &eventrecorderpb.EventData_AlertCreated{}, - }, - expected: "alert_created", - }, - { - name: "unknown", - event: &eventrecorderpb.EventData{}, - expected: "unknown", - }, - { - name: "nil", - event: nil, - expected: "unknown", - }, - } - for _, tc := range tests { - t.Run(tc.name, func(t *testing.T) { - require.Equal(t, tc.expected, extractEventType(tc.event)) - }) - } -} +func TestAlertEventSnapshotsLabels(t *testing.T) { + a := &alert.Alert{Alert: model.Alert{ + Labels: model.LabelSet{"alertname": "Down", "severity": "warning"}, Annotations: model.LabelSet{"summary": "test"}, + StartsAt: time.Now(), EndsAt: time.Now().Add(time.Hour), + }} + event := NewAlertCreatedEvent(a) -func TestLabelSetAsProto(t *testing.T) { - ls := model.LabelSet{"foo": "bar", "baz": "qux"} - proto := LabelSetAsProto(ls) + a.Labels["severity"] = "critical" + a.Annotations["summary"] = "changed" - require.Len(t, proto.Labels, 2) - found := map[string]string{} - for _, lp := range proto.Labels { - found[lp.Key] = lp.Value - } - require.Equal(t, "bar", found["foo"]) - require.Equal(t, "qux", found["baz"]) + got := event.message.GetAlertCreated().Alert + require.Equal(t, "warning", got.Labels["severity"]) + require.Equal(t, "test", got.Annotations["summary"]) } -func TestMatcherAsProto(t *testing.T) { - m, err := labels.NewMatcher(labels.MatchRegexp, "job", "api.*") - require.NoError(t, err) - - proto := MatcherAsProto(m) - require.Equal(t, eventrecorderpb.Matcher_TYPE_REGEXP, proto.Type) - require.Equal(t, "job", proto.Name) - require.Equal(t, "api.*", proto.Pattern) - require.NotEmpty(t, proto.Rendered) -} +func TestSilenceEventSnapshotsAnnotationsAndMatchers(t *testing.T) { + silence := &silencepb.Silence{ + Annotations: map[string]string{"owner": "ops"}, + MatcherSets: []*silencepb.MatcherSet{{Matchers: []*silencepb.Matcher{{ + Type: silencepb.Matcher_EQUAL, Name: "service", Pattern: "api", + }}}}, + ReceiverMatcherSets: []*silencepb.MatcherSet{{Matchers: []*silencepb.Matcher{{ + Type: silencepb.Matcher_EQUAL, Name: "team", Pattern: "platform", + }}}}, + } + event := NewSilenceCreatedEvent(silence) -func TestMatchersAsProto(t *testing.T) { - m1, err := labels.NewMatcher(labels.MatchEqual, "env", "prod") - require.NoError(t, err) - m2, err := labels.NewMatcher(labels.MatchNotEqual, "team", "") - require.NoError(t, err) + silence.Annotations["owner"] = "changed" + silence.MatcherSets[0].Matchers[0].Pattern = "changed" + silence.ReceiverMatcherSets[0].Matchers[0].Pattern = "changed" - protos := MatchersAsProto(labels.Matchers{m1, m2}) - require.Len(t, protos, 2) - require.Equal(t, eventrecorderpb.Matcher_TYPE_EQUAL, protos[0].Type) - require.Equal(t, eventrecorderpb.Matcher_TYPE_NOT_EQUAL, protos[1].Type) + got := event.message.GetSilenceCreated().Silence + require.Equal(t, "ops", got.Annotations["owner"]) + require.Equal(t, "api", got.Matchers[0].Pattern) + require.Equal(t, "platform", got.ReceiverMatcherSets[0].Matchers[0].Pattern) } -func TestInhibitRuleAsProto(t *testing.T) { +func TestInhibitRuleSnapshot(t *testing.T) { source, err := labels.NewMatcher(labels.MatchEqual, "severity", "critical") require.NoError(t, err) target, err := labels.NewMatcher(labels.MatchEqual, "severity", "warning") require.NoError(t, err) equal := map[model.LabelName]struct{}{"cluster": {}, "alertname": {}} - proto := InhibitRuleAsProto("my-rule", labels.Matchers{source}, labels.Matchers{target}, equal) + rule := NewInhibitRule("my-rule", labels.Matchers{source}, labels.Matchers{target}, equal) + delete(equal, "cluster") + + require.Equal(t, "my-rule", rule.message.Name) + require.Equal(t, []string{"alertname", "cluster"}, rule.message.EqualLabels) + require.Equal(t, "severity", rule.message.SourceMatchers[0].Name) +} + +func TestEventTypeName(t *testing.T) { + require.Equal(t, "unknown", (EventData{}).typeName()) + require.Equal(t, "unknown", (Event{}).typeName()) + require.Equal(t, "alert_created", NewAlertCreatedEvent(nil).typeName()) +} + +func TestConstructorsHandleNilMatchers(t *testing.T) { + require.NotPanics(t, func() { + group := NewAlertGroup("", nil, "", "", labels.Matchers{nil}, "") + require.Empty(t, group.message.Matchers) + event := NewSilenceCreatedEvent(&silencepb.Silence{ + Matchers: []*silencepb.Matcher{nil}, + MatcherSets: []*silencepb.MatcherSet{nil, {Matchers: []*silencepb.Matcher{nil}}}, + ReceiverMatcherSets: []*silencepb.MatcherSet{nil, {Matchers: []*silencepb.Matcher{nil}}}, + }) + silence := event.message.GetSilenceCreated().Silence + require.Empty(t, silence.Matchers) + require.Len(t, silence.MatcherSets, 1) + require.Empty(t, silence.MatcherSets[0].Matchers) + require.Len(t, silence.ReceiverMatcherSets, 1) + require.Empty(t, silence.ReceiverMatcherSets[0].Matchers) + enveloped := event.withMetadata(nil, "", 0) + _, err := enveloped.MarshalJSON() + require.NoError(t, err) + _, err = enveloped.MarshalProtobuf() + require.NoError(t, err) + }) +} + +func TestSilenceEventPreservesLegacyMatchers(t *testing.T) { + event := NewSilenceCreatedEvent(&silencepb.Silence{ + Matchers: []*silencepb.Matcher{{Type: silencepb.Matcher_REGEXP, Name: "service", Pattern: "api.*"}}, + MatcherSets: []*silencepb.MatcherSet{{Matchers: []*silencepb.Matcher{{ + Type: silencepb.Matcher_EQUAL, Name: "fallback", Pattern: "ignored", + }}}}, + }) + + got := event.message.GetSilenceCreated().Silence.Matchers + require.Len(t, got, 1) + require.Equal(t, "service", got[0].Name) + require.Equal(t, "api.*", got[0].Pattern) +} + +func TestSilenceMatcherUnknownTypeHasNoRenderedValue(t *testing.T) { + matcher := silenceMatcherToEvents(&silencepb.Matcher{Type: silencepb.Matcher_Type(99), Name: "service", Pattern: "api"}) + require.Equal(t, events.Matcher_TYPE_UNSPECIFIED, matcher.Type) + require.Empty(t, matcher.Rendered) +} - require.Equal(t, "my-rule", proto.Name) - require.Len(t, proto.SourceMatchers, 1) - require.Equal(t, "severity", proto.SourceMatchers[0].Name) - require.Len(t, proto.TargetMatchers, 1) - require.Equal(t, "severity", proto.TargetMatchers[0].Name) - require.Equal(t, []string{"alertname", "cluster"}, proto.EqualLabels) +func TestNilMatchersAreAbsentFromJSON(t *testing.T) { + event := NewAlertGroupedEvent(NewAlertGroup("", nil, "", "", labels.Matchers{nil}, ""), NewGroupedAlertReference(1)).withMetadata(nil, "", 0) + data, err := event.MarshalJSON() + require.NoError(t, err) + + var decoded map[string]any + require.NoError(t, json.Unmarshal(data, &decoded)) + groupInfo := decoded["data"].(map[string]any)["alertGrouped"].(map[string]any)["groupInfo"].(map[string]any) + require.NotContains(t, groupInfo, "matchers") +} + +func TestEventConstructors(t *testing.T) { + group := NewAlertGroup("", nil, "", "", nil, "") + grouped := NewGroupedAlertReference(1) + rule := NewInhibitRule("", nil, nil, nil) + constructed := []EventData{ + NewAlertmanagerStartupEvent("", ""), + NewAlertmanagerShutdownEvent(), + NewAlertCreatedEvent(nil), + NewAlertGroupedEvent(group, grouped), + NewAlertResolvedEvent(group, grouped), + NewNotificationEvent(Notification{Group: group}), + NewSilenceMutedAlertEvent(nil, 0, nil), + NewSilenceCreatedEvent(nil), + NewSilenceUpdatedEvent(nil), + NewInhibitionMutedAlertEvent([]InhibitRule{rule}, 0, nil, nil), + } + + for _, event := range constructed { + require.NotNil(t, event.message.EventType) + } } diff --git a/eventrecorder/file.go b/eventrecorder/file.go index d29572de66..152072da9e 100644 --- a/eventrecorder/file.go +++ b/eventrecorder/file.go @@ -22,9 +22,6 @@ import ( "sync" "github.com/fsnotify/fsnotify" - "google.golang.org/protobuf/encoding/protojson" - - "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" ) // FileOutputConfig configures a JSONL file event recorder output. @@ -173,8 +170,8 @@ func (fo *FileOutput) watchLoop(ready chan<- error) { // SendEvent serializes the event as a JSON line and appends it to the // file. It returns the number of bytes written (including the trailing // newline) for the bytes-written metric. -func (fo *FileOutput) SendEvent(event *eventrecorderpb.Event) (int, error) { - data, err := protojson.Marshal(event) +func (fo *FileOutput) SendEvent(event Event) (int, error) { + data, err := event.MarshalJSON() if err != nil { return 0, &serializeError{err: err} } diff --git a/eventrecorder/kafka.go b/eventrecorder/kafka.go index d60f7082b7..3abe955676 100644 --- a/eventrecorder/kafka.go +++ b/eventrecorder/kafka.go @@ -25,10 +25,7 @@ import ( "github.com/prometheus/client_golang/prometheus" commoncfg "github.com/prometheus/common/config" "github.com/twmb/franz-go/pkg/kgo" - "google.golang.org/protobuf/encoding/protojson" - "google.golang.org/protobuf/proto" - "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" "github.com/prometheus/alertmanager/kafka" ) @@ -224,15 +221,15 @@ func (ko *KafkaOutput) Name() string { return ko.name } // SendEvent serializes the event in the configured format (JSON or // protobuf) and queues it for asynchronous delivery. It returns the // serialized size (for the bytes-written metric). -func (ko *KafkaOutput) SendEvent(event *eventrecorderpb.Event) (int, error) { +func (ko *KafkaOutput) SendEvent(event Event) (int, error) { var ( data []byte err error ) if ko.format == kafka.FormatProtobuf { - data, err = proto.Marshal(event) + data, err = event.MarshalProtobuf() } else { - data, err = protojson.Marshal(event) + data, err = event.MarshalJSON() } if err != nil { return 0, &serializeError{err: err} diff --git a/eventrecorder/kafka_test.go b/eventrecorder/kafka_test.go index 9fac564542..6e66982592 100644 --- a/eventrecorder/kafka_test.go +++ b/eventrecorder/kafka_test.go @@ -30,7 +30,7 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" "gopkg.in/yaml.v2" - "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" + events "github.com/prometheus/alertmanager/eventrecorder/events/v2" "github.com/prometheus/alertmanager/kafka" ) @@ -106,19 +106,19 @@ func counterValue(t *testing.T, c prometheus.Counter) float64 { return m.GetCounter().GetValue() } -func sampleEvent() *eventrecorderpb.Event { - return &eventrecorderpb.Event{ +func sampleEvent() Event { + return Event{message: &events.Event{ Timestamp: timestamppb.New(time.Unix(1700000000, 0)), Instance: "test-host", - Data: &eventrecorderpb.EventData{ - EventType: &eventrecorderpb.EventData_AlertmanagerStartupEvent{ - AlertmanagerStartupEvent: &eventrecorderpb.AlertmanagerStartupEvent{ + Data: &events.EventData{ + EventType: &events.EventData_AlertmanagerStartupEvent{ + AlertmanagerStartupEvent: &events.AlertmanagerStartupEvent{ Version: "v-test", BuildContext: "test-build", }, }, }, - } + }, eventType: "alertmanager_startup_event"} } // --- tests. @@ -142,6 +142,7 @@ func TestKafkaOutput_SendEvent_JSON(t *testing.T) { require.NoError(t, err) ev := sampleEvent() + evpb := ev.protoMessage().(*events.Event) n, err := ko.SendEvent(ev) require.NoError(t, err) require.Positive(t, n) @@ -150,9 +151,9 @@ func TestKafkaOutput_SendEvent_JSON(t *testing.T) { records := readRecords(t, brokers, topic, 1, 5*time.Second) require.Len(t, records, 1) - var got eventrecorderpb.Event + var got events.Event require.NoError(t, protojson.Unmarshal(records[0].Value, &got)) - require.Equal(t, ev.Instance, got.Instance) + require.Equal(t, evpb.Instance, got.Instance) require.Equal(t, "v-test", got.GetData().GetAlertmanagerStartupEvent().GetVersion()) require.Equal(t, "test-host", string(records[0].Key)) } @@ -176,6 +177,7 @@ func TestKafkaOutput_SendEvent_Protobuf(t *testing.T) { require.NoError(t, err) ev := sampleEvent() + evpb := ev.protoMessage().(*events.Event) n, err := ko.SendEvent(ev) require.NoError(t, err) require.Positive(t, n) @@ -184,10 +186,10 @@ func TestKafkaOutput_SendEvent_Protobuf(t *testing.T) { records := readRecords(t, brokers, topic, 1, 5*time.Second) require.Len(t, records, 1) - var got eventrecorderpb.Event + var got events.Event require.NoError(t, proto.Unmarshal(records[0].Value, &got)) - require.Equal(t, ev.Instance, got.Instance) - require.Equal(t, ev.Timestamp.AsTime().Unix(), got.Timestamp.AsTime().Unix()) + require.Equal(t, evpb.Instance, got.Instance) + require.Equal(t, evpb.Timestamp.AsTime().Unix(), got.Timestamp.AsTime().Unix()) require.Equal(t, "v-test", got.GetData().GetAlertmanagerStartupEvent().GetVersion()) require.Equal(t, "test-host", string(records[0].Key)) } diff --git a/eventrecorder/recorder.go b/eventrecorder/recorder.go index ce3161ac36..3c11bc78b8 100644 --- a/eventrecorder/recorder.go +++ b/eventrecorder/recorder.go @@ -33,7 +33,6 @@ import ( "google.golang.org/protobuf/types/known/timestamppb" "github.com/prometheus/alertmanager/cluster" - "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" ) const ( @@ -69,12 +68,9 @@ type Recorder struct { } // writeRequest is a single event queued for background serialization -// and writing. It carries the proto message so that the expensive -// protojson.Marshal call happens in the write-loop goroutine, not on -// the caller's hot path. +// and writing. type writeRequest struct { - event *eventrecorderpb.Event - eventType string + event Event } // sharedRecorder holds the mutable state shared by all copies of a @@ -104,7 +100,8 @@ type cfgUpdateMsg struct { // Destination is a single event destination. Each implementation // owns its own serialization: it receives the structured event and is -// responsible for encoding it (e.g. JSON or protobuf) and delivering it. +// responsible for encoding it with Event.MarshalJSON or +// Event.MarshalProtobuf and delivering it. // // Owning serialization per destination — rather than handing every // destination a pre-encoded JSON blob — avoids the footgun of, say, a @@ -119,7 +116,7 @@ type Destination interface { // delivery error. A serialization failure should be returned // wrapped in *serializeError so the recorder can attribute it to // the serialize-errors metric. - SendEvent(event *eventrecorderpb.Event) (size int, err error) + SendEvent(event Event) (size int, err error) io.Closer } @@ -277,57 +274,51 @@ func (c *sharedRecorder) marshalAndSend(req writeRequest, outputs []Destination) size, err := out.SendEvent(req.event) if err != nil { if _, ok := errors.AsType[*serializeError](err); ok { - c.metrics.eventSerializeErrors.WithLabelValues(req.eventType).Inc() + c.metrics.eventSerializeErrors.WithLabelValues(req.event.typeName()).Inc() } - c.metrics.eventsRecorded.WithLabelValues(req.eventType, name, "error").Inc() - c.logger.Error("Failed to write event", "event_type", req.eventType, "output", name, "err", err) + c.metrics.eventsRecorded.WithLabelValues(req.event.typeName(), name, "error").Inc() + c.logger.Error("Failed to write event", "event_type", req.event.typeName(), "output", name, "err", err) continue } - c.metrics.eventsRecorded.WithLabelValues(req.eventType, name, "success").Inc() - c.metrics.eventRecorderBytesWritten.WithLabelValues(req.eventType, name).Add(float64(size)) + c.metrics.eventsRecorded.WithLabelValues(req.event.typeName(), name, "success").Inc() + c.metrics.eventRecorderBytesWritten.WithLabelValues(req.event.typeName(), name).Add(float64(size)) } } -// RecordEvent wraps the event and places it on a bounded queue for -// background serialization and delivery. If the queue is full the -// event is dropped (never blocks the caller). Recording only occurs -// when the context has been decorated with WithEventRecording. +// RecordEvent wraps the event data with metadata and places it on a bounded +// queue for background serialization and delivery. If the queue is full the +// event is dropped (never blocks the caller). Recording only occurs when the +// context has been decorated with WithEventRecording. // -// The event is supplied as a builder function rather than a value so -// that callers on hot read paths do not pay to construct an event -// (protobuf conversions, fingerprint slices, etc.) that would only be -// discarded when recording is disabled. The builder is invoked only +// The event data is supplied as a builder function rather than a value so +// that callers on hot read paths do not pay to snapshot alerts and fingerprints +// for an event that would only be discarded when recording is disabled. The +// builder is invoked only // after the recording gates pass, and exactly once. // // The expensive protojson.Marshal call is deferred to the write-loop -// goroutine so that the caller's hot path only pays for the proto -// wrapping and a channel send. -func (r Recorder) RecordEvent(ctx context.Context, build func() *eventrecorderpb.EventData) { +// goroutine so that the caller's hot path only pays for snapshot construction +// and a channel send. +func (r Recorder) RecordEvent(ctx context.Context, build func() EventData) { if r.core == nil || r.core.events == nil { return } if !EventRecordingEnabled(ctx) { return } - - event := build() - eventType := extractEventType(event) - - wrappedEvent := &eventrecorderpb.Event{ - Timestamp: timestamppb.Now(), - Instance: r.core.instance, - Data: event, - } - + data := build() + clusterPosition := uint64(0) if peer := r.core.peer.Load(); peer != nil { - wrappedEvent.ClusterPosition = uint32(peer.Position()) + clusterPosition = uint64(peer.Position()) } + event := data.withMetadata(timestamppb.Now(), r.core.instance, clusterPosition) + request := writeRequest{event: event} select { - case r.core.events <- writeRequest{event: wrappedEvent, eventType: eventType}: + case r.core.events <- request: default: // Queue full; drop event to avoid blocking alertmanager. - r.core.metrics.eventsDropped.WithLabelValues(eventType).Inc() + r.core.metrics.eventsDropped.WithLabelValues(event.typeName()).Inc() } } diff --git a/eventrecorder/recorder_test.go b/eventrecorder/recorder_test.go index 9dfa797a15..cc3cb3d52e 100644 --- a/eventrecorder/recorder_test.go +++ b/eventrecorder/recorder_test.go @@ -21,15 +21,13 @@ import ( "time" "github.com/stretchr/testify/require" - - "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" ) // mockDestination records all events written to it. type mockDestination struct { mu sync.Mutex name string - events []*eventrecorderpb.Event + events []Event } func newMockDestination(name string) *mockDestination { @@ -37,7 +35,7 @@ func newMockDestination(name string) *mockDestination { } func (m *mockDestination) Name() string { return m.name } -func (m *mockDestination) SendEvent(event *eventrecorderpb.Event) (int, error) { +func (m *mockDestination) SendEvent(event Event) (int, error) { m.mu.Lock() defer m.mu.Unlock() m.events = append(m.events, event) @@ -51,17 +49,15 @@ func (m *mockDestination) eventCount() int { return len(m.events) } -func startupEvent() *eventrecorderpb.EventData { - return &eventrecorderpb.EventData{ - EventType: &eventrecorderpb.EventData_AlertmanagerStartupEvent{ - AlertmanagerStartupEvent: &eventrecorderpb.AlertmanagerStartupEvent{ - Version: "test", - }, - }, - } +func startupEvent() EventData { + return NewAlertmanagerStartupEvent("test", "") } func newTestRecorder(outputs ...Destination) Recorder { + return newTestRecorderWithConfig(Config{}, outputs...) +} + +func newTestRecorderWithConfig(cfg Config, outputs ...Destination) Recorder { core := &sharedRecorder{ instance: "test", logger: slog.Default(), @@ -71,7 +67,7 @@ func newTestRecorder(outputs ...Destination) Recorder { done: make(chan struct{}), } core.wg.Add(1) - go core.writeLoop(outputs, Config{}) + go core.writeLoop(outputs, cfg) return Recorder{core: core} } @@ -186,6 +182,37 @@ func TestEventRecorderConfigEqual_TypeMismatch(t *testing.T) { "outputs of different types must compare unequal") } +func TestRecorderOutputSchema(t *testing.T) { + out := newMockDestination("test:mock") + rec := newTestRecorder(out) + defer rec.Close() + + rec.RecordEvent(recordCtx(), startupEvent) + require.Eventually(t, func() bool { + out.mu.Lock() + defer out.mu.Unlock() + if len(out.events) != 1 { + return false + } + return out.events[0].message != nil + }, time.Second, 10*time.Millisecond) +} + +func TestRecordEventBuildsEventFromEventData(t *testing.T) { + out := newMockDestination("test:mock") + rec := newTestRecorder(out) + defer rec.Close() + + built := NewAlertmanagerShutdownEvent() + rec.RecordEvent(recordCtx(), func() EventData { return built }) + require.Eventually(t, func() bool { return out.eventCount() == 1 }, time.Second, 10*time.Millisecond) + + out.mu.Lock() + defer out.mu.Unlock() + require.Same(t, built.message, out.events[0].message.Data) + require.NotNil(t, out.events[0].message.Timestamp) +} + // marshalAndSend hands the structured event to every destination; the // destination owns serialization. Verify a destination receives the // event (and the recorder records it). @@ -199,7 +226,9 @@ func TestMarshalAndSend_DeliversEvent(t *testing.T) { require.Eventually(t, func() bool { out.mu.Lock() defer out.mu.Unlock() - return len(out.events) == 1 && - out.events[0].GetData().GetAlertmanagerStartupEvent() != nil + if len(out.events) != 1 { + return false + } + return out.events[0].message.GetData().GetAlertmanagerStartupEvent() != nil }, time.Second, 10*time.Millisecond) } diff --git a/eventrecorder/stdout.go b/eventrecorder/stdout.go index 1b2652c468..51e4d92fe6 100644 --- a/eventrecorder/stdout.go +++ b/eventrecorder/stdout.go @@ -15,10 +15,6 @@ package eventrecorder import ( "os" - - "google.golang.org/protobuf/encoding/protojson" - - "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" ) // StdoutOutputConfig configures a stdout event recorder output. @@ -45,8 +41,8 @@ func (s *StdoutOutput) Name() string { return "stdout" } // It returns the byte count written (including the trailing newline) and // any write error encountered. A serialization failure is wrapped in // serializeError so the recorder attributes it to the correct metric. -func (s *StdoutOutput) SendEvent(event *eventrecorderpb.Event) (int, error) { - data, err := protojson.Marshal(event) +func (s *StdoutOutput) SendEvent(event Event) (int, error) { + data, err := event.MarshalJSON() if err != nil { return 0, &serializeError{err: err} } diff --git a/eventrecorder/webhook.go b/eventrecorder/webhook.go index 1a4972ae1b..0fc36c5fdd 100644 --- a/eventrecorder/webhook.go +++ b/eventrecorder/webhook.go @@ -28,10 +28,8 @@ import ( "github.com/prometheus/client_golang/prometheus" commoncfg "github.com/prometheus/common/config" "github.com/prometheus/common/model" - "google.golang.org/protobuf/encoding/protojson" amcommoncfg "github.com/prometheus/alertmanager/config/common" - "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" ) // WebhookOutputConfig configures an HTTP webhook event recorder output. @@ -297,8 +295,8 @@ func (wo *WebhookOutput) Name() string { // a worker. It returns the serialized size (for the bytes-written // metric). If the internal queue is full the event is dropped and // counted via the output-drops metric. -func (wo *WebhookOutput) SendEvent(event *eventrecorderpb.Event) (int, error) { - data, err := protojson.Marshal(event) +func (wo *WebhookOutput) SendEvent(event Event) (int, error) { + data, err := event.MarshalJSON() if err != nil { return 0, &serializeError{err: err} } diff --git a/eventrecorder/webhook_test.go b/eventrecorder/webhook_test.go index 2cbc79f432..37b65ea041 100644 --- a/eventrecorder/webhook_test.go +++ b/eventrecorder/webhook_test.go @@ -194,7 +194,7 @@ func TestWebhookOutput_BatchingByEncodedSize(t *testing.T) { defer srv.Close() event := sampleEvent() - encoded, err := protojson.Marshal(event) + encoded, err := protojson.Marshal(event.protoMessage()) require.NoError(t, err) out, err := NewWebhookOutput(WebhookOutputConfig{ URL: mustParseURL(t, srv.URL), diff --git a/inhibit/inhibit.go b/inhibit/inhibit.go index c441054be6..494322dc64 100644 --- a/inhibit/inhibit.go +++ b/inhibit/inhibit.go @@ -29,7 +29,6 @@ import ( amcommoncfg "github.com/prometheus/alertmanager/config/common" "github.com/prometheus/alertmanager/eventrecorder" - "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" "github.com/prometheus/alertmanager/marker" "github.com/prometheus/alertmanager/pkg/labels" "github.com/prometheus/alertmanager/provider" @@ -223,9 +222,9 @@ func (ih *Inhibitor) Mutes(ctx context.Context, lset model.LabelSet) bool { ), ) - ih.recorder.RecordEvent(ctx, func() *eventrecorderpb.EventData { + ih.recorder.RecordEvent(ctx, func() eventrecorder.EventData { return eventrecorder.NewInhibitionMutedAlertEvent( - []*eventrecorderpb.InhibitRule{eventrecorder.InhibitRuleAsProto(r.Name, r.SourceMatchers, r.TargetMatchers, r.Equal)}, + []eventrecorder.InhibitRule{eventrecorder.NewInhibitRule(r.Name, r.SourceMatchers, r.TargetMatchers, r.Equal)}, fp, lset, []model.Fingerprint{inhibitedByFP}, ) diff --git a/notify/event.go b/notify/event.go index 740cd0e77e..e93a47d396 100644 --- a/notify/event.go +++ b/notify/event.go @@ -13,131 +13,102 @@ package notify -// This file contains helpers for constructing event recorder protobuf messages +// This file contains helpers for constructing event recorder events // from the notification pipeline context. It lives in the notify package // because it accesses unexported context keys (keyFiringAlerts, etc.). import ( "context" - "google.golang.org/protobuf/types/known/durationpb" - "github.com/prometheus/alertmanager/eventrecorder" - "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" "github.com/prometheus/alertmanager/types" ) -func groupedAlertAsProto(alert *types.Alert) *eventrecorderpb.GroupedAlert { - return &eventrecorderpb.GroupedAlert{ - Hash: hashAlert(alert), - Details: eventrecorder.AlertAsProto(alert), - } +func groupedAlertEvent(alert *types.Alert) eventrecorder.GroupedAlert { + return eventrecorder.NewGroupedAlert(hashAlert(alert), alert) } -func extractAlertGroupInfo(ctx context.Context) *eventrecorderpb.AlertGroupInfo { +func extractAlertGroupInfo(ctx context.Context) eventrecorder.AlertGroup { groupKey, _ := ExtractGroupKey(ctx) receiverName, _ := ReceiverName(ctx) groupLabels, _ := GroupLabels(ctx) groupMatchers, _ := GroupMatchers(ctx) aggrGroupID, _ := AggrGroupID(ctx) - return &eventrecorderpb.AlertGroupInfo{ - GroupKey: groupKey.String(), - GroupLabels: eventrecorder.LabelSetAsProto(groupLabels), - GroupId: groupKey.Hash(), - ReceiverName: receiverName, - Matchers: eventrecorder.MatchersAsProto(groupMatchers), - GroupUuid: aggrGroupID, - } + return eventrecorder.NewAlertGroup( + groupKey.String(), groupLabels, groupKey.Hash(), receiverName, groupMatchers, aggrGroupID, + ) } -func extractGroupedAlerts(ctx context.Context, key notifyKey) []*eventrecorderpb.GroupedAlert { - var result []*eventrecorderpb.GroupedAlert +func extractGroupedAlerts(ctx context.Context, key notifyKey) []eventrecorder.GroupedAlert { + var result []eventrecorder.GroupedAlert if list, ok := ctx.Value(key).([]uint64); ok { for _, hash := range list { - result = append(result, &eventrecorderpb.GroupedAlert{Hash: hash}) + result = append(result, eventrecorder.NewGroupedAlertReference(hash)) } } return result } -func extractMutedGroupedAlerts(ctx context.Context) []*eventrecorderpb.GroupedAlert { - var result []*eventrecorderpb.GroupedAlert +func extractMutedGroupedAlerts(ctx context.Context) []eventrecorder.GroupedAlert { + var result []eventrecorder.GroupedAlert if muted, ok := MutedAlerts(ctx); ok { for hash := range muted { - result = append(result, &eventrecorderpb.GroupedAlert{Hash: hash}) + result = append(result, eventrecorder.NewGroupedAlertReference(hash)) } } return result } -func notifyReasonToProto(reason NotifyReason) eventrecorderpb.NotifyReason { +func notifyReasonToEvent(reason NotifyReason) eventrecorder.NotificationReason { switch reason { case ReasonFirstNotification: - return eventrecorderpb.NotifyReason_NOTIFY_REASON_FIRST_NOTIFICATION + return eventrecorder.NotificationReasonFirstNotification case ReasonNewAlertsInGroup: - return eventrecorderpb.NotifyReason_NOTIFY_REASON_NEW_ALERTS_IN_GROUP + return eventrecorder.NotificationReasonNewAlertsInGroup case ReasonAllAlertsResolved: - return eventrecorderpb.NotifyReason_NOTIFY_REASON_ALL_ALERTS_RESOLVED + return eventrecorder.NotificationReasonAllAlertsResolved case ReasonNewResolvedAlerts: - return eventrecorderpb.NotifyReason_NOTIFY_REASON_NEW_RESOLVED_ALERTS + return eventrecorder.NotificationReasonNewResolvedAlerts case ReasonRepeatIntervalElapsed: - return eventrecorderpb.NotifyReason_NOTIFY_REASON_REPEAT_INTERVAL_ELAPSED + return eventrecorder.NotificationReasonRepeatIntervalElapsed default: - return eventrecorderpb.NotifyReason_NOTIFY_REASON_UNSPECIFIED + return eventrecorder.NotificationReasonUnspecified } } -// NewNotificationEvent constructs a NotificationEvent from the pipeline +// NewNotificationEvent constructs notification event data from the pipeline // context after a successful notification delivery. -func NewNotificationEvent(ctx context.Context, alerts []*types.Alert, integration Integration) *eventrecorderpb.EventData { - groupedAlerts := make([]*eventrecorderpb.GroupedAlert, 0, len(alerts)) +func NewNotificationEvent(ctx context.Context, alerts []*types.Alert, integration Integration) eventrecorder.EventData { + groupedAlerts := make([]eventrecorder.GroupedAlert, 0, len(alerts)) for _, alert := range alerts { - groupedAlerts = append(groupedAlerts, groupedAlertAsProto(alert)) + groupedAlerts = append(groupedAlerts, groupedAlertEvent(alert)) } notifyReason, _ := NotificationReason(ctx) repeatInterval, _ := RepeatInterval(ctx) flushID, _ := FlushID(ctx) - notification := &eventrecorderpb.NotificationEvent{ + return eventrecorder.NewNotificationEvent(eventrecorder.Notification{ Alerts: groupedAlerts, FiringAlerts: extractGroupedAlerts(ctx, keyFiringAlerts), ResolvedAlerts: extractGroupedAlerts(ctx, keyResolvedAlerts), MutedAlerts: extractMutedGroupedAlerts(ctx), - GroupInfo: extractAlertGroupInfo(ctx), - RepeatInterval: durationpb.New(repeatInterval), - Reason: notifyReasonToProto(notifyReason), - FlushId: flushID, - Integration: &eventrecorderpb.Integration{ - Name: integration.Name(), - Index: int64(integration.Index()), - }, - } - - return &eventrecorderpb.EventData{ - EventType: &eventrecorderpb.EventData_Notification{Notification: notification}, - } + Group: extractAlertGroupInfo(ctx), + RepeatInterval: repeatInterval, + Reason: notifyReasonToEvent(notifyReason), + FlushID: flushID, + Integration: integration.Name(), + IntegrationIdx: int64(integration.Index()), + }) } -func NewAlertResolvedEvent(groupInfo *eventrecorderpb.AlertGroupInfo, alert *types.Alert) *eventrecorderpb.EventData { - return &eventrecorderpb.EventData{ - EventType: &eventrecorderpb.EventData_AlertResolved{ - AlertResolved: &eventrecorderpb.AlertResolvedEvent{ - Alert: groupedAlertAsProto(alert), - GroupInfo: groupInfo, - }, - }, - } +// NewAlertResolvedEvent constructs alert-resolved event data. +func NewAlertResolvedEvent(groupInfo eventrecorder.AlertGroup, alert *types.Alert) eventrecorder.EventData { + return eventrecorder.NewAlertResolvedEvent(groupInfo, groupedAlertEvent(alert)) } -func NewAlertGroupedEvent(groupInfo *eventrecorderpb.AlertGroupInfo, alert *types.Alert) *eventrecorderpb.EventData { - return &eventrecorderpb.EventData{ - EventType: &eventrecorderpb.EventData_AlertGrouped{ - AlertGrouped: &eventrecorderpb.AlertGroupedEvent{ - Alert: groupedAlertAsProto(alert), - GroupInfo: groupInfo, - }, - }, - } +// NewAlertGroupedEvent constructs alert-grouped event data. +func NewAlertGroupedEvent(groupInfo eventrecorder.AlertGroup, alert *types.Alert) eventrecorder.EventData { + return eventrecorder.NewAlertGroupedEvent(groupInfo, groupedAlertEvent(alert)) } diff --git a/notify/retry_stage.go b/notify/retry_stage.go index d535042067..fb3b93ef0c 100644 --- a/notify/retry_stage.go +++ b/notify/retry_stage.go @@ -27,7 +27,6 @@ import ( "github.com/prometheus/alertmanager/alert" "github.com/prometheus/alertmanager/eventrecorder" - "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" ) // RetryStage notifies via passed integration with exponential backoff until it @@ -179,7 +178,7 @@ func (r RetryStage) exec(ctx context.Context, l *slog.Logger, alerts ...*alert.A l.Info("Notify success") } - r.recorder.RecordEvent(ctx, func() *eventrecorderpb.EventData { + r.recorder.RecordEvent(ctx, func() eventrecorder.EventData { return NewNotificationEvent(ctx, sent, r.integration) }) return ctx, alerts, nil diff --git a/proto/eventrecorder/events/v2/events.proto b/proto/eventrecorder/events/v2/events.proto new file mode 100644 index 0000000000..5d1ef36c46 --- /dev/null +++ b/proto/eventrecorder/events/v2/events.proto @@ -0,0 +1,186 @@ +syntax = "proto3"; + +package events.v2; + +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; + +option go_package = "github.com/prometheus/alertmanager/eventrecorder/events/v2;eventsv2"; + +// Event is the top-level envelope written to each event recorder output. +message Event { + google.protobuf.Timestamp timestamp = 1 [json_name = "@timestamp"]; + string instance = 2; + EventData data = 3; + uint64 cluster_position = 4; +} + +// EventData carries the payload for a single event recorder entry. +message EventData { + oneof event_type { + AlertmanagerStartupEvent alertmanager_startup_event = 1; + AlertmanagerShutdownEvent alertmanager_shutdown_event = 2; + AlertCreatedEvent alert_created = 3; + AlertResolvedEvent alert_resolved = 4; + AlertGroupedEvent alert_grouped = 5; + NotificationEvent notification = 6; + SilenceCreatedEvent silence_created = 7; + SilenceUpdatedEvent silence_updated = 8; + SilenceMutedAlertEvent silence_muted_alert = 9; + InhibitionMutedAlertEvent inhibition_muted_alert = 10; + } +} + +// AlertmanagerStartupEvent is emitted once when the process starts. +message AlertmanagerStartupEvent { + string version = 1; + string build_context = 2; +} + +// AlertmanagerShutdownEvent is emitted when the process shuts down gracefully. +message AlertmanagerShutdownEvent {} + +// Alert represents a snapshot of an alert at the time the event was recorded. +message Alert { + uint64 fingerprint = 1; + string name = 2; + map labels = 3; + map annotations = 4; + google.protobuf.Timestamp starts_at = 5; + google.protobuf.Timestamp ends_at = 6; + bool resolved = 7; +} + +// GroupedAlert is a reference to an alert within an aggregation group. +message GroupedAlert { + uint64 hash = 1; + optional Alert details = 2; +} + +// AlertGroupInfo describes an alert's aggregation group context. +message AlertGroupInfo { + string group_key = 1; + map group_labels = 2; + string group_id = 3; + string receiver_name = 4; + repeated Matcher matchers = 5; + string group_uuid = 6; +} + +// AlertCreatedEvent is emitted when a new alert is inserted. +message AlertCreatedEvent { + Alert alert = 1; +} + +// AlertResolvedEvent is emitted when a resolved alert leaves its group. +message AlertResolvedEvent { + GroupedAlert alert = 1; + AlertGroupInfo group_info = 2; +} + +// AlertGroupedEvent is emitted when an alert first enters a group. +message AlertGroupedEvent { + GroupedAlert alert = 1; + AlertGroupInfo group_info = 2; +} + +// NotifyReason describes why a notification was sent. +enum NotifyReason { + NOTIFY_REASON_UNSPECIFIED = 0; + NOTIFY_REASON_FIRST_NOTIFICATION = 1; + NOTIFY_REASON_NEW_ALERTS_IN_GROUP = 2; + NOTIFY_REASON_NEW_RESOLVED_ALERTS = 3; + NOTIFY_REASON_ALL_ALERTS_RESOLVED = 4; + NOTIFY_REASON_REPEAT_INTERVAL_ELAPSED = 5; +} + +// Integration identifies a notification integration. +message Integration { + string name = 1; + int64 index = 2; +} + +// NotificationEvent is emitted after a notification is delivered. +message NotificationEvent { + repeated GroupedAlert alerts = 1; + repeated GroupedAlert firing_alerts = 2; + repeated GroupedAlert resolved_alerts = 3; + repeated GroupedAlert muted_alerts = 4; + AlertGroupInfo group_info = 5; + google.protobuf.Duration repeat_interval = 6; + NotifyReason reason = 7; + uint64 flush_id = 8; + Integration integration = 9; +} + +// Silence is a snapshot of a silence definition. +message Silence { + string id = 1; + repeated Matcher matchers = 2; + map annotations = 3; + google.protobuf.Timestamp starts_at = 4; + google.protobuf.Timestamp ends_at = 5; + google.protobuf.Timestamp updated_at = 6; + string created_by = 7; + string comment = 8; + repeated MatcherSet matcher_sets = 9; + repeated MatcherSet receiver_matcher_sets = 10; +} + +// Matcher defines a single label matching rule. +message Matcher { + enum Type { + TYPE_UNSPECIFIED = 0; + TYPE_EQUAL = 1; + TYPE_REGEXP = 2; + TYPE_NOT_EQUAL = 3; + TYPE_NOT_REGEXP = 4; + } + + Type type = 1; + string name = 2; + string pattern = 3; + string rendered = 4; +} + +// MatcherSet is a conjunction of matchers. +message MatcherSet { + repeated Matcher matchers = 1; +} + +// SilenceCreatedEvent is emitted when a silence is created. +message SilenceCreatedEvent { + Silence silence = 1; +} + +// SilenceUpdatedEvent is emitted when a silence is modified. +message SilenceUpdatedEvent { + Silence silence = 1; +} + +// MutedAlert identifies an alert suppressed by a silence or inhibition rule. +message MutedAlert { + map labels = 1; + uint64 fingerprint = 2; +} + +// SilenceMutedAlertEvent is emitted when a silence suppresses an alert. +message SilenceMutedAlertEvent { + Silence silence = 1; + MutedAlert muted_alert = 2; +} + +// InhibitRule is a snapshot of an inhibition rule definition. +message InhibitRule { + repeated Matcher source_matchers = 1; + repeated Matcher target_matchers = 2; + repeated string equal_labels = 3; + string name = 4; +} + +// InhibitionMutedAlertEvent is emitted when inhibition suppresses an alert. +message InhibitionMutedAlertEvent { + repeated InhibitRule inhibit_rules = 1; + MutedAlert muted_alert = 2; + repeated uint64 inhibiting_fingerprints = 3; +} diff --git a/provider/mem/mem.go b/provider/mem/mem.go index 7646eb9fdf..f392a0c70d 100644 --- a/provider/mem/mem.go +++ b/provider/mem/mem.go @@ -29,7 +29,6 @@ import ( "go.opentelemetry.io/otel/trace" "github.com/prometheus/alertmanager/eventrecorder" - "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" "github.com/prometheus/alertmanager/featurecontrol" "github.com/prometheus/alertmanager/provider" "github.com/prometheus/alertmanager/store" @@ -348,7 +347,7 @@ func (a *Alerts) Put(ctx context.Context, alerts ...*types.Alert) error { a.callback.PostStore(alert, existing) if !existing { - a.recorder.RecordEvent(ctx, func() *eventrecorderpb.EventData { + a.recorder.RecordEvent(ctx, func() eventrecorder.EventData { return eventrecorder.NewAlertCreatedEvent(alert) }) } diff --git a/silence/silence.go b/silence/silence.go index c0d089c2e1..26d21567f7 100644 --- a/silence/silence.go +++ b/silence/silence.go @@ -47,7 +47,6 @@ import ( "github.com/prometheus/alertmanager/alert" "github.com/prometheus/alertmanager/cluster" "github.com/prometheus/alertmanager/eventrecorder" - "github.com/prometheus/alertmanager/eventrecorder/eventrecorderpb" "github.com/prometheus/alertmanager/marker" "github.com/prometheus/alertmanager/matcher/compat" "github.com/prometheus/alertmanager/pkg/labels" @@ -285,9 +284,9 @@ func (s *Silencer) Mutes(ctx context.Context, lset model.LabelSet) bool { activeIDs = append(activeIDs, sil.Id) allIDs = append(allIDs, sil.Id) - s.recorder.RecordEvent(ctx, func() *eventrecorderpb.EventData { + s.recorder.RecordEvent(ctx, func() eventrecorder.EventData { return eventrecorder.NewSilenceMutedAlertEvent( - eventrecorder.SilenceAsProto(sil), fp, lset, + sil, fp, lset, ) }) default: @@ -876,10 +875,8 @@ func (s *Silences) Set(ctx context.Context, sil *pb.Silence) error { return err } if changed { - s.recorder.RecordEvent(ctx, func() *eventrecorderpb.EventData { - return eventrecorder.NewSilenceUpdatedEvent( - eventrecorder.SilenceAsProto(sil), - ) + s.recorder.RecordEvent(ctx, func() eventrecorder.EventData { + return eventrecorder.NewSilenceUpdatedEvent(sil) }) } return nil @@ -926,10 +923,8 @@ func (s *Silences) Set(ctx context.Context, sil *pb.Silence) error { return err } if added { - s.recorder.RecordEvent(ctx, func() *eventrecorderpb.EventData { - return eventrecorder.NewSilenceCreatedEvent( - eventrecorder.SilenceAsProto(sil), - ) + s.recorder.RecordEvent(ctx, func() eventrecorder.EventData { + return eventrecorder.NewSilenceCreatedEvent(sil) }) } return nil