Skip to content

Commit 48017dd

Browse files
committed
feat: complete dev of kube metrics parse
1 parent 2886634 commit 48017dd

4 files changed

Lines changed: 117 additions & 7 deletions

File tree

cmd/metrics/parser.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package metrics
2+
3+
import (
4+
"bufio"
5+
"io"
6+
"net/http"
7+
"os"
8+
"strings"
9+
10+
cmdx "github.com/esonhugh/k8spider/cmd"
11+
"github.com/esonhugh/k8spider/pkg/metrics"
12+
log "github.com/sirupsen/logrus"
13+
"github.com/spf13/cobra"
14+
)
15+
16+
var MetricOpt struct {
17+
From string
18+
}
19+
20+
func init() {
21+
cmdx.RootCmd.AddCommand(MetricCmd)
22+
MetricCmd.PersistentFlags().StringVarP(&MetricOpt.From, "metric", "m", "", "metrics from (file / remote url)")
23+
24+
}
25+
26+
var MetricCmd = &cobra.Command{
27+
Use: "metric",
28+
Short: "parse kube stat metrics to readable resource",
29+
Run: func(cmd *cobra.Command, args []string) {
30+
if MetricOpt.From == "" {
31+
return
32+
}
33+
log.Debugf("parse metrics from %v", MetricOpt.From)
34+
rule := metrics.DefaultMatchRules()
35+
if err := rule.Compile(); err != nil {
36+
log.Fatalf("compile rule failed: %v", err)
37+
}
38+
log.Debugf("compiled rules completed, start to get resource \n")
39+
40+
ot := output()
41+
42+
var r io.Reader
43+
if strings.HasPrefix("http://", MetricOpt.From) || strings.HasPrefix("https://", MetricOpt.From) {
44+
resp, err := http.Get(MetricOpt.From)
45+
if err != nil {
46+
log.Fatalf("get metrics from %v failed: %v", MetricOpt.From, err)
47+
}
48+
defer resp.Body.Close()
49+
r = resp.Body
50+
} else {
51+
f, err := os.OpenFile(MetricOpt.From, os.O_RDONLY, 0666)
52+
if err != nil {
53+
log.Fatalf("open file %v failed: %v", MetricOpt.From, err)
54+
}
55+
defer f.Close()
56+
r = f
57+
}
58+
log.Debugf("start to parse metrics line by line\n")
59+
60+
var rx []*metrics.MetricMatcher
61+
scanner := bufio.NewScanner(r)
62+
for scanner.Scan() {
63+
line := scanner.Text()
64+
res, err := rule.Match(line)
65+
if err != nil {
66+
continue
67+
} else {
68+
log.Debugf("matched: %s", res.DumpString())
69+
rx = append(rx, res.CopyData())
70+
}
71+
}
72+
if err := scanner.Err(); err != nil {
73+
log.Warnf("scan metrics failed and break out, reason: %v", err)
74+
}
75+
var res metrics.ResourceList = metrics.ConvertToResource(rx)
76+
log.Debugf("parse metrics completed, start to print result\n")
77+
78+
res.Print(ot)
79+
},
80+
}
81+
82+
func output() io.WriteCloser {
83+
if cmdx.Opts.OutputFile != "" {
84+
f, err := os.OpenFile(cmdx.Opts.OutputFile, os.O_CREATE|os.O_WRONLY, 0644)
85+
if err != nil {
86+
log.Warnf("create output file failed: %v", err)
87+
return nil
88+
}
89+
return f
90+
} else {
91+
return os.Stdout
92+
}
93+
}

main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
_ "github.com/esonhugh/k8spider/cmd/all"
66
_ "github.com/esonhugh/k8spider/cmd/axfr"
77
_ "github.com/esonhugh/k8spider/cmd/dnsutils"
8+
_ "github.com/esonhugh/k8spider/cmd/metrics"
89
_ "github.com/esonhugh/k8spider/cmd/neighbor"
910
_ "github.com/esonhugh/k8spider/cmd/service"
1011
_ "github.com/esonhugh/k8spider/cmd/subnet"

pkg/metrics/metrics_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,5 @@ func TestConvertToResource(t *testing.T) {
6060
rules = append(rules, r)
6161
}
6262
var res ResourceList = ConvertToResource(rules)
63-
_, _ = output.WriteString(res.JSON() + "\n")
64-
t.Logf(res.JSON())
63+
res.Print(os.Stderr)
6564
}

pkg/metrics/resource.go

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
package metrics
22

3-
import "encoding/json"
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"io"
7+
"os"
8+
9+
log "github.com/sirupsen/logrus"
10+
)
411

512
type Resource struct {
613
Namespace string `json:"namespace"`
@@ -37,12 +44,22 @@ func (r *Resource) JSON() string {
3744
return string(b)
3845
}
3946

40-
func (rl *ResourceList) JSON() string {
41-
var res = ""
47+
func (rl *ResourceList) Print(writer ...io.Writer) {
48+
var W io.Writer
49+
if len(writer) == 0 {
50+
W = os.Stdout
51+
} else {
52+
w := io.MultiWriter(writer...)
53+
W = io.MultiWriter(os.Stdout, w)
54+
}
4255
for _, r := range *rl {
43-
res += r.JSON() + "\n"
56+
data, err := json.Marshal(r.JSON())
57+
if err != nil {
58+
log.Error(err)
59+
return
60+
}
61+
_, _ = fmt.Fprintf(W, "%v\n", string(data))
4462
}
45-
return res
4663
}
4764

4865
type ResourceMergeHook func(m *MetricMatcher, resource ResourceList) (res *Resource, addFlag bool)

0 commit comments

Comments
 (0)