From 1f7b04847abac84e3226801aeeee6c24a32339fb Mon Sep 17 00:00:00 2001 From: Mustafain Ali Khan Date: Fri, 9 Feb 2024 03:59:16 +0000 Subject: [PATCH] Add tool to deserialize alertmanager state file Signed-off-by: Mustafain Ali Khan --- Makefile | 6 ++ cmd/deserializer/main.go | 141 +++++++++++++++++++++++++++++++++++++++ go.mod | 1 + vendor/modules.txt | 1 + 4 files changed, 149 insertions(+) create mode 100644 cmd/deserializer/main.go diff --git a/Makefile b/Makefile index 5a3af2ee1..6b386183f 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ chunktool: cmd/chunktool/chunktool logtool: cmd/logtool/logtool e2ealerting: cmd/e2ealerting/e2ealerting blockscopy: cmd/blockscopy/blockscopy +deserializer: cmd/deserializer/deserializer benchtool-image: $(SUDO) docker build -t $(IMAGE_PREFIX)/benchtool -f cmd/benchtool/Dockerfile . @@ -63,6 +64,9 @@ cmd/rules-migrator/rules-migrator: $(APP_GO_FILES) cmd/rules-migrator/main.go cmd/blockscopy/blockscopy: $(APP_GO_FILES) cmd/blockscopy/main.go CGO_ENABLED=0 go build $(GO_FLAGS) -o $@ ./$(@D) +cmd/deserializer/deserializer: $(APP_GO_FILES) cmd/deserializer/main.go + CGO_ENABLED=0 go build $(GO_FLAGS) -o $@ ./$(@D) + lint: golangci-lint run -v @@ -76,6 +80,7 @@ cross: CGO_ENABLED=0 gox -output="dist/{{.Dir}}-{{.OS}}-{{.Arch}}" -ldflags=${LDFLAGS} -arch="amd64" -os="linux windows darwin" -osarch="darwin/arm64" ./cmd/logtool CGO_ENABLED=0 gox -output="dist/{{.Dir}}-{{.OS}}-{{.Arch}}" -ldflags=${LDFLAGS} -arch="amd64" -os="linux windows darwin" -osarch="darwin/arm64" ./cmd/rules-migrator CGO_ENABLED=0 gox -output="dist/{{.Dir}}-{{.OS}}-{{.Arch}}" -ldflags=${LDFLAGS} -arch="amd64" -os="linux windows darwin" -osarch="darwin/arm64" ./cmd/sim + CGO_ENABLED=0 gox -output="dist/{{.Dir}}-{{.OS}}-{{.Arch}}" -ldflags=${LDFLAGS} -arch="amd64" -os="linux windows darwin" -osarch="darwin/arm64" ./cmd/deserializer test: go test -mod=vendor -p=8 ./pkg/... @@ -87,3 +92,4 @@ clean: rm -rf cmd/logtool/logtool rm -rf cmd/e2ealerting/e2ealerting rm -rf cmd/blockscopy/blockscopy + rm -rf cmd/deserializer/deserializer diff --git a/cmd/deserializer/main.go b/cmd/deserializer/main.go new file mode 100644 index 000000000..5961b3bd5 --- /dev/null +++ b/cmd/deserializer/main.go @@ -0,0 +1,141 @@ +package main + +import ( + "bytes" + "encoding/json" + "flag" + "fmt" + "github.com/cortexproject/cortex/pkg/alertmanager/alertspb" + "github.com/gogo/protobuf/proto" + "github.com/matttproud/golang_protobuf_extensions/pbutil" + "github.com/prometheus/alertmanager/nflog/nflogpb" + "github.com/prometheus/alertmanager/silence/silencepb" + "io" + "log" + "os" + "strings" +) + +var ( + out bytes.Buffer + outputFile string + intputFile string +) + +func main() { + flag.CommandLine.StringVar(&intputFile, "file", "", "path of fullstate file to deserialize") + flag.CommandLine.StringVar(&outputFile, "output", "", "file for deserialized output") + + flag.Parse() + + if intputFile == "" { + log.Fatalf("No full state file specified.") + } + + decodeFullState(intputFile) + + outputToFile(outputFile) +} + +func decodeFullState(path string) { + in, err := os.ReadFile(path) + if err != nil { + log.Fatalln("Error reading file:", err) + } + fs := alertspb.FullStateDesc{} + err = proto.Unmarshal(in, &fs) + if err != nil { + log.Fatalln("Error unmarshalling full state:", err) + } + + for _, part := range fs.GetState().Parts { + out.WriteString("\n----\n") + if isNfLog(part.Key) { + parseNotifications(part.Data) + } else if isSilence(part.Key) { + parseSilences(part.Data) + } else { + out.WriteString(fmt.Sprintf("Unknown part type: %s", part.Key)) + } + + } +} + +func parseNotifications(data []byte) { + out.WriteString("Alerts:\n") + r := bytes.NewReader(data) + for { + nf := nflogpb.MeshEntry{} + n, err := pbutil.ReadDelimited(r, &nf) + if err != nil && err != io.EOF { + log.Fatalf("unable to read alert notifications, %v", err) + } + if n == 0 || err == io.EOF { + break + } + result, err := json.Marshal(nf) + if err != nil { + log.Fatalf("unable to marshal to json, %v", err) + } + _, err = out.WriteString(string(result) + "\n") + if err != nil { + log.Fatalf("unable to write output, %v", err) + } + } +} + +func parseSilences(data []byte) { + out.WriteString("Silences:\n") + r := bytes.NewReader(data) + for { + silence := silencepb.MeshSilence{} + n, err := pbutil.ReadDelimited(r, &silence) + if err != nil && err != io.EOF { + log.Fatalf("unable to read silences, %v", err) + } + if n == 0 || err == io.EOF { + break + } + + result, err := json.Marshal(silence) + if err != nil { + log.Fatalf("unable to marshal to json, %v", err) + } + + _, err = out.WriteString(string(result) + "\n") + if err != nil { + log.Fatalf("unable to write output, %v", err) + } + } +} + +func outputToFile(file string) { + if outputFile == "" { + // write to stdout if output file not specified + fmt.Print(out.String()) + return + } + fo, err := os.Create(file) + if err != nil { + panic(err) + } + // close fo on exit and check for its returned error + defer func() { + if err := fo.Close(); err != nil { + panic(err) + } + }() + + _, err = fo.Write(out.Bytes()) + if err != nil { + log.Fatalf("Failed writing output to file: %v", err) + } +} + +func isNfLog(key string) bool { + return strings.HasPrefix(key, "nfl") +} + +func isSilence(key string) bool { + return strings.HasPrefix(key, "sil") +} diff --git a/go.mod b/go.mod index c9f02178c..055639c4e 100644 --- a/go.mod +++ b/go.mod @@ -25,6 +25,7 @@ require ( github.com/gorilla/mux v1.8.0 github.com/grafana-tools/sdk v0.0.0-20220203092117-edae16afa87b github.com/grafana/dskit v0.0.0-20211021180445-3bd016e9d7f1 + github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db github.com/oklog/ulid v1.3.1 github.com/opentracing-contrib/go-stdlib v1.0.0 diff --git a/vendor/modules.txt b/vendor/modules.txt index 827633656..f8d15fe22 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -557,6 +557,7 @@ github.com/mattn/go-ieproxy # github.com/mattn/go-isatty v0.0.14 github.com/mattn/go-isatty # github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 +## explicit github.com/matttproud/golang_protobuf_extensions/pbutil # github.com/miekg/dns v1.1.48 github.com/miekg/dns