Split models package for easier maintenance

This commit is contained in:
Łukasz Mierzwa
2017-06-25 10:21:49 -07:00
parent 26d14d1bd2
commit 4ecc0f199d
6 changed files with 189 additions and 182 deletions

58
models/alert.go Normal file
View File

@@ -0,0 +1,58 @@
package models
import "time"
// AlertStateUnprocessed means that Alertmanager notify didn't yet process it
// and AM doesn't know if alert is active or suppressed
const AlertStateUnprocessed = "unprocessed"
// AlertStateActive is the state in which we know that the alert should fire
const AlertStateActive = "active"
// AlertStateSuppressed means that we know that alert is silenced or inhibited
const AlertStateSuppressed = "suppressed"
// AlertStateList exports all alert states so other packages can get this list
var AlertStateList = []string{
AlertStateUnprocessed,
AlertStateActive,
AlertStateSuppressed,
}
// Alert is vanilla alert + some additional attributes
// unsee extends an alert object with:
// * Links map, it's generated from annotations if annotation value is an url
// it's pulled out of annotation map and returned under links field,
// unsee UI used this to show links differently than other annotations
// * Fingerprint, which is a sha1 of the entire alert
type Alert struct {
Annotations map[string]string `json:"annotations"`
Labels map[string]string `json:"labels"`
StartsAt time.Time `json:"startsAt"`
EndsAt time.Time `json:"endsAt"`
GeneratorURL string `json:"generatorURL"`
State string `json:"state"`
SilencedBy []string `json:"silencedBy"`
InhibitedBy []string `json:"inhibitedBy"`
// unsee fields
Alertmanager []AlertmanagerUpstream `json:"alertmanager"`
Receiver string `json:"receiver"`
Links map[string]string `json:"links"`
ID string `json:"-"`
Fingerprint string `json:"-"`
}
// IsSilenced will return true if alert should be considered silenced
func (a Alert) IsSilenced() bool {
return (a.State == AlertStateSuppressed && len(a.SilencedBy) > 0)
}
// IsInhibited will return true if alert should be considered silenced
func (a Alert) IsInhibited() bool {
return (a.State == AlertStateSuppressed && len(a.InhibitedBy) > 0)
}
// IsActive will return true if alert is not suppressed in any way
func (a Alert) IsActive() bool {
return (a.State == AlertStateActive)
}

49
models/alertgroup.go Normal file
View File

@@ -0,0 +1,49 @@
package models
import (
"crypto/sha1"
"fmt"
"io"
)
// AlertList is flat list of UnseeAlert objects
type AlertList []Alert
func (a AlertList) Len() int {
return len(a)
}
func (a AlertList) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}
func (a AlertList) Less(i, j int) bool {
// compare timestamps, if equal compare fingerprints to stable sort order
if a[i].StartsAt.After(a[j].StartsAt) {
return true
}
if a[i].StartsAt.Before(a[j].StartsAt) {
return false
}
return a[i].Fingerprint < a[j].Fingerprint
}
// AlertGroup is vanilla Alertmanager group, but alerts are flattened
// There is a hash computed from all alerts, it's used by UI to quickly tell
// if there was any change in a group and it needs to refresh it
type AlertGroup struct {
Receiver string `json:"receiver"`
Labels map[string]string `json:"labels"`
Alerts AlertList `json:"alerts"`
ID string `json:"id"`
Hash string `json:"hash"`
StateCount map[string]int `json:"stateCount"`
}
// ContentFingerprint is a checksum of all alerts in the group
func (ag AlertGroup) ContentFingerprint() string {
h := sha1.New()
for _, alert := range ag.Alerts {
io.WriteString(h, alert.Fingerprint)
}
return fmt.Sprintf("%x", h.Sum(nil))
}

10
models/alertmanager.go Normal file
View File

@@ -0,0 +1,10 @@
package models
// AlertmanagerUpstream describes the Alertmanager instance alert was collected
// from
type AlertmanagerUpstream struct {
Name string `json:"name"`
URI string `json:"uri"`
// all silences matching current alert in this upstream
Silences map[string]Silence `json:"silences"`
}

48
models/api.go Normal file
View File

@@ -0,0 +1,48 @@
package models
// Filter holds returned data on any filter passed by the user as part of the query
type Filter struct {
Text string `json:"text"`
Hits int `json:"hits"`
IsValid bool `json:"isValid"`
}
// Color is used by UnseeLabelColor to reprenset colors as RGBA
type Color struct {
Red uint8 `json:"red"`
Green uint8 `json:"green"`
Blue uint8 `json:"blue"`
Alpha uint8 `json:"alpha"`
}
// LabelColors holds color information for labels that should be colored in the UI
// every configured label will have a distinct coloring for each value
type LabelColors struct {
Font Color `json:"font"`
Background Color `json:"background"`
}
// LabelsColorMap is a map of "Label Key" -> "Label Value" -> UnseeLabelColors
type LabelsColorMap map[string]map[string]LabelColors
// LabelsCountMap is a map of "Label Key" -> "Label Value" -> number of occurence
type LabelsCountMap map[string]map[string]int
// AlertsResponse is the structure of JSON response UI will use to get alert data
type AlertsResponse struct {
Status string `json:"status"`
Error string `json:"error,omitempty"`
Timestamp string `json:"timestamp"`
Version string `json:"version"`
AlertGroups []AlertGroup `json:"groups"`
Colors LabelsColorMap `json:"colors"`
Filters []Filter `json:"filters"`
Counters LabelsCountMap `json:"counters"`
}
// Autocomplete is the structure of autocomplete object for filter hints
// this is internal represenation, not what's returned to the user
type Autocomplete struct {
Value string `json:"value"`
Tokens []string `json:"tokens"`
}

View File

@@ -1,182 +0,0 @@
package models
import (
"crypto/sha1"
"fmt"
"io"
"time"
)
// Silence is vanilla silence + some additional attributes
// Unsee adds JIRA support, it can extract JIRA IDs from comments
// extracted ID is used to generate link to JIRA issue
// this means Unsee needs to store additional fields for each silence
type Silence struct {
ID string `json:"id"`
Matchers []struct {
Name string `json:"name"`
Value string `json:"value"`
IsRegex bool `json:"isRegex"`
} `json:"matchers"`
StartsAt time.Time `json:"startsAt"`
EndsAt time.Time `json:"endsAt"`
CreatedAt time.Time `json:"createdAt"`
CreatedBy string `json:"createdBy"`
Comment string `json:"comment"`
// unsee fields
JiraID string `json:"jiraID"`
JiraURL string `json:"jiraURL"`
}
// AlertStateUnprocessed means that Alertmanager notify didn't yet process it
// and AM doesn't know if alert is active or suppressed
const AlertStateUnprocessed = "unprocessed"
// AlertStateActive is the state in which we know that the alert should fire
const AlertStateActive = "active"
// AlertStateSuppressed means that we know that alert is silenced or inhibited
const AlertStateSuppressed = "suppressed"
// AlertStateList exports all alert states so other packages can get this list
var AlertStateList = []string{
AlertStateUnprocessed,
AlertStateActive,
AlertStateSuppressed,
}
// AlertmanagerUpstream describes the Alertmanager instance alert was collected
// from
type AlertmanagerUpstream struct {
Name string `json:"name"`
URI string `json:"uri"`
// all silences matching current alert in this upstream
Silences map[string]Silence `json:"silences"`
}
// Alert is vanilla alert + some additional attributes
// unsee extends an alert object with:
// * Links map, it's generated from annotations if annotation value is an url
// it's pulled out of annotation map and returned under links field,
// unsee UI used this to show links differently than other annotations
// * Fingerprint, which is a sha1 of the entire alert
type Alert struct {
Annotations map[string]string `json:"annotations"`
Labels map[string]string `json:"labels"`
StartsAt time.Time `json:"startsAt"`
EndsAt time.Time `json:"endsAt"`
GeneratorURL string `json:"generatorURL"`
State string `json:"state"`
SilencedBy []string `json:"silencedBy"`
InhibitedBy []string `json:"inhibitedBy"`
// unsee fields
Alertmanager []AlertmanagerUpstream `json:"alertmanager"`
Receiver string `json:"receiver"`
Links map[string]string `json:"links"`
ID string `json:"-"`
Fingerprint string `json:"-"`
}
// IsSilenced will return true if alert should be considered silenced
func (a Alert) IsSilenced() bool {
return (a.State == AlertStateSuppressed && len(a.SilencedBy) > 0)
}
// IsInhibited will return true if alert should be considered silenced
func (a Alert) IsInhibited() bool {
return (a.State == AlertStateSuppressed && len(a.InhibitedBy) > 0)
}
// IsActive will return true if alert is not suppressed in any way
func (a Alert) IsActive() bool {
return (a.State == AlertStateActive)
}
// AlertList is flat list of UnseeAlert objects
type AlertList []Alert
func (a AlertList) Len() int {
return len(a)
}
func (a AlertList) Swap(i, j int) {
a[i], a[j] = a[j], a[i]
}
func (a AlertList) Less(i, j int) bool {
// compare timestamps, if equal compare fingerprints to stable sort order
if a[i].StartsAt.After(a[j].StartsAt) {
return true
}
if a[i].StartsAt.Before(a[j].StartsAt) {
return false
}
return a[i].Fingerprint < a[j].Fingerprint
}
// AlertGroup is vanilla Alertmanager group, but alerts are flattened
// There is a hash computed from all alerts, it's used by UI to quickly tell
// if there was any change in a group and it needs to refresh it
type AlertGroup struct {
Receiver string `json:"receiver"`
Labels map[string]string `json:"labels"`
Alerts AlertList `json:"alerts"`
ID string `json:"id"`
Hash string `json:"hash"`
StateCount map[string]int `json:"stateCount"`
}
// ContentFingerprint is a checksum of all alerts in the group
func (ag AlertGroup) ContentFingerprint() string {
h := sha1.New()
for _, alert := range ag.Alerts {
io.WriteString(h, alert.Fingerprint)
}
return fmt.Sprintf("%x", h.Sum(nil))
}
// Filter holds returned data on any filter passed by the user as part of the query
type Filter struct {
Text string `json:"text"`
Hits int `json:"hits"`
IsValid bool `json:"isValid"`
}
// Color is used by UnseeLabelColor to reprenset colors as RGBA
type Color struct {
Red uint8 `json:"red"`
Green uint8 `json:"green"`
Blue uint8 `json:"blue"`
Alpha uint8 `json:"alpha"`
}
// LabelColors holds color information for labels that should be colored in the UI
// every configured label will have a distinct coloring for each value
type LabelColors struct {
Font Color `json:"font"`
Background Color `json:"background"`
}
// LabelsColorMap is a map of "Label Key" -> "Label Value" -> UnseeLabelColors
type LabelsColorMap map[string]map[string]LabelColors
// LabelsCountMap is a map of "Label Key" -> "Label Value" -> number of occurence
type LabelsCountMap map[string]map[string]int
// AlertsResponse is the structure of JSON response UI will use to get alert data
type AlertsResponse struct {
Status string `json:"status"`
Error string `json:"error,omitempty"`
Timestamp string `json:"timestamp"`
Version string `json:"version"`
AlertGroups []AlertGroup `json:"groups"`
Colors LabelsColorMap `json:"colors"`
Filters []Filter `json:"filters"`
Counters LabelsCountMap `json:"counters"`
}
// Autocomplete is the structure of autocomplete object for filter hints
// this is internal represenation, not what's returned to the user
type Autocomplete struct {
Value string `json:"value"`
Tokens []string `json:"tokens"`
}

24
models/silence.go Normal file
View File

@@ -0,0 +1,24 @@
package models
import "time"
// Silence is vanilla silence + some additional attributes
// Unsee adds JIRA support, it can extract JIRA IDs from comments
// extracted ID is used to generate link to JIRA issue
// this means Unsee needs to store additional fields for each silence
type Silence struct {
ID string `json:"id"`
Matchers []struct {
Name string `json:"name"`
Value string `json:"value"`
IsRegex bool `json:"isRegex"`
} `json:"matchers"`
StartsAt time.Time `json:"startsAt"`
EndsAt time.Time `json:"endsAt"`
CreatedAt time.Time `json:"createdAt"`
CreatedBy string `json:"createdBy"`
Comment string `json:"comment"`
// unsee fields
JiraID string `json:"jiraID"`
JiraURL string `json:"jiraURL"`
}