From 4249e4168f78bfa1b46496231622c7d21eaec449 Mon Sep 17 00:00:00 2001 From: ryanfkeepers Date: Mon, 12 Feb 2024 14:00:24 -0700 Subject: [PATCH] introduce telemetry alerts Introduces a new type of alert- internal_telemetry- which can be used separately from user-visible alerts to provide more precise contextual identification. --- src/internal/operations/helpers.go | 4 ++- src/pkg/fault/alert.go | 44 +++++++++++++++++++++++++++--- src/pkg/fault/alert_test.go | 20 ++++++++++++++ 3 files changed, 63 insertions(+), 5 deletions(-) diff --git a/src/internal/operations/helpers.go b/src/internal/operations/helpers.go index 06e457909..78eae3521 100644 --- a/src/internal/operations/helpers.go +++ b/src/internal/operations/helpers.go @@ -75,6 +75,8 @@ func LogFaultErrors(ctx context.Context, fe *fault.Errors, prefix string) { } for i, alert := range fe.Alerts { - log.With("alert", alert).Infof("%s alert %d of %d: %s", pfxMsg, i+1, la, alert.Message) + if alert.Type == fault.AlertTypeUserVisible { + log.With("alert", alert).Infof("%s alert %d of %d: %s", pfxMsg, i+1, la, alert.Message) + } } } diff --git a/src/pkg/fault/alert.go b/src/pkg/fault/alert.go index c5599d413..7eacee4b4 100644 --- a/src/pkg/fault/alert.go +++ b/src/pkg/fault/alert.go @@ -8,6 +8,14 @@ const ( AlertPreviousPathCollision = "previous_path_collision" ) +type alertType string + +const ( + AlertTypeUnknown = "" + AlertTypeUserVisible = "user_visible" + AlertTypeInternalTelemetry = "internal_telemetry" +) + var _ print.Printable = &Alert{} // Alerts are informational-only notifications. The purpose of alerts is to @@ -17,8 +25,9 @@ var _ print.Printable = &Alert{} // be in use. IE: Errors do not also get alerts, since the error itself is a // form of end-user communication already. type Alert struct { - Item Item `json:"item"` - Message string `json:"message"` + Type alertType `json:"type"` + Item Item `json:"item"` + Message string `json:"message"` } // String complies with the stringer interface. @@ -62,12 +71,39 @@ func (a Alert) Values(bool) []string { return []string{"Alert", a.Message, cn, a.Item.Name, a.Item.ID} } -func NewAlert(message, namespace, itemID, name string, addtl map[string]any) *Alert { +// NewAlert produces a USER VISIBLE alert. Use this if you want the end user +// to see the alert at the end of the run. +func NewAlert( + message, namespace, entityID, name string, + addtl map[string]any, +) *Alert { return &Alert{ + Type: AlertTypeUserVisible, Message: message, Item: Item{ Namespace: namespace, - ID: itemID, + ID: entityID, + Name: name, + Additional: addtl, + }, + } +} + +// NewTelemetryAlert produces a NON-USER VISIBLE alert. Use this if you want +// to create an alert event for additional tracking and telemetry without the +// user seeing the details at the end of the run. Note that this data is still +// accessible from the backup metadata, so it will be possible for users to +// see it, if wanted/necessary. But they do have to go looking for it specifically. +func NewTelemetryAlert( + message, namespace, entityID, name string, + addtl map[string]any, +) *Alert { + return &Alert{ + Type: AlertTypeInternalTelemetry, + Message: message, + Item: Item{ + Namespace: namespace, + ID: entityID, Name: name, Additional: addtl, }, diff --git a/src/pkg/fault/alert_test.go b/src/pkg/fault/alert_test.go index da5b4f55f..3c52aede1 100644 --- a/src/pkg/fault/alert_test.go +++ b/src/pkg/fault/alert_test.go @@ -48,6 +48,26 @@ func (suite *AlertUnitSuite) TestNewAlert() { a := fault.NewAlert("message-to-show", "ns", "item_id", "item_name", addtl) expect := fault.Alert{ + Type: fault.AlertTypeUserVisible, + Item: fault.Item{ + Namespace: "ns", + ID: "item_id", + Name: "item_name", + Additional: addtl, + }, + Message: "message-to-show", + } + + assert.Equal(t, expect, *a) +} + +func (suite *AlertUnitSuite) TestNewTelemetryAlert() { + t := suite.T() + addtl := map[string]any{"foo": "bar"} + a := fault.NewTelemetryAlert("message-to-show", "ns", "item_id", "item_name", addtl) + + expect := fault.Alert{ + Type: fault.AlertTypeInternalTelemetry, Item: fault.Item{ Namespace: "ns", ID: "item_id",