add logging

This commit is contained in:
decauwsemaecker.glen@gmail.com 2017-04-06 19:32:59 -05:00
parent 689360936b
commit f028e6bbc8
6 changed files with 47 additions and 17 deletions

View File

@ -2,6 +2,5 @@
TODO: TODO:
+ Decent Logging;
+ README Documentation; + README Documentation;
+ Unit-Tests; + Unit-Tests;

View File

@ -3,6 +3,7 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"log"
"os" "os"
"time" "time"
@ -11,8 +12,8 @@ import (
// CLI Flags // CLI Flags
var ( var (
timeout = flag.Duration("t", time.Second*2, "consensus's voting timeout") timeout = flag.Duration("t", time.Second*5, "consensus's voting timeout")
verbose = flag.Bool("v", false, "verbose logging") verbose = flag.Bool("v", false, "log errors to STDERR, when defined")
) )
func main() { func main() {
@ -22,11 +23,15 @@ func main() {
cfg.WithTimeout(*timeout) cfg.WithTimeout(*timeout)
} }
// TODO: Add Logging (and use the verbose flag) // optionally create the logger,
// if no logger is defined, all logs will be discarded.
var logger *log.Logger
if verbose != nil && *verbose {
logger = externalip.NewLogger(os.Stderr)
}
// create the consensus // create the consensus
consensus := externalip.DefaultConsensus( consensus := externalip.DefaultConsensus(cfg, logger)
externalip.DefaultConsensusConfig().WithTimeout(*timeout))
// retrieve the external ip // retrieve the external ip
ip, err := consensus.ExternalIP() ip, err := consensus.ExternalIP()

View File

@ -1,7 +1,7 @@
package externalip package externalip
import ( import (
"fmt" "log"
"net" "net"
"sync" "sync"
"time" "time"
@ -20,8 +20,8 @@ func DefaultConsensusConfig() *ConsensusConfig {
// with default and recommended HTTPSources. // with default and recommended HTTPSources.
// TLS-Protected providers get more power, // TLS-Protected providers get more power,
// compared to plain-text providers. // compared to plain-text providers.
func DefaultConsensus(cfg *ConsensusConfig) *Consensus { func DefaultConsensus(cfg *ConsensusConfig, logger *log.Logger) *Consensus {
consensus := NewConsensus(cfg) consensus := NewConsensus(cfg, logger)
// TLS-protected providers // TLS-protected providers
consensus.AddVoter(NewHTTPSource("https://icanhazip.com/"), 3) consensus.AddVoter(NewHTTPSource("https://icanhazip.com/"), 3)
@ -34,7 +34,6 @@ func DefaultConsensus(cfg *ConsensusConfig) *Consensus {
consensus.AddVoter(NewHTTPSource("http://whatismyip.akamai.com/"), 1) consensus.AddVoter(NewHTTPSource("http://whatismyip.akamai.com/"), 1)
consensus.AddVoter(NewHTTPSource("http://tnx.nl/ip"), 1) consensus.AddVoter(NewHTTPSource("http://tnx.nl/ip"), 1)
consensus.AddVoter(NewHTTPSource("http://myip.dnsomatic.com/"), 1) consensus.AddVoter(NewHTTPSource("http://myip.dnsomatic.com/"), 1)
consensus.AddVoter(NewHTTPSource("http://ipecho.net/plain"), 1)
consensus.AddVoter(NewHTTPSource("http://diagnostic.opendns.com/myip"), 1) consensus.AddVoter(NewHTTPSource("http://diagnostic.opendns.com/myip"), 1)
return consensus return consensus
@ -42,12 +41,16 @@ func DefaultConsensus(cfg *ConsensusConfig) *Consensus {
// NewConsensus creates a new Consensus, with no sources. // NewConsensus creates a new Consensus, with no sources.
// When the given cfg is <nil>, the `DefaultConsensusConfig` will be used. // When the given cfg is <nil>, the `DefaultConsensusConfig` will be used.
func NewConsensus(cfg *ConsensusConfig) *Consensus { func NewConsensus(cfg *ConsensusConfig, logger *log.Logger) *Consensus {
if cfg == nil { if cfg == nil {
cfg = DefaultConsensusConfig() cfg = DefaultConsensusConfig()
} }
if logger == nil {
logger = NewLogger(nil)
}
return &Consensus{ return &Consensus{
timeout: cfg.Timeout, timeout: cfg.Timeout,
logger: logger,
} }
} }
@ -70,6 +73,7 @@ func (cfg *ConsensusConfig) WithTimeout(timeout time.Duration) *ConsensusConfig
type Consensus struct { type Consensus struct {
voters []voter voters []voter
timeout time.Duration timeout time.Duration
logger *log.Logger
} }
// AddVoter adds a voter to this consensus. // AddVoter adds a voter to this consensus.
@ -103,7 +107,7 @@ func (c *Consensus) ExternalIP() (net.IP, error) {
wg.Add(1) wg.Add(1)
go func(v voter) { go func(v voter) {
defer wg.Done() defer wg.Done()
ip, err := v.source.IP(c.timeout) ip, err := v.source.IP(c.timeout, c.logger)
if err == nil && ip != nil { if err == nil && ip != nil {
vlock.Lock() vlock.Lock()
defer vlock.Unlock() defer vlock.Unlock()
@ -116,9 +120,6 @@ func (c *Consensus) ExternalIP() (net.IP, error) {
// or until the voting process times out // or until the voting process times out
select { select {
case <-waitWG(&wg): case <-waitWG(&wg):
fmt.Println("done!") // TODO: Log instead
case <-time.After(c.timeout):
fmt.Println("timeout!") // TODO: Log instead
} }
// if no votes were casted succesfully, // if no votes were casted succesfully,

18
log.go Normal file
View File

@ -0,0 +1,18 @@
package externalip
import (
"io"
"io/ioutil"
"log"
)
// NewLogger returns a new standard logger, with a given writer.
// if w is <nil>, all logs will be discarded.
func NewLogger(w io.Writer) *log.Logger {
if w == nil {
w = ioutil.Discard
}
return log.New(w, "",
log.Ldate|log.Ltime|log.Lmicroseconds|log.Llongfile|log.Lshortfile)
}

View File

@ -2,6 +2,7 @@ package externalip
import ( import (
"io/ioutil" "io/ioutil"
"log"
"net" "net"
"net/http" "net/http"
"strings" "strings"
@ -37,11 +38,12 @@ func (s *HTTPSource) WithParser(parser ContentParser) *HTTPSource {
} }
// IP implements Source.IP // IP implements Source.IP
func (s *HTTPSource) IP(timeout time.Duration) (net.IP, error) { func (s *HTTPSource) IP(timeout time.Duration, logger *log.Logger) (net.IP, error) {
// Define the GET method with the correct url, // Define the GET method with the correct url,
// setting the User-Agent to our library // setting the User-Agent to our library
req, err := http.NewRequest("GET", s.url, nil) req, err := http.NewRequest("GET", s.url, nil)
if err != nil { if err != nil {
logger.Printf("[ERROR] could not create a GET Request for %q: %v\n", s.url, err)
return nil, err return nil, err
} }
req.Header.Set("User-Agent", "go-external-ip (github.com/glendc/go-external-ip)") req.Header.Set("User-Agent", "go-external-ip (github.com/glendc/go-external-ip)")
@ -50,12 +52,14 @@ func (s *HTTPSource) IP(timeout time.Duration) (net.IP, error) {
// Do the request and read the body for non-error results. // Do the request and read the body for non-error results.
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
logger.Printf("[ERROR] could not GET %q: %v\n", s.url, err)
return nil, err return nil, err
} }
defer resp.Body.Close() defer resp.Body.Close()
bytes, err := ioutil.ReadAll(resp.Body) bytes, err := ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
logger.Printf("[ERROR] could not read response from %q: %v\n", s.url, err)
return nil, err return nil, err
} }
@ -64,6 +68,7 @@ func (s *HTTPSource) IP(timeout time.Duration) (net.IP, error) {
if s.parser != nil { if s.parser != nil {
raw, err = s.parser(raw) raw, err = s.parser(raw)
if err != nil { if err != nil {
logger.Printf("[ERROR] could not parse response from %q: %v\n", s.url, err)
return nil, err return nil, err
} }
} }
@ -71,6 +76,7 @@ func (s *HTTPSource) IP(timeout time.Duration) (net.IP, error) {
// validate the IP // validate the IP
externalIP := net.ParseIP(strings.TrimSpace(raw)) externalIP := net.ParseIP(strings.TrimSpace(raw))
if externalIP == nil { if externalIP == nil {
logger.Printf("[ERROR] %q returned an invalid IP: %v\n", s.url, err)
return nil, InvalidIPError(raw) return nil, InvalidIPError(raw)
} }

View File

@ -1,6 +1,7 @@
package externalip package externalip
import ( import (
"log"
"net" "net"
"time" "time"
) )
@ -11,7 +12,7 @@ type Source interface {
// net.IP should never be <nil> when error is <nil> // net.IP should never be <nil> when error is <nil>
// It is recommended that the IP function times out, // It is recommended that the IP function times out,
// if no result could be found, after the given timeout duration. // if no result could be found, after the given timeout duration.
IP(timeout time.Duration) (net.IP, error) IP(timeout time.Duration, logger *log.Logger) (net.IP, error)
} }
// voter adds weight to the IP given by a source. // voter adds weight to the IP given by a source.