Skip to content

Commit

Permalink
Add 'loadtester' executable
Browse files Browse the repository at this point in the history
Currently only test Livepeer API's HTTP push
  • Loading branch information
darkdarkdragon committed Sep 23, 2020
1 parent b179b3b commit eeb4bb7
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,13 @@ jobs:
make lapi
make mapi
make connector
make loadtester
- name: Compress Posix
if: matrix.os != 'windows-latest'
run: |
gzip -9 -S .${{runner.os}}.gz streamtester
gzip -9 -S .${{runner.os}}.gz loadtester
gzip -9 -S .${{runner.os}}.gz lapi
gzip -9 -S .${{runner.os}}.gz testdriver
gzip -9 -S .${{runner.os}}.gz mapi
Expand All @@ -97,6 +99,7 @@ jobs:
with:
files: |
streamtester.${{runner.os}}.gz
loadtester.${{runner.os}}.gz
lapi.${{runner.os}}.gz
mapi.${{runner.os}}.gz
testdriver.${{runner.os}}.gz
Expand Down
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ RUN echo $version
RUN go build -ldflags="-X 'github.com/livepeer/stream-tester/model.Version=$version' -X 'github.com/livepeer/stream-tester/model.IProduction=true'" -tags h264 cmd/streamtester/streamtester.go
RUN go build -ldflags="-X 'github.com/livepeer/stream-tester/model.Version=$version' -X 'github.com/livepeer/stream-tester/model.IProduction=true'" cmd/testdriver/testdriver.go
RUN go build -ldflags="-X 'github.com/livepeer/stream-tester/model.Version=$version' -X 'github.com/livepeer/stream-tester/model.IProduction=true'" cmd/mist-api-connector/mist-api-connector.go
RUN go build -ldflags="-X 'github.com/livepeer/stream-tester/model.Version=$version' -X 'github.com/livepeer/stream-tester/model.IProduction=true'" cmd/loadtester/loadtester.go
# RUN ls -a /usr
# RUN find / -name libavformat.so.58

Expand All @@ -42,6 +43,7 @@ COPY --from=builder /root/bbb_sunflower_1080p_30fps_normal_2min.mp4 bbb_sunflowe
COPY --from=builder /root/streamtester streamtester
COPY --from=builder /root/testdriver testdriver
COPY --from=builder /root/mist-api-connector mist-api-connector
COPY --from=builder /root/loadtester loadtester
# COPY --from=builder /usr/lib/libavformat.so.58 /usr/lib/libavformat.so.58
# COPY --from=builder /usr/lib/libavutil.so.56 /usr/lib/libavutil.so.56
# COPY --from=builder /usr/lib/libavcodec.so.58 /usr/lib/libavcodec.so.58
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ ldflags := -X 'github.com/livepeer/stream-tester/model.Version=$(shell git descr
streamtester:
go build -ldflags="$(ldflags)" cmd/streamtester/streamtester.go

.PHONY: loadtester
loadtester:
go build -ldflags="$(ldflags)" cmd/loadtester/loadtester.go

.PHONY: testdriver
testdriver:
go build -ldflags="$(ldflags)" cmd/testdriver/testdriver.go
Expand Down
123 changes: 123 additions & 0 deletions cmd/loadtester/loadtester.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Load tester is a tool to do load testing
package main

import (
"context"
"flag"
"fmt"
"os"
"os/signal"
"runtime"
"syscall"
"time"

"github.com/golang/glog"
"github.com/livepeer/joy4/format"
"github.com/livepeer/stream-tester/apis/livepeer"
"github.com/livepeer/stream-tester/internal/testers"
"github.com/livepeer/stream-tester/internal/utils"
"github.com/livepeer/stream-tester/model"
"github.com/peterbourgon/ff/v2"
)

func init() {
format.RegisterAll()
}

func main() {
flag.Set("logtostderr", "true")
vFlag := flag.Lookup("v")

fs := flag.NewFlagSet("loadteter", flag.ExitOnError)

verbosity := fs.String("v", "", "Log verbosity. {4|5|6}")
version := fs.Bool("version", false, "Print out the version")

// startDelay := fs.Duration("start-delay", 0*time.Second, "time delay before start")
streamDuration := fs.Duration("stream-dur", 0, "How long to stream (0 to stream whole file)")

profiles := fs.Uint("profiles", 2, "number of transcoded profiles should be in output")
sim := fs.Uint("sim", 1, "Number of simulteneous streams to stream")
fileArg := fs.String("file", "bbb_sunflower_1080p_30fps_normal_t02.mp4", "File to stream")
apiToken := fs.String("api-token", "", "Token of the Livepeer API to be used")
apiServer := fs.String("api-server", "livepeer.com", "Server of the Livepeer API to be used")

_ = fs.String("config", "", "config file (optional)")

ff.Parse(fs, os.Args[1:],
ff.WithConfigFileFlag("config"),
ff.WithConfigFileParser(ff.PlainParser),
ff.WithEnvVarPrefix("LOADTESTER"),
)
flag.CommandLine.Parse(nil)
vFlag.Value.Set(*verbosity)

hostName, _ := os.Hostname()
fmt.Println("Loadtester version: " + model.Version)
fmt.Printf("Compiler version: %s %s\n", runtime.Compiler, runtime.Version())
fmt.Printf("Hostname %s OS %s IPs %v\n", hostName, runtime.GOOS, utils.GetIPs())
fmt.Printf("Production: %v\n", model.Production)

fmt.Printf("\nCurrently only HTTP push is supported\n\n")

if *version {
return
}
if _, err := os.Stat(*fileArg); os.IsNotExist(err) {
fmt.Printf("File '%s' does not exists", *fileArg)
os.Exit(1)
}
if *profiles == 0 {
fmt.Printf("Number of profiles couldn't be set to zero")
os.Exit(1)
}

if *apiToken == "" {
glog.Fatalf("-api-token should be specified")
}

model.ProfilesNum = int(*profiles)
var err error

lapi := livepeer.NewLivepeer(*apiToken, *apiServer, nil)
lapi.Init()
glog.Infof("Choosen server: %s", lapi.GetServer())
ingests, err := lapi.Ingest(false)
if err != nil {
panic(err)
}
glog.Infof("Got ingests: %+v", ingests)
broadcasters, err := lapi.Broadcasters()
if err != nil {
panic(err)
}
glog.Infof("Got broadcasters: %+v", broadcasters)

gctx, gcancel := context.WithCancel(context.Background()) // to be used as global parent context, in the future
sr := testers.NewHTTPLoadTester(gctx, gcancel, lapi, 0)
baseManifesID, err := sr.StartStreams(*fileArg, "", "", "", "443", *sim, 1, *streamDuration, false, true, true, 3, 5*time.Second, 0)
if err != nil {
panic(err)
}
glog.Infof("Base manfiest id: %s", baseManifesID)
exitc := make(chan os.Signal, 1)
signal.Notify(exitc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
go func() {
<-exitc
fmt.Println("Got Ctrl-C, cancelling")
gcancel()
sr.Cancel()
time.Sleep(2 * time.Second)
stats, _ := sr.Stats("")
fmt.Println(stats.FormatForConsole())
}()
glog.Infof("Waiting for test to complete")
<-sr.Done()
<-gctx.Done()
time.Sleep(1 * time.Second)
fmt.Println("========= Stats: =========")
stats, _ := sr.Stats("")
fmt.Println(stats.FormatForConsole())
fmt.Println(stats.FormatErrorsForConsole())
os.Exit(model.ExitCode)
}
5 changes: 4 additions & 1 deletion internal/utils/net.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package utils

import (
"context"
"crypto/tls"
"fmt"
"io/ioutil"
Expand Down Expand Up @@ -51,8 +52,10 @@ func httpDo(req *http.Request, sourceIP string) (*http.Response, error) {

func getExternalIP(iip string) string {
// TODO probably should put this (along w wizard GETs) into common code
req, _ := http.NewRequest("GET", "https://api.ipify.org?format=text", nil)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
req, _ := http.NewRequestWithContext(ctx, "GET", "https://api.ipify.org?format=text", nil)
resp, err := httpDo(req, iip)
cancel()
if err != nil {
glog.Error("Could not look up public IP address")
return ""
Expand Down

0 comments on commit eeb4bb7

Please sign in to comment.