Skip to content

Instantly share code, notes, and snippets.

@bttger
Created June 22, 2023 15:26
Show Gist options
  • Save bttger/0cf84c1f4167ab0f3cc58f7202c1ae72 to your computer and use it in GitHub Desktop.
Save bttger/0cf84c1f4167ab0f3cc58f7202c1ae72 to your computer and use it in GitHub Desktop.
Monitor your internet connection in a reliable interval
package main
import (
"bufio"
"flag"
"fmt"
"log"
"net/http"
"os"
"strings"
"time"
)
const (
serverURL = "https://1.1.1.1/media/manifest.json"
logFile = "connmon.log"
timeFormat = "2006-01-02 15:04:05"
timeoutLogMsg = "%s - Timeout\n"
successLogMsg = "%s - Success - Time taken: %s\n"
)
var httpClient = &http.Client{
Timeout: 500 * time.Millisecond,
}
func main() {
monitorMode := flag.Bool("m", false, "Monitor internet connection and update logs")
statsMode := flag.Bool("s", false, "Print statistics of monitoring logs")
flag.Parse()
if *monitorMode {
monitorConnection()
} else if *statsMode {
printStatistics()
} else {
log.Println("Please specify a mode: -m or -s")
}
}
func monitorConnection() {
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
for range ticker.C {
go func() {
start := time.Now()
_, err := httpClient.Get(serverURL)
elapsed := time.Since(start)
currentTime := time.Now().Format(timeFormat)
if err != nil {
appendToFile(logFile, fmt.Sprintf(timeoutLogMsg, currentTime))
fmt.Printf("\rDisconnected")
} else {
appendToFile(logFile, fmt.Sprintf(successLogMsg, currentTime, elapsed))
fmt.Printf("\rConnected ")
}
}()
}
}
func appendToFile(filename, text string) {
f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
defer f.Close()
if _, err := f.WriteString(text); err != nil {
log.Fatal(err)
}
}
func printStatistics() {
file, err := os.Open(logFile)
if err != nil {
log.Fatal(err)
}
defer file.Close()
var total, timeouts int
var totalResponseTime time.Duration
responseTimeBuckets := map[string]int{
"<100ms": 0,
"100-200ms": 0,
"200-300ms": 0,
"300-400ms": 0,
"400-500ms": 0,
">500ms": 0,
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
total++
if strings.Contains(line, "Timeout") {
timeouts++
} else {
parts := strings.Split(line, "Time taken: ")
if len(parts) == 2 {
responseTime, err := time.ParseDuration(strings.TrimSpace(parts[1]))
if err == nil {
totalResponseTime += responseTime
switch {
case responseTime < 100*time.Millisecond:
responseTimeBuckets["<100ms"]++
case responseTime < 200*time.Millisecond:
responseTimeBuckets["100-200ms"]++
case responseTime < 300*time.Millisecond:
responseTimeBuckets["200-300ms"]++
case responseTime < 400*time.Millisecond:
responseTimeBuckets["300-400ms"]++
case responseTime < 500*time.Millisecond:
responseTimeBuckets["400-500ms"]++
default:
responseTimeBuckets[">500ms"]++
}
}
}
}
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
successes := total - timeouts
averageResponseTime := time.Duration(0)
if successes > 0 {
averageResponseTime = totalResponseTime / time.Duration(successes)
}
fmt.Printf("Total requests: %d\n", total)
fmt.Printf("Timeouts: %d\n", timeouts)
if total > 0 {
fmt.Printf("Percentage of timeouts: %.2f%%\n", (float64(timeouts)/float64(total))*100)
}
fmt.Printf("Average response time for successful requests: %s\n", averageResponseTime)
bucketOrder := []string{"<100ms", "100-200ms", "200-300ms", "300-400ms", "400-500ms", ">500ms"}
fmt.Println("Response time distribution:")
for _, bucket := range bucketOrder {
fmt.Printf("%s: %d\n", bucket, responseTimeBuckets[bucket])
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment