mirror of
https://github.com/httprunner/httprunner.git
synced 2026-05-15 04:19:28 +08:00
117 lines
3.6 KiB
Go
117 lines
3.6 KiB
Go
package dial
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/go-ping/ping"
|
|
"github.com/pkg/errors"
|
|
"github.com/rs/zerolog/log"
|
|
|
|
"github.com/httprunner/httprunner/v4/hrp/internal/builtin"
|
|
)
|
|
|
|
type PingOptions struct {
|
|
Count int
|
|
Timeout time.Duration
|
|
Interval time.Duration
|
|
SaveTests bool
|
|
}
|
|
|
|
type PingResult struct {
|
|
Suc bool `json:"suc"`
|
|
ErrMsg string `json:"errMsg"`
|
|
Ip string `json:"ip"`
|
|
AvgCost int `json:"avgCost"`
|
|
MaxCost int `json:"maxCost"`
|
|
MinCost int `json:"minCost"`
|
|
Lost int `json:"lost"`
|
|
PingCount int `json:"pingCount"`
|
|
PacketSize int `json:"packetSize"`
|
|
ReceivePacketCount int `json:"receivePacketCount"`
|
|
SendPacketCount int `json:"sendPacketCount"`
|
|
SuccessCount int `json:"successCount"`
|
|
DebugLog string `json:"debugLog"`
|
|
}
|
|
|
|
func DoPing(pingOptions *PingOptions, args []string) (err error) {
|
|
if len(args) != 1 {
|
|
return errors.New("there should be one argument")
|
|
}
|
|
|
|
var pingResult PingResult
|
|
defer func() {
|
|
if pingOptions.SaveTests {
|
|
dir, _ := os.Getwd()
|
|
pingResultName := fmt.Sprintf("ping_result_%v.json", time.Now().Format("20060102150405"))
|
|
pingResultPath := filepath.Join(dir, pingResultName)
|
|
err = builtin.Dump2JSON(pingResult, pingResultPath)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("save ping result failed")
|
|
}
|
|
}
|
|
}()
|
|
|
|
pingTarget := args[0]
|
|
|
|
parsedURL, err := url.Parse(pingTarget)
|
|
if err == nil && parsedURL.Host != "" {
|
|
log.Info().Msgf("parse input url %v and extract host %v", pingTarget, parsedURL.Host)
|
|
pingTarget = strings.Split(parsedURL.Host, ":")[0]
|
|
}
|
|
|
|
log.Info().Msgf("ping host %v", pingTarget)
|
|
pinger, err := ping.NewPinger(pingTarget)
|
|
if err != nil {
|
|
log.Error().Err(err).Msgf("fail to get pinger for %s", pingTarget)
|
|
pingResult.Suc = false
|
|
pingResult.ErrMsg = err.Error()
|
|
pingResult.DebugLog = err.Error()
|
|
return
|
|
}
|
|
pinger.Count = pingOptions.Count
|
|
pinger.Timeout = pingOptions.Timeout
|
|
pinger.Interval = pingOptions.Interval
|
|
|
|
pinger.OnRecv = func(pkt *ping.Packet) {
|
|
pingResult.DebugLog += fmt.Sprintf("%d bytes from %s: icmp_seq=%d time=%v\n",
|
|
pkt.Nbytes, pkt.IPAddr, pkt.Seq, pkt.Rtt)
|
|
}
|
|
pinger.OnFinish = func(stats *ping.Statistics) {
|
|
pingResult.DebugLog += fmt.Sprintf("\n--- %s ping statistics ---\n", stats.Addr)
|
|
pingResult.DebugLog += fmt.Sprintf("%d packets transmitted, %d packets received, %v%% packet loss\n",
|
|
stats.PacketsSent, stats.PacketsRecv, stats.PacketLoss)
|
|
pingResult.DebugLog += fmt.Sprintf("round-trip min/avg/max/stddev = %v/%v/%v/%v\n",
|
|
stats.MinRtt, stats.AvgRtt, stats.MaxRtt, stats.StdDevRtt)
|
|
}
|
|
pingResult.DebugLog += fmt.Sprintf("PING %s (%s):\n", pinger.Addr(), pinger.IPAddr())
|
|
|
|
err = pinger.Run() // blocks until finished
|
|
if err != nil {
|
|
log.Error().Err(err).Msgf("fail to run ping for %s", parsedURL)
|
|
pingResult.Suc = false
|
|
pingResult.ErrMsg = err.Error()
|
|
pingResult.DebugLog = err.Error()
|
|
return
|
|
}
|
|
fmt.Print(pingResult.DebugLog)
|
|
stats := pinger.Statistics() // get send/receive/rtt stats
|
|
pingResult.Ip = pinger.IPAddr().String()
|
|
pingResult.AvgCost = int(stats.AvgRtt / time.Millisecond)
|
|
pingResult.MaxCost = int(stats.MaxRtt / time.Millisecond)
|
|
pingResult.MinCost = int(stats.MinRtt / time.Millisecond)
|
|
pingResult.Lost = int(stats.PacketLoss)
|
|
pingResult.PingCount = pingOptions.Count
|
|
pingResult.PacketSize = pinger.Size
|
|
pingResult.ReceivePacketCount = stats.PacketsRecv
|
|
pingResult.SendPacketCount = stats.PacketsSent
|
|
pingResult.SuccessCount = stats.PacketsRecv
|
|
pingResult.Suc = true
|
|
pingResult.ErrMsg = ""
|
|
return
|
|
}
|