Created
December 14, 2012 18:18
-
-
Save dustin/4287420 to your computer and use it in GitHub Desktop.
Based on phone home data, build an extrusion map.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "archive/zip" | |
| "flag" | |
| "log" | |
| "os" | |
| "text/template" | |
| "time" | |
| "code.google.com/p/dsallings-couch-go" | |
| "github.com/dustin/go-humanize" | |
| ) | |
| const kml_head = `<?xml version="1.0" encoding="UTF-8"?> | |
| <kml xmlns="http://www.opengis.net/kml/2.2"> | |
| <Document> | |
| <Style id="win"> | |
| <IconStyle><color>01ffffff</color><scale>1</scale></IconStyle> | |
| <LineStyle> | |
| <color>ffff0000</color> | |
| <colorMode>normal</colorMode> | |
| <width>2</width> | |
| </LineStyle> | |
| </Style> | |
| <Style id="lnx"> | |
| <IconStyle><color>01ffffff</color><scale>1</scale></IconStyle> | |
| <LineStyle> | |
| <color>ff00ff00</color> | |
| <colorMode>normal</colorMode> | |
| <width>2</width> | |
| </LineStyle> | |
| </Style> | |
| <Style id="mac"> | |
| <IconStyle><color>01ff00ff</color><scale>1</scale></IconStyle> | |
| <LineStyle> | |
| <color>ffff00ff</color> | |
| <colorMode>normal</colorMode> | |
| <width>2</width> | |
| </LineStyle> | |
| </Style> | |
| <Style id="sol"> | |
| <IconStyle><color>01ffffff</color><scale>1</scale></IconStyle> | |
| <LineStyle> | |
| <color>ff00ffff</color> | |
| <colorMode>normal</colorMode> | |
| <width>2</width> | |
| </LineStyle> | |
| </Style> | |
| <Style id="mixed"> | |
| <IconStyle><color>01ffffff</color><scale>1</scale></IconStyle> | |
| <LineStyle> | |
| <color>ff0000ff</color> | |
| <colorMode>normal</colorMode> | |
| <width>2</width> | |
| </LineStyle> | |
| </Style> | |
| ` | |
| const kml_point_source = `<Placemark> | |
| <visibility>1</visibility> | |
| <name>{{.NumNodes}} node {{.LongOS}} cluster</name> | |
| <description><![CDATA[First seen on {{.First}}. | |
| Has {{.PrettySize}} RAM | |
| over the whole cluster. Currently on version {{.Version}}.]]> | |
| </description> | |
| <styleUrl>#{{.OS}}</styleUrl> | |
| <Point> | |
| <extrude>1</extrude> | |
| <altitudeMode>relativeToGround</altitudeMode> | |
| <coordinates>{{.Longitude}},{{.Latitude}},{{.Altitude}}</coordinates> | |
| </Point> | |
| </Placemark> | |
| ` | |
| var kml_point = template.New("point") | |
| const kml_tail = `</Document></kml>` | |
| func init() { | |
| var err error | |
| kml_point, err = kml_point.Parse(kml_point_source) | |
| if err != nil { | |
| log.Panicf("Error parsing template: %v", err) | |
| } | |
| } | |
| type ResultRow struct { | |
| Value struct { | |
| RamMax int64 | |
| OS string | |
| NumNodes int | |
| First string | |
| Version string | |
| Longitude float64 | |
| Latitude float64 | |
| PrettySize string | |
| Altitude int | |
| LongOS string | |
| } | |
| } | |
| type Results struct { | |
| Rows []ResultRow | |
| } | |
| func maybefatal(msg string, err error) { | |
| if err != nil { | |
| log.Fatalf("%s: %v", msg, err) | |
| } | |
| } | |
| func lengthen(o string) string { | |
| switch o { | |
| case "lnx": | |
| o = "Linux" | |
| case "mac": | |
| o = "Mac" | |
| case "win": | |
| o = "Windows" | |
| } | |
| return o | |
| } | |
| func main() { | |
| dburl := flag.String("couch", "http://localhost:5984/cbstats", | |
| "Stats location.") | |
| filename := flag.String("kmz", "data.kmz", "File to create.") | |
| days := flag.Int("days", 30, "Number of days to include") | |
| minNodes := flag.Int("nodes", 3, | |
| "Minimum number of nodes a cluster must have") | |
| flag.Parse() | |
| d := time.Now().Add(time.Hour * -24 * time.Duration(*days)) | |
| startkey := d.Format("2006-01-02") | |
| db, err := couch.Connect(*dburl) | |
| if err != nil { | |
| log.Fatalf("Error connecting to couchdb: %v", err) | |
| } | |
| query_results := Results{} | |
| err = db.Query("_design/geo/_view/vitals", | |
| map[string]interface{}{"startkey": startkey}, | |
| &query_results) | |
| maybefatal("Error querying couchdb", err) | |
| f, err := os.Create(*filename + ".tmp") | |
| maybefatal("Error creating file", err) | |
| defer f.Close() | |
| z := zip.NewWriter(f) | |
| defer z.Close() | |
| dockml, err := z.Create("doc.kml") | |
| maybefatal("Error creating kml zip thing", err) | |
| dockml.Write([]byte(kml_head)) | |
| for _, r := range query_results.Rows { | |
| v := r.Value | |
| if v.NumNodes >= *minNodes { | |
| v.LongOS = lengthen(v.OS) | |
| v.PrettySize = humanize.Bytes(uint64(v.RamMax)) | |
| v.Altitude = v.NumNodes * 50000 | |
| kml_point.Execute(dockml, v) | |
| } | |
| } | |
| dockml.Write([]byte(kml_tail)) | |
| os.Rename(*filename+".tmp", *filename) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment