mirror of
https://github.com/prometheus/alertmanager
synced 2025-04-11 03:31:55 +00:00
Add cluster command to show cluster and peer statuses. (#2256)
Signed-off-by: Fahri Yardımcı <f.yardimci06@gmail.com> Signed-off-by: Fahri Yardımcı <f.yardimci06@gmail.com>
This commit is contained in:
parent
de80d907d1
commit
12db463c7f
43
cli/cluster.go
Normal file
43
cli/cluster.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// Copyright 2020 Prometheus Team
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package cli
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"gopkg.in/alecthomas/kingpin.v2"
|
||||||
|
|
||||||
|
"github.com/prometheus/alertmanager/cli/format"
|
||||||
|
)
|
||||||
|
|
||||||
|
const clusterHelp = `View cluster status and peers.`
|
||||||
|
|
||||||
|
// clusterCmd represents the cluster command
|
||||||
|
func configureClusterCmd(app *kingpin.Application) {
|
||||||
|
clusterCmd := app.Command("cluster", clusterHelp)
|
||||||
|
clusterCmd.Command("show", clusterHelp).Default().Action(execWithTimeout(showStatus)).PreAction(requireAlertManagerURL)
|
||||||
|
}
|
||||||
|
|
||||||
|
func showStatus(ctx context.Context, _ *kingpin.ParseContext) error {
|
||||||
|
alertManagerStatus, err := getRemoteAlertmanagerConfigStatus(ctx, alertmanagerURL)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
formatter, found := format.Formatters[output]
|
||||||
|
if !found {
|
||||||
|
return errors.New("unknown output formatter")
|
||||||
|
}
|
||||||
|
return formatter.FormatClusterStatus(alertManagerStatus.Cluster)
|
||||||
|
}
|
@ -39,6 +39,7 @@ type Formatter interface {
|
|||||||
FormatSilences([]models.GettableSilence) error
|
FormatSilences([]models.GettableSilence) error
|
||||||
FormatAlerts([]*models.GettableAlert) error
|
FormatAlerts([]*models.GettableAlert) error
|
||||||
FormatConfig(*models.AlertmanagerStatus) error
|
FormatConfig(*models.AlertmanagerStatus) error
|
||||||
|
FormatClusterStatus(status *models.ClusterStatus) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Formatters is a map of cli argument names to formatter interface object.
|
// Formatters is a map of cli argument names to formatter interface object.
|
||||||
|
@ -89,6 +89,27 @@ func (formatter *ExtendedFormatter) FormatConfig(status *models.AlertmanagerStat
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FormatClusterStatus formats the cluster status with peers into a readable string.
|
||||||
|
func (formatter *ExtendedFormatter) FormatClusterStatus(status *models.ClusterStatus) error {
|
||||||
|
w := tabwriter.NewWriter(formatter.writer, 0, 0, 2, ' ', 0)
|
||||||
|
fmt.Fprintf(w,
|
||||||
|
"Cluster Status:\t%s\nNode Name:\t%s\n\n",
|
||||||
|
*status.Status,
|
||||||
|
status.Name,
|
||||||
|
)
|
||||||
|
fmt.Fprintln(w, "Address\tName")
|
||||||
|
sort.Sort(ByAddress(status.Peers))
|
||||||
|
for _, peer := range status.Peers {
|
||||||
|
fmt.Fprintf(
|
||||||
|
w,
|
||||||
|
"%s\t%s\t\n",
|
||||||
|
*peer.Address,
|
||||||
|
*peer.Name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return w.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
func extendedFormatLabels(labels models.LabelSet) string {
|
func extendedFormatLabels(labels models.LabelSet) string {
|
||||||
output := []string{}
|
output := []string{}
|
||||||
for name, value := range labels {
|
for name, value := range labels {
|
||||||
|
@ -47,3 +47,8 @@ func (formatter *JSONFormatter) FormatConfig(status *models.AlertmanagerStatus)
|
|||||||
enc := json.NewEncoder(formatter.writer)
|
enc := json.NewEncoder(formatter.writer)
|
||||||
return enc.Encode(status)
|
return enc.Encode(status)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (formatter *JSONFormatter) FormatClusterStatus(status *models.ClusterStatus) error {
|
||||||
|
enc := json.NewEncoder(formatter.writer)
|
||||||
|
return enc.Encode(status)
|
||||||
|
}
|
||||||
|
@ -75,6 +75,16 @@ func (formatter *SimpleFormatter) FormatConfig(status *models.AlertmanagerStatus
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (formatter *SimpleFormatter) FormatClusterStatus(status *models.ClusterStatus) error {
|
||||||
|
w := tabwriter.NewWriter(formatter.writer, 0, 0, 2, ' ', 0)
|
||||||
|
fmt.Fprintf(w,
|
||||||
|
"Cluster Status:\t%s\nNode Name:\t%s\n",
|
||||||
|
*status.Status,
|
||||||
|
status.Name,
|
||||||
|
)
|
||||||
|
return w.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
func simpleFormatMatchers(matchers models.Matchers) string {
|
func simpleFormatMatchers(matchers models.Matchers) string {
|
||||||
output := []string{}
|
output := []string{}
|
||||||
for _, matcher := range matchers {
|
for _, matcher := range matchers {
|
||||||
|
@ -14,6 +14,9 @@
|
|||||||
package format
|
package format
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/prometheus/alertmanager/api/v2/models"
|
"github.com/prometheus/alertmanager/api/v2/models"
|
||||||
@ -34,3 +37,19 @@ func (s ByStartsAt) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
|||||||
func (s ByStartsAt) Less(i, j int) bool {
|
func (s ByStartsAt) Less(i, j int) bool {
|
||||||
return time.Time(*s[i].StartsAt).Before(time.Time(*s[j].StartsAt))
|
return time.Time(*s[i].StartsAt).Before(time.Time(*s[j].StartsAt))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ByAddress []*models.PeerStatus
|
||||||
|
|
||||||
|
func (s ByAddress) Len() int { return len(s) }
|
||||||
|
func (s ByAddress) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||||
|
func (s ByAddress) Less(i, j int) bool {
|
||||||
|
ip1, port1, _ := net.SplitHostPort(*s[i].Address)
|
||||||
|
ip2, port2, _ := net.SplitHostPort(*s[j].Address)
|
||||||
|
if ip1 == ip2 {
|
||||||
|
p1, _ := strconv.Atoi(port1)
|
||||||
|
p2, _ := strconv.Atoi(port2)
|
||||||
|
return p1 < p2
|
||||||
|
} else {
|
||||||
|
return bytes.Compare(net.ParseIP(ip1), net.ParseIP(ip2)) < 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -111,6 +111,7 @@ func Execute() {
|
|||||||
configureAlertCmd(app)
|
configureAlertCmd(app)
|
||||||
configureSilenceCmd(app)
|
configureSilenceCmd(app)
|
||||||
configureCheckConfigCmd(app)
|
configureCheckConfigCmd(app)
|
||||||
|
configureClusterCmd(app)
|
||||||
configureConfigCmd(app)
|
configureConfigCmd(app)
|
||||||
|
|
||||||
err = resolver.Bind(app, os.Args[1:])
|
err = resolver.Bind(app, os.Args[1:])
|
||||||
|
Loading…
Reference in New Issue
Block a user