Skip to content

Commit

Permalink
add metric.go and traceroute.go
Browse files Browse the repository at this point in the history
  • Loading branch information
hurricane1988 committed Aug 10, 2023
1 parent 71987e9 commit b126f02
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 1 deletion.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ kube-tools memory -P 8888 -S 10240
```shell
kube-tools memory -P 8888 -S 10240
```
### 4. metrics
```shell
kube-tools metric -P 8080
```

## Contribution
If you find any issues or have any improvement suggestions, feel free to raise an issue or submit a pull request. We welcome your contributions!
Expand Down
4 changes: 4 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ import (
"github.com/wonderivan/logger"
"os"

"kube-tools/pkg/metric"
"kube-tools/pkg/scan_port"
"kube-tools/pkg/simulate_memory"
"kube-tools/pkg/traceroute"
)

// 定义根命令
Expand All @@ -42,6 +44,8 @@ func Execute() {
// 注册子端口扫描子命令到root根命令
rootCmd.AddCommand(scan_port.ExecutePortScan())
rootCmd.AddCommand(simulate_memory.ExecuteSimulateRaw())
rootCmd.AddCommand(metric.ExecuteMetric())
rootCmd.AddCommand(traceroute.ExecuteTraceroute())
if err := rootCmd.Execute(); err != nil {
logger.Error(err)
os.Exit(1)
Expand Down
13 changes: 12 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,23 @@ go 1.20

require (
github.com/Ullaakut/nmap/v3 v3.0.2
github.com/prometheus/client_golang v1.16.0
github.com/spf13/cobra v1.7.0
github.com/wonderivan/logger v1.0.0
golang.org/x/net v0.10.0
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.11.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.11.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
)
84 changes: 84 additions & 0 deletions pkg/metric/metric.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
Copyright 2023 QKP Authors
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 metric

import (
"fmt"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/spf13/cobra"
"net/http"
"time"
)

// 定义全局metric指标变量
var (
// Counter 是一个特殊的指标,用于跟踪事件计数器,例如请求的数量、错误的数量等
opsProcessed = promauto.NewCounter(prometheus.CounterOpts{
Name: "kube_tools_processed_ops_total",
Help: "Total number of processed ops.",
})
opsFailed = promauto.NewCounter(prometheus.CounterOpts{
Name: "kube_tools_failed_ops_total",
Help: "Total number of failed ops.",
})
// Histogram选项。它有多个字段,用于设置Histogram的属性,如桶的数量、桶的边界等。这个结构体通常用于创建指标的Histogram类型
opsDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
Name: "kube_tools_duration_seconds",
Help: "Duration of ops in seconds.",
}, []string{"method", "host", "client", "path", "status"})
)

// ExecuteMetric 定义端口扫描执行器
func ExecuteMetric() *cobra.Command {
// metric 定义端口扫描子命令
var metric = &cobra.Command{
Use: "metric",
Short: "expose metric information for testing.",
Long: "expose metric information for testing.",
Run: startServer,
}
// 初始化命令
metric.Flags().StringP("port", "P", "8080", "ports to scan")
return metric
}

func startServer(cmd *cobra.Command, args []string) {
port, _ := cmd.Flags().GetString("port")
http.Handle("/metrics", promhttp.Handler())
http.HandleFunc("/", metricHandler)
http.ListenAndServe(":"+port, nil)
}

func metricHandler(w http.ResponseWriter, r *http.Request) {
start := time.Now()
// 模拟判断请求是否成功的逻辑,这里我们随机模拟
isSuccess := (time.Now().UnixNano() % 2) == 0
if isSuccess {
w.WriteHeader(http.StatusOK)
w.Write([]byte("Success"))
opsProcessed.Inc()
} else {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("Fail"))
opsFailed.Inc()
}
duration := time.Since(start).Seconds()
// 记录HTTP请求耗时的指标
opsDuration.WithLabelValues(r.Method, r.Host, r.RemoteAddr, r.URL.Path, fmt.Sprintf("%d", http.StatusOK)).Observe(duration)
}
132 changes: 132 additions & 0 deletions pkg/traceroute/traceroute.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
Copyright 2023 QKP Authors
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 traceroute

import (
"fmt"
"github.com/spf13/cobra"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
"log"
"net"
"os"
"time"
)

// ExecuteTraceroute 定义端口扫描执行器
func ExecuteTraceroute() *cobra.Command {
// traceroute 定义网络链路跟踪命令
var traceroute = &cobra.Command{
Use: "traceroute",
Short: "traceroute the network with icmp protocol.",
Long: "traceroute the network with icmp protocol.",
Run: runner,
}
// 初始化命令
traceroute.Flags().StringP("host", "H", "localhost", "host to scan")
return traceroute
}

// runner 扫描端口
func runner(cmd *cobra.Command, args []string) {
host, _ := cmd.Flags().GetString("host")

ips, err := net.LookupIP(host)
if err != nil {
log.Fatal(err)
}
var dst net.IPAddr
for _, ip := range ips {
if ip.To4() != nil {
dst.IP = ip
fmt.Printf("using %v for tracing an IP packet route to %s\n", dst.IP, host)
break
}
}
if dst.IP == nil {
log.Fatal("no A record found")
}

c, err := net.ListenPacket("ip4:1", "0.0.0.0") // ICMP for IPv4
if err != nil {
log.Fatal(err)
}
defer c.Close()
p := ipv4.NewPacketConn(c)

if err := p.SetControlMessage(ipv4.FlagTTL|ipv4.FlagSrc|ipv4.FlagDst|ipv4.FlagInterface, true); err != nil {
log.Fatal(err)
}
wm := icmp.Message{
Type: ipv4.ICMPTypeEcho, Code: 0,
Body: &icmp.Echo{
ID: os.Getpid() & 0xffff,
Data: []byte("HELLO-R-U-THERE"),
},
}

rb := make([]byte, 1500)
for i := 1; i <= 64; i++ { // up to 64 hops
wm.Body.(*icmp.Echo).Seq = i
wb, err := wm.Marshal(nil)
if err != nil {
log.Fatal(err)
}
if err := p.SetTTL(i); err != nil {
log.Fatal(err)
}

// In the real world usually there are several
// multiple traffic-engineered paths for each hop.
// You may need to probe a few times to each hop.
begin := time.Now()
if _, err := p.WriteTo(wb, nil, &dst); err != nil {
log.Fatal(err)
}
if err := p.SetReadDeadline(time.Now().Add(3 * time.Second)); err != nil {
log.Fatal(err)
}
n, cm, peer, err := p.ReadFrom(rb)
if err != nil {
if err, ok := err.(net.Error); ok && err.Timeout() {
fmt.Printf("%v\t*\n", i)
continue
}
log.Fatal(err)
}
rm, err := icmp.ParseMessage(1, rb[:n])
if err != nil {
log.Fatal(err)
}
rtt := time.Since(begin)

// In the real world you need to determine whether the
// received message is yours using ControlMessage.Src,
// ControlMessage.Dst, icmp.Echo.ID and icmp.Echo.Seq.
switch rm.Type {
case ipv4.ICMPTypeTimeExceeded:
names, _ := net.LookupAddr(peer.String())
fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, cm)
case ipv4.ICMPTypeEchoReply:
names, _ := net.LookupAddr(peer.String())
fmt.Printf("%d\t%v %+v %v\n\t%+v\n", i, peer, names, rtt, cm)
return
default:
log.Printf("unknown ICMP message: %+v\n", rm)
}
}
}

0 comments on commit b126f02

Please sign in to comment.