Move to vendor

Signed-off-by: Olivier Gambier <olivier@docker.com>
This commit is contained in:
Olivier Gambier 2016-03-18 14:07:13 -07:00
parent c8d8e7e357
commit 77e69b9cf3
1268 changed files with 34 additions and 24 deletions

View file

@ -0,0 +1 @@
language: go

View file

@ -0,0 +1,24 @@
Copyright (c) 2013 Yuriy Vasiyarov. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,11 @@
New Relic Platform Agent SDK for Go(golang)
====================
[![Build Status](https://travis-ci.org/yvasiyarov/newrelic_platform_go.png?branch=master)](https://travis-ci.org/yvasiyarov/newrelic_platform_go)
This package provide very simple interface to NewRelic Platform http://newrelic.com/platform
For example of usage see examples/wave_plugin.go
For real-word example, you can have a look at:
https://github.com/yvasiyarov/newrelic_sphinx

View file

@ -0,0 +1,27 @@
package newrelic_platform_go
import (
"log"
"os"
)
type Agent struct {
Host string `json:"host"`
Version string `json:"version"`
Pid int `json:"pid"`
}
func NewAgent(Version string) *Agent {
agent := &Agent{
Version: Version,
}
return agent
}
func (agent *Agent) CollectEnvironmentInfo() {
var err error
agent.Pid = os.Getpid()
if agent.Host, err = os.Hostname(); err != nil {
log.Fatalf("Can not get hostname: %#v \n", err)
}
}

View file

@ -0,0 +1,71 @@
package newrelic_platform_go
import (
"log"
"math"
)
type ComponentData interface{}
type IComponent interface {
Harvest(plugin INewrelicPlugin) ComponentData
SetDuration(duration int)
AddMetrica(model IMetrica)
ClearSentData()
}
type PluginComponent struct {
Name string `json:"name"`
GUID string `json:"guid"`
Duration int `json:"duration"`
Metrics map[string]MetricaValue `json:"metrics"`
MetricaModels []IMetrica `json:"-"`
}
func NewPluginComponent(name string, guid string) *PluginComponent {
c := &PluginComponent{
Name: name,
GUID: guid,
}
return c
}
func (component *PluginComponent) AddMetrica(model IMetrica) {
component.MetricaModels = append(component.MetricaModels, model)
}
func (component *PluginComponent) ClearSentData() {
component.Metrics = nil
}
func (component *PluginComponent) SetDuration(duration int) {
component.Duration = duration
}
func (component *PluginComponent) Harvest(plugin INewrelicPlugin) ComponentData {
component.Metrics = make(map[string]MetricaValue, len(component.MetricaModels))
for i := 0; i < len(component.MetricaModels); i++ {
model := component.MetricaModels[i]
metricaKey := plugin.GetMetricaKey(model)
if newValue, err := model.GetValue(); err == nil {
if math.IsInf(newValue, 0) || math.IsNaN(newValue) {
newValue = 0
}
if existMetric, ok := component.Metrics[metricaKey]; ok {
if floatExistVal, ok := existMetric.(float64); ok {
component.Metrics[metricaKey] = NewAggregatedMetricaValue(floatExistVal, newValue)
} else if aggregatedValue, ok := existMetric.(*AggregatedMetricaValue); ok {
aggregatedValue.Aggregate(newValue)
} else {
panic("Invalid type in metrica value")
}
} else {
component.Metrics[metricaKey] = newValue
}
} else {
log.Printf("Can not get metrica: %v, got error:%#v", model.GetName(), err)
}
}
return component
}

View file

@ -0,0 +1,2 @@
// Package newrelic_platform_go is New Relic Platform Agent SDK for Go language.
package newrelic_platform_go

View file

@ -0,0 +1,72 @@
package main
import (
"github.com/yvasiyarov/newrelic_platform_go"
)
type WaveMetrica struct {
sawtoothMax int
sawtoothCounter int
}
func (metrica *WaveMetrica) GetName() string {
return "Wave_Metrica"
}
func (metrica *WaveMetrica) GetUnits() string {
return "Queries/Second"
}
func (metrica *WaveMetrica) GetValue() (float64, error) {
metrica.sawtoothCounter++
if metrica.sawtoothCounter > metrica.sawtoothMax {
metrica.sawtoothCounter = 0
}
return float64(metrica.sawtoothCounter), nil
}
type SquareWaveMetrica struct {
squarewaveMax int
squarewaveCounter int
}
func (metrica *SquareWaveMetrica) GetName() string {
return "SquareWave_Metrica"
}
func (metrica *SquareWaveMetrica) GetUnits() string {
return "Queries/Second"
}
func (metrica *SquareWaveMetrica) GetValue() (float64, error) {
returnValue := 0
metrica.squarewaveCounter++
if metrica.squarewaveCounter < (metrica.squarewaveMax / 2) {
returnValue = 0
} else {
returnValue = metrica.squarewaveMax
}
if metrica.squarewaveCounter > metrica.squarewaveMax {
metrica.squarewaveCounter = 0
}
return float64(returnValue), nil
}
func main() {
plugin := newrelic_platform_go.NewNewrelicPlugin("0.0.1", "7bceac019c7dcafae1ef95be3e3a3ff8866de246", 60)
component := newrelic_platform_go.NewPluginComponent("Wave component", "com.exmaple.plugin.gowave")
plugin.AddComponent(component)
m := &WaveMetrica{
sawtoothMax: 10,
sawtoothCounter: 5,
}
component.AddMetrica(m)
m1 := &SquareWaveMetrica{
squarewaveMax: 4,
squarewaveCounter: 1,
}
component.AddMetrica(m1)
plugin.Verbose = true
plugin.Run()
}

View file

@ -0,0 +1,42 @@
package newrelic_platform_go
import (
"math"
)
type IMetrica interface {
GetValue() (float64, error)
GetName() string
GetUnits() string
}
type MetricaValue interface{}
type SimpleMetricaValue float64
type AggregatedMetricaValue struct {
Min float64 `json:"min"`
Max float64 `json:"max"`
Total float64 `json:"total"`
Count int `json:"count"`
SumOfSquares float64 `json:"sum_of_squares"`
}
func NewAggregatedMetricaValue(existValue float64, newValue float64) *AggregatedMetricaValue {
v := &AggregatedMetricaValue{
Min: math.Min(newValue, existValue),
Max: math.Max(newValue, existValue),
Total: newValue + existValue,
Count: 2,
SumOfSquares: newValue*newValue + existValue*existValue,
}
return v
}
func (aggregatedValue *AggregatedMetricaValue) Aggregate(newValue float64) {
aggregatedValue.Min = math.Min(newValue, aggregatedValue.Min)
aggregatedValue.Max = math.Max(newValue, aggregatedValue.Max)
aggregatedValue.Total += newValue
aggregatedValue.Count++
aggregatedValue.SumOfSquares += newValue * newValue
}

View file

@ -0,0 +1,15 @@
{
"Version": "0.0.1",
"Vendor": "yvasiyarov",
"Authors": [
{
"FullName": "Yuriy Vasiyarov",
"Email": "varyous@gmail.com"
}
],
"ExtraFiles": [
"README.md",
"LICENSE"
],
"Homepage": "https://github.com/yvasiyarov/newrelic_platform_go"
}

View file

@ -0,0 +1,194 @@
package newrelic_platform_go
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"strings"
"time"
)
const (
NEWRELIC_API_URL = "https://platform-api.newrelic.com/platform/v1/metrics"
)
type INewrelicPlugin interface {
GetMetricaKey(metrica IMetrica) string
Harvest() error
Run()
AddComponent(component IComponent)
}
type NewrelicPlugin struct {
Agent *Agent `json:"agent"`
Components []ComponentData `json:"components"`
ComponentModels []IComponent `json:"-"`
LastPollTime time.Time `json:"-"`
Verbose bool `json:"-"`
LicenseKey string `json:"-"`
PollIntervalInSecond int `json:"-"`
}
func NewNewrelicPlugin(version string, licenseKey string, pollInterval int) *NewrelicPlugin {
plugin := &NewrelicPlugin{
LicenseKey: licenseKey,
PollIntervalInSecond: pollInterval,
}
plugin.Agent = NewAgent(version)
plugin.Agent.CollectEnvironmentInfo()
plugin.ComponentModels = []IComponent{}
return plugin
}
func (plugin *NewrelicPlugin) Harvest() error {
startTime := time.Now()
var duration int
if plugin.LastPollTime.IsZero() {
duration = plugin.PollIntervalInSecond
} else {
duration = int(startTime.Sub(plugin.LastPollTime).Seconds())
}
plugin.Components = make([]ComponentData, 0, len(plugin.ComponentModels))
for i := 0; i < len(plugin.ComponentModels); i++ {
plugin.ComponentModels[i].SetDuration(duration)
plugin.Components = append(plugin.Components, plugin.ComponentModels[i].Harvest(plugin))
}
if httpCode, err := plugin.SendMetricas(); err != nil {
log.Printf("Can not send metricas to newrelic: %#v\n", err)
return err
} else {
if plugin.Verbose {
log.Printf("Got HTTP response code:%d", httpCode)
}
if err, isFatal := plugin.CheckResponse(httpCode); isFatal {
log.Printf("Got fatal error:%v\n", err)
return err
} else {
if err != nil {
log.Printf("WARNING: %v", err)
}
return err
}
}
return nil
}
func (plugin *NewrelicPlugin) GetMetricaKey(metrica IMetrica) string {
var keyBuffer bytes.Buffer
keyBuffer.WriteString("Component/")
keyBuffer.WriteString(metrica.GetName())
keyBuffer.WriteString("[")
keyBuffer.WriteString(metrica.GetUnits())
keyBuffer.WriteString("]")
return keyBuffer.String()
}
func (plugin *NewrelicPlugin) SendMetricas() (int, error) {
client := &http.Client{}
var metricasJson []byte
var encodingError error
if plugin.Verbose {
metricasJson, encodingError = json.MarshalIndent(plugin, "", " ")
} else {
metricasJson, encodingError = json.Marshal(plugin)
}
if encodingError != nil {
return 0, encodingError
}
jsonAsString := string(metricasJson)
if plugin.Verbose {
log.Printf("Send data:%s \n", jsonAsString)
}
if httpRequest, err := http.NewRequest("POST", NEWRELIC_API_URL, strings.NewReader(jsonAsString)); err != nil {
return 0, err
} else {
httpRequest.Header.Set("X-License-Key", plugin.LicenseKey)
httpRequest.Header.Set("Content-Type", "application/json")
httpRequest.Header.Set("Accept", "application/json")
if httpResponse, err := client.Do(httpRequest); err != nil {
return 0, err
} else {
defer httpResponse.Body.Close()
return httpResponse.StatusCode, nil
}
}
// we will never get there
return 0, nil
}
func (plugin *NewrelicPlugin) ClearSentData() {
for _, component := range plugin.ComponentModels {
component.ClearSentData()
}
plugin.Components = nil
plugin.LastPollTime = time.Now()
}
func (plugin *NewrelicPlugin) CheckResponse(httpResponseCode int) (error, bool) {
isFatal := false
var err error
switch httpResponseCode {
case http.StatusOK:
{
plugin.ClearSentData()
}
case http.StatusForbidden:
{
err = fmt.Errorf("Authentication error (no license key header, or invalid license key).\n")
isFatal = true
}
case http.StatusBadRequest:
{
err = fmt.Errorf("The request or headers are in the wrong format or the URL is incorrect.\n")
isFatal = true
}
case http.StatusNotFound:
{
err = fmt.Errorf("Invalid URL\n")
isFatal = true
}
case http.StatusRequestEntityTooLarge:
{
err = fmt.Errorf("Too many metrics were sent in one request, or too many components (instances) were specified in one request, or other single-request limits were reached.\n")
//discard metrics
plugin.ClearSentData()
}
case http.StatusInternalServerError, http.StatusBadGateway, http.StatusServiceUnavailable, http.StatusGatewayTimeout:
{
err = fmt.Errorf("Got %v response code.Metricas will be aggregated", httpResponseCode)
}
}
return err, isFatal
}
func (plugin *NewrelicPlugin) Run() {
plugin.Harvest()
tickerChannel := time.Tick(time.Duration(plugin.PollIntervalInSecond) * time.Second)
for ts := range tickerChannel {
plugin.Harvest()
if plugin.Verbose {
log.Printf("Harvest ended at:%v\n", ts)
}
}
}
func (plugin *NewrelicPlugin) AddComponent(component IComponent) {
plugin.ComponentModels = append(plugin.ComponentModels, component)
}