Skip to content

Commit a8dd2cf

Browse files
authored
Merge pull request #369 from nicolai86/feature/introduce-logging-interface
Introduce Logger
2 parents e6795dc + 9308618 commit a8dd2cf

4 files changed

Lines changed: 126 additions & 108 deletions

File tree

pkg/api/api.go

Lines changed: 46 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@ import (
2323
"text/tabwriter"
2424
"text/template"
2525
"time"
26-
27-
log "github.com/Sirupsen/logrus"
28-
"github.com/moul/anonuuid"
29-
"github.com/moul/http2curl"
3026
)
3127

3228
// Default values
@@ -68,9 +64,11 @@ type ScalewayAPI struct {
6864
// Cache is used to quickly resolve identifiers from names
6965
Cache *ScalewayCache
7066

71-
client *http.Client
72-
anonuuid anonuuid.AnonUUID
73-
verbose bool
67+
client *http.Client
68+
verbose bool
69+
70+
//
71+
Logger
7472
}
7573

7674
// ScalewayAPIError represents a Scaleway API Error
@@ -93,30 +91,31 @@ type ScalewayAPIError struct {
9391

9492
// Error returns a string representing the error
9593
func (e ScalewayAPIError) Error() string {
96-
if e.Message != "" {
97-
return e.Message
98-
}
99-
if e.APIMessage != "" {
100-
return e.APIMessage
101-
}
102-
if e.StatusCode != 0 {
103-
return fmt.Sprintf("Invalid return code, got %d", e.StatusCode)
104-
}
105-
panic(e)
106-
}
107-
108-
// Debug create a debug log entry with HTTP error informations
109-
func (e ScalewayAPIError) Debug() {
110-
log.WithFields(log.Fields{
94+
var b bytes.Buffer
95+
for k, v := range map[string]interface{}{
11196
"StatusCode": e.StatusCode,
11297
"Type": e.Type,
11398
"Message": e.Message,
114-
}).Debug(e.APIMessage)
99+
"APIMessage": e.APIMessage,
100+
} {
101+
fmt.Fprintf(&b, " %-30s %s", fmt.Sprintf("%s: ", k), v)
102+
}
103+
return b.String()
104+
}
115105

116-
// error.Fields handling
117-
for k, v := range e.Fields {
118-
log.Debugf(" %-30s %s", fmt.Sprintf("%s: ", k), v)
106+
// HideAPICredentials removes API credentials from a string
107+
func (s *ScalewayAPI) HideAPICredentials(input string) string {
108+
output := input
109+
if s.Token != "" {
110+
output = strings.Replace(output, s.Token, "00000000-0000-4000-8000-000000000000", -1)
111+
}
112+
if s.Organization != "" {
113+
output = strings.Replace(output, s.Organization, "00000000-0000-5000-9000-000000000000", -1)
114+
}
115+
if s.password != "" {
116+
output = strings.Replace(output, s.password, "XX-XX-XX-XX", -1)
119117
}
118+
return output
120119
}
121120

122121
// ScalewayIPAddress represents a Scaleway IP address
@@ -832,7 +831,7 @@ type MarketImages struct {
832831
}
833832

834833
// NewScalewayAPI creates a ready-to-use ScalewayAPI client
835-
func NewScalewayAPI(organization, token, userAgent string) (*ScalewayAPI, error) {
834+
func NewScalewayAPI(organization, token, userAgent string, options ...func(*ScalewayAPI)) (*ScalewayAPI, error) {
836835
cache, err := NewScalewayCache()
837836
if err != nil {
838837
return nil, err
@@ -842,13 +841,16 @@ func NewScalewayAPI(organization, token, userAgent string) (*ScalewayAPI, error)
842841
Organization: organization,
843842
Token: token,
844843
Cache: cache,
844+
Logger: NewDefaultLogger(),
845845
verbose: os.Getenv("SCW_VERBOSE_API") != "",
846846
password: "",
847847
userAgent: userAgent,
848848

849849
// internal
850-
anonuuid: *anonuuid.New(),
851-
client: &http.Client{},
850+
client: &http.Client{},
851+
}
852+
for _, option := range options {
853+
option(s)
852854
}
853855

854856
if os.Getenv("SCW_TLSVERIFY") == "0" {
@@ -882,15 +884,8 @@ func (s *ScalewayAPI) GetResponse(apiURL, resource string) (*http.Response, erro
882884
req.Header.Set("Content-Type", "application/json")
883885
req.Header.Set("User-Agent", s.userAgent)
884886

885-
curl, err := http2curl.GetCurlCommand(req)
886-
if err != nil {
887-
return nil, err
888-
}
889-
if os.Getenv("SCW_SENSITIVE") != "1" {
890-
log.Debug(s.HideAPICredentials(curl.String()))
891-
} else {
892-
log.Debug(curl.String())
893-
}
887+
s.LogHTTP(req)
888+
894889
return s.client.Do(req)
895890
}
896891

@@ -911,15 +906,7 @@ func (s *ScalewayAPI) PostResponse(apiURL, resource string, data interface{}) (*
911906
req.Header.Set("Content-Type", "application/json")
912907
req.Header.Set("User-Agent", s.userAgent)
913908

914-
curl, err := http2curl.GetCurlCommand(req)
915-
if err != nil {
916-
return nil, err
917-
}
918-
if os.Getenv("SCW_SENSITIVE") != "1" {
919-
log.Debug(s.HideAPICredentials(curl.String()))
920-
} else {
921-
log.Debug(curl.String())
922-
}
909+
s.LogHTTP(req)
923910

924911
return s.client.Do(req)
925912
}
@@ -941,15 +928,7 @@ func (s *ScalewayAPI) PatchResponse(apiURL, resource string, data interface{}) (
941928
req.Header.Set("Content-Type", "application/json")
942929
req.Header.Set("User-Agent", s.userAgent)
943930

944-
curl, err := http2curl.GetCurlCommand(req)
945-
if err != nil {
946-
return nil, err
947-
}
948-
if os.Getenv("SCW_SENSITIVE") != "1" {
949-
log.Debug(s.HideAPICredentials(curl.String()))
950-
} else {
951-
log.Debug(curl.String())
952-
}
931+
s.LogHTTP(req)
953932

954933
return s.client.Do(req)
955934
}
@@ -971,15 +950,7 @@ func (s *ScalewayAPI) PutResponse(apiURL, resource string, data interface{}) (*h
971950
req.Header.Set("Content-Type", "application/json")
972951
req.Header.Set("User-Agent", s.userAgent)
973952

974-
curl, err := http2curl.GetCurlCommand(req)
975-
if err != nil {
976-
return nil, err
977-
}
978-
if os.Getenv("SCW_SENSITIVE") != "1" {
979-
log.Debug(s.HideAPICredentials(curl.String()))
980-
} else {
981-
log.Debug(curl.String())
982-
}
953+
s.LogHTTP(req)
983954

984955
return s.client.Do(req)
985956
}
@@ -996,15 +967,7 @@ func (s *ScalewayAPI) DeleteResponse(apiURL, resource string) (*http.Response, e
996967
req.Header.Set("Content-Type", "application/json")
997968
req.Header.Set("User-Agent", s.userAgent)
998969

999-
curl, err := http2curl.GetCurlCommand(req)
1000-
if err != nil {
1001-
return nil, err
1002-
}
1003-
if os.Getenv("SCW_SENSITIVE") != "1" {
1004-
log.Debug(s.HideAPICredentials(curl.String()))
1005-
} else {
1006-
log.Debug(curl.String())
1007-
}
970+
s.LogHTTP(req)
1008971

1009972
return s.client.Do(req)
1010973
}
@@ -1027,22 +990,21 @@ func (s *ScalewayAPI) handleHTTPError(goodStatusCode []int, resp *http.Response)
1027990
if !good {
1028991
var scwError ScalewayAPIError
1029992

1030-
err := json.Unmarshal(body, &scwError)
1031-
if err != nil {
993+
if err := json.Unmarshal(body, &scwError); err != nil {
1032994
return nil, err
1033995
}
1034996
scwError.StatusCode = resp.StatusCode
1035-
scwError.Debug()
997+
s.Debugf("%s", scwError.Error())
1036998
return nil, scwError
1037999
}
10381000
if s.verbose {
10391001
var js bytes.Buffer
10401002

10411003
err = json.Indent(&js, body, "", " ")
10421004
if err != nil {
1043-
log.Debug(string(body))
1005+
s.Debugf("%s", string(body))
10441006
} else {
1045-
log.Debug(js.String())
1007+
s.Debugf("%s", js.String())
10461008
}
10471009
}
10481010
return body, nil
@@ -1069,12 +1031,11 @@ func (s *ScalewayAPI) GetServers(all bool, limit int) (*[]ScalewayServer, error)
10691031
return nil, err
10701032
}
10711033

1072-
var servers ScalewayServers
1073-
10741034
body, err := s.handleHTTPError([]int{200}, resp)
10751035
if err != nil {
10761036
return nil, err
10771037
}
1038+
var servers ScalewayServers
10781039
if err = json.Unmarshal(body, &servers); err != nil {
10791040
return nil, err
10801041
}
@@ -1708,8 +1669,6 @@ func (s *ScalewayUserdata) String() string {
17081669

17091670
// GetUserdata gets a specific userdata for a server
17101671
func (s *ScalewayAPI) GetUserdata(serverID, key string, metadata bool) (*ScalewayUserdata, error) {
1711-
var data ScalewayUserdata
1712-
var err error
17131672
var url, endpoint string
17141673

17151674
endpoint = ComputeAPI
@@ -1720,6 +1679,7 @@ func (s *ScalewayAPI) GetUserdata(serverID, key string, metadata bool) (*Scalewa
17201679
url = fmt.Sprintf("servers/%s/user_data/%s", serverID, key)
17211680
}
17221681

1682+
var err error
17231683
resp, err := s.GetResponse(endpoint, url)
17241684
if resp != nil {
17251685
defer resp.Body.Close()
@@ -1731,6 +1691,7 @@ func (s *ScalewayAPI) GetUserdata(serverID, key string, metadata bool) (*Scalewa
17311691
if resp.StatusCode != 200 {
17321692
return nil, fmt.Errorf("no such user_data %q (%d)", key, resp.StatusCode)
17331693
}
1694+
var data ScalewayUserdata
17341695
data, err = ioutil.ReadAll(resp.Body)
17351696
return &data, err
17361697
}
@@ -1760,12 +1721,7 @@ func (s *ScalewayAPI) PatchUserdata(serverID, key string, value []byte, metadata
17601721
req.Header.Set("Content-Type", "text/plain")
17611722
req.Header.Set("User-Agent", s.userAgent)
17621723

1763-
curl, err := http2curl.GetCurlCommand(req)
1764-
if os.Getenv("SCW_SENSITIVE") != "1" {
1765-
log.Debug(s.HideAPICredentials(curl.String()))
1766-
} else {
1767-
log.Debug(curl.String())
1768-
}
1724+
s.LogHTTP(req)
17691725

17701726
resp, err := s.client.Do(req)
17711727
if resp != nil {
@@ -2420,7 +2376,7 @@ func (s *ScalewayAPI) GetQuotas() (*ScalewayGetQuotas, error) {
24202376
// GetBootscriptID returns exactly one bootscript matching
24212377
func (s *ScalewayAPI) GetBootscriptID(needle, arch string) (string, error) {
24222378
// Parses optional type prefix, i.e: "bootscript:name" -> "name"
2423-
if anonuuid.IsUUID(needle) == nil {
2379+
if len(strings.Split(needle, ":")) == 1 {
24242380
return needle, nil
24252381
}
24262382

@@ -2440,21 +2396,6 @@ func (s *ScalewayAPI) GetBootscriptID(needle, arch string) (string, error) {
24402396
return "", showResolverResults(needle, bootscripts)
24412397
}
24422398

2443-
// HideAPICredentials removes API credentials from a string
2444-
func (s *ScalewayAPI) HideAPICredentials(input string) string {
2445-
output := input
2446-
if s.Token != "" {
2447-
output = strings.Replace(output, s.Token, s.anonuuid.FakeUUID(s.Token), -1)
2448-
}
2449-
if s.Organization != "" {
2450-
output = strings.Replace(output, s.Organization, s.anonuuid.FakeUUID(s.Organization), -1)
2451-
}
2452-
if s.password != "" {
2453-
output = strings.Replace(output, s.password, "XX-XX-XX-XX", -1)
2454-
}
2455-
return output
2456-
}
2457-
24582399
func rootNetDial(network, addr string) (net.Conn, error) {
24592400
dialer := net.Dialer{
24602401
Timeout: 10 * time.Second,

pkg/api/api_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ func TestNewScalewayAPI(t *testing.T) {
1616
So(api.Organization, ShouldEqual, "my-organization")
1717
So(api.Cache, ShouldNotBeNil)
1818
So(api.client, ShouldNotBeNil)
19-
So(api.anonuuid, ShouldNotBeNil)
19+
So(api.Logger, ShouldNotBeNil)
2020
})
2121
}

pkg/api/logger.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// Copyright (C) 2015 Scaleway. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE.md file.
4+
5+
package api
6+
7+
import (
8+
"fmt"
9+
"log"
10+
"net/http"
11+
"os"
12+
)
13+
14+
// Logger handles logging concerns for the Scaleway API SDK
15+
type Logger interface {
16+
LogHTTP(*http.Request)
17+
Fatalf(format string, v ...interface{})
18+
Debugf(format string, v ...interface{})
19+
Infof(format string, v ...interface{})
20+
Warnf(format string, v ...interface{})
21+
}
22+
23+
// NewDefaultLogger returns a logger which is configured for stdout
24+
func NewDefaultLogger() Logger {
25+
return &defaultLogger{
26+
Logger: log.New(os.Stdout, "", log.LstdFlags),
27+
}
28+
}
29+
30+
type defaultLogger struct {
31+
*log.Logger
32+
}
33+
34+
func (l *defaultLogger) LogHTTP(r *http.Request) {
35+
l.Printf("%s %s\n", r.Method, r.URL.RawPath)
36+
}
37+
func (l *defaultLogger) Fatalf(format string, v ...interface{}) {
38+
l.Printf("[FATAL] %s\n", fmt.Sprintf(format, v))
39+
os.Exit(1)
40+
}
41+
func (l *defaultLogger) Debugf(format string, v ...interface{}) {
42+
l.Printf("[DEBUG] %s\n", fmt.Sprintf(format, v))
43+
}
44+
func (l *defaultLogger) Infof(format string, v ...interface{}) {
45+
l.Printf("[INFO ] %s\n", fmt.Sprintf(format, v))
46+
}
47+
func (l *defaultLogger) Warnf(format string, v ...interface{}) {
48+
l.Printf("[WARN ] %s\n", fmt.Sprintf(format, v))
49+
}

0 commit comments

Comments
 (0)