From a7c1de0e23f15f8f42749d1e8e121cb0041e7bef Mon Sep 17 00:00:00 2001 From: Anton Novojilov Date: Sun, 12 Jun 2016 18:37:21 -0400 Subject: [PATCH 01/12] Version 2 --- changelog.md | 7 +++ examples/basic_example.go | 49 ++++++++++++++++++++ examples/collector_example.go | 52 ++++++++++++++++++++++ librato.go | 84 ++++++++++++++++++++--------------- 4 files changed, 156 insertions(+), 36 deletions(-) create mode 100644 examples/basic_example.go create mode 100644 examples/collector_example.go diff --git a/changelog.md b/changelog.md index 47874b4..837fc6f 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,12 @@ ## Changelog +#### v2.0.0 + +* Added usage examples +* Using values instead pointers for measurements (gauge/counter) structs +* Now `librato.AddMetrics` supports sending many metrics at once +* Code refactoring + #### v1.2.1 * Added pkg.re usage diff --git a/examples/basic_example.go b/examples/basic_example.go new file mode 100644 index 0000000..7a5eefa --- /dev/null +++ b/examples/basic_example.go @@ -0,0 +1,49 @@ +package main + +// ////////////////////////////////////////////////////////////////////////////////// // + +import ( + "fmt" + "time" + + "pkg.re/essentialkaos/ek.v1/rand" + + "github.com/essentialkaos/librato" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + +func main() { + librato.Mail = "mail@domain.com" + librato.Token = "abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234" + + for { + errs := librato.AddMetric( + librato.Gauge{ + Name: "example:gauge_1", + Value: rand.Int(1000), + }, + librato.Gauge{ + Name: "example:gauge_2", + Value: float64(rand.Int(1000)) / float64(rand.Int(20)), + Source: "go_librato_example", + }, + librato.Counter{ + Name: "example:counter_1", + Value: rand.Int(1000), + }, + ) + + if len(errs) != 0 { + fmt.Println("Errors:") + + for _, err := range errs { + fmt.Printf(" %v\n", err) + } + } else { + fmt.Println("Data sended to Librato Metrics") + } + + time.Sleep(time.Minute) + } +} diff --git a/examples/collector_example.go b/examples/collector_example.go new file mode 100644 index 0000000..db158c2 --- /dev/null +++ b/examples/collector_example.go @@ -0,0 +1,52 @@ +package main + +// ////////////////////////////////////////////////////////////////////////////////// // + +import ( + "fmt" + "time" + + "pkg.re/essentialkaos/ek.v1/rand" + + "github.com/essentialkaos/librato" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + +func main() { + librato.Mail = "mail@domain.com" + librato.Token = "abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234" + + collector := librato.NewCollector(time.Minute, collectSomeMetrics) + collector.ErrorHandler = errorHandler + + for { + time.Sleep(time.Hour) + } +} + +func collectSomeMetrics() []librato.Measurement { + return []librato.Measurement{ + librato.Gauge{ + Name: "example:gauge_1", + Value: rand.Int(1000), + }, + librato.Gauge{ + Name: "example:gauge_2", + Value: float64(rand.Int(1000)) / float64(rand.Int(20)), + Source: "go_librato_example", + }, + librato.Counter{ + Name: "example:counter_1", + Value: rand.Int(1000), + }, + } +} + +func errorHandler(errs []error) { + fmt.Println("Errors:") + + for _, err := range errs { + fmt.Printf(" %v\n", err) + } +} diff --git a/librato.go b/librato.go index 51adf06..5af01f0 100644 --- a/librato.go +++ b/librato.go @@ -23,7 +23,7 @@ import ( // ////////////////////////////////////////////////////////////////////////////////// // // VERSION contains current version of librato package and used as part of User-Agent -const VERSION = "1.2.1" +const VERSION = "2.0.0" // ////////////////////////////////////////////////////////////////////////////////// // @@ -187,9 +187,9 @@ type Annotation struct { // ////////////////////////////////////////////////////////////////////////////////// // -type mesData struct { - Gauges []*Gauge `json:"gauges,omitempty"` - Counters []*Counter `json:"counters,omitempty"` +type measurements struct { + Gauges []Gauge `json:"gauges,omitempty"` + Counters []Counter `json:"counters,omitempty"` } type paramsErrorMap struct { @@ -241,9 +241,9 @@ func NewMetrics(period time.Duration, maxQueueSize int) (*Metrics, error) { metrics := &Metrics{ maxQueueSize: maxQueueSize, period: period, - lastSendingDate: -1, initialized: true, queue: make([]Measurement, 0), + lastSendingDate: -1, } err := validateMetrics(metrics) @@ -266,8 +266,8 @@ func NewMetrics(period time.Duration, maxQueueSize int) (*Metrics, error) { func NewCollector(period time.Duration, collectFunc func() []Measurement) *Collector { collector := &Collector{ period: period, - lastSendingDate: -1, collectFunc: collectFunc, + lastSendingDate: -1, } if sources == nil { @@ -281,28 +281,38 @@ func NewCollector(period time.Duration, collectFunc func() []Measurement) *Colle } // AddMetric synchronously send metric to librato -func AddMetric(m Measurement) []error { - err := m.Validate() +func AddMetric(m ...Measurement) []error { + data := &measurements{} - if err != nil { - return []error{err} + var errs []error + + for _, metric := range m { + err := metric.Validate() + + if err != nil { + errs = append(errs, err) + } } - data := &mesData{} + if len(errs) != 0 { + return errs + } - switch m.(type) { - case *Gauge: - data.Gauges = append(data.Gauges, m.(*Gauge)) + for _, metric := range m { + switch metric.(type) { + case Gauge: + data.Gauges = append(data.Gauges, metric.(Gauge)) - case *Counter: - data.Counters = append(data.Counters, m.(*Counter)) + case Counter: + data.Counters = append(data.Counters, metric.(Counter)) + } } return execRequest(req.POST, APIEndpoint+"/v1/metrics/", data) } // AddAnnotation synchronously send annotation to librato -func AddAnnotation(stream string, a *Annotation) []error { +func AddAnnotation(stream string, a Annotation) []error { if stream == "" { return []error{errors.New("Stream name can't be empty")} } @@ -328,7 +338,7 @@ func DeleteAnnotations(stream string) []error { // ////////////////////////////////////////////////////////////////////////////////// // // Add adds gauge to sending queue -func (mt *Metrics) Add(m Measurement) error { +func (mt *Metrics) Add(m ...Measurement) error { var err error err = validateMetrics(mt) @@ -337,13 +347,15 @@ func (mt *Metrics) Add(m Measurement) error { return err } - err = m.Validate() + for _, metric := range m { + err = metric.Validate() - if err != nil { - return err + if err != nil { + return err + } } - mt.queue = append(mt.queue, m) + mt.queue = append(mt.queue, m...) if len(mt.queue) >= mt.maxQueueSize { mt.Send() @@ -391,7 +403,7 @@ func (cl *Collector) Send() []error { ms := cl.collectFunc() - if ms == nil || len(ms) == 0 { + if len(ms) == 0 { return []error{} } @@ -408,12 +420,12 @@ func (cl *Collector) Send() []error { // ////////////////////////////////////////////////////////////////////////////////// // // Validate validates gauge struct -func (g *Gauge) Validate() error { +func (g Gauge) Validate() error { return validateGauge(g) } // Validate validates gauge struct -func (c *Counter) Validate() error { +func (c Counter) Validate() error { return validateCounter(c) } @@ -488,19 +500,19 @@ func sendingLoop() { // convertMeasurementSlice convert slice with measurements to struct // with counters and gauges slices -func convertMeasurementSlice(queue []Measurement) *mesData { - result := &mesData{} +func convertMeasurementSlice(queue []Measurement) *measurements { + result := &measurements{} now := time.Now().Unix() for _, m := range queue { switch m.(type) { - case *Gauge: + case Gauge: if result.Gauges == nil { - result.Gauges = make([]*Gauge, 0) + result.Gauges = make([]Gauge, 0) } - gauge := m.(*Gauge) + gauge := m.(Gauge) if gauge.MeasureTime != 0 { gauge.MeasureTime = now @@ -508,12 +520,12 @@ func convertMeasurementSlice(queue []Measurement) *mesData { result.Gauges = append(result.Gauges, gauge) - case *Counter: + case Counter: if result.Counters == nil { - result.Counters = make([]*Counter, 0) + result.Counters = make([]Counter, 0) } - counter := m.(*Counter) + counter := m.(Counter) if counter.MeasureTime != 0 { counter.MeasureTime = now @@ -570,7 +582,7 @@ func validateMetrics(m *Metrics) error { } // validateCounter validate counter struct -func validateCounter(c *Counter) error { +func validateCounter(c Counter) error { if c.Name == "" { return errors.New("Counter property Name can't be empty") } @@ -589,7 +601,7 @@ func validateCounter(c *Counter) error { } // validateGauge validate gauge struct -func validateGauge(g *Gauge) error { +func validateGauge(g Gauge) error { if g.Name == "" { return errors.New("Gauge property Name can't be empty") } @@ -638,7 +650,7 @@ func validateGauge(g *Gauge) error { } // validateAnotation validate annotation struct -func validateAnotation(a *Annotation) error { +func validateAnotation(a Annotation) error { if a.Title == "" { return errors.New("Annotation property Title can't be empty") } From 7fe35ca41dd2ee3fbc0f23a4508bb5fe82ee6475 Mon Sep 17 00:00:00 2001 From: Anton Novojilov Date: Mon, 13 Jun 2016 06:21:23 -0400 Subject: [PATCH 02/12] Updated readme --- readme.md | 105 ++---------------------------------------------------- 1 file changed, 2 insertions(+), 103 deletions(-) diff --git a/readme.md b/readme.md index 0acff3d..3e2d62b 100644 --- a/readme.md +++ b/readme.md @@ -1,118 +1,17 @@ -### Librato [![GoDoc](https://godoc.org/pkg.re/essentialkaos/librato.v1?status.svg)](https://godoc.org/pkg.re/essentialkaos/librato.v1) +### Librato [![GoDoc](https://godoc.org/pkg.re/essentialkaos/librato.v2?status.svg)](https://godoc.org/pkg.re/essentialkaos/librato.v2) Package for working with [Librato Metrics](https://www.librato.com) API from go code. #### Installation ```` -go get pkg.re/essentialkaos/librato.v1 +go get pkg.re/essentialkaos/librato.v2 ```` #### Status This package is unnder heavy construction, please do not use in production code. -#### Example - -```Go -package main - -// ////////////////////////////////////////////////////////////////////////////////// // - -import ( - "os" - "time" - - "pkg.re/essentialkaos/librato.v1" -) - -// ////////////////////////////////////////////////////////////////////////////////// // - -func main() { - - // Set auth credentials which will be used for all actions - librato.Mail = "mail@domain.com" - librato.Token = "mysupertokenhere" - - var errs []error - - // Add annotation to service:annotation stream - errs = librato.AddAnnotation("service:annotation", - &librato.Annotation{ - Title: "Deploy v31", - Source: "server123", - Desc: "Revision: abcd1234", - Links: []string{ - "https://build-service.com/build/31", - "https://git-repo.com/commit/abcd1234", - }, - }, - ) - - // Exit with 1 if we have errors - if len(errs) != 0 { - os.Exit(1) - } - - // Delete stream service:annotation with all annotations - errs = librato.DeleteAnnotations("service:annotation") - - if len(errs) != 0 { - os.Exit(1) - } - - // Add counter - errs = librato.AddMetric( - &librato.Counter{ - Name: "service:random1", - Value: 345, - }, - ) - - if len(errs) != 0 { - os.Exit(1) - } - - // Add gauge - errs = librato.AddMetric( - &librato.Gauge{ - Name: "service:random2", - Value: 45.2, - }, - ) - - if len(errs) != 0 { - os.Exit(1) - } - - // Create struct for async sending metrics data - // With this preferences metrics will be sended to Librato once - // a minute or if queue size reached 60 elements - metrics, err := librato.NewMetrics(time.Minute, 60) - - if err != nil { - os.Exit(1) - } - - metrics.Add( - &librato.Counter{ - Name: "service:random1", - Value: 345, - }, - ) - - metrics.Add( - &librato.Gauge{ - Name: "service:random2", - Value: 45.2, - }, - ) - - // Force sending metrics before exit - metrics.Send() -} -``` - #### License [EKOL](https://essentialkaos.com/ekol) From 75a522eb8e7f2643a9cf5bada246434bfe7f5658 Mon Sep 17 00:00:00 2001 From: Anton Novojilov Date: Mon, 13 Jun 2016 06:23:23 -0400 Subject: [PATCH 03/12] Updated readme --- readme.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/readme.md b/readme.md index 3e2d62b..bca2a16 100644 --- a/readme.md +++ b/readme.md @@ -1,17 +1,17 @@ -### Librato [![GoDoc](https://godoc.org/pkg.re/essentialkaos/librato.v2?status.svg)](https://godoc.org/pkg.re/essentialkaos/librato.v2) +## Librato [![GoDoc](https://godoc.org/pkg.re/essentialkaos/librato.v2?status.svg)](https://godoc.org/pkg.re/essentialkaos/librato.v2) Package for working with [Librato Metrics](https://www.librato.com) API from go code. -#### Installation +### Installation ```` go get pkg.re/essentialkaos/librato.v2 ```` -#### Status +### Status This package is unnder heavy construction, please do not use in production code. -#### License +### License [EKOL](https://essentialkaos.com/ekol) From 4474188b550c2395103bb8de1dda0836123c5fb7 Mon Sep 17 00:00:00 2001 From: Anton Novojilov Date: Mon, 13 Jun 2016 06:24:42 -0400 Subject: [PATCH 04/12] Improved collector example --- examples/collector_example.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/collector_example.go b/examples/collector_example.go index db158c2..f8da514 100644 --- a/examples/collector_example.go +++ b/examples/collector_example.go @@ -26,6 +26,8 @@ func main() { } func collectSomeMetrics() []librato.Measurement { + fmt.Println("Metrics collected") + return []librato.Measurement{ librato.Gauge{ Name: "example:gauge_1", From 9f6b946082f04a0b5a60b2d10e97bc6a9b53df05 Mon Sep 17 00:00:00 2001 From: Anton Novojilov Date: Mon, 13 Jun 2016 06:36:58 -0400 Subject: [PATCH 05/12] More examples added --- examples/annotations_example.go | 55 +++++++++++++++++++++++++++++++++ examples/async_example.go | 51 ++++++++++++++++++++++++++++++ readme.md | 7 +++++ 3 files changed, 113 insertions(+) create mode 100644 examples/annotations_example.go create mode 100644 examples/async_example.go diff --git a/examples/annotations_example.go b/examples/annotations_example.go new file mode 100644 index 0000000..c5fe9e7 --- /dev/null +++ b/examples/annotations_example.go @@ -0,0 +1,55 @@ +package main + +// ////////////////////////////////////////////////////////////////////////////////// // + +import ( + "fmt" + "time" + + "github.com/essentialkaos/librato" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + +func main() { + librato.Mail = "mail@domain.com" + librato.Token = "abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234" + + // Add annotation to example:annotation_1 stream + errs := librato.AddAnnotation("example:annotation_1", + librato.Annotation{ + Title: "Deploy v31", + Source: "server123", + Desc: "Revision: abcd1234", + Links: []string{ + "https://build-service.com/build/31", + "https://git-repo.com/commit/abcd1234", + }, + }, + ) + + if len(errs) != 0 { + fmt.Println("Errors:") + + for _, err := range errs { + fmt.Printf(" %v\n", err) + } + } else { + fmt.Println("Annotation added") + } + + time.Sleep(time.Minute) + + // Delete stream example:annotation_1 with all annotations + errs = librato.DeleteAnnotations("example:annotation_1") + + if len(errs) != 0 { + fmt.Println("Errors:") + + for _, err := range errs { + fmt.Printf(" %v\n", err) + } + } else { + fmt.Println("Annotation deleted") + } +} diff --git a/examples/async_example.go b/examples/async_example.go new file mode 100644 index 0000000..4b98fc9 --- /dev/null +++ b/examples/async_example.go @@ -0,0 +1,51 @@ +package main + +// ////////////////////////////////////////////////////////////////////////////////// // + +import ( + "fmt" + "time" + + "pkg.re/essentialkaos/ek.v1/rand" + + "github.com/essentialkaos/librato" +) + +// ////////////////////////////////////////////////////////////////////////////////// // + +func main() { + librato.Mail = "mail@domain.com" + librato.Token = "abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234" + + // Create struct for async sending metrics data + // With this preferences metrics will be sended to Librato once + // a minute or if queue size reached 60 elements + metrics, err := librato.NewMetrics(time.Minute, 60) + + if err != nil { + fmt.Printf("Error: %v\n", err) + return + } + + for { + metrics.Add( + librato.Gauge{ + Name: "example:gauge_1", + Value: rand.Int(1000), + }, + ) + + // Force sending metrics before exit + errs := metrics.Send() + + if len(errs) != 0 { + fmt.Println("Errors:") + + for _, err := range errs { + fmt.Printf(" %v\n", err) + } + } + + time.Sleep(15 * time.Second) + } +} diff --git a/readme.md b/readme.md index bca2a16..6656537 100644 --- a/readme.md +++ b/readme.md @@ -8,6 +8,13 @@ Package for working with [Librato Metrics](https://www.librato.com) API from go go get pkg.re/essentialkaos/librato.v2 ```` +### Examples + +* [Basic Usage](examples/basic_example.go) +* [Metrics Collector](examples/collector_example.go) +* [Async Sending](examples/async_example.go) +* [Annotations](examples/annotations_example.go) + ### Status This package is unnder heavy construction, please do not use in production code. From 31b3d219046c055937c3e7a8726e583528fd9b31 Mon Sep 17 00:00:00 2001 From: Anton Novojilov Date: Mon, 13 Jun 2016 06:38:23 -0400 Subject: [PATCH 06/12] Fixed async example --- examples/async_example.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/examples/async_example.go b/examples/async_example.go index 4b98fc9..38d22e5 100644 --- a/examples/async_example.go +++ b/examples/async_example.go @@ -35,17 +35,6 @@ func main() { }, ) - // Force sending metrics before exit - errs := metrics.Send() - - if len(errs) != 0 { - fmt.Println("Errors:") - - for _, err := range errs { - fmt.Printf(" %v\n", err) - } - } - time.Sleep(15 * time.Second) } } From 65ad1bed2a05dff7252ea9a056d15f1d0a071c86 Mon Sep 17 00:00:00 2001 From: Anton Novojilov Date: Mon, 13 Jun 2016 06:39:18 -0400 Subject: [PATCH 07/12] Readme updated --- readme.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/readme.md b/readme.md index 6656537..741a32a 100644 --- a/readme.md +++ b/readme.md @@ -15,10 +15,6 @@ go get pkg.re/essentialkaos/librato.v2 * [Async Sending](examples/async_example.go) * [Annotations](examples/annotations_example.go) -### Status - -This package is unnder heavy construction, please do not use in production code. - ### License [EKOL](https://essentialkaos.com/ekol) From 133a69ea0cdf7ef24c2dd69222c01afc060ee19d Mon Sep 17 00:00:00 2001 From: Anton Novojilov Date: Mon, 13 Jun 2016 07:29:39 -0400 Subject: [PATCH 08/12] Added TravisCI config --- .travis.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..0173fce --- /dev/null +++ b/.travis.yml @@ -0,0 +1,19 @@ +language: go + +go: + - 1.6.2 + - tip + +sudo: false + +os: + - linux + +before_install: + - go get pkg.re/essentialkaos/ek.v1 + +script: + - go build examples/annotations_example.go + - go build examples/async_example.go + - go build examples/basic_example.go + - go build examples/collector_example.go From 8c249176046ac886149774a36f93a9b60743b2bc Mon Sep 17 00:00:00 2001 From: Anton Novojilov Date: Mon, 13 Jun 2016 07:35:49 -0400 Subject: [PATCH 09/12] Added dummy makefile --- Makefile | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Makefile diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1c9a8d7 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +# Dummy make file +# \ No newline at end of file From 89557b16b7ee90d01840c243c2ee1a0b99477e82 Mon Sep 17 00:00:00 2001 From: Anton Novojilov Date: Mon, 13 Jun 2016 07:37:51 -0400 Subject: [PATCH 10/12] Added TravisCI badge to readme --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 741a32a..eb3ee5d 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -## Librato [![GoDoc](https://godoc.org/pkg.re/essentialkaos/librato.v2?status.svg)](https://godoc.org/pkg.re/essentialkaos/librato.v2) +## Librato [![GoDoc](https://godoc.org/pkg.re/essentialkaos/librato.v2?status.svg)](https://godoc.org/pkg.re/essentialkaos/librato.v2) [![Build Status](https://travis-ci.org/essentialkaos/librato.svg?branch=master)](https://travis-ci.org/essentialkaos/librato) Package for working with [Librato Metrics](https://www.librato.com) API from go code. From bdc56eb7b247db4b106e0e03f2294028e52c84ff Mon Sep 17 00:00:00 2001 From: Anton Novojilov Date: Mon, 13 Jun 2016 07:39:56 -0400 Subject: [PATCH 11/12] Readme little bit changed --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index eb3ee5d..498affe 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -## Librato [![GoDoc](https://godoc.org/pkg.re/essentialkaos/librato.v2?status.svg)](https://godoc.org/pkg.re/essentialkaos/librato.v2) [![Build Status](https://travis-ci.org/essentialkaos/librato.svg?branch=master)](https://travis-ci.org/essentialkaos/librato) +# Librato [![GoDoc](https://godoc.org/pkg.re/essentialkaos/librato.v2?status.svg)](https://godoc.org/pkg.re/essentialkaos/librato.v2) [![Build Status](https://travis-ci.org/essentialkaos/librato.svg?branch=master)](https://travis-ci.org/essentialkaos/librato) Package for working with [Librato Metrics](https://www.librato.com) API from go code. From 4ba51dbe2b5195836ef2c5df53aaa3e05a4ba043 Mon Sep 17 00:00:00 2001 From: Anton Novojilov Date: Mon, 13 Jun 2016 07:41:49 -0400 Subject: [PATCH 12/12] Readme updated --- readme.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/readme.md b/readme.md index 498affe..54b84be 100644 --- a/readme.md +++ b/readme.md @@ -2,6 +2,10 @@ Package for working with [Librato Metrics](https://www.librato.com) API from go code. +* [Installation](#installation) +* [Examples](#examples) +* [License](#license) + ### Installation ````