From be0704451ac0280831585db256905250c445e940 Mon Sep 17 00:00:00 2001 From: Knut Ahlers Date: Mon, 5 Jun 2017 17:23:52 +0200 Subject: [PATCH] Improve logging, fix tagging error Signed-off-by: Knut Ahlers --- main.go | 42 ++++++++++++++++++------------ osm/osm.go | 76 ++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 88 insertions(+), 30 deletions(-) diff --git a/main.go b/main.go index 1780c38..3382f7c 100644 --- a/main.go +++ b/main.go @@ -3,7 +3,6 @@ package main import ( "errors" "fmt" - "log" "os" "strconv" @@ -11,13 +10,15 @@ import ( "github.com/Luzifer/gpxhydrant/gpx" "github.com/Luzifer/gpxhydrant/osm" "github.com/Luzifer/rconfig" + log "github.com/Sirupsen/logrus" ) var ( cfg = struct { Comment string `flag:"comment,c" default:"Added hydrants from GPX file" description:"Comment for the changeset"` - Debug bool `flag:"debug,d" default:"false" description:"Enable debug logging"` + Debug bool `flag:"debug,d" default:"false" description:"Enable debug logging (Deprecated: Use --log-level=debug)"` GPXFile string `flag:"gpx-file,f" description:"File containing GPX waypoints"` + LogLevel string `flag:"log-level" default:"info" description:"Log level (debug, info, warn, error)"` MachRange int64 `flag:"match-range" default:"5" description:"Range of meters to match GPX hydrants to OSM nodes"` NoOp bool `flag:"noop,n" default:"false" description:"Fetch data from OSM but do not write"` OSM struct { @@ -60,6 +61,17 @@ func init() { os.Exit(0) } + if l, err := log.ParseLevel(cfg.LogLevel); err == nil { + log.SetLevel(l) + } else { + log.Fatalf("Unable to parse log level: %s", err) + } + + // Support deprecated parameter to overwrite log level + if cfg.Debug { + log.SetLevel(log.DebugLevel) + } + if cfg.GPXFile == "" { log.Fatalf("gpx-file is a required parameter") } @@ -69,12 +81,6 @@ func init() { } } -func logDebugf(format string, values ...interface{}) { - if cfg.Debug { - log.Printf(format, values...) - } -} - func hydrantsFromGPXFile() ([]*hydrant, bounds) { // Read and parse GPX file gpsFile, err := os.Open(cfg.GPXFile) @@ -94,12 +100,12 @@ func hydrantsFromGPXFile() ([]*hydrant, bounds) { for _, wp := range gpxData.Waypoints { h, e := parseWaypoint(wp) if e != nil { - if cfg.Debug || e != errWrongGPXComment { - log.Printf("Found waypoint not suitable for converting: %s (Reason: %s)", wp.Name, e) + if e != errWrongGPXComment { + log.Debugf("Found waypoint not suitable for converting: %s (Reason: %s)", wp.Name, e) } continue } - logDebugf("Found a hydrant from waypoint %s: %#v", wp.Name, h) + log.Debugf("Found a hydrant from waypoint %s: %#v", wp.Name, h) hydrants = append(hydrants, h) bds.Update(h.Latitude, h.Longitude) @@ -118,10 +124,10 @@ func createChangeset(osmClient *osm.Client) *osm.Changeset { log.Fatalf("Unable to create changeset: %s", err) } - logDebugf("Working on Changeset %d", cs.ID) + log.Debugf("Working on Changeset %d", cs.ID) cs.Tags = []osm.Tag{ - {Key: "comment", Value: cfg.Comment}, + //{Key: "comment", Value: cfg.Comment}, {Key: "created_by", Value: fmt.Sprintf("gpxhydrant %s", version)}, } @@ -141,7 +147,7 @@ func getHydrantsFromOSM(osmClient *osm.Client, bds bounds) []*hydrant { log.Fatalf("Unable to get map data: %s", err) } - logDebugf("Retrieved %d nodes from map", len(mapData.Nodes)) + log.Debugf("Retrieved %d nodes from map", len(mapData.Nodes)) availableHydrants := []*hydrant{} for _, n := range mapData.Nodes { @@ -165,6 +171,8 @@ func main() { log.Fatalf("Unable to log into OSM: %s", err) } + osmClient.DebugHTTPRequests = log.GetLevel() == log.DebugLevel + // Retrieve currently available information from OSM availableHydrants := getHydrantsFromOSM(osmClient, bds) @@ -189,7 +197,7 @@ func updateOrCreateHydrants(hydrants, availableHydrants []*hydrant, osmClient *o if err := osmClient.SaveNode(h.ToNode(), createChangeset(osmClient)); err != nil { log.Fatalf("Unable to create node using the OSM API: %s", err) } - logDebugf("Created a hydrant: %s", h.Name) + log.Debugf("Created a hydrant: %s", h.Name) }, ) continue @@ -201,7 +209,7 @@ func updateOrCreateHydrants(hydrants, availableHydrants []*hydrant, osmClient *o } if !found.NeedsUpdate(h) { - logDebugf("Found a good looking hydrant which needs no update: %#v", h) + log.Debugf("Found a good looking hydrant which needs no update: %#v", h) // Everything matches, we don't care continue } @@ -214,7 +222,7 @@ func updateOrCreateHydrants(hydrants, availableHydrants []*hydrant, osmClient *o if err := osmClient.SaveNode(h.ToNode(), createChangeset(osmClient)); err != nil { log.Fatalf("Unable to create node using the OSM API: %s", err) } - logDebugf("Changed a hydrant: %s", h.Name) + log.Debugf("Changed a hydrant: %s", h.Name) }, ) } diff --git a/osm/osm.go b/osm/osm.go index d1c3cd6..82aecbd 100644 --- a/osm/osm.go +++ b/osm/osm.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "io/ioutil" + "math" "net/http" "strconv" "time" @@ -24,6 +25,8 @@ type Client struct { APIBaseURL string HTTPClient *http.Client CurrentUser *User + + DebugHTTPRequests bool } // New instantiates a new client and retrieves information about the current user. Set useDevServer to true to change the API URL to the api06.dev.openstreetmap.org server. @@ -34,6 +37,8 @@ func New(username, password string, useDevServer bool) (*Client, error) { APIBaseURL: liveAPIBaseURL, HTTPClient: http.DefaultClient, + + DebugHTTPRequests: false, } if useDevServer { @@ -65,25 +70,58 @@ func (c *Client) doPlain(method, path string, body io.Reader) (string, error) { } func (c *Client) do(method, path string, body io.Reader) (io.ReadCloser, error) { + var reqBodyBuffer *bytes.Buffer = nil + if body != nil { + reqBodyBuffer = bytes.NewBufferString("") + io.Copy(reqBodyBuffer, body) + + body = bytes.NewBuffer(reqBodyBuffer.Bytes()) + } + req, _ := http.NewRequest(method, c.APIBaseURL+path, body) req.SetBasicAuth(c.username, c.password) + if method != "GET" { + req.Header.Set("Content-Type", "text/xml; charset=utf-8") + } + res, err := c.HTTPClient.Do(req) if err != nil { return nil, err } - if res.StatusCode != http.StatusOK { - d, e := ioutil.ReadAll(res.Body) - if e != nil { - return nil, fmt.Errorf("OSM API responded with status code %d and reading response failed", res.StatusCode) + resBody := bytes.NewBufferString("") + io.Copy(resBody, res.Body) + + if c.DebugHTTPRequests { + buf := bytes.NewBufferString("") + fmt.Fprintf(buf, "---------- REQUEST ----------\n") + fmt.Fprintf(buf, "%s %s\n", method, req.URL.String()) + for k, v := range req.Header { + fmt.Fprintf(buf, "%s: %s\n", k, v[0]) + } + fmt.Fprintf(buf, "\n") + if reqBodyBuffer != nil { + trunc := int(math.Min(float64(reqBodyBuffer.Len()), 1024)) + fmt.Fprintf(buf, "%s\n\n", reqBodyBuffer.String()[0:trunc]) } - res.Body.Close() - return nil, fmt.Errorf("OSM API responded with status code %d (%s)", res.StatusCode, d) + fmt.Fprintf(buf, "---------- RESPONSE ----------\n") + for k, v := range res.Header { + fmt.Fprintf(buf, "%s: %s\n", k, v[0]) + } + fmt.Fprintf(buf, "\n") + trunc := int(math.Min(float64(resBody.Len()), 1024)) + fmt.Fprintf(buf, "%s\n", resBody.String()[0:trunc]) + + fmt.Println(buf.String()) } - return res.Body, nil + if res.StatusCode != http.StatusOK { + return nil, fmt.Errorf("OSM API responded with status code %d", res.StatusCode) + } + + return ioutil.NopCloser(resBody), nil } func (c *Client) doParse(method, path string, body io.Reader, output interface{}) error { @@ -137,8 +175,12 @@ func (c *Client) GetMyChangesets(onlyOpen bool) ([]*Changeset, error) { // CreateChangeset creates a new changeset func (c *Client) CreateChangeset() (*Changeset, error) { - body := bytes.NewBuffer([]byte{}) - if err := xml.NewEncoder(body).Encode(Wrap{Changesets: []*Changeset{{}}}); err != nil { + body := bytes.NewBufferString(xml.Header) + + enc := xml.NewEncoder(body) + enc.Indent("", " ") + + if err := enc.Encode(Wrap{Changesets: []*Changeset{{}}}); err != nil { return nil, err } @@ -169,8 +211,12 @@ func (c *Client) SaveChangeset(cs *Changeset) error { data := Wrap{Changesets: []*Changeset{cs}} - body := bytes.NewBuffer([]byte{}) - if err := xml.NewEncoder(body).Encode(data); err != nil { + body := bytes.NewBufferString(xml.Header) + + enc := xml.NewEncoder(body) + enc.Indent("", " ") + + if err := enc.Encode(data); err != nil { return err } @@ -225,8 +271,12 @@ func (c *Client) SaveNode(n *Node, cs *Changeset) error { data := Wrap{Nodes: []*Node{n}} - body := bytes.NewBuffer([]byte{}) - if err := xml.NewEncoder(body).Encode(data); err != nil { + body := bytes.NewBufferString(xml.Header) + + enc := xml.NewEncoder(body) + enc.Indent("", " ") + + if err := enc.Encode(data); err != nil { return err }