add logging
This commit is contained in:
parent
689360936b
commit
f028e6bbc8
@ -2,6 +2,5 @@
|
|||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
|
|
||||||
+ Decent Logging;
|
|
||||||
+ README Documentation;
|
+ README Documentation;
|
||||||
+ Unit-Tests;
|
+ Unit-Tests;
|
||||||
|
@ -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()
|
||||||
|
19
consensus.go
19
consensus.go
@ -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
18
log.go
Normal 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)
|
||||||
|
}
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
types.go
3
types.go
@ -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.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user