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

4
vendor/github.com/yvasiyarov/gorelic/.gitignore generated vendored Normal file
View file

@ -0,0 +1,4 @@
*.nut
*.swp
examples/example1
examples/example_web

1
vendor/github.com/yvasiyarov/gorelic/.travis.yml generated vendored Normal file
View file

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

24
vendor/github.com/yvasiyarov/gorelic/LICENSE generated vendored Normal file
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.

119
vendor/github.com/yvasiyarov/gorelic/README.md generated vendored Normal file
View file

@ -0,0 +1,119 @@
# GoRelic
New Relic agent for Go runtime. It collect a lot of metrics about scheduler, garbage collector and memory allocator and
send them to NewRelic.
### Requirements
- Go 1.1 or higher
- github.com/yvasiyarov/gorelic
- github.com/yvasiyarov/newrelic_platform_go
- github.com/yvasiyarov/go-metrics
You have to install manually only first two dependencies. All other dependencies will be installed automatically
by Go toolchain.
### Installation
```bash
go get github.com/yvasiyarov/gorelic
```
and add to the initialization part of your application following code:
```go
import (
"github.com/yvasiyarov/gorelic"
)
....
agent := gorelic.NewAgent()
agent.Verbose = true
agent.NewrelicLicense = "YOUR NEWRELIC LICENSE KEY THERE"
agent.Run()
```
### Middleware
If you using Beego, Martini, Revel or Gin framework you can hook up gorelic with your application by using the following middleware:
- https://github.com/yvasiyarov/beego_gorelic
- https://github.com/yvasiyarov/martini_gorelic
- https://github.com/yvasiyarov/gocraft_gorelic
- http://wiki.colar.net/revel_newelic
- https://github.com/jingweno/negroni-gorelic
- https://github.com/brandfolder/gin-gorelic
### Configuration
- NewrelicLicense - its the only mandatory setting of this agent.
- NewrelicName - component name in NewRelic dashboard. Default value: "Go daemon"
- NewrelicPollInterval - how often metrics will be sent to NewRelic. Default value: 60 seconds
- Verbose - print some usefull for debugging information. Default value: false
- CollectGcStat - should agent collect garbage collector statistic or not. Default value: true
- CollectHTTPStat - should agent collect HTTP metrics. Default value: false
- CollectMemoryStat - should agent collect memory allocator statistic or not. Default value: true
- GCPollInterval - how often should GC statistic collected. Default value: 10 seconds. It has performance impact. For more information, please, see metrics documentation.
- MemoryAllocatorPollInterval - how often should memory allocator statistic collected. Default value: 60 seconds. It has performance impact. For more information, please, read metrics documentation.
## Metrics reported by plugin
This agent use functions exposed by runtime or runtime/debug packages to collect most important information about Go runtime.
### General metrics
- Runtime/General/NOGoroutines - number of runned go routines, as it reported by NumGoroutine() from runtime package
- Runtime/General/NOCgoCalls - number of runned cgo calls, as it reported by NumCgoCall() from runtime package
### Garbage collector metrics
- Runtime/GC/NumberOfGCCalls - Nuber of GC calls, as it reported by ReadGCStats() from runtime/debug
- Runtime/GC/PauseTotalTime - Total pause time diring GC calls, as it reported by ReadGCStats() from runtime/debug (in nanoseconds)
- Runtime/GC/GCTime/Max - max GC time
- Runtime/GC/GCTime/Min - min GC time
- Runtime/GC/GCTime/Mean - GC mean time
- Runtime/GC/GCTime/Percentile95 - 95% percentile of GC time
All this metrics are measured in nanoseconds. Last 4 of them can be inaccurate if GC called more often then once in GCPollInterval.
If in your workload GC is called more often - you can consider decreasing value of GCPollInterval.
But be carefull, ReadGCStats() blocks mheap, so its not good idea to set GCPollInterval to very low values.
### Memory allocator
- Component/Runtime/Memory/SysMem/Total - number of bytes/minute allocated from OS totally.
- Component/Runtime/Memory/SysMem/Stack - number of bytes/minute allocated from OS for stacks.
- Component/Runtime/Memory/SysMem/MSpan - number of bytes/minute allocated from OS for internal MSpan structs.
- Component/Runtime/Memory/SysMem/MCache - number of bytes/minute allocated from OS for internal MCache structs.
- Component/Runtime/Memory/SysMem/Heap - number of bytes/minute allocated from OS for heap.
- Component/Runtime/Memory/SysMem/BuckHash - number of bytes/minute allocated from OS for internal BuckHash structs.
- Component/Runtime/Memory/Operations/NoFrees - number of memory frees per minute
- Component/Runtime/Memory/Operations/NoMallocs - number of memory allocations per minute
- Component/Runtime/Memory/Operations/NoPointerLookups - number of pointer lookups per minute
- Component/Runtime/Memory/InUse/Total - total amount of memory in use
- Component/Runtime/Memory/InUse/Heap - amount of memory in use for heap
- Component/Runtime/Memory/InUse/MCacheInuse - amount of memory in use for MCache internal structures
- Component/Runtime/Memory/InUse/MSpanInuse - amount of memory in use for MSpan internal structures
- Component/Runtime/Memory/InUse/Stack - amount of memory in use for stacks
### Process metrics
- Component/Runtime/System/Threads - number of OS threads used
- Runtime/System/FDSize - number of file descriptors, used by process
- Runtime/System/Memory/VmPeakSize - VM max size
- Runtime/System/Memory/VmCurrent - VM current size
- Runtime/System/Memory/RssPeak - max size of resident memory set
- Runtime/System/Memory/RssCurrent - current size of resident memory set
All this metrics collected once in MemoryAllocatorPollInterval. In order to collect this statistic agent use ReadMemStats() routine.
This routine calls stoptheworld() internally and it block everything. So, please, consider this when you change MemoryAllocatorPollInterval value.
### HTTP metrics
- throughput (requests per second), calculated for last minute
- mean throughput (requests per second)
- mean response time
- min response time
- max response time
- 75%, 90%, 95% percentiles for response time
In order to collect HTTP metrics, handler functions must be wrapped using WrapHTTPHandlerFunc:
```go
http.HandleFunc("/", agent.WrapHTTPHandlerFunc(handler))
```
## TODO
- Collect per-size allocation statistic
- Collect user defined metrics

137
vendor/github.com/yvasiyarov/gorelic/agent.go generated vendored Normal file
View file

@ -0,0 +1,137 @@
package gorelic
import (
"errors"
"fmt"
metrics "github.com/yvasiyarov/go-metrics"
"github.com/yvasiyarov/newrelic_platform_go"
"log"
"net/http"
)
const (
// DefaultNewRelicPollInterval - how often we will report metrics to NewRelic.
// Recommended values is 60 seconds
DefaultNewRelicPollInterval = 60
// DefaultGcPollIntervalInSeconds - how often we will get garbage collector run statistic
// Default value is - every 10 seconds
// During GC stat pooling - mheap will be locked, so be carefull changing this value
DefaultGcPollIntervalInSeconds = 10
// DefaultMemoryAllocatorPollIntervalInSeconds - how often we will get memory allocator statistic.
// Default value is - every 60 seconds
// During this process stoptheword() is called, so be carefull changing this value
DefaultMemoryAllocatorPollIntervalInSeconds = 60
//DefaultAgentGuid is plugin ID in NewRelic.
//You should not change it unless you want to create your own plugin.
DefaultAgentGuid = "com.github.yvasiyarov.GoRelic"
//CurrentAgentVersion is plugin version
CurrentAgentVersion = "0.0.6"
//DefaultAgentName in NewRelic GUI. You can change it.
DefaultAgentName = "Go daemon"
)
//Agent - is NewRelic agent implementation.
//Agent start separate go routine which will report data to NewRelic
type Agent struct {
NewrelicName string
NewrelicLicense string
NewrelicPollInterval int
Verbose bool
CollectGcStat bool
CollectMemoryStat bool
CollectHTTPStat bool
GCPollInterval int
MemoryAllocatorPollInterval int
AgentGUID string
AgentVersion string
plugin *newrelic_platform_go.NewrelicPlugin
HTTPTimer metrics.Timer
}
//NewAgent build new Agent objects.
func NewAgent() *Agent {
agent := &Agent{
NewrelicName: DefaultAgentName,
NewrelicPollInterval: DefaultNewRelicPollInterval,
Verbose: false,
CollectGcStat: true,
CollectMemoryStat: true,
GCPollInterval: DefaultGcPollIntervalInSeconds,
MemoryAllocatorPollInterval: DefaultMemoryAllocatorPollIntervalInSeconds,
AgentGUID: DefaultAgentGuid,
AgentVersion: CurrentAgentVersion,
}
return agent
}
//WrapHTTPHandlerFunc instrument HTTP handler functions to collect HTTP metrics
func (agent *Agent) WrapHTTPHandlerFunc(h tHTTPHandlerFunc) tHTTPHandlerFunc {
agent.initTimer()
return func(w http.ResponseWriter, req *http.Request) {
proxy := newHTTPHandlerFunc(h)
proxy.timer = agent.HTTPTimer
proxy.ServeHTTP(w, req)
}
}
//WrapHTTPHandler instrument HTTP handler object to collect HTTP metrics
func (agent *Agent) WrapHTTPHandler(h http.Handler) http.Handler {
agent.initTimer()
proxy := newHTTPHandler(h)
proxy.timer = agent.HTTPTimer
return proxy
}
//Run initialize Agent instance and start harvest go routine
func (agent *Agent) Run() error {
if agent.NewrelicLicense == "" {
return errors.New("please, pass a valid newrelic license key")
}
agent.plugin = newrelic_platform_go.NewNewrelicPlugin(agent.AgentVersion, agent.NewrelicLicense, agent.NewrelicPollInterval)
component := newrelic_platform_go.NewPluginComponent(agent.NewrelicName, agent.AgentGUID)
agent.plugin.AddComponent(component)
addRuntimeMericsToComponent(component)
if agent.CollectGcStat {
addGCMericsToComponent(component, agent.GCPollInterval)
agent.debug(fmt.Sprintf("Init GC metrics collection. Poll interval %d seconds.", agent.GCPollInterval))
}
if agent.CollectMemoryStat {
addMemoryMericsToComponent(component, agent.MemoryAllocatorPollInterval)
agent.debug(fmt.Sprintf("Init memory allocator metrics collection. Poll interval %d seconds.", agent.MemoryAllocatorPollInterval))
}
if agent.CollectHTTPStat {
agent.initTimer()
addHTTPMericsToComponent(component, agent.HTTPTimer)
agent.debug(fmt.Sprintf("Init HTTP metrics collection."))
}
agent.plugin.Verbose = agent.Verbose
go agent.plugin.Run()
return nil
}
//Initialize global metrics.Timer object, used to collect HTTP metrics
func (agent *Agent) initTimer() {
if agent.HTTPTimer == nil {
agent.HTTPTimer = metrics.NewTimer()
}
agent.CollectHTTPStat = true
}
//Print debug messages
func (agent *Agent) debug(msg string) {
if agent.Verbose {
log.Println(msg)
}
}

2
vendor/github.com/yvasiyarov/gorelic/doc.go generated vendored Normal file
View file

@ -0,0 +1,2 @@
// Package gorelic is an New Relic agent implementation for Go runtime. It collect a lot of metrics about Go scheduler, garbage collector and memory allocator and send them to NewRelic.
package gorelic

View file

@ -0,0 +1,52 @@
package main
import (
"flag"
"github.com/yvasiyarov/gorelic"
"log"
"math/rand"
"runtime"
"time"
)
var newrelicLicense = flag.String("newrelic-license", "", "Newrelic license")
func allocateAndSum(arraySize int) int {
arr := make([]int, arraySize, arraySize)
for i := range arr {
arr[i] = rand.Int()
}
time.Sleep(time.Duration(rand.Intn(3000)) * time.Millisecond)
result := 0
for _, v := range arr {
result += v
}
//log.Printf("Array size is: %d, sum is: %d\n", arraySize, result)
return result
}
func doSomeJob(numRoutines int) {
for {
for i := 0; i < numRoutines; i++ {
go allocateAndSum(rand.Intn(1024) * 1024)
}
log.Printf("All %d routines started\n", numRoutines)
time.Sleep(1000 * time.Millisecond)
runtime.GC()
}
}
func main() {
flag.Parse()
if *newrelicLicense == "" {
log.Fatalf("Please, pass a valid newrelic license key.\n Use --help to get more information about available options\n")
}
agent := gorelic.NewAgent()
agent.Verbose = true
agent.NewrelicLicense = *newrelicLicense
agent.Run()
doSomeJob(100)
}

View file

@ -0,0 +1,63 @@
package main
import (
"expvar"
"flag"
"github.com/yvasiyarov/gorelic"
"io"
"log"
"math/rand"
"net/http"
"runtime"
"time"
)
var newrelicLicense = flag.String("newrelic-license", "", "Newrelic license")
var numCalls = expvar.NewInt("num_calls")
func allocateAndSum(arraySize int) int {
arr := make([]int, arraySize, arraySize)
for i := range arr {
arr[i] = rand.Int()
}
time.Sleep(time.Duration(rand.Intn(3000)) * time.Millisecond)
result := 0
for _, v := range arr {
result += v
}
//log.Printf("Array size is: %d, sum is: %d\n", arraySize, result)
return result
}
func doSomeJob(numRoutines int) {
for i := 0; i < numRoutines; i++ {
go allocateAndSum(rand.Intn(1024) * 1024)
}
log.Printf("All %d routines started\n", numRoutines)
time.Sleep(1000 * time.Millisecond)
runtime.GC()
}
func helloServer(w http.ResponseWriter, req *http.Request) {
doSomeJob(5)
io.WriteString(w, "Did some work")
}
func main() {
flag.Parse()
if *newrelicLicense == "" {
log.Fatalf("Please, pass a valid newrelic license key.\n Use --help to get more information about available options\n")
}
agent := gorelic.NewAgent()
agent.Verbose = true
agent.CollectHTTPStat = true
agent.NewrelicLicense = *newrelicLicense
agent.Run()
http.HandleFunc("/", agent.WrapHTTPHandlerFunc(helloServer))
http.ListenAndServe(":8080", nil)
}

65
vendor/github.com/yvasiyarov/gorelic/gc_metrics.go generated vendored Normal file
View file

@ -0,0 +1,65 @@
package gorelic
import (
metrics "github.com/yvasiyarov/go-metrics"
"github.com/yvasiyarov/newrelic_platform_go"
"time"
)
func newGCMetricaDataSource(pollInterval int) goMetricaDataSource {
r := metrics.NewRegistry()
metrics.RegisterDebugGCStats(r)
go metrics.CaptureDebugGCStats(r, time.Duration(pollInterval)*time.Second)
return goMetricaDataSource{r}
}
func addGCMericsToComponent(component newrelic_platform_go.IComponent, pollInterval int) {
metrics := []*baseGoMetrica{
&baseGoMetrica{
name: "NumberOfGCCalls",
units: "calls",
dataSourceKey: "debug.GCStats.NumGC",
},
&baseGoMetrica{
name: "PauseTotalTime",
units: "nanoseconds",
dataSourceKey: "debug.GCStats.PauseTotal",
},
}
ds := newGCMetricaDataSource(pollInterval)
for _, m := range metrics {
m.basePath = "Runtime/GC/"
m.dataSource = ds
component.AddMetrica(&gaugeMetrica{m})
}
histogramMetrics := []*histogramMetrica{
&histogramMetrica{
statFunction: histogramMax,
baseGoMetrica: &baseGoMetrica{name: "Max"},
},
&histogramMetrica{
statFunction: histogramMin,
baseGoMetrica: &baseGoMetrica{name: "Min"},
},
&histogramMetrica{
statFunction: histogramMean,
baseGoMetrica: &baseGoMetrica{name: "Mean"},
},
&histogramMetrica{
statFunction: histogramPercentile,
percentileValue: 0.95,
baseGoMetrica: &baseGoMetrica{name: "Percentile95"},
},
}
for _, m := range histogramMetrics {
m.baseGoMetrica.units = "nanoseconds"
m.baseGoMetrica.dataSourceKey = "debug.GCStats.Pause"
m.baseGoMetrica.basePath = "Runtime/GC/GCTime/"
m.baseGoMetrica.dataSource = ds
component.AddMetrica(m)
}
}

105
vendor/github.com/yvasiyarov/gorelic/gometrica.go generated vendored Normal file
View file

@ -0,0 +1,105 @@
package gorelic
import (
"fmt"
metrics "github.com/yvasiyarov/go-metrics"
)
const (
histogramMin = iota
histogramMax
histogramMean
histogramPercentile
histogramStdDev
histogramVariance
noHistogramFunctions
)
type goMetricaDataSource struct {
metrics.Registry
}
func (ds goMetricaDataSource) GetGaugeValue(key string) (float64, error) {
if valueContainer := ds.Get(key); valueContainer == nil {
return 0, fmt.Errorf("metrica with name %s is not registered\n", key)
} else if gauge, ok := valueContainer.(metrics.Gauge); ok {
return float64(gauge.Value()), nil
} else {
return 0, fmt.Errorf("metrica container has unexpected type: %T\n", valueContainer)
}
}
func (ds goMetricaDataSource) GetHistogramValue(key string, statFunction int, percentile float64) (float64, error) {
if valueContainer := ds.Get(key); valueContainer == nil {
return 0, fmt.Errorf("metrica with name %s is not registered\n", key)
} else if histogram, ok := valueContainer.(metrics.Histogram); ok {
switch statFunction {
default:
return 0, fmt.Errorf("unsupported stat function for histogram: %s\n", statFunction)
case histogramMax:
return float64(histogram.Max()), nil
case histogramMin:
return float64(histogram.Min()), nil
case histogramMean:
return float64(histogram.Mean()), nil
case histogramStdDev:
return float64(histogram.StdDev()), nil
case histogramVariance:
return float64(histogram.Variance()), nil
case histogramPercentile:
return float64(histogram.Percentile(percentile)), nil
}
} else {
return 0, fmt.Errorf("metrica container has unexpected type: %T\n", valueContainer)
}
}
type baseGoMetrica struct {
dataSource goMetricaDataSource
basePath string
name string
units string
dataSourceKey string
}
func (metrica *baseGoMetrica) GetName() string {
return metrica.basePath + metrica.name
}
func (metrica *baseGoMetrica) GetUnits() string {
return metrica.units
}
type gaugeMetrica struct {
*baseGoMetrica
}
func (metrica *gaugeMetrica) GetValue() (float64, error) {
return metrica.dataSource.GetGaugeValue(metrica.dataSourceKey)
}
type gaugeIncMetrica struct {
*baseGoMetrica
previousValue float64
}
func (metrica *gaugeIncMetrica) GetValue() (float64, error) {
var value float64
var currentValue float64
var err error
if currentValue, err = metrica.dataSource.GetGaugeValue(metrica.dataSourceKey); err == nil {
value = currentValue - metrica.previousValue
metrica.previousValue = currentValue
}
return value, err
}
type histogramMetrica struct {
*baseGoMetrica
statFunction int
percentileValue float64
}
func (metrica *histogramMetrica) GetValue() (float64, error) {
return metrica.dataSource.GetHistogramValue(metrica.dataSourceKey, metrica.statFunction, metrica.percentileValue)
}

194
vendor/github.com/yvasiyarov/gorelic/http_metrics.go generated vendored Normal file
View file

@ -0,0 +1,194 @@
package gorelic
import (
metrics "github.com/yvasiyarov/go-metrics"
"github.com/yvasiyarov/newrelic_platform_go"
"net/http"
"time"
)
type tHTTPHandlerFunc func(http.ResponseWriter, *http.Request)
type tHTTPHandler struct {
originalHandler http.Handler
originalHandlerFunc tHTTPHandlerFunc
isFunc bool
timer metrics.Timer
}
var httpTimer metrics.Timer
func newHTTPHandlerFunc(h tHTTPHandlerFunc) *tHTTPHandler {
return &tHTTPHandler{
isFunc: true,
originalHandlerFunc: h,
}
}
func newHTTPHandler(h http.Handler) *tHTTPHandler {
return &tHTTPHandler{
isFunc: false,
originalHandler: h,
}
}
func (handler *tHTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
startTime := time.Now()
defer handler.timer.UpdateSince(startTime)
if handler.isFunc {
handler.originalHandlerFunc(w, req)
} else {
handler.originalHandler.ServeHTTP(w, req)
}
}
type baseTimerMetrica struct {
dataSource metrics.Timer
name string
units string
}
func (metrica *baseTimerMetrica) GetName() string {
return metrica.name
}
func (metrica *baseTimerMetrica) GetUnits() string {
return metrica.units
}
type timerRate1Metrica struct {
*baseTimerMetrica
}
func (metrica *timerRate1Metrica) GetValue() (float64, error) {
return metrica.dataSource.Rate1(), nil
}
type timerRateMeanMetrica struct {
*baseTimerMetrica
}
func (metrica *timerRateMeanMetrica) GetValue() (float64, error) {
return metrica.dataSource.RateMean(), nil
}
type timerMeanMetrica struct {
*baseTimerMetrica
}
func (metrica *timerMeanMetrica) GetValue() (float64, error) {
return metrica.dataSource.Mean() / float64(time.Millisecond), nil
}
type timerMinMetrica struct {
*baseTimerMetrica
}
func (metrica *timerMinMetrica) GetValue() (float64, error) {
return float64(metrica.dataSource.Min()) / float64(time.Millisecond), nil
}
type timerMaxMetrica struct {
*baseTimerMetrica
}
func (metrica *timerMaxMetrica) GetValue() (float64, error) {
return float64(metrica.dataSource.Max()) / float64(time.Millisecond), nil
}
type timerPercentile75Metrica struct {
*baseTimerMetrica
}
func (metrica *timerPercentile75Metrica) GetValue() (float64, error) {
return metrica.dataSource.Percentile(0.75) / float64(time.Millisecond), nil
}
type timerPercentile90Metrica struct {
*baseTimerMetrica
}
func (metrica *timerPercentile90Metrica) GetValue() (float64, error) {
return metrica.dataSource.Percentile(0.90) / float64(time.Millisecond), nil
}
type timerPercentile95Metrica struct {
*baseTimerMetrica
}
func (metrica *timerPercentile95Metrica) GetValue() (float64, error) {
return metrica.dataSource.Percentile(0.95) / float64(time.Millisecond), nil
}
func addHTTPMericsToComponent(component newrelic_platform_go.IComponent, timer metrics.Timer) {
rate1 := &timerRate1Metrica{
baseTimerMetrica: &baseTimerMetrica{
name: "http/throughput/1minute",
units: "rps",
dataSource: timer,
},
}
component.AddMetrica(rate1)
rateMean := &timerRateMeanMetrica{
baseTimerMetrica: &baseTimerMetrica{
name: "http/throughput/rateMean",
units: "rps",
dataSource: timer,
},
}
component.AddMetrica(rateMean)
responseTimeMean := &timerMeanMetrica{
baseTimerMetrica: &baseTimerMetrica{
name: "http/responseTime/mean",
units: "ms",
dataSource: timer,
},
}
component.AddMetrica(responseTimeMean)
responseTimeMax := &timerMaxMetrica{
baseTimerMetrica: &baseTimerMetrica{
name: "http/responseTime/max",
units: "ms",
dataSource: timer,
},
}
component.AddMetrica(responseTimeMax)
responseTimeMin := &timerMinMetrica{
baseTimerMetrica: &baseTimerMetrica{
name: "http/responseTime/min",
units: "ms",
dataSource: timer,
},
}
component.AddMetrica(responseTimeMin)
responseTimePercentile75 := &timerPercentile75Metrica{
baseTimerMetrica: &baseTimerMetrica{
name: "http/responseTime/percentile75",
units: "ms",
dataSource: timer,
},
}
component.AddMetrica(responseTimePercentile75)
responseTimePercentile90 := &timerPercentile90Metrica{
baseTimerMetrica: &baseTimerMetrica{
name: "http/responseTime/percentile90",
units: "ms",
dataSource: timer,
},
}
component.AddMetrica(responseTimePercentile90)
responseTimePercentile95 := &timerPercentile95Metrica{
baseTimerMetrica: &baseTimerMetrica{
name: "http/responseTime/percentile95",
units: "ms",
dataSource: timer,
},
}
component.AddMetrica(responseTimePercentile95)
}

110
vendor/github.com/yvasiyarov/gorelic/memory_metrics.go generated vendored Normal file
View file

@ -0,0 +1,110 @@
package gorelic
import (
metrics "github.com/yvasiyarov/go-metrics"
"github.com/yvasiyarov/newrelic_platform_go"
"time"
)
func newMemoryMetricaDataSource(pollInterval int) goMetricaDataSource {
r := metrics.NewRegistry()
metrics.RegisterRuntimeMemStats(r)
metrics.CaptureRuntimeMemStatsOnce(r)
go metrics.CaptureRuntimeMemStats(r, time.Duration(pollInterval)*time.Second)
return goMetricaDataSource{r}
}
func addMemoryMericsToComponent(component newrelic_platform_go.IComponent, pollInterval int) {
gaugeMetrics := []*baseGoMetrica{
//Memory in use metrics
&baseGoMetrica{
name: "InUse/Total",
units: "bytes",
dataSourceKey: "runtime.MemStats.Alloc",
},
&baseGoMetrica{
name: "InUse/Heap",
units: "bytes",
dataSourceKey: "runtime.MemStats.HeapAlloc",
},
&baseGoMetrica{
name: "InUse/Stack",
units: "bytes",
dataSourceKey: "runtime.MemStats.StackInuse",
},
&baseGoMetrica{
name: "InUse/MSpanInuse",
units: "bytes",
dataSourceKey: "runtime.MemStats.MSpanInuse",
},
&baseGoMetrica{
name: "InUse/MCacheInuse",
units: "bytes",
dataSourceKey: "runtime.MemStats.MCacheInuse",
},
}
ds := newMemoryMetricaDataSource(pollInterval)
for _, m := range gaugeMetrics {
m.basePath = "Runtime/Memory/"
m.dataSource = ds
component.AddMetrica(&gaugeMetrica{m})
}
gaugeIncMetrics := []*baseGoMetrica{
//NO operations graph
&baseGoMetrica{
name: "Operations/NoPointerLookups",
units: "lookups",
dataSourceKey: "runtime.MemStats.Lookups",
},
&baseGoMetrica{
name: "Operations/NoMallocs",
units: "mallocs",
dataSourceKey: "runtime.MemStats.Mallocs",
},
&baseGoMetrica{
name: "Operations/NoFrees",
units: "frees",
dataSourceKey: "runtime.MemStats.Frees",
},
// Sytem memory allocations
&baseGoMetrica{
name: "SysMem/Total",
units: "bytes",
dataSourceKey: "runtime.MemStats.Sys",
},
&baseGoMetrica{
name: "SysMem/Heap",
units: "bytes",
dataSourceKey: "runtime.MemStats.HeapSys",
},
&baseGoMetrica{
name: "SysMem/Stack",
units: "bytes",
dataSourceKey: "runtime.MemStats.StackSys",
},
&baseGoMetrica{
name: "SysMem/MSpan",
units: "bytes",
dataSourceKey: "runtime.MemStats.MSpanSys",
},
&baseGoMetrica{
name: "SysMem/MCache",
units: "bytes",
dataSourceKey: "runtime.MemStats.MCacheSys",
},
&baseGoMetrica{
name: "SysMem/BuckHash",
units: "bytes",
dataSourceKey: "runtime.MemStats.BuckHashSys",
},
}
for _, m := range gaugeIncMetrics {
m.basePath = "Runtime/Memory/"
m.dataSource = ds
component.AddMetrica(&gaugeIncMetrica{baseGoMetrica: m})
}
}

15
vendor/github.com/yvasiyarov/gorelic/nut.json generated vendored Normal file
View file

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

196
vendor/github.com/yvasiyarov/gorelic/runtime_metrics.go generated vendored Normal file
View file

@ -0,0 +1,196 @@
package gorelic
import (
"fmt"
"github.com/yvasiyarov/newrelic_platform_go"
"io/ioutil"
"os"
"runtime"
"strconv"
"strings"
"time"
)
const linuxSystemQueryInterval = 60
// Number of goroutines metrica
type noGoroutinesMetrica struct{}
func (metrica *noGoroutinesMetrica) GetName() string {
return "Runtime/General/NOGoroutines"
}
func (metrica *noGoroutinesMetrica) GetUnits() string {
return "goroutines"
}
func (metrica *noGoroutinesMetrica) GetValue() (float64, error) {
return float64(runtime.NumGoroutine()), nil
}
// Number of CGO calls metrica
type noCgoCallsMetrica struct {
lastValue int64
}
func (metrica *noCgoCallsMetrica) GetName() string {
return "Runtime/General/NOCgoCalls"
}
func (metrica *noCgoCallsMetrica) GetUnits() string {
return "calls"
}
func (metrica *noCgoCallsMetrica) GetValue() (float64, error) {
currentValue := runtime.NumCgoCall()
value := float64(currentValue - metrica.lastValue)
metrica.lastValue = currentValue
return value, nil
}
//OS specific metrics data source interface
type iSystemMetricaDataSource interface {
GetValue(key string) (float64, error)
}
// iSystemMetricaDataSource fabrica
func newSystemMetricaDataSource() iSystemMetricaDataSource {
var ds iSystemMetricaDataSource
switch runtime.GOOS {
default:
ds = &systemMetricaDataSource{}
case "linux":
ds = &linuxSystemMetricaDataSource{
systemData: make(map[string]string),
}
}
return ds
}
//Default implementation of iSystemMetricaDataSource. Just return an error
type systemMetricaDataSource struct{}
func (ds *systemMetricaDataSource) GetValue(key string) (float64, error) {
return 0, fmt.Errorf("this metrica was not implemented yet for %s", runtime.GOOS)
}
// Linux OS implementation of ISystemMetricaDataSource
type linuxSystemMetricaDataSource struct {
lastUpdate time.Time
systemData map[string]string
}
func (ds *linuxSystemMetricaDataSource) GetValue(key string) (float64, error) {
if err := ds.checkAndUpdateData(); err != nil {
return 0, err
} else if val, ok := ds.systemData[key]; !ok {
return 0, fmt.Errorf("system data with key %s was not found", key)
} else if key == "VmSize" || key == "VmPeak" || key == "VmHWM" || key == "VmRSS" {
valueParts := strings.Split(val, " ")
if len(valueParts) != 2 {
return 0, fmt.Errorf("invalid format for value %s", key)
}
valConverted, err := strconv.ParseFloat(valueParts[0], 64)
if err != nil {
return 0, err
}
switch valueParts[1] {
case "kB":
valConverted *= 1 << 10
case "mB":
valConverted *= 1 << 20
case "gB":
valConverted *= 1 << 30
}
return valConverted, nil
} else if valConverted, err := strconv.ParseFloat(val, 64); err != nil {
return valConverted, nil
} else {
return valConverted, nil
}
}
func (ds *linuxSystemMetricaDataSource) checkAndUpdateData() error {
startTime := time.Now()
if startTime.Sub(ds.lastUpdate) > time.Second*linuxSystemQueryInterval {
path := fmt.Sprintf("/proc/%d/status", os.Getpid())
rawStats, err := ioutil.ReadFile(path)
if err != nil {
return err
}
lines := strings.Split(string(rawStats), "\n")
for _, line := range lines {
parts := strings.Split(line, ":")
if len(parts) == 2 {
k := strings.TrimSpace(parts[0])
v := strings.TrimSpace(parts[1])
ds.systemData[k] = v
}
}
ds.lastUpdate = startTime
}
return nil
}
// OS specific metrica
type systemMetrica struct {
sourceKey string
newrelicName string
units string
dataSource iSystemMetricaDataSource
}
func (metrica *systemMetrica) GetName() string {
return metrica.newrelicName
}
func (metrica *systemMetrica) GetUnits() string {
return metrica.units
}
func (metrica *systemMetrica) GetValue() (float64, error) {
return metrica.dataSource.GetValue(metrica.sourceKey)
}
func addRuntimeMericsToComponent(component newrelic_platform_go.IComponent) {
component.AddMetrica(&noGoroutinesMetrica{})
component.AddMetrica(&noCgoCallsMetrica{})
ds := newSystemMetricaDataSource()
metrics := []*systemMetrica{
&systemMetrica{
sourceKey: "Threads",
units: "Threads",
newrelicName: "Runtime/System/Threads",
},
&systemMetrica{
sourceKey: "FDSize",
units: "fd",
newrelicName: "Runtime/System/FDSize",
},
// Peak virtual memory size
&systemMetrica{
sourceKey: "VmPeak",
units: "bytes",
newrelicName: "Runtime/System/Memory/VmPeakSize",
},
//Virtual memory size
&systemMetrica{
sourceKey: "VmSize",
units: "bytes",
newrelicName: "Runtime/System/Memory/VmCurrent",
},
//Peak resident set size
&systemMetrica{
sourceKey: "VmHWM",
units: "bytes",
newrelicName: "Runtime/System/Memory/RssPeak",
},
//Resident set size
&systemMetrica{
sourceKey: "VmRSS",
units: "bytes",
newrelicName: "Runtime/System/Memory/RssCurrent",
},
}
for _, m := range metrics {
m.dataSource = ds
component.AddMetrica(m)
}
}