Skip to content

Commit

Permalink
cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
ao committed Jul 24, 2024
1 parent 56a6dd7 commit aafcb80
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 124 deletions.
16 changes: 16 additions & 0 deletions cmd/banner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package main

func Banner() string {
return `
▄████ ▒█████ █████▒██▓ ▒█████ ▒█████ ▓█████▄
██▒ ▀█▒▒██▒ ██▒▓██ ▒▓██▒ ▒██▒ ██▒▒██▒ ██▒▒██▀ ██▌
▒██░▄▄▄░▒██░ ██▒▒████ ░▒██░ ▒██░ ██▒▒██░ ██▒░██ █▌
░▓█ ██▓▒██ ██░░▓█▒ ░▒██░ ▒██ ██░▒██ ██░░▓█▄ ▌
░▒▓███▀▒░ ████▓▒░░▒█░ ░██████▒░ ████▓▒░░ ████▓▒░░▒████▓
░▒ ▒ ░ ▒░▒░▒░ ▒ ░ ░ ▒░▓ ░░ ▒░▒░▒░ ░ ▒░▒░▒░ ▒▒▓ ▒
░ ░ ░ ▒ ▒░ ░ ░ ░ ▒ ░ ░ ▒ ▒░ ░ ▒ ▒░ ░ ▒ ▒
░ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ░ ░ ░ ░ ▒ ░ ░ ░ ▒ ░ ░ ░
░ ░ ░ ░ ░ ░ ░ ░ ░ ░
`
}
164 changes: 164 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package main

import (
"flag"
"fmt"
"os"
"os/signal"
"sort"
"sync"
"sync/atomic"
"syscall"
"time"
)

const (
colorReset = "\033[0m"
colorGreen = "\033[32m"
colorOrange = "\033[33m"
)

func main() {
fmt.Println(Banner())

var targetURL string
var concurrency int
var duration time.Duration
var showHelp bool

flag.StringVar(&targetURL, "url", "", "Target URL")
flag.IntVar(&concurrency, "n", 5, "Concurrency Step")
flag.DurationVar(&duration, "t", 10*time.Second, "Duration for which the program should run")
flag.BoolVar(&showHelp, "help", false, "Show help")

flag.Parse()

if targetURL == "" {
fmt.Println("Please specify a target URL")
flag.Usage()
os.Exit(0)
}

if showHelp {
flag.Usage()
os.Exit(0)
}

var wg sync.WaitGroup
var counter int32
var totalRequests int32
var successfulRequests int32
var failedRequests int32
var requestTimes []time.Duration
var mu sync.Mutex

// Interrupt handling for graceful shutdown
stop := make(chan os.Signal, 1)
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)

go func() {
<-stop
wg.Wait() // Wait for ongoing requests to finish
os.Exit(0)
}()

startTime := time.Now()

timer := time.NewTimer(duration)
defer timer.Stop()

ticker := time.NewTicker(time.Second)
defer ticker.Stop()

fmt.Printf("Running for %s\n\n", duration)

go func() {
for range ticker.C {
elapsedTime := time.Since(startTime)
remainingTime := duration - elapsedTime
fmt.Printf("\nTime elapsed: %ds - Time remaining: %ds\n", int(elapsedTime.Seconds()), int(remainingTime.Seconds()))

intervalWg := sync.WaitGroup{}

for i := 0; i < concurrency; i++ {
wg.Add(1)
intervalWg.Add(1)
atomic.AddInt32(&counter, 1)
atomic.AddInt32(&totalRequests, 1)
go func() {
makeRequest(targetURL, &counter, &wg, &successfulRequests, &failedRequests, &requestTimes, &mu)
intervalWg.Done()
}()
}
intervalWg.Wait() // Wait for all requests in this interval to finish
}
}()

<-timer.C // Wait for the duration to elapse

// Stop the ticker
ticker.Stop()

// Wait until all requests are done
wg.Wait()

elapsed := time.Since(startTime)

// Print summary report in tabular format
printSummaryReport(targetURL, concurrency, elapsed, totalRequests, successfulRequests, failedRequests, requestTimes)
}

func printSummaryReport(targetURL string, concurrency int, elapsed time.Duration, totalRequests, successfulRequests, failedRequests int32, requestTimes []time.Duration) {
durationStr := elapsed.Round(time.Millisecond).String()

// Calculate min, median, and max request times
sort.Slice(requestTimes, func(i, j int) bool {
return requestTimes[i] < requestTimes[j]
})
minTime := requestTimes[0]
maxTime := requestTimes[len(requestTimes)-1]
medianTime := requestTimes[len(requestTimes)/2]

// Determine the maximum length of the target URL and set the width accordingly
titlesWidth := 25
maxWidth := 40
if len(targetURL) > maxWidth {
maxWidth = len(targetURL)
}

// Create dynamic separator
separator := createSeparator(titlesWidth, maxWidth)

fmt.Println("\n*** Summary Report ***")
fmt.Println(separator)
fmt.Printf("| %-*s | %-*s |\n", titlesWidth, "Target URL", maxWidth, targetURL)
fmt.Println(separator)
fmt.Printf("| %-*s | %-*d |\n", titlesWidth, "Concurrency", maxWidth, concurrency)
fmt.Println(separator)
fmt.Printf("| %-*s | %-*s |\n", titlesWidth, "Duration", maxWidth, durationStr)
fmt.Println(separator)
fmt.Printf("| %-*s | %-*d |\n", titlesWidth, "Total Requests", maxWidth, totalRequests)
fmt.Println(separator)
fmt.Printf("| %-*s | %-*d |\n", titlesWidth, "Successful Requests", maxWidth, successfulRequests)
fmt.Println(separator)
fmt.Printf("| %-*s | %-*d |\n", titlesWidth, "Failed Requests", maxWidth, failedRequests)
fmt.Println(separator)
fmt.Printf("| %-*s | %-*s |\n", titlesWidth, "Min Request Time", maxWidth, minTime)
fmt.Println(separator)
fmt.Printf("| %-*s | %-*s |\n", titlesWidth, "Median Request Time", maxWidth, medianTime)
fmt.Println(separator)
fmt.Printf("| %-*s | %-*s |\n", titlesWidth, "Max Request Time", maxWidth, maxTime)
fmt.Println(separator)
}

func createSeparator(labelWidth, valueWidth int) string {
return fmt.Sprintf("+-%s-+-%s-+", dashes(labelWidth), dashes(valueWidth))
}

func dashes(n int) string {
ret := ""
for i := 0; i < n; i++ {
ret += "-"
}
return ret
}
31 changes: 31 additions & 0 deletions cmd/requests.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package main

import (
"fmt"
"net/http"
"sync"
"sync/atomic"
"time"
)

func makeRequest(url string, counter *int32, wg *sync.WaitGroup, successfulRequests *int32, failedRequests *int32, requestTimes *[]time.Duration, mu *sync.Mutex) {
defer wg.Done()
defer atomic.AddInt32(counter, -1)

start := time.Now()
res, err := http.Get(url)
elapsed := time.Since(start)

mu.Lock()
*requestTimes = append(*requestTimes, elapsed)
mu.Unlock()

if err != nil {
fmt.Printf("%sError making request: %v (Duration: %s)%s\n", colorOrange, err, elapsed, colorReset)
atomic.AddInt32(failedRequests, 1)
} else {
fmt.Printf("%sRequest successful (Duration: %s) %d%s\n", colorGreen, elapsed, res.StatusCode, colorReset)
atomic.AddInt32(successfulRequests, 1)
res.Body.Close()
}
}
124 changes: 0 additions & 124 deletions main.go

This file was deleted.

0 comments on commit aafcb80

Please sign in to comment.