Skip to content

Commit

Permalink
all writes are passing thru cobra
Browse files Browse the repository at this point in the history
  • Loading branch information
rbarazzutti committed Aug 21, 2023
1 parent 54eac7a commit c146a16
Show file tree
Hide file tree
Showing 12 changed files with 101 additions and 46 deletions.
50 changes: 50 additions & 0 deletions app/consolelogger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright 2022 Raphaël P. Barazzutti
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// SPDX-License-Identifier: Apache-2.0

package app

import (
"fmt"
"github.com/spf13/cobra"
)

type ConsoleLogger interface {
Printf(format string, a ...any) (int, error)
}

func NewConsoleBasicLogger() ConsoleLogger {
return &consoleLoggerImpl{}
}

type consoleLoggerImpl struct {
}

func (logger *consoleLoggerImpl) Printf(format string, a ...any) (int, error) {
return fmt.Printf(format, a...)
}

func NewConsoleCobraLogger(command *cobra.Command) ConsoleLogger {
return &consoleLoggerCmdImpl{cmd: command}
}

type consoleLoggerCmdImpl struct {
cmd *cobra.Command
}

func (logger *consoleLoggerCmdImpl) Printf(format string, a ...any) (int, error) {
logger.cmd.Printf(format, a...)
return 0, nil
}
24 changes: 10 additions & 14 deletions app/httpping.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ package app

import (
"fever.ch/http-ping/stats"
"fmt"
"io"
"os"
"os/signal"
"time"
Expand All @@ -32,9 +30,8 @@ type HTTPPing interface {

type httpPingImpl struct {
config *Config
stdout io.Writer
pinger Pinger
logger logger
logger PingLogger
}

type httpPingTestVersion struct {
Expand Down Expand Up @@ -78,7 +75,7 @@ func (h *httpPingTestVersion) checkHttp(prep func(*Config)) <-chan string {
prep(&configCopy)

rc := RuntimeConfig{}
wc, _ := newWebClient(&configCopy, &rc)
wc, _ := newWebClient(&configCopy, &rc, h.logger)
m := wc.DoMeasure(false)

http3Advertisement := ""
Expand All @@ -98,40 +95,39 @@ func (h *httpPingTestVersion) checkHttp(prep func(*Config)) <-chan string {
}

// NewHTTPPing builds a new instance of HTTPPing or error if something goes wrong
func NewHTTPPing(config *Config, stdout io.Writer) (HTTPPing, error) {
func NewHTTPPing(config *Config, consoleLogger ConsoleLogger) (HTTPPing, error) {

runtimeConfig := &RuntimeConfig{
RedirectCallBack: func(url string) {
_, _ = fmt.Fprintf(stdout, " ─→ redirected to %s\n", url)
_, _ = consoleLogger.Printf(" ─→ redirected to %s\n", url)
},
}

pinger, err := NewPinger(config, runtimeConfig)
pinger, err := NewPinger(config, runtimeConfig, consoleLogger)

if err != nil {
return nil, err
}

var logger logger
var logger PingLogger

if config.LogLevel == 0 {
logger = newQuietLogger(config, stdout, pinger)
logger = newQuietLogger(config, consoleLogger, pinger)
} else if config.LogLevel == 2 {
logger = newVerboseLogger(config, stdout, pinger)
logger = newVerboseLogger(config, consoleLogger, pinger)
} else {
logger = newStandardLogger(config, stdout, pinger)
logger = newStandardLogger(config, consoleLogger, pinger)
}

if config.TestVersion {
return &httpPingTestVersion{
baseConfig: config,
logger: newStandardLogger(config, stdout, pinger),
logger: newStandardLogger(config, consoleLogger, pinger),
}, nil
}

return &httpPingImpl{
config: config,
stdout: stdout,
pinger: pinger,
logger: logger,
}, nil
Expand Down
11 changes: 10 additions & 1 deletion app/httpping_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,25 @@ package app
import (
"bytes"
"fever.ch/http-ping/stats"
"fmt"
"io"
"strings"
"testing"
)

type consoleLoggerMock struct {
b io.Writer
}

func (logger *consoleLoggerMock) Printf(format string, a ...any) (int, error) {
return fmt.Fprintf(logger.b, format, a...)
}

type PingerMock struct{}

func TestHTTPPing(t *testing.T) {
b := bytes.NewBufferString("")
instance, _ := NewHTTPPing(&Config{Count: 10}, b)
instance, _ := NewHTTPPing(&Config{Count: 10}, &consoleLoggerMock{b: b})
instance.(*httpPingImpl).pinger = &PingerMock{}
_ = instance.Run()

Expand Down
5 changes: 2 additions & 3 deletions app/pinger.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@ type pingerImpl struct {
}

// NewPinger builds a new pingerImpl
func NewPinger(config *Config, runtimeConfig *RuntimeConfig) (Pinger, error) {
func NewPinger(config *Config, runtimeConfig *RuntimeConfig, logger ConsoleLogger) (Pinger, error) {

pinger := pingerImpl{}

pinger.config = config

client, err := NewWebClientBuilder(config, runtimeConfig)
client, err := NewWebClientBuilder(config, runtimeConfig, logger)
if err != nil {
return nil, fmt.Errorf("%s (%s)", err, config.IPProtocol)
}
Expand All @@ -89,7 +89,6 @@ func (pinger *pingerImpl) Ping() <-chan *HTTPMeasure {
i := pinger.clientBuilder.NewInstance()
i.DoMeasure(true)
pinger.clientBuilder.SetURL(i.GetURL())

}

for i := 0; i < pinger.config.Workers; i++ {
Expand Down
2 changes: 1 addition & 1 deletion app/pinger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type webClientBuilderMock struct{}

func TestPinger(t *testing.T) {
wanted := 123
pinger, _ := NewPinger(&Config{Workers: 1, Count: int64(wanted)}, &RuntimeConfig{})
pinger, _ := NewPinger(&Config{Workers: 1, Count: int64(wanted)}, &RuntimeConfig{}, nil)
pinger.(*pingerImpl).clientBuilder = &webClientBuilderMock{}
ch := pinger.Ping()

Expand Down
22 changes: 10 additions & 12 deletions app/pinglogger.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@ package app

import (
"fever.ch/http-ping/stats"
"fmt"
"io"
"strings"
"time"
)

type logger interface {
type PingLogger interface {
onMeasure(httpMeasure *HTTPMeasure)
onTick(measure throughputMeasure)
onClose()
Expand All @@ -41,18 +39,18 @@ type measures struct {

type quietLogger struct {
config *Config
stdout io.Writer
consoleLogger ConsoleLogger
pinger Pinger
measures measures
throughputMeasures []throughputMeasure
}

func newQuietLogger(config *Config, stdout io.Writer, pinger Pinger) logger {
return &quietLogger{config: config, stdout: stdout, pinger: pinger}
func newQuietLogger(config *Config, consoleLogger ConsoleLogger, pinger Pinger) PingLogger {
return &quietLogger{config: config, consoleLogger: consoleLogger, pinger: pinger}
}

func (logger *quietLogger) Printf(format string, a ...any) (int, error) {
return fmt.Fprintf(logger.stdout,format, a...)
return logger.consoleLogger.Printf(format, a...)
}

func (logger *quietLogger) onMeasure(m *HTTPMeasure) {
Expand Down Expand Up @@ -121,8 +119,8 @@ type standardLogger struct {
quietLogger
}

func newStandardLogger(config *Config, stdout io.Writer, pinger Pinger) *standardLogger {
return &standardLogger{quietLogger{config: config, stdout: stdout, pinger: pinger}}
func newStandardLogger(config *Config, consoleLogger ConsoleLogger, pinger Pinger) *standardLogger {
return &standardLogger{quietLogger{config: config, consoleLogger: consoleLogger, pinger: pinger}}
}

func (logger *standardLogger) onMeasure(measure *HTTPMeasure) {
Expand All @@ -140,7 +138,7 @@ func (logger *standardLogger) onMeasure(measure *HTTPMeasure) {

func (logger *standardLogger) onTick(m throughputMeasure) {
logger.quietLogger.onTick(m)
fmt.Printf(" throughput: %s queries/sec, average latency: %.1f ms\n", m.String(), m.queriesDuration.ToFloat(time.Microsecond)/float64(1000*m.count))
logger.Printf(" throughput: %s queries/sec, average latency: %.1f ms\n", m.String(), m.queriesDuration.ToFloat(time.Microsecond)/float64(1000*m.count))
}

func (logger *standardLogger) onClose() {
Expand All @@ -160,9 +158,9 @@ func (logger *quietLogger) bell() {
}
}

func newVerboseLogger(config *Config, stdout io.Writer, pinger Pinger) logger {
func newVerboseLogger(config *Config, consoleLogger ConsoleLogger, pinger Pinger) PingLogger {
return &verboseLogger{
standardLogger: *newStandardLogger(config, stdout, pinger),
standardLogger: *newStandardLogger(config, consoleLogger, pinger),
measureSum: &HTTPMeasure{
MeasuresCollection: stats.NewMeasureRegistry(),
},
Expand Down
1 change: 1 addition & 0 deletions app/tput.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ type throughputMeasurer struct {
ts time.Time
counter uint64
duration stats.Measure
logger *PingLogger
}

type throughputMeasure struct {
Expand Down
4 changes: 2 additions & 2 deletions app/webclient_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ func TestWithEmbeddedWebServer(t *testing.T) {
var webClient WebClientBuilder
var measure *HTTPMeasure

webClient, _ = NewWebClientBuilder(&Config{Target: fmt.Sprintf("%s/500", url), NoCheckCertificate: true}, &RuntimeConfig{})
webClient, _ = NewWebClientBuilder(&Config{Target: fmt.Sprintf("%s/500", url), NoCheckCertificate: true}, &RuntimeConfig{}, nil)
measure = webClient.NewInstance().DoMeasure(false)

if !measure.IsFailure || measure.StatusCode != 500 {
t.Errorf("Request to server should have failed, 500")
}

webClient, _ = NewWebClientBuilder(&Config{Target: fmt.Sprintf("%s/200", url), NoCheckCertificate: true}, &RuntimeConfig{})
webClient, _ = NewWebClientBuilder(&Config{Target: fmt.Sprintf("%s/200", url), NoCheckCertificate: true}, &RuntimeConfig{}, nil)
measure = webClient.NewInstance().DoMeasure(false)

if measure.IsFailure || measure.StatusCode != 200 {
Expand Down
7 changes: 4 additions & 3 deletions app/webclientbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,12 @@ type webClientBuilderImpl struct {
runtimeConfig *RuntimeConfig
url *url.URL
resolver *resolver
logger ConsoleLogger
}

// NewWebClientBuilder builds a new instance of webClientImpl which will provides functions for Http-Ping
func NewWebClientBuilder(config *Config, runtimeConfig *RuntimeConfig) (WebClientBuilder, error) {
webClient := webClientBuilderImpl{config: config, runtimeConfig: runtimeConfig}
func NewWebClientBuilder(config *Config, runtimeConfig *RuntimeConfig, logger ConsoleLogger) (WebClientBuilder, error) {
webClient := webClientBuilderImpl{config: config, runtimeConfig: runtimeConfig, logger: logger}
parsedURL, err := url.Parse(config.Target)
if err != nil {
return nil, err
Expand All @@ -66,7 +67,7 @@ func (webClientBuilder *webClientBuilderImpl) GetURL() *url.URL {
}

func (webClientBuilder *webClientBuilderImpl) NewInstance() WebClient {
w, _ := newWebClient(webClientBuilder.config, webClientBuilder.runtimeConfig)
w, _ := newWebClient(webClientBuilder.config, webClientBuilder.runtimeConfig, webClientBuilder.logger)

w.url = webClientBuilder.url
w.updateConnTarget()
Expand Down
10 changes: 6 additions & 4 deletions app/webclientimpl.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type webClientImpl struct {
runtimeConfig *RuntimeConfig
url *url.URL
resolver *resolver
logger ConsoleLogger

writes int64
reads int64
Expand Down Expand Up @@ -69,7 +70,7 @@ func (webClient *webClientImpl) updateConnTarget() {

func newHttp2RoundTripper(config *Config, runtimeConfig *RuntimeConfig, w *webClientImpl) (http.RoundTripper, error) {

webClient := webClientImpl{config: config, runtimeConfig: runtimeConfig}
webClient := webClientImpl{config: config, runtimeConfig: runtimeConfig, logger: w.logger}
parsedURL, err := url.Parse(config.Target)
if err != nil {
return nil, err
Expand Down Expand Up @@ -144,8 +145,8 @@ func newTransport(config *Config, runtimeConfig *RuntimeConfig, w *webClientImpl
return newHttp2RoundTripper(config, runtimeConfig, w)
}

func newWebClient(config *Config, runtimeConfig *RuntimeConfig) (*webClientImpl, error) {
webClient := &webClientImpl{}
func newWebClient(config *Config, runtimeConfig *RuntimeConfig, logger ConsoleLogger) (*webClientImpl, error) {
webClient := &webClientImpl{logger: logger}

err := webClient.update(config, runtimeConfig)

Expand Down Expand Up @@ -267,7 +268,8 @@ func (webClient *webClientImpl) DoMeasure(followRedirect bool) *HTTPMeasure {
altSvcH3 := checkAltSvcH3Header(res.Header)

if !strings.HasPrefix(req.RequestURI, "http://") && altSvcH3 != nil && !strings.HasPrefix(res.Proto, "HTTP/3") && !webClient.config.Http1 && !webClient.config.Http2 {
_, _ = fmt.Printf(" ─→ server advertised HTTP/3 endpoint, using HTTP/3\n")

webClient.logger.Printf(" ─→ server advertised HTTP/3 endpoint, using HTTP/3\n")

return webClient.moveToHttp3(*altSvcH3, measureContext.timerRegistry, followRedirect)
}
Expand Down
9 changes: 4 additions & 5 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"fmt"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"io"
"math"
"net"
"net/http"
Expand Down Expand Up @@ -56,7 +55,7 @@ type extraConfig struct {
type runner struct {
config *app.Config
xp *extraConfig
appLogic func(config *app.Config, stdout io.Writer) (app.HTTPPing, error)
appLogic func(config *app.Config, consoleLogger app.ConsoleLogger) (app.HTTPPing, error)
cmd *cobra.Command
args []string
}
Expand All @@ -77,7 +76,7 @@ func (runner *runner) run() error {
}
}

instance, err := runner.appLogic(runner.config, runner.cmd.OutOrStdout())
instance, err := runner.appLogic(runner.config, app.NewConsoleCobraLogger(runner.cmd))
if err != nil {
return err
}
Expand Down Expand Up @@ -210,15 +209,15 @@ func splitPair(str string) (string, string, error) {
return "", "", fmt.Errorf("format should be \"key=value\", where key is a non-empty string of alphanumberic characters and value any string, illegal format: \"%s\"", str)
}

func runAndError(config *app.Config, xp *extraConfig, appLogic func(config *app.Config, stdout io.Writer) (app.HTTPPing, error)) func(cmd *cobra.Command, args []string) error {
func runAndError(config *app.Config, xp *extraConfig, appLogic func(config *app.Config, consoleLogger app.ConsoleLogger) (app.HTTPPing, error)) func(cmd *cobra.Command, args []string) error {

return func(cmd *cobra.Command, args []string) error {
r := runner{appLogic: appLogic, config: config, xp: xp, cmd: cmd, args: args}
return r.run()
}
}

func prepareRootCmd(appLogic func(config *app.Config, stdout io.Writer) (app.HTTPPing, error)) *cobra.Command {
func prepareRootCmd(appLogic func(config *app.Config, consoleLogger app.ConsoleLogger) (app.HTTPPing, error)) *cobra.Command {

var config = &app.Config{}

Expand Down
2 changes: 1 addition & 1 deletion cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func (httpPingMock *httpPingMock) Run() error {
return nil
}

func (httpPingMockBuilder *httpPingMockBuilder) newHTTPPingMock(config *app.Config, _ io.Writer) (app.HTTPPing, error) {
func (httpPingMockBuilder *httpPingMockBuilder) newHTTPPingMock(config *app.Config, _ app.ConsoleLogger) (app.HTTPPing, error) {
httpPingMockBuilder.config = config
return &httpPingMock{}, nil
}
Expand Down

0 comments on commit c146a16

Please sign in to comment.