mirror of
https://github.com/prymitive/karma
synced 2026-08-17 11:27:01 +00:00
committed by
Łukasz Mierzwa
parent
4598bbb067
commit
2b963c65d1
@@ -11,3 +11,6 @@
|
||||
|
||||
- ghcr.io/prymitive/karma is now used as the primary repository for docker
|
||||
images instead of Docker Hub
|
||||
- `alertAcknowledgement:commentPrefix` config option was replaced by
|
||||
`alertAcknowledgement:comment` that can be used to customise the entire
|
||||
comment.
|
||||
|
||||
@@ -12,7 +12,7 @@ env ALERTMANAGER_TIMEOUT=10s
|
||||
env ALERTACKNOWLEDGEMENT_ENABLED=true
|
||||
env ALERTACKNOWLEDGEMENT_DURATION=5m
|
||||
env ALERTACKNOWLEDGEMENT_AUTHOR=karma
|
||||
env ALERTACKNOWLEDGEMENT_COMMENTPREFIX=ACK
|
||||
env ALERTACKNOWLEDGEMENT_COMMENT="ACK! This alert was acknowledged via unit tests"
|
||||
|
||||
env ANNOTATIONS_DEFAULT_HIDDEN=true
|
||||
env ANNOTATIONS_HIDDEN='help summary'
|
||||
@@ -106,7 +106,7 @@ level=info msg="alertAcknowledgement:"
|
||||
level=info msg=" enabled: true"
|
||||
level=info msg=" duration: 5m0s"
|
||||
level=info msg=" author: karma"
|
||||
level=info msg=" commentPrefix: ACK"
|
||||
level=info msg=" comment: '\"ACK!'"
|
||||
level=info msg="annotations:"
|
||||
level=info msg=" default:"
|
||||
level=info msg=" hidden: true"
|
||||
|
||||
@@ -93,7 +93,7 @@ level=info msg="alertAcknowledgement:"
|
||||
level=info msg=" enabled: true"
|
||||
level=info msg=" duration: 7m0s"
|
||||
level=info msg=" author: karma"
|
||||
level=info msg=" commentPrefix: ACK!"
|
||||
level=info msg=" comment: ACK! This is comment"
|
||||
level=info msg="annotations:"
|
||||
level=info msg=" default:"
|
||||
level=info msg=" hidden: true"
|
||||
@@ -261,7 +261,7 @@ alertAcknowledgement:
|
||||
enabled: true
|
||||
duration: 7m0s
|
||||
author: karma
|
||||
commentPrefix: ACK!
|
||||
comment: ACK! This is comment
|
||||
annotations:
|
||||
default:
|
||||
hidden: true
|
||||
|
||||
@@ -37,7 +37,7 @@ alertAcknowledgement:
|
||||
enabled: zzz
|
||||
duration: 7m0s
|
||||
author: karma
|
||||
commentPrefix: ACK!
|
||||
comment: comment
|
||||
annotations:
|
||||
default:
|
||||
hidden: z
|
||||
|
||||
@@ -39,7 +39,7 @@ level=info msg="alertAcknowledgement:"
|
||||
level=info msg=" enabled: false"
|
||||
level=info msg=" duration: 15m0s"
|
||||
level=info msg=" author: karma"
|
||||
level=info msg=" commentPrefix: ACK!"
|
||||
level=info msg=" comment: ACK! This alert was acknowledged using karma on %NOW%"
|
||||
level=info msg="annotations:"
|
||||
level=info msg=" default:"
|
||||
level=info msg=" hidden: false"
|
||||
|
||||
@@ -39,7 +39,7 @@ level=info msg="alertAcknowledgement:"
|
||||
level=info msg=" enabled: false"
|
||||
level=info msg=" duration: 15m0s"
|
||||
level=info msg=" author: karma"
|
||||
level=info msg=" commentPrefix: ACK!"
|
||||
level=info msg=" comment: ACK! This alert was acknowledged using karma on %NOW%"
|
||||
level=info msg="annotations:"
|
||||
level=info msg=" default:"
|
||||
level=info msg=" hidden: false"
|
||||
|
||||
@@ -39,7 +39,7 @@ level=info msg="alertAcknowledgement:"
|
||||
level=info msg=" enabled: false"
|
||||
level=info msg=" duration: 15m0s"
|
||||
level=info msg=" author: karma"
|
||||
level=info msg=" commentPrefix: ACK!"
|
||||
level=info msg=" comment: ACK! This alert was acknowledged using karma on %NOW%"
|
||||
level=info msg="annotations:"
|
||||
level=info msg=" default:"
|
||||
level=info msg=" hidden: false"
|
||||
|
||||
@@ -41,7 +41,7 @@ level=info msg="alertAcknowledgement:"
|
||||
level=info msg=" enabled: false"
|
||||
level=info msg=" duration: 15m0s"
|
||||
level=info msg=" author: karma"
|
||||
level=info msg=" commentPrefix: ACK!"
|
||||
level=info msg=" comment: ACK! This alert was acknowledged using karma on %NOW%"
|
||||
level=info msg="annotations:"
|
||||
level=info msg=" default:"
|
||||
level=info msg=" hidden: false"
|
||||
|
||||
@@ -39,7 +39,7 @@ level=info msg="alertAcknowledgement:"
|
||||
level=info msg=" enabled: false"
|
||||
level=info msg=" duration: 15m0s"
|
||||
level=info msg=" author: karma"
|
||||
level=info msg=" commentPrefix: ACK!"
|
||||
level=info msg=" comment: ACK! This alert was acknowledged using karma on %NOW%"
|
||||
level=info msg="annotations:"
|
||||
level=info msg=" default:"
|
||||
level=info msg=" hidden: false"
|
||||
|
||||
+1
-1
@@ -167,7 +167,7 @@ func alerts(w http.ResponseWriter, r *http.Request) {
|
||||
Enabled: config.Config.AlertAcknowledgement.Enabled,
|
||||
DurationSeconds: int(config.Config.AlertAcknowledgement.Duration.Seconds()),
|
||||
Author: config.Config.AlertAcknowledgement.Author,
|
||||
CommentPrefix: config.Config.AlertAcknowledgement.CommentPrefix,
|
||||
Comment: config.Config.AlertAcknowledgement.Comment,
|
||||
},
|
||||
}
|
||||
resp.Authentication = models.AuthenticationInfo{
|
||||
|
||||
@@ -857,7 +857,7 @@ func TestEmptySettings(t *testing.T) {
|
||||
Enabled: false,
|
||||
DurationSeconds: 900,
|
||||
Author: "karma",
|
||||
CommentPrefix: "ACK!",
|
||||
Comment: "ACK! This alert was acknowledged using karma on %NOW%",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ alertAcknowledgement:
|
||||
enabled: true
|
||||
duration: 15m0s
|
||||
author: karma-ack
|
||||
commentPrefix: ACK!
|
||||
annotations:
|
||||
hidden:
|
||||
- help
|
||||
|
||||
+15
-5
@@ -412,7 +412,7 @@ alertAcknowledgement:
|
||||
enabled: bool
|
||||
duration: duration
|
||||
author: string
|
||||
commentPrefix: string
|
||||
comment: string
|
||||
```
|
||||
|
||||
- `enabled` - setting it to true will enable creation of short lived
|
||||
@@ -421,8 +421,8 @@ alertAcknowledgement:
|
||||
[time.Duration](https://golang.org/pkg/time/#ParseDuration) format.
|
||||
- `author` - default author for acknowledgement silences. If user set the
|
||||
author field on the silence form then that value will be used instead.
|
||||
- `commentPrefix` - a string that will be added as a prefix to autogenerated
|
||||
silence comment (optional).
|
||||
- `comment` - custom comment used for acknowledgement silences (optional).
|
||||
If the comment contains `%NOW%` it will be replaced by current timestamp.
|
||||
|
||||
Defaults:
|
||||
|
||||
@@ -431,7 +431,17 @@ alertAcknowledgement:
|
||||
enabled: false
|
||||
duration: 15m0s
|
||||
author: karma
|
||||
commentPrefix: ACK!
|
||||
comment: ACK! This alert was acknowledged using karma
|
||||
```
|
||||
|
||||
Example with timestamp in the comment:
|
||||
|
||||
```YAML
|
||||
alertAcknowledgement:
|
||||
enabled: false
|
||||
duration: 15m0s
|
||||
author: karma
|
||||
comment: ACK! This alert was acknowledged using karma on %NOW%
|
||||
```
|
||||
|
||||
A common problem is setting a correct duration for the silence.
|
||||
@@ -446,7 +456,7 @@ short lived acknowledgement silences if there are alerts firing against those
|
||||
silences, which means that the user doesn't need to worry about setting proper
|
||||
duration for such silences.
|
||||
To use it run an instance of kthxbye with every alertmanager instance or
|
||||
cluster and configure it to use the same comment prefix as `commentPrefix`.
|
||||
cluster and configure it to use the same comment prefix in `comment`.
|
||||
With this setup when user clicks to acknowledge an alert karma will create
|
||||
a short lived silence and kthxbye will keep that silence in Alertmanager
|
||||
until there are no alerts matching it, meaning that the issue was resolved.
|
||||
|
||||
@@ -58,7 +58,7 @@ func SetupFlags(f *pflag.FlagSet) {
|
||||
f.Bool("alertAcknowledgement.enabled", false, "Enable alert acknowledging")
|
||||
f.Duration("alertAcknowledgement.duration", time.Minute*15, "Initial silence duration when acknowledging alerts with short lived silences")
|
||||
f.String("alertAcknowledgement.author", "karma", "Default silence author when acknowledging alerts with short lived silences")
|
||||
f.String("alertAcknowledgement.commentPrefix", "ACK!", "Comment prefix used when acknowledging alerts with short lived silences")
|
||||
f.String("alertAcknowledgement.comment", "ACK! This alert was acknowledged using karma on %NOW%", "Comment used when acknowledging alerts with short lived silences")
|
||||
|
||||
f.String("authorization.acl.silences", "", "Path to silence ACL config file")
|
||||
|
||||
@@ -193,8 +193,8 @@ func readEnvVariables(k *koanf.Koanf) {
|
||||
return "alertAcknowledgement.duration"
|
||||
case "ALERTACKNOWLEDGEMENT_AUTHOR":
|
||||
return "alertAcknowledgement.author"
|
||||
case "ALERTACKNOWLEDGEMENT_COMMENTPREFIX":
|
||||
return "alertAcknowledgement.commentPrefix"
|
||||
case "ALERTACKNOWLEDGEMENT_COMMENT":
|
||||
return "alertAcknowledgement.comment"
|
||||
case "AUTHENTICATION_HEADER_VALUE_RE":
|
||||
return "authentication.header.value_re"
|
||||
case "SILENCEFORM_STRIP_LABELS":
|
||||
|
||||
@@ -52,7 +52,7 @@ alertAcknowledgement:
|
||||
enabled: false
|
||||
duration: 15m0s
|
||||
author: karma
|
||||
commentPrefix: ACK!
|
||||
comment: ACK! This alert was acknowledged using karma on %NOW%
|
||||
annotations:
|
||||
default:
|
||||
hidden: true
|
||||
|
||||
@@ -81,10 +81,10 @@ type configSchema struct {
|
||||
CORS AlertmanagerCORS `yaml:"-" koanf:"cors"`
|
||||
}
|
||||
AlertAcknowledgement struct {
|
||||
Enabled bool
|
||||
Duration time.Duration
|
||||
Author string
|
||||
CommentPrefix string `yaml:"commentPrefix" koanf:"commentPrefix"`
|
||||
Enabled bool
|
||||
Duration time.Duration
|
||||
Author string
|
||||
Comment string
|
||||
} `yaml:"alertAcknowledgement" koanf:"alertAcknowledgement"`
|
||||
Annotations struct {
|
||||
Default struct {
|
||||
|
||||
@@ -281,7 +281,7 @@ type AlertAcknowledgementSettings struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
DurationSeconds int `json:"durationSeconds"`
|
||||
Author string `json:"author"`
|
||||
CommentPrefix string `json:"commentPrefix"`
|
||||
Comment string `json:"comment"`
|
||||
}
|
||||
|
||||
// Settings is used to export karma configuration that is used by UI
|
||||
|
||||
@@ -31,7 +31,7 @@ beforeEach(() => {
|
||||
enabled: true,
|
||||
durationSeconds: 123,
|
||||
author: "default author",
|
||||
commentPrefix: "PREFIX",
|
||||
comment: "COMMENT",
|
||||
};
|
||||
alertStore.data.setUpstreams({
|
||||
counters: { total: 1, healthy: 1, failed: 0 },
|
||||
@@ -284,8 +284,7 @@ describe("<AlertAck />", () => {
|
||||
silenceFormStore.data.setAuthor("karma/ui");
|
||||
await MountAndClick();
|
||||
expect(JSON.parse((fetchMock.lastOptions() as any).body)).toEqual({
|
||||
comment:
|
||||
"PREFIX This alert was acknowledged using karma on Tue, 01 Feb 2000 00:00:00 GMT",
|
||||
comment: "COMMENT",
|
||||
createdBy: "karma/ui",
|
||||
endsAt: "2000-02-01T00:02:03.000Z",
|
||||
matchers: [
|
||||
@@ -299,11 +298,29 @@ describe("<AlertAck />", () => {
|
||||
it("uses settings when generating payload", async () => {
|
||||
alertStore.settings.values.alertAcknowledgement.durationSeconds = 237;
|
||||
alertStore.settings.values.alertAcknowledgement.author = "me";
|
||||
alertStore.settings.values.alertAcknowledgement.commentPrefix = "";
|
||||
alertStore.settings.values.alertAcknowledgement.comment = "comment";
|
||||
await MountAndClick();
|
||||
expect(JSON.parse((fetchMock.lastOptions() as any).body)).toEqual({
|
||||
comment: "comment",
|
||||
createdBy: "me",
|
||||
endsAt: "2000-02-01T00:03:57.000Z",
|
||||
matchers: [
|
||||
{ isRegex: false, name: "alertname", value: "Fake Alert" },
|
||||
{ isRegex: true, name: "foo", value: "(bar|baz)" },
|
||||
],
|
||||
startsAt: "2000-02-01T00:00:00.000Z",
|
||||
});
|
||||
});
|
||||
|
||||
it("injects timestamp when configured", async () => {
|
||||
alertStore.settings.values.alertAcknowledgement.durationSeconds = 237;
|
||||
alertStore.settings.values.alertAcknowledgement.author = "me";
|
||||
alertStore.settings.values.alertAcknowledgement.comment =
|
||||
"ACK! This alert was acknowledged using karma on %NOW%";
|
||||
await MountAndClick();
|
||||
expect(JSON.parse((fetchMock.lastOptions() as any).body)).toEqual({
|
||||
comment:
|
||||
"This alert was acknowledged using karma on Tue, 01 Feb 2000 00:00:00 GMT",
|
||||
"ACK! This alert was acknowledged using karma on Tue, 01 Feb 2000 00:00:00 GMT",
|
||||
createdBy: "me",
|
||||
endsAt: "2000-02-01T00:03:57.000Z",
|
||||
matchers: [
|
||||
@@ -319,11 +336,10 @@ describe("<AlertAck />", () => {
|
||||
alertStore.info.authentication.username = "auth@example.com";
|
||||
alertStore.settings.values.alertAcknowledgement.durationSeconds = 222;
|
||||
alertStore.settings.values.alertAcknowledgement.author = "me";
|
||||
alertStore.settings.values.alertAcknowledgement.commentPrefix = "FOO:";
|
||||
alertStore.settings.values.alertAcknowledgement.comment = "FOO: bar";
|
||||
await MountAndClick();
|
||||
expect(JSON.parse((fetchMock.lastOptions() as any).body)).toEqual({
|
||||
comment:
|
||||
"FOO: This alert was acknowledged using karma on Tue, 01 Feb 2000 00:00:00 GMT",
|
||||
comment: "FOO: bar",
|
||||
createdBy: "auth@example.com",
|
||||
endsAt: "2000-02-01T00:03:42.000Z",
|
||||
matchers: [
|
||||
@@ -339,12 +355,11 @@ describe("<AlertAck />", () => {
|
||||
alertStore.info.authentication.username = "wrong";
|
||||
alertStore.settings.values.alertAcknowledgement.durationSeconds = 222;
|
||||
alertStore.settings.values.alertAcknowledgement.author = "me";
|
||||
alertStore.settings.values.alertAcknowledgement.commentPrefix = "FOO:";
|
||||
alertStore.settings.values.alertAcknowledgement.comment = "FOO: bar";
|
||||
silenceFormStore.data.setAuthor("bob@example.com");
|
||||
await MountAndClick();
|
||||
expect(JSON.parse((fetchMock.lastOptions() as any).body)).toEqual({
|
||||
comment:
|
||||
"FOO: This alert was acknowledged using karma on Tue, 01 Feb 2000 00:00:00 GMT",
|
||||
comment: "FOO: bar",
|
||||
createdBy: "bob@example.com",
|
||||
endsAt: "2000-02-01T00:03:42.000Z",
|
||||
matchers: [
|
||||
@@ -358,12 +373,11 @@ describe("<AlertAck />", () => {
|
||||
it("uses default author as fallback", async () => {
|
||||
alertStore.settings.values.alertAcknowledgement.durationSeconds = 222;
|
||||
alertStore.settings.values.alertAcknowledgement.author = "me";
|
||||
alertStore.settings.values.alertAcknowledgement.commentPrefix = "FOO:";
|
||||
alertStore.settings.values.alertAcknowledgement.comment = "FOO: bar";
|
||||
silenceFormStore.data.setAuthor("");
|
||||
await MountAndClick();
|
||||
expect(JSON.parse((fetchMock.lastOptions() as any).body)).toEqual({
|
||||
comment:
|
||||
"FOO: This alert was acknowledged using karma on Tue, 01 Feb 2000 00:00:00 GMT",
|
||||
comment: "FOO: bar",
|
||||
createdBy: "me",
|
||||
endsAt: "2000-02-01T00:03:42.000Z",
|
||||
matchers: [
|
||||
|
||||
@@ -74,19 +74,17 @@ const AlertAck: FC<{
|
||||
const durationSeconds = toJS(
|
||||
alertStore.settings.values.alertAcknowledgement.durationSeconds
|
||||
);
|
||||
const commentPrefix = toJS(
|
||||
alertStore.settings.values.alertAcknowledgement.commentPrefix
|
||||
);
|
||||
const now = new Date();
|
||||
const comment = toJS(
|
||||
alertStore.settings.values.alertAcknowledgement.comment
|
||||
).replace("%NOW%", now.toUTCString());
|
||||
c.push({
|
||||
payload: GenerateAlertmanagerSilenceData(
|
||||
now,
|
||||
addSeconds(now, durationSeconds),
|
||||
MatchersFromGroup(group, [], group.alerts, true),
|
||||
author,
|
||||
`${
|
||||
commentPrefix ? commentPrefix + " " : ""
|
||||
}This alert was acknowledged using karma on ${now.toUTCString()}`
|
||||
comment
|
||||
),
|
||||
clusterName: clusterName,
|
||||
members: clusterMembers,
|
||||
|
||||
@@ -182,7 +182,7 @@ export interface APISettingsT {
|
||||
enabled: boolean;
|
||||
durationSeconds: number;
|
||||
author: string;
|
||||
commentPrefix: string;
|
||||
comment: string;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -413,7 +413,7 @@ class AlertStore {
|
||||
enabled: false as boolean,
|
||||
durationSeconds: 900,
|
||||
author: "karma / author missing",
|
||||
commentPrefix: "",
|
||||
comment: "ACK! This alert was acknowledged using karma",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -73,7 +73,7 @@ const EmptyAPIResponse = (): APIAlertsResponseT => ({
|
||||
enabled: false,
|
||||
durationSeconds: 900,
|
||||
author: "karma / author missing",
|
||||
commentPrefix: "",
|
||||
comment: "ACK! Mock comment",
|
||||
},
|
||||
staticColorLabels: ["job"],
|
||||
annotationsDefaultHidden: false,
|
||||
|
||||
Reference in New Issue
Block a user