abstract dumpFsm

Signed-off-by: Wangchong Zhou <fffonion@gmail.com>
This commit is contained in:
Wangchong Zhou 2018-09-21 18:09:36 -07:00
parent e634997791
commit 5e1df60d22
No known key found for this signature in database
GPG key ID: B607274584E8D5E5
2 changed files with 32 additions and 31 deletions

28
main.go
View file

@ -14,8 +14,10 @@
package main package main
import ( import (
"bufio"
"net" "net"
"net/http" "net/http"
"os"
"strconv" "strconv"
"github.com/howeyc/fsnotify" "github.com/howeyc/fsnotify"
@ -118,6 +120,20 @@ func watchConfig(fileName string, mapper *mapper.MetricMapper) {
} }
} }
func dumpFSM(mapper *mapper.MetricMapper, dumpFilename string) error {
f, err := os.Create(dumpFilename)
if err != nil {
return err
}
log.Infoln("Start dumping FSM to", dumpFilename)
w := bufio.NewWriter(f)
mapper.FSM.DumpFSM(w)
w.Flush()
f.Close()
log.Infoln("Finish dumping FSM")
return nil
}
func main() { func main() {
var ( var (
listenAddress = kingpin.Flag("web.listen-address", "The address on which to expose the web interface and generated Prometheus metrics.").Default(":9102").String() listenAddress = kingpin.Flag("web.listen-address", "The address on which to expose the web interface and generated Prometheus metrics.").Default(":9102").String()
@ -179,17 +195,17 @@ func main() {
} }
mapper := &mapper.MetricMapper{MappingsCount: mappingsCount} mapper := &mapper.MetricMapper{MappingsCount: mappingsCount}
if *dumpFSMPath != "" {
err := mapper.FSM.SetDumpFSMPath(*dumpFSMPath)
if err != nil {
log.Fatal("Error setting dump FSM path:", err)
}
}
if *mappingConfig != "" { if *mappingConfig != "" {
err := mapper.InitFromFile(*mappingConfig) err := mapper.InitFromFile(*mappingConfig)
if err != nil { if err != nil {
log.Fatal("Error loading config:", err) log.Fatal("Error loading config:", err)
} }
if *dumpFSMPath != "" {
err := dumpFSM(mapper, *dumpFSMPath)
if err != nil {
log.Fatal("Error dumpping FSM:", err)
}
}
go watchConfig(*mappingConfig, mapper) go watchConfig(*mappingConfig, mapper)
} }
exporter := NewExporter(mapper) exporter := NewExporter(mapper)

View file

@ -1,9 +1,8 @@
package fsm package fsm
import ( import (
"bufio"
"fmt" "fmt"
"os" "io"
"regexp" "regexp"
"strings" "strings"
@ -38,17 +37,11 @@ type fsmBacktrackStackCursor struct {
type FSM struct { type FSM struct {
root *mappingState root *mappingState
needsBacktracking bool needsBacktracking bool
dumpFSMPath string
metricTypes []string metricTypes []string
disableOrdering bool disableOrdering bool
statesCount int statesCount int
} }
func (fsm *FSM) SetDumpFSMPath(path string) error {
fsm.dumpFSMPath = path
return nil
}
func NewFSM(metricTypes []string, maxPossibleTransitions int, disableOrdering bool) *FSM { func NewFSM(metricTypes []string, maxPossibleTransitions int, disableOrdering bool) *FSM {
fsm := FSM{} fsm := FSM{}
root := &mappingState{} root := &mappingState{}
@ -128,40 +121,32 @@ func (f *FSM) AddState(match string, name string, labels prometheus.Labels, matc
} }
func (f *FSM) DumpFSM() { func (f *FSM) DumpFSM(w io.Writer) {
if f.dumpFSMPath == "" {
return
}
log.Infoln("Start dumping FSM to", f.dumpFSMPath)
idx := 0 idx := 0
states := make(map[int]*mappingState) states := make(map[int]*mappingState)
states[idx] = f.root states[idx] = f.root
fd, _ := os.Create(f.dumpFSMPath) w.Write([]byte("digraph g {\n"))
w := bufio.NewWriter(fd) w.Write([]byte("rankdir=LR\n")) // make it vertical
w.WriteString("digraph g {\n") w.Write([]byte("node [ label=\"\",style=filled,fillcolor=white,shape=circle ]\n")) // remove label of node
w.WriteString("rankdir=LR\n") // make it vertical
w.WriteString("node [ label=\"\",style=filled,fillcolor=white,shape=circle ]\n") // remove label of node
for idx < len(states) { for idx < len(states) {
for field, transition := range states[idx].transitions { for field, transition := range states[idx].transitions {
states[len(states)] = transition states[len(states)] = transition
w.WriteString(fmt.Sprintf("%d -> %d [label = \"%s\"];\n", idx, len(states)-1, field)) w.Write([]byte(fmt.Sprintf("%d -> %d [label = \"%s\"];\n", idx, len(states)-1, field)))
if idx == 0 { if idx == 0 {
// color for metric types // color for metric types
w.WriteString(fmt.Sprintf("%d [color=\"#D6B656\",fillcolor=\"#FFF2CC\"];\n", len(states)-1)) w.Write([]byte(fmt.Sprintf("%d [color=\"#D6B656\",fillcolor=\"#FFF2CC\"];\n", len(states)-1)))
} else if transition.transitions == nil || len(transition.transitions) == 0 { } else if transition.transitions == nil || len(transition.transitions) == 0 {
// color for end state // color for end state
w.WriteString(fmt.Sprintf("%d [color=\"#82B366\",fillcolor=\"#D5E8D4\"];\n", len(states)-1)) w.Write([]byte(fmt.Sprintf("%d [color=\"#82B366\",fillcolor=\"#D5E8D4\"];\n", len(states)-1)))
} }
} }
idx++ idx++
} }
// color for start state // color for start state
w.WriteString(fmt.Sprintf("0 [color=\"#a94442\",fillcolor=\"#f2dede\"];\n")) w.Write([]byte(fmt.Sprintf("0 [color=\"#a94442\",fillcolor=\"#f2dede\"];\n")))
w.WriteString("}") w.Write([]byte("}"))
w.Flush()
log.Infoln("Finish dumping FSM")
} }
func (f *FSM) TestIfNeedBacktracking(mappings []string) bool { func (f *FSM) TestIfNeedBacktracking(mappings []string) bool {