types

package module
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 20, 2026 License: MIT Imports: 14 Imported by: 0

README

types

Go Reference Go Report Card CI

A Go shared library package providing common interfaces and data structures for the Slack Manager system. This package defines contracts for database access, logging, metrics, and core domain types like alerts and issues.

Important: When to Use This Library

Most users don't need to import this library directly. When using the Slack Manager, this package is automatically pulled in as a dependency by other components in the ecosystem:

You only need to import this library directly if:

  • You're developing a custom database plugin (implementing the DB interface)
  • You're developing a custom queue/messaging plugin
  • You're building custom tooling that needs access to the core types

For sending alerts to Slack Manager, use the Go Client instead.

Overview

The types package serves as the foundation for the Slack Manager ecosystem, providing:

  • Dependency Injection Interfaces: Abstractions for database, logging, and metrics that allow implementations to be plugged in
  • Core Domain Types: Rich type definitions for alerts, issues, webhooks, and escalations
  • Validation & Cleaning: Built-in validation and normalization for all data structures
  • Type Safety: Strongly-typed enums for severities, access levels, button styles, and display modes

This library is used by the main Slack Manager application, infrastructure plugins, and the Go client.

Installation

go get github.com/slackmgr/types

Core Interfaces

These interfaces define the contracts that implementations must satisfy. They enable dependency injection and allow the Slack Manager to work with different storage backends, logging frameworks, and metrics systems.

DB Interface

The DB interface abstracts all database operations for the Slack Manager. Implementations must handle persistence for alerts, issues, move mappings, and channel processing state.

type DB interface {
    Init(ctx context.Context, skipSchemaValidation bool) error
    SaveAlert(ctx context.Context, alert *Alert) error
    SaveIssue(ctx context.Context, issue Issue) error
    SaveIssues(ctx context.Context, issues ...Issue) error
    MoveIssue(ctx context.Context, issue Issue, sourceChannelID, targetChannelID string) error
    FindOpenIssueByCorrelationID(ctx context.Context, channelID, correlationID string) (string, json.RawMessage, error)
    FindIssueBySlackPostID(ctx context.Context, channelID, postID string) (string, json.RawMessage, error)
    FindActiveChannels(ctx context.Context) ([]string, error)
    LoadOpenIssuesInChannel(ctx context.Context, channelID string) (map[string]json.RawMessage, error)
    SaveMoveMapping(ctx context.Context, moveMapping MoveMapping) error
    FindMoveMapping(ctx context.Context, channelID, correlationID string) (json.RawMessage, error)
    DeleteMoveMapping(ctx context.Context, channelID, correlationID string) error
    SaveChannelProcessingState(ctx context.Context, state *ChannelProcessingState) error
    FindChannelProcessingState(ctx context.Context, channelID string) (*ChannelProcessingState, error)
    DropAllData(ctx context.Context) error
}

Key Points:

  • Issues and move mappings are stored as opaque JSON (json.RawMessage) to allow implementation flexibility
  • Database implementations should never depend on the internal structure of issues or move mappings
  • Implementations available: DynamoDB plugin, PostgreSQL plugin
Logger Interface

The Logger interface provides structured logging with field support and multiple log levels.

type Logger interface {
    Debug(msg string)
    Debugf(format string, args ...any)
    Info(msg string)
    Infof(format string, args ...any)
    Error(msg string)
    Errorf(format string, args ...any)
    WithField(key string, value any) Logger
    WithFields(fields map[string]any) Logger
}

Key Points:

  • Supports Debug, Info, and Error levels
  • Allows chaining with WithField and WithFields for structured logging
  • A no-op implementation (NoopLogger) is provided for testing
Metrics Interface

The Metrics interface provides Prometheus-style metrics with support for counters, gauges, and histograms.

type Metrics interface {
    RegisterCounter(name, help string, labels ...string)
    RegisterGauge(name, help string, labels ...string)
    RegisterHistogram(name, help string, buckets []float64, labels ...string)
    Add(name string, value float64, labelValues ...string)
    Inc(name string, labelValues ...string)
    Set(name string, value float64, labelValues ...string)
    Observe(name string, value float64, labelValues ...string)
}

Key Points:

  • Supports standard Prometheus metric types
  • Labels can be defined at registration and specified at observation time
  • A no-op implementation (NoopMetrics) is provided for testing

Core Domain Types

Alert

The Alert struct is the central type representing an alert sent to the Slack Manager. It contains comprehensive information about the alert including severity, content, routing, escalations, and webhooks.

Constructor Functions:

func NewPanicAlert() *Alert     // Severity: panic
func NewErrorAlert() *Alert     // Severity: error
func NewWarningAlert() *Alert   // Severity: warning
func NewResolvedAlert() *Alert  // Severity: resolved
func NewInfoAlert() *Alert      // Severity: info

Key Fields:

Field Type Description
Timestamp time.Time When the alert was created (auto-replaced if > 7 days old)
CorrelationID string Groups related alerts into issues (auto-generated if not set)
Severity AlertSeverity Alert severity: panic, error, warning, resolved, or info
Header string Alert title (max 130 chars, auto-truncated)
Text string Alert body (max 10,000 chars, auto-truncated)
SlackChannelID string Target Slack channel ID or name
RouteKey string Alternative routing via configured routes
IssueFollowUpEnabled bool Whether to track this alert as an issue
AutoResolveSeconds int Auto-resolve after N seconds (30 - 63,113,851)
Webhooks []*Webhook Interactive buttons (max 5)
Escalation []*Escalation Escalation points (max 3)
Fields []*Field Additional key-value fields (max 20)

Methods:

  • Clean(): Normalizes and truncates all fields to valid values
  • Validate(): Returns error if any field is invalid
  • UniqueID(): Returns a deterministic, base64-encoded unique ID

Validation:

  • The package defines extensive constants for maximum lengths (e.g., MaxHeaderLength = 130)
  • All validation methods return descriptive errors
  • Validation includes: channel IDs, URLs, emoji format, severity values, escalation timing

Special Features:

  • Status Emoji Replacement: Use :status: in header or text, and it will be replaced with the appropriate emoji based on severity
  • Conditional Content: HeaderWhenResolved and TextWhenResolved allow different content for resolved states
  • Auto-correlation: If no CorrelationID is provided, one is generated by hashing key fields
  • Ignore Patterns: IgnoreIfTextContains allows filtering out known noise
AlertSeverity

Alert severity levels with associated emojis in Slack:

const (
    AlertPanic    AlertSeverity = "panic"    // Panic icon
    AlertError    AlertSeverity = "error"    // Red error icon
    AlertWarning  AlertSeverity = "warning"  // Yellow warning icon
    AlertResolved AlertSeverity = "resolved" // Green OK icon
    AlertInfo     AlertSeverity = "info"     // Blue info icon
)

Helper Functions:

  • SeverityIsValid(s AlertSeverity) bool
  • SeverityPriority(s AlertSeverity) int (3 = panic, 2 = error, 1 = warning, 0 = resolved/info)
  • ValidSeverities() []string
Escalation

Defines escalation points that trigger when an issue remains unresolved.

type Escalation struct {
    Severity      AlertSeverity  // New severity when escalation triggers
    DelaySeconds  int            // Delay since issue creation (min 30s)
    SlackMentions []string       // Mentions to add (e.g., "<!here>", "<@U12345678>")
    MoveToChannel string         // Move issue to different channel
}

Key Points:

  • Escalations are sorted by DelaySeconds and triggered in order
  • Minimum delay: 30 seconds, minimum diff between escalations: 30 seconds
  • Severity can only be panic, error, or warning (not resolved or info)
  • Maximum 3 escalation points per alert
Webhook

Interactive buttons that appear on Slack posts. When clicked, they trigger HTTP POST requests or custom handlers.

type Webhook struct {
    ID               string                    // Unique within alert
    URL              string                    // HTTP URL or handler identifier
    ButtonText       string                    // Button label (max 25 chars)
    ButtonStyle      WebhookButtonStyle        // "primary" or "danger"
    AccessLevel      WebhookAccessLevel        // Who can click: global_admins, channel_admins, channel_members
    DisplayMode      WebhookDisplayMode        // When to show: always, open_issue, resolved_issue
    ConfirmationText string                    // Optional confirmation dialog text
    Payload          map[string]any            // Data sent in POST body
    PlainTextInput   []*WebhookPlainTextInput  // Text input fields
    CheckboxInput    []*WebhookCheckboxInput   // Checkbox groups
}

Related Types:

  • WebhookPlainTextInput: Text input with min/max length, multiline support, initial value
  • WebhookCheckboxInput: Checkbox group with label and multiple options
  • WebhookCheckboxOption: Individual checkbox with value, text, and selected state

Enums:

  • WebhookButtonStyle: primary, danger
  • WebhookAccessLevel: global_admins, channel_admins, channel_members
  • WebhookDisplayMode: always, open_issue, resolved_issue
WebhookCallback

Represents data received when a webhook is triggered by a user clicking a button.

type WebhookCallback struct {
    ID            string              // Webhook ID
    UserID        string              // Slack user ID who clicked
    UserRealName  string              // User's display name
    ChannelID     string              // Channel where button was clicked
    MessageID     string              // Slack message ID
    Timestamp     time.Time           // When button was clicked
    Input         map[string]string   // Text input values
    CheckboxInput map[string][]string // Checkbox selected values
    Payload       map[string]any      // Original webhook payload + metadata
}

Helper Methods:

  • GetPayloadValue(key string) any
  • GetPayloadString(key string) string
  • GetPayloadInt(key string, defaultValue int) int
  • GetPayloadBool(key string, defaultValue bool) bool
  • GetInputValue(key string) string
  • GetCheckboxInputSelectedValues(key string) []string
Issue

The Issue interface represents an issue in a Slack channel. Issues group related alerts together and track their resolution status.

type Issue interface {
    json.Marshaler
    ChannelID() string        // Slack channel ID
    UniqueID() string         // Base64-encoded unique ID for storage
    GetCorrelationID() string // Correlation ID for grouping alerts
    IsOpen() bool             // Whether issue is open (not archived)
    CurrentPostID() string    // Slack message ID (empty if no post yet)
}

Key Points:

  • The actual implementation is internal to the Slack Manager and may change
  • Database implementations must store issues as opaque JSON
  • Correlation IDs are not guaranteed to be unique and should not be used as database keys
MoveMapping

The MoveMapping interface tracks issues that have been moved from one channel to another.

type MoveMapping interface {
    json.Marshaler
    ChannelID() string        // Original channel ID
    UniqueID() string         // Base64-encoded unique ID for storage
    GetCorrelationID() string // Correlation ID that was moved
}

Key Points:

  • Ensures new alerts with the same correlation ID go to the new channel
  • Stored as opaque JSON in the database
  • Internal implementation may change without notice
ChannelProcessingState

Tracks per-channel processing state to prevent concurrent processing and ensure regular intervals.

type ChannelProcessingState struct {
    ChannelID           string    // Slack channel ID
    Created             time.Time // When processing state was created
    LastChannelActivity time.Time // Last activity in channel
    LastProcessed       time.Time // When channel was last processed
    OpenIssues          int       // Number of open issues
}

Constructor:

func NewChannelProcessingState(channelID string) *ChannelProcessingState

Field Specifications

The Field struct is used for additional key-value pairs displayed in Slack:

type Field struct {
    Title string // Max 30 chars, auto-truncated
    Value string // Max 200 chars, auto-truncated
}

Maximum 20 fields per alert.

Testing Utilities

Database Testing

The dbtests package provides a shared test suite that can be run against any DB implementation:

import "github.com/slackmgr/types/dbtests"

// In your database implementation tests:
func TestDatabaseCompliance(t *testing.T) {
    db := NewYourDatabase()
    dbtests.RunAllTests(t, db)
}

This ensures your database implementation correctly satisfies the DB interface contract.

No-op Implementations

For testing purposes, no-op implementations are provided:

  • NoopLogger: Logger that does nothing
  • NoopMetrics: Metrics that do nothing
  • InMemoryFifoQueue: Simple in-memory FIFO queue (test-only, not for production)

Usage Example

package main

import (
    "github.com/slackmgr/types"
)

func main() {
    // Create an alert
    alert := types.NewErrorAlert()
    alert.Header = "Database Connection Failed"
    alert.Text = "Unable to connect to production database. Error: connection timeout"
    alert.SlackChannelID = "C12345678"
    alert.IssueFollowUpEnabled = true
    alert.AutoResolveSeconds = 300 // Auto-resolve after 5 minutes

    // Add fields
    alert.Fields = []*types.Field{
        {Title: "Host", Value: "db-prod-01"},
        {Title: "Port", Value: "5432"},
    }

    // Add escalation
    alert.Escalation = []*types.Escalation{
        {
            Severity:      types.AlertPanic,
            DelaySeconds:  300,
            SlackMentions: []string{"<!here>"},
        },
    }

    // Add webhook button
    alert.Webhooks = []*types.Webhook{
        {
            ID:               "restart",
            URL:              "https://example.com/webhook/restart",
            ButtonText:       "Restart DB",
            ButtonStyle:      types.WebhookButtonStyleDanger,
            AccessLevel:      types.WebhookAccessLevelChannelAdmins,
            ConfirmationText: "Are you sure you want to restart the database?",
            Payload: map[string]any{
                "action": "restart_database",
                "host":   "db-prod-01",
            },
        },
    }

    // Clean and validate
    alert.Clean()
    if err := alert.Validate(); err != nil {
        panic(err)
    }

    // Use with Slack Manager API or directly with the manager
}

Validation Constants

The package defines extensive validation constants. Key limits include:

Constant Value Description
MaxHeaderLength 130 Alert header length
MaxTextLength 10,000 Alert text length
MaxFieldCount 20 Fields per alert
MaxWebhookCount 5 Webhooks per alert
MaxEscalationCount 3 Escalation points per alert
MinAutoResolveSeconds 30 Minimum auto-resolve time
MaxAutoResolveSeconds 63,113,851 Maximum auto-resolve time (~2 years)
MinEscalationDelaySeconds 30 Minimum first escalation delay
MinEscalationDelayDiffSeconds 30 Minimum time between escalations

See alert.go for the complete list of constants.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Copyright (c) 2026 Peter Aglen

Documentation

Overview

Package types provides shared interfaces and data structures for the Slack Manager system.

This package defines contracts for database access, logging, metrics, and core domain types like alerts and issues. It serves as the foundation for the Slack Manager ecosystem, enabling dependency injection and allowing different implementations to be plugged in.

Core Interfaces

DB - Database abstraction for persisting alerts, issues, move mappings, and channel processing state. Implementations must handle storage as opaque JSON to allow flexibility.

Logger - Structured logging interface with Debug/Info/Error levels and field support. Supports method chaining with WithField and WithFields.

Metrics - Prometheus-style metrics interface supporting counters, gauges, and histograms. Allows registration of metrics with labels and observation of values.

Core Domain Types

Alert - The central type representing an alert with comprehensive validation and cleaning. Contains severity, header, text, fields, webhooks, escalations, and routing information. Use constructor functions: NewPanicAlert(), NewErrorAlert(), NewWarningAlert(), NewResolvedAlert(), NewInfoAlert().

Issue - Interface for tracking issue state in channels. Issues group related alerts together using correlation IDs. The actual implementation is internal and stored as opaque JSON.

MoveMapping - Interface for tracking issues that have been moved between channels. Ensures new alerts with the same correlation ID go to the new channel.

ChannelProcessingState - Tracks per-channel processing timestamps and open issue counts to prevent concurrent processing and ensure regular intervals.

Webhook Support

The package provides rich webhook support with interactive buttons, input forms, and access control:

  • Webhook - Interactive button configuration with HTTP callbacks or custom handlers
  • WebhookCallback - Data received when a webhook is triggered
  • WebhookAccessLevel - Control who can click buttons (global_admins, channel_admins, channel_members)
  • WebhookButtonStyle - Visual style (primary, danger)
  • WebhookDisplayMode - When to show buttons (always, open_issue, resolved_issue)

Validation and Cleaning

Alert provides extensive validation and cleaning methods:

  • Clean() - Normalizes and truncates all fields to valid values
  • Validate() - Returns error if any field is invalid
  • Individual validation methods for specific fields (ValidateSlackChannelIDAndRouteKey, etc.)

The package defines comprehensive constants for maximum lengths and limits (e.g., MaxHeaderLength = 130).

Testing Utilities

The dbtests subpackage provides a shared test suite that can be run against any DB implementation to ensure compliance with the interface contract.

No-op implementations (NoopLogger, NoopMetrics) are provided for testing purposes. InMemoryFifoQueue is provided for testing but should not be used in production.

Usage Example

// Initialize a new error-level notification
alert := types\.NewErrorAlert()
alert.Header = "Database Connection Failed"
alert.Text = "Unable to connect to production database"
alert.SlackChannelID = "C12345678"
alert.IssueFollowUpEnabled = true
alert.AutoResolveSeconds = 300

// Add fields
alert.Fields = []*types\.Field{
    {Title: "Host", Value: "db-prod-01"},
    {Title: "Port", Value: "5432"},
}

// Add escalation
alert.Escalation = []*types\.Escalation{
    {
        Severity:      types\.AlertPanic,
        DelaySeconds:  300,
        SlackMentions: []string{"<!here>"},
    },
}

// Add webhook button
alert.Webhooks = []*types\.Webhook{
    {
        ID:          "restart",
        URL:         "https://example.com/webhook/restart",
        ButtonText:  "Restart DB",
        ButtonStyle: types\.WebhookButtonStyleDanger,
        AccessLevel: types\.WebhookAccessLevelChannelAdmins,
    },
}

// Clean and validate
alert.Clean()
if err := alert.Validate(); err != nil {
    panic(err)
}

Index

Constants

View Source
const (
	// MaxTimestampAge is the maximum age of an alert timestamp.
	// If the timestamp is older than this, it will be replaced with the current time.
	MaxTimestampAge = 7 * 24 * time.Hour

	// MaxSlackChannelIDLength is the maximum length of a Slack channel ID or name.
	MaxSlackChannelIDLength = 80
	// MaxRouteKeyLength is the maximum length of a routing key for channel routing.
	MaxRouteKeyLength = 1000
	// MaxHeaderLength is the maximum length of the alert header (title).
	// Slack's header block limit is 150 characters; we reserve space for status emoji replacement.
	MaxHeaderLength = 130
	// MaxFallbackTextLength is the maximum length of the fallback notification text.
	MaxFallbackTextLength = 150
	// MaxTextLength is the maximum length of the alert text (body).
	MaxTextLength = 10000
	// MaxAuthorLength is the maximum length of the author field.
	MaxAuthorLength = 100
	// MaxHostLength is the maximum length of the host field.
	MaxHostLength = 100
	// MaxFooterLength is the maximum length of the footer field.
	MaxFooterLength = 300
	// MaxUsernameLength is the maximum length of the bot username.
	MaxUsernameLength = 100
	// MaxFieldTitleLength is the maximum length of a field title.
	MaxFieldTitleLength = 30
	// MaxFieldValueLength is the maximum length of a field value.
	MaxFieldValueLength = 200
	// MaxIconEmojiLength is the maximum length of the icon emoji (excluding colons).
	MaxIconEmojiLength = 50
	// MaxMentionLength is the maximum length of a Slack mention (excluding angle brackets).
	MaxMentionLength = 20
	// MaxCorrelationIDLength is the maximum length of the correlation ID.
	MaxCorrelationIDLength = 500

	// MinAutoResolveSeconds is the minimum seconds before auto-resolving an issue.
	MinAutoResolveSeconds = 30
	// MaxAutoResolveSeconds is the maximum seconds before auto-resolving an issue (approximately 2 years).
	MaxAutoResolveSeconds = 63113851

	// MaxIgnoreIfTextContainsLength is the maximum length of each ignore pattern.
	MaxIgnoreIfTextContainsLength = 1000
	// MaxIgnoreIfTextContainsCount is the maximum number of ignore patterns per alert.
	MaxIgnoreIfTextContainsCount = 20

	// MaxFieldCount is the maximum number of fields per alert.
	MaxFieldCount = 20

	// MaxWebhookCount is the maximum number of webhooks per alert.
	MaxWebhookCount = 5
	// MaxWebhookIDLength is the maximum length of a webhook ID.
	MaxWebhookIDLength = 100
	// MaxWebhookURLLength is the maximum length of a webhook URL.
	MaxWebhookURLLength = 1000
	// MaxWebhookButtonTextLength is the maximum length of button text (Slack limit: 25 characters).
	MaxWebhookButtonTextLength = 25
	// MaxWebhookConfirmationTextLength is the maximum length of confirmation dialog text.
	MaxWebhookConfirmationTextLength = 1000
	// MaxWebhookPayloadCount is the maximum number of key-value pairs in webhook payload.
	MaxWebhookPayloadCount = 50
	// MaxWebhookPlainTextInputCount is the maximum number of text inputs per webhook.
	MaxWebhookPlainTextInputCount = 10
	// MaxWebhookCheckboxInputCount is the maximum number of checkbox groups per webhook.
	MaxWebhookCheckboxInputCount = 10
	// MaxWebhookInputIDLength is the maximum length of an input field ID.
	MaxWebhookInputIDLength = 200
	// MaxWebhookInputDescriptionLength is the maximum length of an input field description/placeholder.
	MaxWebhookInputDescriptionLength = 200
	// MaxWebhookInputLabelLength is the maximum length of a checkbox group label.
	MaxWebhookInputLabelLength = 200
	// MaxWebhookInputTextLength is the maximum length of text input content.
	MaxWebhookInputTextLength = 3000
	// MaxWebhookCheckboxOptionCount is the maximum number of options per checkbox group.
	MaxWebhookCheckboxOptionCount = 5
	// MaxWebhookCheckboxOptionTextLength is the maximum length of checkbox option text.
	MaxWebhookCheckboxOptionTextLength = 50
	// MaxCheckboxOptionValueLength is the maximum length of a checkbox option value.
	MaxCheckboxOptionValueLength = 100

	// MaxEscalationCount is the maximum number of escalation points per alert.
	MaxEscalationCount = 3
	// MinEscalationDelaySeconds is the minimum delay before the first escalation triggers.
	MinEscalationDelaySeconds = 30
	// MinEscalationDelayDiffSeconds is the minimum time between consecutive escalations.
	MinEscalationDelayDiffSeconds = 30
	// MaxEscalationSlackMentionCount is the maximum number of Slack mentions per escalation.
	MaxEscalationSlackMentionCount = 10
)

Variables

View Source
var (
	// SlackChannelIDOrNameRegex matches valid Slack channel IDs and channel names.
	// Channel names are mapped to channel IDs by the API.
	SlackChannelIDOrNameRegex = regexp.MustCompile(fmt.Sprintf(`^[0-9a-zA-Z\-_]{1,%d}$`, MaxSlackChannelIDLength))

	// IconRegex matches valid Slack icon emojis, on the format ':emoji:'.
	IconRegex = regexp.MustCompile(fmt.Sprintf(`^:[^:]{1,%d}:$`, MaxIconEmojiLength))

	// SlackMentionRegex matches valid Slack mentions, such as <!here>, <!channel> and <@U12345678>.
	SlackMentionRegex = regexp.MustCompile(fmt.Sprintf(`^((<!here>)|(<!channel>)|(<@[^>\s]{1,%d}>))$`, MaxMentionLength))
)

Functions

func SeverityIsValid

func SeverityIsValid(s AlertSeverity) bool

func SeverityPriority

func SeverityPriority(s AlertSeverity) int

func ValidSeverities

func ValidSeverities() []string

func ValidWebhookAccessLevels

func ValidWebhookAccessLevels() []string

ValidWebhookAccessLevels returns a slice of valid WebhookAccessLevel values.

func ValidWebhookButtonStyles

func ValidWebhookButtonStyles() []string

ValidWebhookButtonStyles returns a slice of valid WebhookButtonStyle values.

func ValidWebhookDisplayModes

func ValidWebhookDisplayModes() []string

ValidWebhookDisplayModes returns a slice of valid WebhookDisplayMode values.

func WebhookAccessLevelIsValid

func WebhookAccessLevelIsValid(s WebhookAccessLevel) bool

WebhookAccessLevelIsValid returns true if the provided WebhookAccessLevel is valid.

func WebhookButtonStyleIsValid

func WebhookButtonStyleIsValid(s WebhookButtonStyle) bool

WebhookButtonStyleIsValid returns true if the provided WebhookButtonStyle is valid.

func WebhookDisplayModeIsValid

func WebhookDisplayModeIsValid(s WebhookDisplayMode) bool

WebhookDisplayModeIsValid returns true if the provided WebhookDisplayMode is valid.

Types

type Alert

type Alert struct {
	// Timestamp is the time when the alert was created. If the timestamp is empty (or older than 7 days), it will be replaced with the current time.
	Timestamp time.Time `json:"timestamp"`

	// CorrelationID is an optional field used to group related alerts together in issues.
	// If unset, the correlation ID is constructed by hashing [Header, Text, Author, Host, SlackChannelID].
	// It is strongly recommended to set this to an explicit value, which makes sense in your context, rather than relying on the default hash value.
	// With a custom correlation ID, you can update both header and text without creating a new issue.
	CorrelationID string `json:"correlationId"`

	// Type is the type of alert, such as 'compliance', 'security' or 'metrics'.
	// It is primarily used for routing, when the alert RouteKey field is used (rather than SlackChannelID).
	// This field is optional, and case-insensitive.
	Type string `json:"type"`

	// Header is the main header (title) of the alert.
	// It is automatically truncated at MaxHeaderLength characters.
	// Include :status: in the header (or text) to have it replaced with the appropriate emoji for the issue severity.
	// This field is optional, but Header and Text cannot both be empty.
	Header string `json:"header"`

	// HeaderWhenResolved is the main header (title) of the issue when in the *resolved* state.
	// It is automatically truncated at MaxHeaderLength characters.
	// This field is optional. If unset, the Header field is used for all issue states.
	HeaderWhenResolved string `json:"headerWhenResolved"`

	// Text is the main text (body) of the alert.
	// It is automatically truncated at MaxTextLength characters.
	// Include :status: in the text (or header) to have it replaced with the appropriate emoji for the issue severity.
	// This field is optional, but Header and Text cannot both be empty.
	Text string `json:"text"`

	// TextWhenResolved is the main text (body) of the alert when in the *resolved* state.
	// It is automatically truncated at MaxTextLength characters.
	// This field is optional. If unset, the Text field is used for all issue states.
	TextWhenResolved string `json:"textWhenResolved"`

	// FallbackText is the text displayed in Slack notifications.
	// It should be a short, human-readable summary of the alert, without markdown or line breaks.
	// It is automatically truncated at MaxFallbackTextLength characters.
	// This field is optional. If unset, Slack decides what to display in notifications (which may not always be ideal).
	FallbackText string `json:"fallbackText"`

	// Author is the 'author' of the alert (if relevant), displayed as a context block in the Slack post.
	// It is automatically truncated at MaxAuthorLength characters.
	// This field is optional.
	Author string `json:"author"`

	// Host is the 'host' on which the alert originated (if any), displayed as a context block in the Slack post.
	// It is automatically truncated at MaxHostLength characters.
	// This field is optional.
	Host string `json:"host"`

	// Footer is the 'footer' of the alert, displayed as a context block at the bottom of the Slack post.
	// It is automatically truncated at MaxFooterLength characters.
	// This field is optional.
	Footer string `json:"footer"`

	// Link is an optional link (url) to more information about the alert, displayed as a context block in the Slack post.
	// This field is optional, but if set, it must be a valid absolute URL, starting with http:// or https://
	Link string `json:"link"`

	// IssueFollowUpEnabled is a flag that determines if the issue should be automatically resolved after a certain time.
	// If set to true, the issue will be resolved after AutoResolveSeconds seconds.
	// Set to false for fire-and-forget alerts, where no follow-up is needed (i.e. no issue tracking).
	IssueFollowUpEnabled bool `json:"issueFollowUpEnabled"`

	// AutoResolveSeconds is the number of seconds after which the issue should be automatically resolved, if IssueFollowUpEnabled is true.
	// The value must be between MinAutoResolveSeconds and MaxAutoResolveSeconds.
	AutoResolveSeconds int `json:"autoResolveSeconds"`

	// AutoResolveAsInconclusive is a flag that determines if the issue should be automatically resolved as 'inconclusive' instead of 'resolved'.
	// This affects the which emoji is used in the Slack post.
	// The default value is false, which means the issue is resolved with status 'resolved'.
	AutoResolveAsInconclusive bool `json:"autoResolveAsInconclusive"`

	// Severity is the severity of the alert, such as 'panic', 'error', 'warning', 'resolved' or 'info'.
	// This value determines the emoji used in the Slack post (for the :status: placeholder in header or text).
	// The value must be one of the predefined AlertSeverity constants.
	// If unset, the severity is automatically set to 'error'.
	Severity AlertSeverity `json:"severity"`

	// SlackChannelID is the ID of the Slack channel where the alert should be posted.
	// Slack channel names are also accepted, and are automatically converted to channel IDs by the API.
	// The value must be an existing channel ID or name, and the Slack Manager integration must have been added to the channel.
	// This field is optional.
	// If both SlackChannelID and RouteKey are set, SlackChannelID takes precedence.
	// If both SlackChannelID and RouteKey are empty, the API will still accept the alert IF a fallback mapping exists. Otherwise, it will return an error.
	SlackChannelID string `json:"slackChannelId"`

	// RouteKey is the case-insensitive route key of the alert, used for routing to the correct Slack channel by the API.
	// The API will return an error if the route key does not match any configured route.
	// This field is optional.
	// If both SlackChannelID and RouteKey are set, SlackChannelID takes precedence.
	// If both SlackChannelID and RouteKey are empty, the API will still accept the alert IF a fallback mapping exists. Otherwise, it will return an error.
	RouteKey string `json:"routeKey"`

	// Username is the username that the alert should be posted as in Slack.
	// This field is optional. If omitted, the alert is posted as the default bot user.
	Username string `json:"username"`

	// IconEmoji is the emoji that the alert should be posted with in Slack, on the format ':emoji:'.
	IconEmoji string `json:"iconEmoji"`

	// Fields are rendered in a compact format that allows for 2 columns of side-by-side text.
	Fields []*Field `json:"fields"`

	// NotificationDelaySeconds is the number of seconds to wait before creating an actual Slack post.
	// If the issue is resolved before the delay is over, no Slack post is created for the issue.
	// This is useful for issues that may be resolved quickly, to avoid unnecessary notifications.
	NotificationDelaySeconds int `json:"notificationDelaySeconds"`

	// ArchivingDelaySeconds is the number of seconds to wait before archiving the issue, after it is resolved.
	// A non-archived issue is re-opened if a new alert with the same CorrelationID is received, and the same Slack post is updated.
	// An archived issue can never be re-opened, and any new alerts with the same CorrelationID will generate a new issue and new Slack post.
	ArchivingDelaySeconds int `json:"archivingDelaySeconds"`

	// Escalation defines a list of escalation points for this alert's issue.
	// Each escalation can increase severity, add Slack mentions, or move the issue to a different channel after a specified delay.
	// Escalations are sorted by DelaySeconds and triggered in order if the issue remains unresolved.
	// Maximum of MaxEscalationCount escalations allowed.
	Escalation []*Escalation `json:"escalation"`

	// IgnoreIfTextContains is a list of substrings that, if found in the alert text, will cause the alert to be ignored.
	// This is useful for filtering out known noise or false positives.
	// Maximum of MaxIgnoreIfTextContainsCount items, each up to MaxIgnoreIfTextContainsLength characters.
	IgnoreIfTextContains []string `json:"ignoreIfTextContains"`

	// Webhooks defines interactive buttons that appear on the Slack post.
	// Each webhook triggers an HTTP POST to the specified URL when clicked.
	// Webhooks can include confirmation dialogs, input forms, and access level restrictions.
	// Maximum of MaxWebhookCount webhooks allowed.
	Webhooks []*Webhook `json:"webhooks"`

	// Metadata is an arbitrary key-value map for storing custom data with the alert.
	// This data is passed through to webhook payloads and can be used for tracking or correlation purposes.
	// The Slack Manager does not interpret this data.
	Metadata map[string]any `json:"metadata"`

	// Deprecated: FailOnRateLimitError is no longer in use.
	FailOnRateLimitError bool `json:"failOnRateLimitError"`
}

Alert represents a single alert that can be sent to the Slack Manager. Alerts with the same CorrelationID are grouped together in issues by the Slack Manager.

func NewAlert

func NewAlert(severity AlertSeverity) *Alert

NewAlert returns an alert with the specified severity

func NewErrorAlert

func NewErrorAlert() *Alert

NewErrorAlert returns an alert with the severity set to 'error'

func NewInfoAlert

func NewInfoAlert() *Alert

NewInfoAlert returns an alert with the severity set to 'info'

func NewPanicAlert

func NewPanicAlert() *Alert

NewPanicAlert returns an alert with the severity set to 'panic'

func NewResolvedAlert

func NewResolvedAlert() *Alert

NewResolvedAlert returns an alert with the severity set to 'resolved'

func NewWarningAlert

func NewWarningAlert() *Alert

NewWarningAlert returns an alert with the severity set to 'warning'

func (*Alert) Clean

func (a *Alert) Clean()

Clean normalizes and sanitizes all alert fields. It trims whitespace, normalizes case where appropriate, truncates fields that exceed maximum lengths, and applies default values for empty or invalid fields (e.g., sets Severity to 'error' if empty). This method should be called before validation to ensure consistent data.

func (*Alert) UniqueID

func (a *Alert) UniqueID() string

UniqueID returns a unique and deterministic ID for this alert, for database/storage purposes. The ID is based on certain fields of the alert, and is base64 encoded to ensure it is safe for use in URLs and as a database key.

func (*Alert) Validate

func (a *Alert) Validate() error

Validate returns an error if one or more of the required fields are empty or invalid

func (*Alert) ValidateAutoResolve

func (a *Alert) ValidateAutoResolve() error

ValidateAutoResolve validates that AutoResolveSeconds is within the allowed range when IssueFollowUpEnabled is true.

func (*Alert) ValidateCorrelationID

func (a *Alert) ValidateCorrelationID() error

ValidateCorrelationID validates that CorrelationID, if set, does not exceed MaxCorrelationIDLength.

func (*Alert) ValidateEscalation

func (a *Alert) ValidateEscalation() error

ValidateEscalation validates all escalation points in the alert. It checks that the escalation count is within limits, delays are properly spaced, severities are valid for escalation, and Slack mentions and channels are valid.

func (*Alert) ValidateFields

func (a *Alert) ValidateFields() error

ValidateFields validates that the number of fields does not exceed MaxFieldCount.

func (*Alert) ValidateHeaderAndText

func (a *Alert) ValidateHeaderAndText() error

ValidateHeaderAndText validates that at least one of Header or Text is non-empty. An alert must have either a header or text content to be meaningful.

func (*Alert) ValidateIcon

func (a *Alert) ValidateIcon() error

ValidateIcon validates that IconEmoji, if set, matches the expected Slack emoji format ':emoji:'.

func (*Alert) ValidateIgnoreIfTextContains

func (a *Alert) ValidateIgnoreIfTextContains() error

ValidateIgnoreIfTextContains validates that the IgnoreIfTextContains slice does not exceed the maximum count and that each item does not exceed the maximum length.

func (a *Alert) ValidateLink() error

ValidateLink validates that Link, if set, is a valid absolute URL with a scheme.

func (*Alert) ValidateSeverity

func (a *Alert) ValidateSeverity() error

ValidateSeverity validates that Severity is one of the allowed AlertSeverity values.

func (*Alert) ValidateSlackChannelIDAndRouteKey

func (a *Alert) ValidateSlackChannelIDAndRouteKey() error

ValidateSlackChannelIDAndRouteKey validates that SlackChannelID and RouteKey are valid, if set. Both values are allowed to be empty (in which case a fallback mapping must exist in the API).

func (*Alert) ValidateWebhooks

func (a *Alert) ValidateWebhooks() error

ValidateWebhooks validates all webhooks in the alert. It checks that the webhook count is within limits, all required fields are present, URLs are valid, IDs are unique, and all nested inputs are properly configured.

type AlertSeverity

type AlertSeverity string

AlertSeverity represents the severity for a given alert

const (
	// AlertPanic is used for panic situations (panic icon in Slack).
	AlertPanic AlertSeverity = "panic"

	// AlertError is used for error (critical) situations (red error icon in Slack).
	// Alerts with severity 'critical' are automatically converted to 'error'.
	AlertError AlertSeverity = "error"

	// AlertWarning is used for warning situations (yellow warning icon in Slack).
	AlertWarning AlertSeverity = "warning"

	// AlertResolved is used when a previous panic/error/warning situation has been resolved (and IssueFollowUpEnabled is true).
	// The previous icon is replaced with a green OK icon.
	// Not to be confused with an info alert!
	AlertResolved AlertSeverity = "resolved"

	// AlertInfo is used for pure info situations (blue info icon in Slack).
	// Typically used for fire-and-forget status messages, where IssueFollowUpEnabled is false.
	// Not to be confused with a resolved alert!
	AlertInfo AlertSeverity = "info"
)

type ChannelProcessingState

type ChannelProcessingState struct {
	ChannelID           string    `json:"channelId"`
	Created             time.Time `json:"created"`
	LastChannelActivity time.Time `json:"lastChannelActivity"`
	LastProcessed       time.Time `json:"lastProcessed"`
	OpenIssues          int       `json:"openIssues"`
}

ChannelProcessingState represents the state of processing for a specific Slack channel, used internally by the Slack Manager. It tracks when the processing started and when it was last processed. This is used to prevent multiple instances of the Slack Manager from processing the same channel at the same time, and to ensure that processing is done at regular intervals.

func NewChannelProcessingState

func NewChannelProcessingState(channelID string) *ChannelProcessingState

type DB

type DB interface {
	// Init initializes the database, for example by creating necessary tables or collections.
	// Set skipSchemaValidation to true to skip schema validation.
	Init(ctx context.Context, skipSchemaValidation bool) error

	// SaveAlert saves an alert to the database (for auditing purposes).
	// The same alert may be saved multiple times, in case of errors and retries.
	//
	// A database implementation can choose to skip saving the alerts, since they are never read by the manager.
	SaveAlert(ctx context.Context, alert *Alert) error

	// SaveIssue creates or updates a single issue in the database.
	SaveIssue(ctx context.Context, issue Issue) error

	// SaveIssues creates or updates multiple issues in the database.
	SaveIssues(ctx context.Context, issues ...Issue) error

	// MoveIssue moves an issue from one channel to another.
	// This channel ID in the issue must match the targetChannelID.
	// The sourceChannelID is used to find the existing issue in the database.
	MoveIssue(ctx context.Context, issue Issue, sourceChannelID, targetChannelID string) error

	// FindOpenIssueByCorrelationID finds a single open issue in the database, based on the provided channel ID and correlation ID.
	//
	// The database implementation should return an error if the query matches multiple issues, and [nil, nil] if no issue is found.
	FindOpenIssueByCorrelationID(ctx context.Context, channelID, correlationID string) (string, json.RawMessage, error)

	// FindIssueBySlackPostID finds a single issue in the database, based on the provided channel ID and Slack post ID.
	//
	// The database implementation should return an error if the query matches multiple issues, and [nil, nil] if no issue is found.
	FindIssueBySlackPostID(ctx context.Context, channelID, postID string) (string, json.RawMessage, error)

	// FindActiveChannels returns a list of all active channels in the database.
	// An active channel is one that has at least one open issue.
	// The returned list may be empty if no active channels are found.
	FindActiveChannels(ctx context.Context) ([]string, error)

	// LoadOpenIssuesInChannel loads all open (non-archived) issues from the database, for the specified channel ID.
	// The returned list may be empty if no open issues are found in the channel.
	LoadOpenIssuesInChannel(ctx context.Context, channelID string) (map[string]json.RawMessage, error)

	// SaveMoveMapping creates or updates a single move mapping in the database.
	SaveMoveMapping(ctx context.Context, moveMapping MoveMapping) error

	// FindMoveMapping finds a single move mapping in the database, for the specified channel ID and correlation ID.
	//
	// The database implementation should return an error if the query matches multiple mappings, and [nil, nil] if no mapping is found.
	FindMoveMapping(ctx context.Context, channelID, correlationID string) (json.RawMessage, error)

	// DeleteMoveMapping deletes a single move mapping from the database, for the specified channel ID and correlation ID.
	DeleteMoveMapping(ctx context.Context, channelID, correlationID string) error

	// SaveChannelProcessingState creates or updates a single channel processing state in the database.
	SaveChannelProcessingState(ctx context.Context, state *ChannelProcessingState) error

	// FindChannelProcessingState finds a single channel processing state in the database, for the specified channel ID.
	//
	// The database implementation should return an error if the query matches multiple states, and [nil, nil] if no state is found.
	FindChannelProcessingState(ctx context.Context, channelID string) (*ChannelProcessingState, error)

	// DropAllData drops *all* data from the database.
	// This is useful for testing purposes, to reset the database state.
	// It should be used with caution, as it will remove all alerts, issues, move mappings, and processing states.
	DropAllData(ctx context.Context) error
}

DB is an interface for interacting with the database. It must be implemented by any database driver used by the Slack Manager.

type Escalation

type Escalation struct {
	// Severity is the new severity of the issue, when the escalation is triggered.
	Severity AlertSeverity `json:"severity"`

	// DelaySeconds is the number of seconds since the issue was created (first alert received),
	// before the escalation is triggered.
	DelaySeconds int `json:"delaySeconds"`

	// SlackMentions is a list of Slack mentions that should be added to the Slack post when the escalation is triggered.
	SlackMentions []string `json:"slackMentions"`

	// MoveToChannel is the ID or name of the Slack channel where the alert should be moved when the escalation is triggered.
	MoveToChannel string `json:"moveToChannel"`
}

Escalation represents an escalation point for an issue.

type Field

type Field struct {
	// Title is the title of the field. It is automatically truncated at MaxFieldTitleLength characters.
	Title string `json:"title"`

	// Value is the value of the field. It is automatically truncated at MaxFieldValueLength characters.
	Value string `json:"value"`
}

Field is an alert field.

type FifoQueueItem

type FifoQueueItem struct {
	// MessageID is the unique identifier of the message (as defined by the queue implementation).
	MessageID string

	// SlackChannelID is the ID of the Slack channel to which the message is related.
	SlackChannelID string

	// ReceiveTimestamp is the time when the message was received from the queue.
	ReceiveTimestamp time.Time

	// Body is the body of the message.
	Body string

	// Ack acknowledges the successful processing of the message, effectively removing it from the queue.
	// This function cannot be nil.
	//
	// Ack does not accept a context parameter because acknowledgment is a commitment that must complete
	// regardless of the caller's context state. Each queue implementation is responsible for managing
	// its own timeouts and retry logic internally.
	Ack func()

	// Nack negatively acknowledges the processing of the message, thus making it available for reprocessing.
	// This function cannot be nil.
	//
	// Nack does not accept a context parameter because negative acknowledgment is a commitment that must
	// complete regardless of the caller's context state. Each queue implementation is responsible for
	// managing its own timeouts and retry logic internally.
	Nack func()
}

FifoQueueItem represents an item received from a FIFO queue.

type InMemoryDB added in v0.3.1

type InMemoryDB struct {
	// contains filtered or unexported fields
}

InMemoryDB is an in-memory implementation of the DB interface. For TEST purposes only! Do not use in production!

func NewInMemoryDB added in v0.3.1

func NewInMemoryDB() *InMemoryDB

NewInMemoryDB creates a new InMemoryDB instance. For TEST purposes only! Do not use in production!

func (*InMemoryDB) DeleteMoveMapping added in v0.3.1

func (db *InMemoryDB) DeleteMoveMapping(_ context.Context, channelID, correlationID string) error

DeleteMoveMapping deletes a move mapping. No error is returned if the mapping does not exist.

func (*InMemoryDB) DropAllData added in v0.3.1

func (db *InMemoryDB) DropAllData(_ context.Context) error

DropAllData clears all data from the in-memory store.

func (*InMemoryDB) FindActiveChannels added in v0.3.1

func (db *InMemoryDB) FindActiveChannels(_ context.Context) ([]string, error)

FindActiveChannels returns a list of all channels that have at least one open issue.

func (*InMemoryDB) FindChannelProcessingState added in v0.3.1

func (db *InMemoryDB) FindChannelProcessingState(_ context.Context, channelID string) (*ChannelProcessingState, error)

FindChannelProcessingState finds a channel processing state by channel ID. Returns nil without an error if no state is found.

func (*InMemoryDB) FindIssueBySlackPostID added in v0.3.1

func (db *InMemoryDB) FindIssueBySlackPostID(_ context.Context, channelID, postID string) (string, json.RawMessage, error)

FindIssueBySlackPostID finds a single issue by channel ID and Slack post ID. Returns an error if channelID or postID are empty.

func (*InMemoryDB) FindMoveMapping added in v0.3.1

func (db *InMemoryDB) FindMoveMapping(_ context.Context, channelID, correlationID string) (json.RawMessage, error)

FindMoveMapping finds a move mapping by channel ID and correlation ID. Returns an error if channelID or correlationID are empty.

func (*InMemoryDB) FindOpenIssueByCorrelationID added in v0.3.1

func (db *InMemoryDB) FindOpenIssueByCorrelationID(_ context.Context, channelID, correlationID string) (string, json.RawMessage, error)

FindOpenIssueByCorrelationID finds a single open issue by channel ID and correlation ID. Returns an error if channelID or correlationID are empty, or if multiple open issues match.

func (*InMemoryDB) Init added in v0.3.1

func (db *InMemoryDB) Init(_ context.Context, _ bool) error

Init is a no-op for the in-memory implementation.

func (*InMemoryDB) LoadOpenIssuesInChannel added in v0.3.1

func (db *InMemoryDB) LoadOpenIssuesInChannel(_ context.Context, channelID string) (map[string]json.RawMessage, error)

LoadOpenIssuesInChannel loads all open issues for the specified channel.

func (*InMemoryDB) MoveIssue added in v0.3.1

func (db *InMemoryDB) MoveIssue(_ context.Context, issue Issue, sourceChannelID, targetChannelID string) error

MoveIssue moves an issue from one channel to another. Returns an error if sourceChannelID and targetChannelID are the same. If the issue does not exist in the store, this is a no-op.

func (*InMemoryDB) SaveAlert added in v0.3.1

func (db *InMemoryDB) SaveAlert(_ context.Context, alert *Alert) error

SaveAlert saves an alert to the in-memory store.

func (*InMemoryDB) SaveChannelProcessingState added in v0.3.1

func (db *InMemoryDB) SaveChannelProcessingState(_ context.Context, state *ChannelProcessingState) error

SaveChannelProcessingState creates or updates a channel processing state.

func (*InMemoryDB) SaveIssue added in v0.3.1

func (db *InMemoryDB) SaveIssue(_ context.Context, issue Issue) error

SaveIssue creates or updates a single issue.

func (*InMemoryDB) SaveIssues added in v0.3.1

func (db *InMemoryDB) SaveIssues(ctx context.Context, issues ...Issue) error

SaveIssues creates or updates multiple issues.

func (*InMemoryDB) SaveMoveMapping added in v0.3.1

func (db *InMemoryDB) SaveMoveMapping(_ context.Context, moveMapping MoveMapping) error

SaveMoveMapping creates or updates a move mapping.

type InMemoryFifoQueue

type InMemoryFifoQueue struct {
	// contains filtered or unexported fields
}

InMemoryFifoQueue is an in-memory FIFO queue implementation For TEST purposes only! Do not use in production!

func NewInMemoryFifoQueue

func NewInMemoryFifoQueue(name string, bufferSize int, writeTimeout time.Duration) *InMemoryFifoQueue

NewInMemoryFifoQueue creates a new InMemoryFifoQueue instance. name is the name of the queue (for logging purposes only). bufferSize is the maximum number of items that can be stored in the queue. writeTimeout is the maximum time to wait for writing an item to the queue.

For TEST purposes only! Do not use in production!

func (*InMemoryFifoQueue) Name

func (q *InMemoryFifoQueue) Name() string

Name returns the name of the queue.

func (*InMemoryFifoQueue) Receive

func (q *InMemoryFifoQueue) Receive(ctx context.Context, sinkCh chan<- *FifoQueueItem) error

Receive receives messages from the queue, to the specified sink channel. An error is returned if the context is canceled. The sink channel is closed when the function returns.

func (*InMemoryFifoQueue) Send

func (q *InMemoryFifoQueue) Send(ctx context.Context, slackChannelID, _, body string) error

Send sends a message to the queue. An error is returned if the context is canceled or the write timeout is reached.

type Issue

type Issue interface {
	json.Marshaler

	// ChannelID returns the Slack channel ID that this issue belongs to.
	ChannelID() string

	// UniqueID returns a unique and deterministic ID for this issue, for database/storage purposes.
	// The ID is based on certain issue fields, and is base64 encoded to ensure it is safe for use in URLs and as a database key.
	UniqueID() string

	// GetCorrelationID returns the correlation ID for this issue.
	// The correlation ID is used to group related alerts together, and may or may not be client defined.
	// It is not guaranteed to be unique across all issues, even in the same channel, and *cannot* be used as a unique issue identifier.
	// It is not URL safe, and should thus be encoded before being used in URLs or as part of a database key.
	GetCorrelationID() string

	// IsOpen returns true if this issue is currently open (i.e. not archived).
	// A resolved issue is still considered open until it is archived.
	IsOpen() bool

	// CurrentPostID returns the current Slack post ID associated with this issue.
	// The value may change over time as the issue is updated.
	// If the issue has no current post, it returns an empty string.
	CurrentPostID() string
}

Issue represents an issue in a Slack channel. It is used to track alerts, their resolution status, and their association with Slack posts.

The actual implementation of this interface is internal to the Slack Manager, and may change without notice. The database implementation should only store a JSON representation of the issue, and should not depend on any specific fields or structures of the issue.

type Logger

type Logger interface {
	Debug(msg string)
	Debugf(format string, args ...any)
	Info(msg string)
	Infof(format string, args ...any)
	Error(msg string)
	Errorf(format string, args ...any)
	WithField(key string, value any) Logger
	WithFields(fields map[string]any) Logger
}

type Metrics

type Metrics interface {
	// RegisterCounter registers a counter metric with the given name, help text, and optional labels.
	RegisterCounter(name, help string, labels ...string)

	// RegisterGauge registers a gauge metric with the given name, help text, and optional labels.
	RegisterGauge(name, help string, labels ...string)

	// RegisterHistogram registers a histogram metric with the given name, help text, buckets, and optional labels.
	RegisterHistogram(name, help string, buckets []float64, labels ...string)

	// Add adds the given value to the specified counter metric, with optional label values.
	Add(name string, value float64, labelValues ...string)

	// Inc increments the specified counter metric by 1, with optional label values.
	Inc(name string, labelValues ...string)

	// Set sets the specified gauge metric to the given value, with optional label values.
	Set(name string, value float64, labelValues ...string)

	// Observe records an observation for the specified histogram metric, with optional label values.
	Observe(name string, value float64, labelValues ...string)
}

type MoveMapping

type MoveMapping interface {
	json.Marshaler

	// ChannelID returns the Slack channel ID that this move mapping belongs to (i.e. the channel where the move was initiated).
	ChannelID() string

	// UniqueID returns a unique and deterministic ID for this move mapping, for database/storage purposes.
	// The ID is based on the original channel and the correlation ID, and is base64 encoded to ensure it is safe for use in URLs and as a database key.
	UniqueID() string

	// GetCorrelationID returns the correlation ID that this move mapping is associated with, for the given channel.
	// It is not URL safe, and should thus be encoded before being used in URLs or as part of a database key.
	GetCorrelationID() string
}

MoveMapping represents an issue that has been moved from one channel to another, based on the correlation ID. It is used to ensure that new alerts with the same correlation ID are not processed in the original channel, but instead are processed in the new channel.

The actual implementation of this interface is internal to the Slack Manager, and may change without notice. The database implementation should only store a JSON representation of the move mapping, and should not depend on any specific fields or structure of the move mapping.

type NoopLogger

type NoopLogger struct{}

func (*NoopLogger) Debug

func (l *NoopLogger) Debug(msg string)

func (*NoopLogger) Debugf

func (l *NoopLogger) Debugf(format string, args ...any)

func (*NoopLogger) Error

func (l *NoopLogger) Error(msg string)

func (*NoopLogger) Errorf

func (l *NoopLogger) Errorf(format string, args ...any)

func (*NoopLogger) Info

func (l *NoopLogger) Info(msg string)

func (*NoopLogger) Infof

func (l *NoopLogger) Infof(format string, args ...any)

func (*NoopLogger) WithField

func (l *NoopLogger) WithField(key string, value any) Logger

func (*NoopLogger) WithFields

func (l *NoopLogger) WithFields(fields map[string]any) Logger

type NoopMetrics

type NoopMetrics struct{}

NoopMetrics is a no-op implementation of the Metrics interface. It does not record any metrics. Use if no metrics are needed.

func (*NoopMetrics) Add

func (m *NoopMetrics) Add(_ string, _ float64, _ ...string)

func (*NoopMetrics) Inc

func (m *NoopMetrics) Inc(_ string, _ ...string)

func (*NoopMetrics) Observe

func (m *NoopMetrics) Observe(_ string, _ float64, _ ...string)

func (*NoopMetrics) RegisterCounter

func (m *NoopMetrics) RegisterCounter(_, _ string, _ ...string)

func (*NoopMetrics) RegisterGauge

func (m *NoopMetrics) RegisterGauge(_, _ string, _ ...string)

func (*NoopMetrics) RegisterHistogram

func (m *NoopMetrics) RegisterHistogram(_, _ string, _ []float64, _ ...string)

func (*NoopMetrics) Set

func (m *NoopMetrics) Set(_ string, _ float64, _ ...string)

type Webhook

type Webhook struct {
	// ID is the unique identifier for this webhook within the alert.
	// It must be unique among all webhooks in the same alert.
	// Maximum length: MaxWebhookIDLength characters.
	ID string `json:"id"`

	// URL specifies the target for the webhook when the button is clicked.
	// For HTTP webhooks, this must be a valid absolute URL starting with http:// or https://.
	// For custom webhook handlers registered in the Slack Manager app, this can be an arbitrary
	// ASCII string identifier that the handler recognizes.
	// The field name "URL" is retained for backwards compatibility.
	// Maximum length: MaxWebhookURLLength characters.
	URL string `json:"url"`

	// ConfirmationText is the text displayed in a confirmation dialog before triggering the webhook.
	// If empty, no confirmation dialog is shown and the webhook is triggered immediately.
	// Maximum length: MaxWebhookConfirmationTextLength characters.
	ConfirmationText string `json:"confirmationText"`

	// ButtonText is the label displayed on the button in Slack.
	// This field is required.
	// Maximum length: MaxWebhookButtonTextLength characters.
	ButtonText string `json:"buttonText"`

	// ButtonStyle determines the visual appearance of the button in Slack.
	// Valid values are defined by WebhookButtonStyle constants.
	// If empty, the default Slack button style is used.
	ButtonStyle WebhookButtonStyle `json:"buttonStyle"`

	// AccessLevel controls who can click this webhook button.
	// Valid values are defined by WebhookAccessLevel constants.
	// If empty, anyone in the channel can trigger the webhook.
	AccessLevel WebhookAccessLevel `json:"accessLevel"`

	// DisplayMode controls when the webhook button is visible.
	// Valid values are defined by WebhookDisplayMode constants.
	// If empty, the button is always visible.
	DisplayMode WebhookDisplayMode `json:"displayMode"`

	// Payload is a map of key-value pairs sent in the HTTP POST body when the webhook is triggered.
	// Alert metadata and input values are merged into this payload.
	// Maximum of MaxWebhookPayloadCount items.
	Payload map[string]any `json:"payload"`

	// PlainTextInput defines text input fields shown in the webhook's modal dialog.
	// User-entered values are included in the webhook payload.
	// Maximum of MaxWebhookPlainTextInputCount inputs.
	PlainTextInput []*WebhookPlainTextInput `json:"plainTextInput"`

	// CheckboxInput defines checkbox groups shown in the webhook's modal dialog.
	// Selected values are included in the webhook payload.
	// Maximum of MaxWebhookCheckboxInputCount inputs.
	CheckboxInput []*WebhookCheckboxInput `json:"checkboxInput"`
}

Webhook represents an interactive button that appears on the Slack post. When clicked, it triggers an HTTP POST request to the specified URL (for http/https URLs), or invokes a custom webhook handler registered in the Slack Manager app.

type WebhookAccessLevel

type WebhookAccessLevel string

WebhookAccessLevel is the access level required to invoke a webhook.

const (
	// WebhookAccessLevelGlobalAdmins indicates that a webhook is available only to Slack Manager global admins.
	WebhookAccessLevelGlobalAdmins WebhookAccessLevel = "global_admins"

	// WebhookAccessLevelChannelAdmins indicates that a webhook is available to the Slack Manager channel admins (and global admins).
	WebhookAccessLevelChannelAdmins WebhookAccessLevel = "channel_admins"

	// WebhookAccessLevelChannelMembers indicates that a webhook is available to all members in a channel.
	WebhookAccessLevelChannelMembers WebhookAccessLevel = "channel_members"
)

type WebhookButtonStyle

type WebhookButtonStyle string

WebhookButtonStyle represents a webhook button style.

const (
	// WebhookButtonStylePrimary represents Slack button style 'primary'.
	WebhookButtonStylePrimary WebhookButtonStyle = "primary"

	// WebhookButtonStyleDanger represents Slack button style 'danger'.
	WebhookButtonStyleDanger WebhookButtonStyle = "danger"
)

type WebhookCallback

type WebhookCallback struct {
	ID            string              `json:"id"`
	UserID        string              `json:"userId"`
	UserRealName  string              `json:"userRealName"`
	ChannelID     string              `json:"channelId"`
	MessageID     string              `json:"messageId"`
	Timestamp     time.Time           `json:"timestamp"`
	Input         map[string]string   `json:"input"`
	CheckboxInput map[string][]string `json:"checkboxInput"`
	Payload       map[string]any      `json:"payload"`
}

func (*WebhookCallback) GetCheckboxInputSelectedValues

func (w *WebhookCallback) GetCheckboxInputSelectedValues(key string) []string

func (*WebhookCallback) GetInputValue

func (w *WebhookCallback) GetInputValue(key string) string

func (*WebhookCallback) GetPayloadBool

func (w *WebhookCallback) GetPayloadBool(key string, defaultValue bool) bool

func (*WebhookCallback) GetPayloadInt

func (w *WebhookCallback) GetPayloadInt(key string, defaultValue int) int

func (*WebhookCallback) GetPayloadString

func (w *WebhookCallback) GetPayloadString(key string) string

func (*WebhookCallback) GetPayloadValue

func (w *WebhookCallback) GetPayloadValue(key string) any

type WebhookCheckboxInput

type WebhookCheckboxInput struct {
	// ID is the unique identifier for this checkbox group.
	// It must be unique among all inputs (both text and checkbox) in the same webhook.
	// The ID is used as the key in the webhook payload.
	// Maximum length: MaxWebhookInputIDLength characters.
	ID string `json:"id"`

	// Label is the text displayed above the checkbox group.
	// Maximum length: MaxWebhookInputLabelLength characters.
	Label string `json:"label"`

	// Options is the list of checkbox options available in this group.
	// Maximum of MaxWebhookCheckboxOptionCount options.
	Options []*WebhookCheckboxOption `json:"options"`
}

WebhookCheckboxInput represents a group of checkboxes in a webhook's modal dialog. Selected option values are included in the webhook payload as an array with the field ID as the key.

type WebhookCheckboxOption

type WebhookCheckboxOption struct {
	// Value is the value included in the webhook payload when this option is selected.
	// Must be unique among all options in the same checkbox group.
	// Maximum length: MaxCheckboxOptionValueLength characters.
	Value string `json:"value"`

	// Text is the label displayed next to the checkbox.
	// Maximum length: MaxWebhookCheckboxOptionTextLength characters.
	Text string `json:"text"`

	// Selected determines whether this checkbox is pre-selected when the modal opens.
	Selected bool `json:"selected"`
}

WebhookCheckboxOption represents a single checkbox option within a WebhookCheckboxInput.

type WebhookDisplayMode

type WebhookDisplayMode string

WebhookDisplayMode represents a display mode for a webhook button.

const (
	// WebhookDisplayModeAlways means that the webhook button is always displayed, regardless of issue state.
	WebhookDisplayModeAlways WebhookDisplayMode = "always"

	// WebhookDisplayModeOpenIssue means that the webhook button is displayed for open issues only (error, warning etc).
	WebhookDisplayModeOpenIssue WebhookDisplayMode = "open_issue"

	// WebhookDisplayModeResolvedIssue means that the webhook button is displayed for resolved issues only.
	WebhookDisplayModeResolvedIssue WebhookDisplayMode = "resolved_issue"
)

type WebhookPlainTextInput

type WebhookPlainTextInput struct {
	// ID is the unique identifier for this input field.
	// It must be unique among all inputs (both text and checkbox) in the same webhook.
	// The ID is used as the key in the webhook payload.
	// Maximum length: MaxWebhookInputIDLength characters.
	ID string `json:"id"`

	// Description is the placeholder text shown in the input field before the user types.
	// Maximum length: MaxWebhookInputDescriptionLength characters.
	Description string `json:"description"`

	// MinLength is the minimum number of characters required for the input.
	// Must be >= 0 and <= MaxLength.
	MinLength int `json:"minLength"`

	// MaxLength is the maximum number of characters allowed for the input.
	// Must be >= MinLength and <= MaxWebhookInputTextLength.
	MaxLength int `json:"maxLength"`

	// Multiline determines whether the input field allows multiple lines of text.
	// If true, a larger textarea is shown instead of a single-line input.
	Multiline bool `json:"multiline"`

	// InitialValue is the default text pre-filled in the input field.
	// Must satisfy the MinLength and MaxLength constraints.
	InitialValue string `json:"initialValue"`
}

WebhookPlainTextInput represents a text input field in a webhook's modal dialog. The user's input is included in the webhook payload with the field ID as the key.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL