Browse Source

feature: 增加网络诊断服务

klw-account2 2 months ago
parent
commit
d6dae3bab7

+ 29 - 0
NetworkDiagnosticServer.go

@@ -0,0 +1,29 @@
+package main
+
+import (
+	"cfTest/networkdiagnostic"
+	pb "cfTest/networkdiagnostic/pb"
+	"google.golang.org/grpc"
+	"net"
+)
+
+const (
+	networkDiagnosticPort = ":50050"
+)
+
+func main() {
+	networkdiagnostic.Init()
+	logger := networkdiagnostic.GetLogger()
+
+	lis, err := net.Listen("tcp", networkDiagnosticPort)
+	if err != nil {
+		logger.Error("failed to listen: ", err)
+	}
+
+	s := grpc.NewServer()
+	pb.RegisterNetworkDiagnosticServiceServer(s, &networkdiagnostic.NetworkDiagnosticServer{})
+	logger.Println("server listening at ", lis.Addr())
+	if err := s.Serve(lis); err != nil {
+		logger.Error("failed to serve: ", err)
+	}
+}

+ 13 - 6
go.mod

@@ -1,6 +1,8 @@
 module cfTest
 
-go 1.18
+go 1.21
+
+toolchain go1.21.0
 
 require (
 	github.com/cloudflare/cloudflare-go v0.98.0
@@ -10,21 +12,26 @@ require (
 	github.com/samber/lo v1.37.0
 	github.com/sirupsen/logrus v1.9.0
 	google.golang.org/grpc v1.64.0
-	google.golang.org/protobuf v1.33.0
+	google.golang.org/protobuf v1.34.2
 	gopkg.in/natefinch/lumberjack.v2 v2.0.0
 )
 
 require (
-	github.com/BurntSushi/toml v1.2.0 // indirect
+	github.com/go-ping/ping v1.1.0
+	github.com/google/uuid v1.6.0 // indirect
+	golang.org/x/sync v0.8.0 // indirect
+)
+
+require (
 	github.com/goccy/go-json v0.10.3 // indirect
 	github.com/google/go-querystring v1.1.0 // indirect
 	github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
 	github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
 	golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
 	golang.org/x/net v0.26.0 // indirect
-	golang.org/x/sys v0.21.0 // indirect
-	golang.org/x/text v0.16.0 // indirect
+	golang.org/x/sys v0.25.0 // indirect
+	golang.org/x/text v0.18.0 // indirect
 	golang.org/x/time v0.5.0 // indirect
-	google.golang.org/genproto v0.0.0-20220808131553-a91ffa7f803e // indirect
+	google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect
 )

+ 28 - 10
go.sum

@@ -1,7 +1,6 @@
 cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0=
-github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
 github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@@ -16,8 +15,11 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
 github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
 github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
 github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
+github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
 github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
 github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
+github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw=
+github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
 github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
@@ -30,8 +32,12 @@ github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaW
 github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
 github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
 github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
+github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
 github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
 github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0 h1:pRhl55Yx1eC7BZ1N+BBWwnKaMyD8uC+34TLdndZMAKk=
@@ -39,6 +45,7 @@ github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0/go.mod h1:XKMd7iuf/RGPSMJ
 github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
 github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
 github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
+github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
 github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
 github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
 github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg=
@@ -50,7 +57,9 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
 github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
 github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
+github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
 github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
 github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -68,6 +77,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
@@ -94,6 +104,7 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
 golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
 golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
 golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -102,19 +113,25 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
+golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
-golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
+golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
-golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
+golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
+golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
 golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
 golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -135,8 +152,8 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
 google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
 google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20220808131553-a91ffa7f803e h1:yXLYwnRRqNHIwwHZLiA9/aC9uieNrOF0owsijAiZJr8=
-google.golang.org/genproto v0.0.0-20220808131553-a91ffa7f803e/go.mod h1:iHe1svFLAZg9VWz891+QbRMwUv9O/1Ww+/mngYeThbc=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61 h1:N9BgCIAUvn/M+p4NJccWPWb3BWh88+zyL0ll9HgbEeM=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20240924160255-9d4c2d233b61/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
 google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
@@ -144,8 +161,8 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
 google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
 google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY=
 google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg=
-google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
-google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
+google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
+google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
@@ -157,5 +174,6 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

+ 97 - 0
networkdiagnostic/NetworkDiagnosticServer.go

@@ -0,0 +1,97 @@
+package networkdiagnostic
+
+import (
+	networkDiagnostic "cfTest/networkdiagnostic/pb"
+	"context"
+	"github.com/go-ping/ping"
+	"github.com/sirupsen/logrus"
+	"gopkg.in/natefinch/lumberjack.v2"
+	"runtime"
+	"time"
+)
+
+var logger *logrus.Logger
+
+type NetworkDiagnosticServer struct {
+	networkDiagnostic.UnimplementedNetworkDiagnosticServiceServer
+}
+
+func (s *NetworkDiagnosticServer) NetworkLatencyProbe(ctx context.Context, probeRequest *networkDiagnostic.NetworkLatencyProbeRequest) (*networkDiagnostic.NetworkLatencyProbeReply, error) {
+	logger.Println("domainName Received: ", probeRequest.GetDomainName())
+	logger.Println("execCount Received: ", probeRequest.GetExecCount())
+	logger.Println("interval Received: ", probeRequest.GetInterval())
+
+	// 业务请求 -> ping
+	pinger, err := ping.NewPinger(probeRequest.GetDomainName())
+	if err != nil {
+		return &networkDiagnostic.NetworkLatencyProbeReply{
+			Error: err.Error(),
+		}, nil
+	}
+	pinger.Count = int(probeRequest.GetExecCount())
+	pinger.Timeout = 5 * time.Second
+	pinger.Interval = time.Duration(probeRequest.GetInterval()) * time.Second
+	if runtime.GOOS == "windows" {
+		pinger.SetPrivileged(true)
+	}
+	err = pinger.Run()
+	if err != nil {
+		return &networkDiagnostic.NetworkLatencyProbeReply{
+			Error: err.Error(),
+		}, nil
+	}
+	status := pinger.Statistics()
+
+	// response
+	return &networkDiagnostic.NetworkLatencyProbeReply{
+		Latency:        float64(status.AvgRtt.Milliseconds()),
+		PacketsReceive: int32(status.PacketsRecv),
+		PacketsSend:    int32(status.PacketsSent),
+		IpAddr:         status.IPAddr.IP.String(),
+	}, nil
+}
+
+// logger
+func Init() {
+	initLogger()
+}
+
+func initLogger() {
+	setupLogger()
+	// 在初始化函数中对包级别的变量进行初始化
+	logger = logrus.StandardLogger()
+	logger.Println("启动NetworkDiagnosticServer, 初始化日志框架...")
+}
+
+func setupLogger() {
+	// 创建一个新的logrus实例
+	log := logrus.New()
+
+	// 设置日志输出为文件,并使用lumberjack库来实现每天生成一个新的日志文件,并保存旧日志文件
+	log.SetOutput(&lumberjack.Logger{
+		Filename:   "../../logs/networkDiagnosticServer/" + generateLogFileName(), // 日志文件路径,使用日期占位符%Y-%m-%d
+		MaxSize:    20,                                                            // 每个日志文件的最大尺寸,单位:MB
+		MaxBackups: 3,                                                             // 最多保留的旧日志文件数
+		MaxAge:     30,                                                            // 最多保留的旧日志文件天数(这里设置为30天)
+		LocalTime:  true,                                                          // 使用本地时间(默认为UTC时间)
+		Compress:   true,                                                          // 是否压缩旧日志文件
+	})
+
+	// 设置日志格式为JSON格式
+	log.SetFormatter(&logrus.JSONFormatter{})
+
+	// 设置日志级别为Debug
+	log.SetLevel(logrus.DebugLevel)
+
+	// 将logrus实例设置为全局的默认日志记录器
+	logrus.StandardLogger().SetOutput(log.Out)
+}
+
+func generateLogFileName() string {
+	currentDate := time.Now().Format("01-02-2006")
+	return "networkDiagnostic_" + currentDate + ".log"
+}
+
+func GetLogger() *logrus.Logger {
+	return logger
+}

+ 284 - 0
networkdiagnostic/pb/networkDiagnostic.pb.go

@@ -0,0 +1,284 @@
+// Code generated by protoc-gen-go. DO NOT EDIT.
+// versions:
+// 	protoc-gen-go v1.34.2
+// 	protoc        v5.28.2
+// source: networkDiagnostic.proto
+
+package networkdiagnostic
+
+import (
+	protoreflect "google.golang.org/protobuf/reflect/protoreflect"
+	protoimpl "google.golang.org/protobuf/runtime/protoimpl"
+	reflect "reflect"
+	sync "sync"
+)
+
+const (
+	// Verify that this generated code is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
+	// Verify that runtime/protoimpl is sufficiently up-to-date.
+	_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
+)
+
+// request
+type NetworkLatencyProbeRequest struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	DomainName string `protobuf:"bytes,1,opt,name=domainName,proto3" json:"domainName,omitempty"`
+	ExecCount  int32  `protobuf:"varint,2,opt,name=execCount,proto3" json:"execCount,omitempty"`
+	Interval   int32  `protobuf:"varint,3,opt,name=interval,proto3" json:"interval,omitempty"`
+}
+
+func (x *NetworkLatencyProbeRequest) Reset() {
+	*x = NetworkLatencyProbeRequest{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_networkDiagnostic_proto_msgTypes[0]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *NetworkLatencyProbeRequest) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*NetworkLatencyProbeRequest) ProtoMessage() {}
+
+func (x *NetworkLatencyProbeRequest) ProtoReflect() protoreflect.Message {
+	mi := &file_networkDiagnostic_proto_msgTypes[0]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use NetworkLatencyProbeRequest.ProtoReflect.Descriptor instead.
+func (*NetworkLatencyProbeRequest) Descriptor() ([]byte, []int) {
+	return file_networkDiagnostic_proto_rawDescGZIP(), []int{0}
+}
+
+func (x *NetworkLatencyProbeRequest) GetDomainName() string {
+	if x != nil {
+		return x.DomainName
+	}
+	return ""
+}
+
+func (x *NetworkLatencyProbeRequest) GetExecCount() int32 {
+	if x != nil {
+		return x.ExecCount
+	}
+	return 0
+}
+
+func (x *NetworkLatencyProbeRequest) GetInterval() int32 {
+	if x != nil {
+		return x.Interval
+	}
+	return 0
+}
+
+// response
+type NetworkLatencyProbeReply struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Latency        float64 `protobuf:"fixed64,1,opt,name=latency,proto3" json:"latency,omitempty"`
+	PacketsReceive int32   `protobuf:"varint,2,opt,name=packetsReceive,proto3" json:"packetsReceive,omitempty"`
+	PacketsSend    int32   `protobuf:"varint,3,opt,name=packetsSend,proto3" json:"packetsSend,omitempty"`
+	IpAddr         string  `protobuf:"bytes,4,opt,name=ipAddr,proto3" json:"ipAddr,omitempty"`
+	Error          string  `protobuf:"bytes,5,opt,name=error,proto3" json:"error,omitempty"`
+}
+
+func (x *NetworkLatencyProbeReply) Reset() {
+	*x = NetworkLatencyProbeReply{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_networkDiagnostic_proto_msgTypes[1]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *NetworkLatencyProbeReply) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*NetworkLatencyProbeReply) ProtoMessage() {}
+
+func (x *NetworkLatencyProbeReply) ProtoReflect() protoreflect.Message {
+	mi := &file_networkDiagnostic_proto_msgTypes[1]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use NetworkLatencyProbeReply.ProtoReflect.Descriptor instead.
+func (*NetworkLatencyProbeReply) Descriptor() ([]byte, []int) {
+	return file_networkDiagnostic_proto_rawDescGZIP(), []int{1}
+}
+
+func (x *NetworkLatencyProbeReply) GetLatency() float64 {
+	if x != nil {
+		return x.Latency
+	}
+	return 0
+}
+
+func (x *NetworkLatencyProbeReply) GetPacketsReceive() int32 {
+	if x != nil {
+		return x.PacketsReceive
+	}
+	return 0
+}
+
+func (x *NetworkLatencyProbeReply) GetPacketsSend() int32 {
+	if x != nil {
+		return x.PacketsSend
+	}
+	return 0
+}
+
+func (x *NetworkLatencyProbeReply) GetIpAddr() string {
+	if x != nil {
+		return x.IpAddr
+	}
+	return ""
+}
+
+func (x *NetworkLatencyProbeReply) GetError() string {
+	if x != nil {
+		return x.Error
+	}
+	return ""
+}
+
+var File_networkDiagnostic_proto protoreflect.FileDescriptor
+
+var file_networkDiagnostic_proto_rawDesc = []byte{
+	0x0a, 0x17, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x44, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73,
+	0x74, 0x69, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x6e, 0x65, 0x74, 0x77, 0x6f,
+	0x72, 0x6b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x22, 0x76, 0x0a, 0x1a,
+	0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x72,
+	0x6f, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x6f,
+	0x6d, 0x61, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a,
+	0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x78,
+	0x65, 0x63, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x65,
+	0x78, 0x65, 0x63, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65,
+	0x72, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65,
+	0x72, 0x76, 0x61, 0x6c, 0x22, 0xac, 0x01, 0x0a, 0x18, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b,
+	0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x52, 0x65, 0x70, 0x6c,
+	0x79, 0x12, 0x18, 0x0a, 0x07, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01,
+	0x28, 0x01, 0x52, 0x07, 0x6c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x26, 0x0a, 0x0e, 0x70,
+	0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x18, 0x02, 0x20,
+	0x01, 0x28, 0x05, 0x52, 0x0e, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x52, 0x65, 0x63, 0x65,
+	0x69, 0x76, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x53, 0x65,
+	0x6e, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x74,
+	0x73, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x18,
+	0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x12, 0x14, 0x0a,
+	0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72,
+	0x72, 0x6f, 0x72, 0x32, 0x8f, 0x01, 0x0a, 0x18, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x44,
+	0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
+	0x12, 0x73, 0x0a, 0x13, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4c, 0x61, 0x74, 0x65, 0x6e,
+	0x63, 0x79, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x12, 0x2d, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72,
+	0x6b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x2e, 0x4e, 0x65, 0x74, 0x77,
+	0x6f, 0x72, 0x6b, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x52,
+	0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b,
+	0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69, 0x63, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f,
+	0x72, 0x6b, 0x4c, 0x61, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x72, 0x6f, 0x62, 0x65, 0x52, 0x65,
+	0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x4a, 0x0a, 0x19, 0x69, 0x6f, 0x2e, 0x67, 0x72, 0x70, 0x63,
+	0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74,
+	0x69, 0x63, 0x42, 0x16, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x44, 0x69, 0x61, 0x67, 0x6e,
+	0x6f, 0x73, 0x74, 0x69, 0x63, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x13, 0x2e, 0x2f,
+	0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x64, 0x69, 0x61, 0x67, 0x6e, 0x6f, 0x73, 0x74, 0x69,
+	0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+}
+
+var (
+	file_networkDiagnostic_proto_rawDescOnce sync.Once
+	file_networkDiagnostic_proto_rawDescData = file_networkDiagnostic_proto_rawDesc
+)
+
+func file_networkDiagnostic_proto_rawDescGZIP() []byte {
+	file_networkDiagnostic_proto_rawDescOnce.Do(func() {
+		file_networkDiagnostic_proto_rawDescData = protoimpl.X.CompressGZIP(file_networkDiagnostic_proto_rawDescData)
+	})
+	return file_networkDiagnostic_proto_rawDescData
+}
+
+var file_networkDiagnostic_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
+var file_networkDiagnostic_proto_goTypes = []any{
+	(*NetworkLatencyProbeRequest)(nil), // 0: networkdiagnostic.NetworkLatencyProbeRequest
+	(*NetworkLatencyProbeReply)(nil),   // 1: networkdiagnostic.NetworkLatencyProbeReply
+}
+var file_networkDiagnostic_proto_depIdxs = []int32{
+	0, // 0: networkdiagnostic.NetworkDiagnosticService.NetworkLatencyProbe:input_type -> networkdiagnostic.NetworkLatencyProbeRequest
+	1, // 1: networkdiagnostic.NetworkDiagnosticService.NetworkLatencyProbe:output_type -> networkdiagnostic.NetworkLatencyProbeReply
+	1, // [1:2] is the sub-list for method output_type
+	0, // [0:1] is the sub-list for method input_type
+	0, // [0:0] is the sub-list for extension type_name
+	0, // [0:0] is the sub-list for extension extendee
+	0, // [0:0] is the sub-list for field type_name
+}
+
+func init() { file_networkDiagnostic_proto_init() }
+func file_networkDiagnostic_proto_init() {
+	if File_networkDiagnostic_proto != nil {
+		return
+	}
+	if !protoimpl.UnsafeEnabled {
+		file_networkDiagnostic_proto_msgTypes[0].Exporter = func(v any, i int) any {
+			switch v := v.(*NetworkLatencyProbeRequest); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_networkDiagnostic_proto_msgTypes[1].Exporter = func(v any, i int) any {
+			switch v := v.(*NetworkLatencyProbeReply); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+	}
+	type x struct{}
+	out := protoimpl.TypeBuilder{
+		File: protoimpl.DescBuilder{
+			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
+			RawDescriptor: file_networkDiagnostic_proto_rawDesc,
+			NumEnums:      0,
+			NumMessages:   2,
+			NumExtensions: 0,
+			NumServices:   1,
+		},
+		GoTypes:           file_networkDiagnostic_proto_goTypes,
+		DependencyIndexes: file_networkDiagnostic_proto_depIdxs,
+		MessageInfos:      file_networkDiagnostic_proto_msgTypes,
+	}.Build()
+	File_networkDiagnostic_proto = out.File
+	file_networkDiagnostic_proto_rawDesc = nil
+	file_networkDiagnostic_proto_goTypes = nil
+	file_networkDiagnostic_proto_depIdxs = nil
+}

+ 122 - 0
networkdiagnostic/pb/networkDiagnostic_grpc.pb.go

@@ -0,0 +1,122 @@
+// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
+// versions:
+// - protoc-gen-go-grpc v1.5.1
+// - protoc             v5.28.2
+// source: networkDiagnostic.proto
+
+package networkdiagnostic
+
+import (
+	context "context"
+	grpc "google.golang.org/grpc"
+	codes "google.golang.org/grpc/codes"
+	status "google.golang.org/grpc/status"
+)
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the grpc package it is being compiled against.
+// Requires gRPC-Go v1.64.0 or later.
+const _ = grpc.SupportPackageIsVersion9
+
+const (
+	NetworkDiagnosticService_NetworkLatencyProbe_FullMethodName = "/networkdiagnostic.NetworkDiagnosticService/NetworkLatencyProbe"
+)
+
+// NetworkDiagnosticServiceClient is the client API for NetworkDiagnosticService service.
+//
+// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
+type NetworkDiagnosticServiceClient interface {
+	NetworkLatencyProbe(ctx context.Context, in *NetworkLatencyProbeRequest, opts ...grpc.CallOption) (*NetworkLatencyProbeReply, error)
+}
+
+type networkDiagnosticServiceClient struct {
+	cc grpc.ClientConnInterface
+}
+
+func NewNetworkDiagnosticServiceClient(cc grpc.ClientConnInterface) NetworkDiagnosticServiceClient {
+	return &networkDiagnosticServiceClient{cc}
+}
+
+func (c *networkDiagnosticServiceClient) NetworkLatencyProbe(ctx context.Context, in *NetworkLatencyProbeRequest, opts ...grpc.CallOption) (*NetworkLatencyProbeReply, error) {
+	cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
+	out := new(NetworkLatencyProbeReply)
+	err := c.cc.Invoke(ctx, NetworkDiagnosticService_NetworkLatencyProbe_FullMethodName, in, out, cOpts...)
+	if err != nil {
+		return nil, err
+	}
+	return out, nil
+}
+
+// NetworkDiagnosticServiceServer is the server API for NetworkDiagnosticService service.
+// All implementations must embed UnimplementedNetworkDiagnosticServiceServer
+// for forward compatibility.
+type NetworkDiagnosticServiceServer interface {
+	NetworkLatencyProbe(context.Context, *NetworkLatencyProbeRequest) (*NetworkLatencyProbeReply, error)
+	mustEmbedUnimplementedNetworkDiagnosticServiceServer()
+}
+
+// UnimplementedNetworkDiagnosticServiceServer must be embedded to have
+// forward compatible implementations.
+//
+// NOTE: this should be embedded by value instead of pointer to avoid a nil
+// pointer dereference when methods are called.
+type UnimplementedNetworkDiagnosticServiceServer struct{}
+
+func (UnimplementedNetworkDiagnosticServiceServer) NetworkLatencyProbe(context.Context, *NetworkLatencyProbeRequest) (*NetworkLatencyProbeReply, error) {
+	return nil, status.Errorf(codes.Unimplemented, "method NetworkLatencyProbe not implemented")
+}
+func (UnimplementedNetworkDiagnosticServiceServer) mustEmbedUnimplementedNetworkDiagnosticServiceServer() {
+}
+func (UnimplementedNetworkDiagnosticServiceServer) testEmbeddedByValue() {}
+
+// UnsafeNetworkDiagnosticServiceServer may be embedded to opt out of forward compatibility for this service.
+// Use of this interface is not recommended, as added methods to NetworkDiagnosticServiceServer will
+// result in compilation errors.
+type UnsafeNetworkDiagnosticServiceServer interface {
+	mustEmbedUnimplementedNetworkDiagnosticServiceServer()
+}
+
+func RegisterNetworkDiagnosticServiceServer(s grpc.ServiceRegistrar, srv NetworkDiagnosticServiceServer) {
+	// If the following call pancis, it indicates UnimplementedNetworkDiagnosticServiceServer was
+	// embedded by pointer and is nil.  This will cause panics if an
+	// unimplemented method is ever invoked, so we test this at initialization
+	// time to prevent it from happening at runtime later due to I/O.
+	if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
+		t.testEmbeddedByValue()
+	}
+	s.RegisterService(&NetworkDiagnosticService_ServiceDesc, srv)
+}
+
+func _NetworkDiagnosticService_NetworkLatencyProbe_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+	in := new(NetworkLatencyProbeRequest)
+	if err := dec(in); err != nil {
+		return nil, err
+	}
+	if interceptor == nil {
+		return srv.(NetworkDiagnosticServiceServer).NetworkLatencyProbe(ctx, in)
+	}
+	info := &grpc.UnaryServerInfo{
+		Server:     srv,
+		FullMethod: NetworkDiagnosticService_NetworkLatencyProbe_FullMethodName,
+	}
+	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+		return srv.(NetworkDiagnosticServiceServer).NetworkLatencyProbe(ctx, req.(*NetworkLatencyProbeRequest))
+	}
+	return interceptor(ctx, in, info, handler)
+}
+
+// NetworkDiagnosticService_ServiceDesc is the grpc.ServiceDesc for NetworkDiagnosticService service.
+// It's only intended for direct use with grpc.RegisterService,
+// and not to be introspected or modified (even as a copy)
+var NetworkDiagnosticService_ServiceDesc = grpc.ServiceDesc{
+	ServiceName: "networkdiagnostic.NetworkDiagnosticService",
+	HandlerType: (*NetworkDiagnosticServiceServer)(nil),
+	Methods: []grpc.MethodDesc{
+		{
+			MethodName: "NetworkLatencyProbe",
+			Handler:    _NetworkDiagnosticService_NetworkLatencyProbe_Handler,
+		},
+	},
+	Streams:  []grpc.StreamDesc{},
+	Metadata: "networkDiagnostic.proto",
+}

+ 30 - 0
networkdiagnostic/ping_test.go

@@ -0,0 +1,30 @@
+package networkdiagnostic_test
+
+import (
+	"fmt"
+	"github.com/go-ping/ping"
+	"runtime"
+	"testing"
+	"time"
+)
+
+func TestPing(t *testing.T) {
+	pinger, err := ping.NewPinger("console.cengcloud.com")
+	if err != nil {
+		panic(err)
+	}
+	os := runtime.GOOS
+	pinger.Count = 3
+	pinger.Timeout = 5 * time.Second
+	pinger.Interval = 1 * time.Second
+	if os == "windows" {
+		pinger.SetPrivileged(true)
+	}
+	err = pinger.Run() // Blocks until finished.
+	if err != nil {
+		panic(err)
+	}
+	stats := pinger.Statistics() // get send/receive/duplicate/rtt stats
+	fmt.Println("", stats)
+	fmt.Println("", os)
+}

+ 31 - 0
networkdiagnostic/readme.md

@@ -0,0 +1,31 @@
+### Supported Operating Systems
+
+#### Linux
+
+This library attempts to send an "unprivileged" ping via UDP. On Linux, this must be enabled with the following sysctl command:
+
+```
+sudo sysctl -w net.ipv4.ping_group_range="0 2147483647"
+```
+
+If you do not wish to do this, you can call `pinger.SetPrivileged(true)` in your code and then use setcap on your binary to allow it to bind to raw sockets (or just run it as root):
+
+```
+setcap cap_net_raw=+ep /path/to/your/compiled/binary
+```
+
+See this blog and the Go x/net/icmp package for more details.
+
+#### Windows
+
+You must use `pinger.SetPrivileged(true)`, otherwise you will receive the following error:
+
+```
+socket: The requested protocol has not been configured into the system, or no implementation for it exists.
+```
+
+Despite the method name, this should work without the need to elevate privileges and has been tested on Windows 10. Please note that accessing packet TTL values is not supported due to limitations in the Go x/net/ipv4 and x/net/ipv6 packages.
+
+#### Plan 9 from Bell Labs
+
+There is no support for Plan 9. This is because the entire `x/net/ipv4` and `x/net/ipv6` packages are not implemented by the Go programming language.