update
commit
d51ccc456b
|
@ -0,0 +1,2 @@
|
|||
nwm
|
||||
runtime
|
|
@ -0,0 +1,62 @@
|
|||
<div>
|
||||
<canvas id="myChart"></canvas>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@^3"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/moment@^2"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@^1"></script>
|
||||
|
||||
<script>
|
||||
const ctx = document.getElementById('myChart');
|
||||
|
||||
const fails = [
|
||||
{{.Data}}
|
||||
]
|
||||
|
||||
new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [
|
||||
{
|
||||
label: 'Public Network',
|
||||
data: fails.filter(el=>el.name=='Public'),
|
||||
borderColor: 'rgb(255, 99, 132)',
|
||||
backgroundColor: 'rgb(255, 99, 132)',
|
||||
},
|
||||
{
|
||||
label: 'DSL',
|
||||
data: fails.filter(el=>el.name=='DSL'),
|
||||
borderColor: 'rgb(75, 192, 192)',
|
||||
backgroundColor: 'rgb(75, 192, 192)'
|
||||
},
|
||||
{
|
||||
label: 'Asus Router',
|
||||
data: fails.filter(el=>el.name=='Asus'),
|
||||
borderColor: 'rgb(255, 205, 86)',
|
||||
backgroundColor: 'rgb(255, 205, 86)'
|
||||
}
|
||||
]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
x: {
|
||||
type: 'time',
|
||||
time: {
|
||||
unit: 'second'
|
||||
},
|
||||
position: 'bottom'
|
||||
},
|
||||
y: {
|
||||
type: 'category',
|
||||
labels: ['', 'ok','failed','']
|
||||
}
|
||||
},
|
||||
decimation: {
|
||||
enabled: true,
|
||||
algorithm: 'lttb'
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,184 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"strings"
|
||||
"syscall"
|
||||
"text/template"
|
||||
"time"
|
||||
)
|
||||
|
||||
//go:embed index.html
|
||||
var tmpl string
|
||||
|
||||
var report = template.Must(template.New("").Parse(tmpl))
|
||||
var write_report chan bool
|
||||
var interval = time.Second * 2
|
||||
|
||||
type Network struct {
|
||||
Name string
|
||||
IP string
|
||||
OnFail string
|
||||
}
|
||||
|
||||
var Networks = []*Network{
|
||||
{
|
||||
Name: "DSL",
|
||||
IP: "220.135.85.67",
|
||||
OnFail: "nmcli connection up DSL",
|
||||
},
|
||||
{
|
||||
Name: "Asus",
|
||||
IP: "192.168.50.48",
|
||||
},
|
||||
}
|
||||
|
||||
func main() {
|
||||
write_report = make(chan bool, 1)
|
||||
|
||||
file, err := os.OpenFile("network.log", os.O_WRONLY|os.O_APPEND|os.O_CREATE, os.ModePerm)
|
||||
if err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
log.Println("starting network monitor")
|
||||
|
||||
go func() {
|
||||
|
||||
perr := false
|
||||
derr := false
|
||||
|
||||
for reducer := 0; ; reducer++ {
|
||||
now := time.Now().Format("2006-01-02 15:04:05")
|
||||
|
||||
// Public
|
||||
go func(print bool) {
|
||||
_, err = net.LookupIP("google.com")
|
||||
if err != nil {
|
||||
if !perr {
|
||||
perr = true
|
||||
log.Println(err)
|
||||
}
|
||||
fmt.Fprintf(file, `{"x": "%s", "y": "%s", "name": "%s"},`, now, "failed", "Public")
|
||||
fmt.Fprintf(file, "\n")
|
||||
} else {
|
||||
perr = false
|
||||
if print {
|
||||
fmt.Fprintf(file, `{"x": "%s", "y": "%s", "name": "%s"},`, now, "ok", "Public")
|
||||
fmt.Fprintf(file, "\n")
|
||||
}
|
||||
}
|
||||
}(reducer == 0)
|
||||
|
||||
// devices
|
||||
go func(print bool) {
|
||||
for i := range Networks {
|
||||
_, err = GetOutboundIP(Networks[i].IP + ":0")
|
||||
if err != nil {
|
||||
if !derr {
|
||||
derr = true
|
||||
log.Println(err)
|
||||
}
|
||||
fmt.Fprintf(file, `{"x": "%s", "y": "%s", "name": "%s"},`, now, "failed", Networks[i].Name)
|
||||
fmt.Fprintf(file, "\n")
|
||||
// fmt.Fprintf(file, "%s\t%s\t%s\n", now, Networks[i].Name, "failed")
|
||||
} else {
|
||||
derr = false
|
||||
if print {
|
||||
fmt.Fprintf(file, `{"x": "%s", "y": "%s", "name": "%s"},`, now, "ok", Networks[i].Name)
|
||||
fmt.Fprintf(file, "\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
}(reducer == 0)
|
||||
|
||||
<-time.After(interval)
|
||||
if reducer >= 9 {
|
||||
reducer = -1
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for {
|
||||
<-time.After(time.Minute * 10)
|
||||
WriteReport()
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
http.ServeFile(w, r, strings.TrimPrefix(r.URL.Path, "/"))
|
||||
})
|
||||
if err := http.ListenAndServe("0.0.0.0:1080", nil); err != nil {
|
||||
log.Fatalln(err)
|
||||
}
|
||||
}()
|
||||
|
||||
wait := make(chan os.Signal, 1)
|
||||
signal.Notify(wait, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
||||
<-wait
|
||||
WriteReport()
|
||||
}
|
||||
|
||||
func WriteReport() {
|
||||
|
||||
select {
|
||||
case write_report <- true:
|
||||
|
||||
default:
|
||||
return
|
||||
}
|
||||
defer func() { <-write_report }()
|
||||
|
||||
f, err := os.OpenFile("report.html", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
data, err := os.ReadFile("network.log")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
content := &bytes.Buffer{}
|
||||
if err = report.Execute(content, map[string]string{"Data": string(data)}); err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
content.WriteTo(f)
|
||||
|
||||
}
|
||||
|
||||
// Get preferred outbound ip of this machine
|
||||
func GetOutboundIP(addr string) (net.IP, error) {
|
||||
|
||||
iface, err := net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dialer := &net.Dialer{LocalAddr: iface}
|
||||
|
||||
conn, err := dialer.Dial("udp", "8.8.8.8:80")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
localAddr := conn.LocalAddr().(*net.UDPAddr)
|
||||
|
||||
return localAddr.IP, nil
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
[Unit]
|
||||
Description=Evan Network Monitor
|
||||
|
||||
[Service]
|
||||
WorkingDirectory=/home/evan/Documents/network-monitor/runtime
|
||||
ExecStart=/home/evan/Documents/network-monitor/nwm
|
||||
Restart=always
|
||||
|
||||
StandardOutput=append:/home/evan/Documents/network-monitor/runtime/service.log
|
||||
StandardError=append:/home/evan/Documents/network-monitor/runtime/service.log
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
|
||||
sudo systemctl stop nwm
|
||||
|
||||
go build -o nwm main.go
|
||||
|
||||
sudo systemctl start nwm
|
Loading…
Reference in New Issue