Vendor circonus (#2082)
This commit is contained in:
parent
1216ad2799
commit
57925ee863
|
@ -820,6 +820,8 @@ func (c *ServerCommand) setupTelemetry(config *server.Config) error {
|
|||
cfg.CheckManager.Check.ForceMetricActivation = telConfig.CirconusCheckForceMetricActivation
|
||||
cfg.CheckManager.Check.InstanceID = telConfig.CirconusCheckInstanceID
|
||||
cfg.CheckManager.Check.SearchTag = telConfig.CirconusCheckSearchTag
|
||||
cfg.CheckManager.Check.DisplayName = telConfig.CirconusCheckDisplayName
|
||||
cfg.CheckManager.Check.Tags = telConfig.CirconusCheckTags
|
||||
cfg.CheckManager.Broker.ID = telConfig.CirconusBrokerID
|
||||
cfg.CheckManager.Broker.SelectTag = telConfig.CirconusBrokerSelectTag
|
||||
|
||||
|
|
|
@ -149,6 +149,13 @@ type Telemetry struct {
|
|||
// narrow down the search results when neither a Submission URL or Check ID is provided.
|
||||
// Default: service:app (e.g. service:consul)
|
||||
CirconusCheckSearchTag string `hcl:"circonus_check_search_tag"`
|
||||
// CirconusCheckTags is a comma separated list of tags to apply to the check. Note that
|
||||
// the value of CirconusCheckSearchTag will always be added to the check.
|
||||
// Default: none
|
||||
CirconusCheckTags string `mapstructure:"circonus_check_tags"`
|
||||
// CirconusCheckDisplayName is the name for the check which will be displayed in the Circonus UI.
|
||||
// Default: value of CirconusCheckInstanceID
|
||||
CirconusCheckDisplayName string `mapstructure:"circonus_check_display_name"`
|
||||
// CirconusBrokerID is an explicit broker to use when creating a new check. The numeric portion
|
||||
// of broker._cid. If metric management is enabled and neither a Submission URL nor Check ID
|
||||
// is provided, an attempt will be made to search for an existing check using Instance ID and
|
||||
|
@ -597,6 +604,8 @@ func parseTelemetry(result *Config, list *ast.ObjectList) error {
|
|||
"circonus_check_force_metric_activation",
|
||||
"circonus_check_instance_id",
|
||||
"circonus_check_search_tag",
|
||||
"circonus_check_display_name",
|
||||
"circonus_check_tags",
|
||||
"circonus_broker_id",
|
||||
"circonus_broker_select_tag",
|
||||
"disable_hostname",
|
||||
|
|
|
@ -122,6 +122,8 @@ func TestLoadConfigFile_json(t *testing.T) {
|
|||
CirconusCheckForceMetricActivation: "",
|
||||
CirconusCheckInstanceID: "",
|
||||
CirconusCheckSearchTag: "",
|
||||
CirconusCheckDisplayName: "",
|
||||
CirconusCheckTags: "",
|
||||
CirconusBrokerID: "",
|
||||
CirconusBrokerSelectTag: "",
|
||||
},
|
||||
|
@ -191,6 +193,8 @@ func TestLoadConfigFile_json2(t *testing.T) {
|
|||
CirconusCheckForceMetricActivation: "true",
|
||||
CirconusCheckInstanceID: "node1:vault",
|
||||
CirconusCheckSearchTag: "service:vault",
|
||||
CirconusCheckDisplayName: "node1:vault",
|
||||
CirconusCheckTags: "cat1:tag1,cat2:tag2",
|
||||
CirconusBrokerID: "0",
|
||||
CirconusBrokerSelectTag: "dc:sfo",
|
||||
},
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
"circonus_check_force_metric_activation": "true",
|
||||
"circonus_check_instance_id": "node1:vault",
|
||||
"circonus_check_search_tag": "service:vault",
|
||||
"circonus_check_display_name": "node1:vault",
|
||||
"circonus_check_tags": "cat1:tag1,cat2:tag2",
|
||||
"circonus_broker_id": "0",
|
||||
"circonus_broker_select_tag": "dc:sfo"
|
||||
}
|
||||
|
|
|
@ -12,14 +12,16 @@ import (
|
|||
|
||||
// BrokerDetail instance attributes
|
||||
type BrokerDetail struct {
|
||||
CN string `json:"cn"`
|
||||
IP string `json:"ipaddress"`
|
||||
MinVer int `json:"minimum_version_required"`
|
||||
Modules []string `json:"modules"`
|
||||
Port int `json:"port"`
|
||||
Skew string `json:"skew"`
|
||||
Status string `json:"status"`
|
||||
Version int `json:"version"`
|
||||
CN string `json:"cn"`
|
||||
ExternalHost string `json:"external_host"`
|
||||
ExternalPort int `json:"external_port"`
|
||||
IP string `json:"ipaddress"`
|
||||
MinVer int `json:"minimum_version_required"`
|
||||
Modules []string `json:"modules"`
|
||||
Port int `json:"port"`
|
||||
Skew string `json:"skew"`
|
||||
Status string `json:"status"`
|
||||
Version int `json:"version"`
|
||||
}
|
||||
|
||||
// Broker definition
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
"net"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -145,10 +146,10 @@ func (cm *CheckManager) brokerSupportsCheckType(checkType CheckTypeType, details
|
|||
|
||||
// Is the broker valid (active, supports check type, and reachable)
|
||||
func (cm *CheckManager) isValidBroker(broker *api.Broker) bool {
|
||||
brokerPort := 0
|
||||
brokerHost := ""
|
||||
brokerPort := ""
|
||||
valid := false
|
||||
for _, detail := range broker.Details {
|
||||
brokerPort = 43191
|
||||
|
||||
// broker must be active
|
||||
if detail.Status != statusActive {
|
||||
|
@ -166,8 +167,24 @@ func (cm *CheckManager) isValidBroker(broker *api.Broker) bool {
|
|||
continue
|
||||
}
|
||||
|
||||
if detail.ExternalPort != 0 {
|
||||
brokerPort = strconv.Itoa(detail.ExternalPort)
|
||||
} else {
|
||||
if detail.Port != 0 {
|
||||
brokerPort = strconv.Itoa(detail.Port)
|
||||
} else {
|
||||
brokerPort = "43191"
|
||||
}
|
||||
}
|
||||
|
||||
if detail.ExternalHost != "" {
|
||||
brokerHost = detail.ExternalHost
|
||||
} else {
|
||||
brokerHost = detail.IP
|
||||
}
|
||||
|
||||
// broker must be reachable and respond within designated time
|
||||
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", detail.IP, brokerPort), cm.brokerMaxResponseTime)
|
||||
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%s", brokerHost, brokerPort), cm.brokerMaxResponseTime)
|
||||
if err != nil {
|
||||
if detail.CN != "trap.noit.circonus.net" {
|
||||
if cm.Debug {
|
||||
|
@ -176,8 +193,8 @@ func (cm *CheckManager) isValidBroker(broker *api.Broker) bool {
|
|||
continue // not able to reach the broker (or respone slow enough for it to be considered not usable)
|
||||
}
|
||||
// if circonus trap broker, try port 443
|
||||
brokerPort = 443
|
||||
conn, err = net.DialTimeout("tcp", fmt.Sprintf("%s:%d", detail.CN, brokerPort), cm.brokerMaxResponseTime)
|
||||
brokerPort = "443"
|
||||
conn, err = net.DialTimeout("tcp", fmt.Sprintf("%s:%s", detail.CN, brokerPort), cm.brokerMaxResponseTime)
|
||||
if err != nil {
|
||||
if cm.Debug {
|
||||
cm.Log.Printf("[DEBUG] Broker '%s' unable to connect %v\n", broker.Name, err)
|
||||
|
|
|
@ -29,21 +29,41 @@ func (cm *CheckManager) UpdateCheck(newMetrics map[string]*api.CheckBundleMetric
|
|||
return
|
||||
}
|
||||
|
||||
// only if there is *something* to update
|
||||
if !cm.forceCheckUpdate && len(newMetrics) == 0 && len(cm.metricTags) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// refresh check bundle (in case there were changes made by other apps or in UI)
|
||||
checkBundle, err := cm.apih.FetchCheckBundleByCID(api.CIDType(cm.checkBundle.Cid))
|
||||
if err != nil {
|
||||
cm.Log.Printf("[ERROR] unable to fetch up-to-date check bundle %v", err)
|
||||
return
|
||||
}
|
||||
cm.cbmu.Lock()
|
||||
cm.checkBundle = checkBundle
|
||||
cm.cbmu.Unlock()
|
||||
|
||||
cm.addNewMetrics(newMetrics)
|
||||
|
||||
if len(cm.metricTags) > 0 {
|
||||
// note: if a tag has been added (queued) for a metric which never gets sent
|
||||
// the tags will be discarded. (setting tags does not *create* metrics.)
|
||||
for metricName, metricTags := range cm.metricTags {
|
||||
// note: if a tag has been added (queued) for a metric which never gets sent
|
||||
// the tags will be discarded. (setting tags does not *create* metrics.)
|
||||
cm.AddMetricTags(metricName, metricTags, false)
|
||||
for metricIdx, metric := range cm.checkBundle.Metrics {
|
||||
if metric.Name == metricName {
|
||||
cm.checkBundle.Metrics[metricIdx].Tags = metricTags
|
||||
break
|
||||
}
|
||||
}
|
||||
cm.mtmu.Lock()
|
||||
delete(cm.metricTags, metricName)
|
||||
cm.mtmu.Unlock()
|
||||
}
|
||||
cm.forceCheckUpdate = true
|
||||
}
|
||||
|
||||
if cm.forceCheckUpdate {
|
||||
|
||||
newCheckBundle, err := cm.apih.UpdateCheckBundle(cm.checkBundle)
|
||||
if err != nil {
|
||||
cm.Log.Printf("[ERROR] updating check bundle %v", err)
|
||||
|
@ -55,8 +75,6 @@ func (cm *CheckManager) UpdateCheck(newMetrics map[string]*api.CheckBundleMetric
|
|||
cm.checkBundle = newCheckBundle
|
||||
cm.cbmu.Unlock()
|
||||
cm.inventoryMetrics()
|
||||
|
||||
cm.cbmu.Unlock()
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -129,8 +147,8 @@ func (cm *CheckManager) initializeTrapURL() error {
|
|||
}
|
||||
} else {
|
||||
searchCriteria := fmt.Sprintf(
|
||||
"(active:1)(host:\"%s\")(type:\"%s\")(tags:%s)",
|
||||
cm.checkInstanceID, cm.checkType, strings.Join(cm.checkSearchTag, ","))
|
||||
"(active:1)(host:\"%s\")(type:\"%s\")(tags:%s)(notes:%s)",
|
||||
cm.checkTarget, cm.checkType, strings.Join(cm.checkSearchTag, ","), fmt.Sprintf("cgm_instanceid=%s", cm.checkInstanceID))
|
||||
checkBundle, err = cm.checkBundleSearch(searchCriteria)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -245,11 +263,11 @@ func (cm *CheckManager) createNewCheck() (*api.CheckBundle, *api.Broker, error)
|
|||
DisplayName: string(cm.checkDisplayName),
|
||||
Metrics: []api.CheckBundleMetric{},
|
||||
MetricLimit: 0,
|
||||
Notes: "",
|
||||
Notes: fmt.Sprintf("cgm_instanceid=%s", cm.checkInstanceID),
|
||||
Period: 60,
|
||||
Status: statusActive,
|
||||
Tags: append(cm.checkSearchTag, cm.checkTags...),
|
||||
Target: string(cm.checkInstanceID),
|
||||
Target: cm.checkTarget,
|
||||
Timeout: 10,
|
||||
Type: string(cm.checkType),
|
||||
}
|
||||
|
|
|
@ -138,6 +138,7 @@ type CheckManager struct {
|
|||
checkType CheckTypeType
|
||||
checkID api.IDType
|
||||
checkInstanceID CheckInstanceIDType
|
||||
checkTarget string
|
||||
checkSearchTag api.TagType
|
||||
checkSecret CheckSecretType
|
||||
checkTags api.TagType
|
||||
|
@ -258,6 +259,7 @@ func NewCheckManager(cfg *Config) (*CheckManager, error) {
|
|||
if cm.checkInstanceID == "" {
|
||||
cm.checkInstanceID = CheckInstanceIDType(fmt.Sprintf("%s:%s", hn, an))
|
||||
}
|
||||
cm.checkTarget = hn
|
||||
|
||||
if cfg.Check.SearchTag == "" {
|
||||
cm.checkSearchTag = []string{fmt.Sprintf("service:%s", an)}
|
||||
|
@ -270,7 +272,7 @@ func NewCheckManager(cfg *Config) (*CheckManager, error) {
|
|||
}
|
||||
|
||||
if cm.checkDisplayName == "" {
|
||||
cm.checkDisplayName = CheckDisplayNameType(fmt.Sprintf("%s /cgm", string(cm.checkInstanceID)))
|
||||
cm.checkDisplayName = CheckDisplayNameType(fmt.Sprintf("%s", string(cm.checkInstanceID)))
|
||||
}
|
||||
|
||||
dur := cfg.Check.MaxURLAge
|
||||
|
|
|
@ -37,58 +37,38 @@ func (cm *CheckManager) AddMetricTags(metricName string, tags []string, appendTa
|
|||
return tagsUpdated
|
||||
}
|
||||
|
||||
metricFound := false
|
||||
if _, exists := cm.metricTags[metricName]; !exists {
|
||||
foundMetric := false
|
||||
|
||||
for metricIdx, metric := range cm.checkBundle.Metrics {
|
||||
if metric.Name == metricName {
|
||||
metricFound = true
|
||||
numNewTags := countNewTags(metric.Tags, tags)
|
||||
|
||||
if numNewTags == 0 {
|
||||
if appendTags {
|
||||
break // no new tags to add
|
||||
} else if len(metric.Tags) == len(tags) {
|
||||
break // no new tags and old/new same length
|
||||
}
|
||||
for _, metric := range cm.checkBundle.Metrics {
|
||||
if metric.Name == metricName {
|
||||
foundMetric = true
|
||||
cm.metricTags[metricName] = metric.Tags
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if appendTags {
|
||||
metric.Tags = append(metric.Tags, tags...)
|
||||
} else {
|
||||
metric.Tags = tags
|
||||
}
|
||||
|
||||
cm.cbmu.Lock()
|
||||
cm.checkBundle.Metrics[metricIdx] = metric
|
||||
cm.cbmu.Unlock()
|
||||
|
||||
tagsUpdated = true
|
||||
if !foundMetric {
|
||||
cm.metricTags[metricName] = []string{}
|
||||
}
|
||||
}
|
||||
|
||||
if tagsUpdated {
|
||||
if cm.Debug {
|
||||
action := "Set"
|
||||
if appendTags {
|
||||
action = "Added"
|
||||
}
|
||||
cm.Log.Printf("[DEBUG] %s metric tag(s) %s %v\n", action, metricName, tags)
|
||||
action := "no new"
|
||||
if appendTags {
|
||||
numNewTags := countNewTags(cm.metricTags[metricName], tags)
|
||||
if numNewTags > 0 {
|
||||
action = "Added"
|
||||
cm.metricTags[metricName] = append(cm.metricTags[metricName], tags...)
|
||||
tagsUpdated = true
|
||||
}
|
||||
cm.cbmu.Lock()
|
||||
cm.forceCheckUpdate = true
|
||||
cm.cbmu.Unlock()
|
||||
} else {
|
||||
if !metricFound {
|
||||
if _, exists := cm.metricTags[metricName]; !exists {
|
||||
if cm.Debug {
|
||||
cm.Log.Printf("[DEBUG] Queing metric tag(s) %s %v\n", metricName, tags)
|
||||
}
|
||||
// queue the tags, the metric is new (e.g. not in the check yet)
|
||||
cm.mtmu.Lock()
|
||||
cm.metricTags[metricName] = append(cm.metricTags[metricName], tags...)
|
||||
cm.mtmu.Unlock()
|
||||
}
|
||||
}
|
||||
action = "Set"
|
||||
cm.metricTags[metricName] = tags
|
||||
tagsUpdated = true
|
||||
}
|
||||
|
||||
if cm.Debug {
|
||||
cm.Log.Printf("[DEBUG] %s metric tag(s) %s %v\n", action, metricName, tags)
|
||||
}
|
||||
|
||||
return tagsUpdated
|
||||
|
@ -103,6 +83,7 @@ func (cm *CheckManager) addNewMetrics(newMetrics map[string]*api.CheckBundleMetr
|
|||
}
|
||||
|
||||
cm.cbmu.Lock()
|
||||
defer cm.cbmu.Unlock()
|
||||
|
||||
numCurrMetrics := len(cm.checkBundle.Metrics)
|
||||
numNewMetrics := len(newMetrics)
|
||||
|
@ -126,8 +107,6 @@ func (cm *CheckManager) addNewMetrics(newMetrics map[string]*api.CheckBundleMetr
|
|||
cm.forceCheckUpdate = true
|
||||
}
|
||||
|
||||
cm.cbmu.Unlock()
|
||||
|
||||
return updatedCheckBundle
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
DEFAULT_HIST_SIZE = int16(100)
|
||||
DEFAULT_HIST_SIZE = uint16(100)
|
||||
)
|
||||
|
||||
var power_of_ten = [...]float64{
|
||||
|
@ -70,6 +70,14 @@ func NewBinFromFloat64(d float64) *Bin {
|
|||
hb.SetFromFloat64(d)
|
||||
return hb
|
||||
}
|
||||
|
||||
type FastL2 struct {
|
||||
l1, l2 int
|
||||
}
|
||||
|
||||
func (hb *Bin) fastl2() FastL2 {
|
||||
return FastL2{l1: int(uint8(hb.exp)), l2: int(uint8(hb.val))}
|
||||
}
|
||||
func (hb *Bin) SetFromFloat64(d float64) *Bin {
|
||||
hb.val = -1
|
||||
if math.IsInf(d, 0) || math.IsNaN(d) {
|
||||
|
@ -117,10 +125,7 @@ func (hb *Bin) SetFromFloat64(d float64) *Bin {
|
|||
return hb
|
||||
}
|
||||
func (hb *Bin) PowerOfTen() float64 {
|
||||
idx := int(hb.exp)
|
||||
if idx < 0 {
|
||||
idx = 256 + idx
|
||||
}
|
||||
idx := int(uint8(hb.exp))
|
||||
return power_of_ten[idx]
|
||||
}
|
||||
|
||||
|
@ -183,69 +188,58 @@ func (hb *Bin) Left() float64 {
|
|||
}
|
||||
|
||||
func (h1 *Bin) Compare(h2 *Bin) int {
|
||||
if h1.val == h2.val && h1.exp == h2.exp {
|
||||
return 0
|
||||
var v1, v2 int
|
||||
|
||||
// slide exp positive,
|
||||
// shift by size of val
|
||||
// multiple by (val != 0)
|
||||
// then add or subtract val accordingly
|
||||
|
||||
if h1.val >= 0 {
|
||||
v1 = ((int(h1.exp)+256)<<8)*int(((h1.val|(^h1.val+1))>>8)&1) + int(h1.val)
|
||||
} else {
|
||||
v1 = ((int(h1.exp)+256)<<8)*int(((h1.val|(^h1.val+1))>>8)&1) - int(h1.val)
|
||||
}
|
||||
if h1.val == -1 {
|
||||
return 1
|
||||
if h2.val >= 0 {
|
||||
v2 = ((int(h2.exp)+256)<<8)*int(((h2.val|(^h2.val+1))>>8)&1) + int(h2.val)
|
||||
} else {
|
||||
v2 = ((int(h2.exp)+256)<<8)*int(((h2.val|(^h2.val+1))>>8)&1) - int(h2.val)
|
||||
}
|
||||
if h2.val == -1 {
|
||||
return -1
|
||||
}
|
||||
if h1.val == 0 {
|
||||
if h2.val > 0 {
|
||||
return 1
|
||||
}
|
||||
return -1
|
||||
}
|
||||
if h2.val == 0 {
|
||||
if h1.val < 0 {
|
||||
return 1
|
||||
}
|
||||
return -1
|
||||
}
|
||||
if h1.val < 0 && h2.val > 0 {
|
||||
return 1
|
||||
}
|
||||
if h1.val > 0 && h2.val < 0 {
|
||||
return -1
|
||||
}
|
||||
if h1.exp == h2.exp {
|
||||
if h1.val < h2.val {
|
||||
return 1
|
||||
}
|
||||
return -1
|
||||
}
|
||||
if h1.exp > h2.exp {
|
||||
if h1.val < 0 {
|
||||
return 1
|
||||
}
|
||||
return -1
|
||||
}
|
||||
if h1.exp < h2.exp {
|
||||
if h1.val < 0 {
|
||||
return -1
|
||||
}
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
|
||||
// return the difference
|
||||
return v2 - v1
|
||||
}
|
||||
|
||||
// This histogram structure tracks values are two decimal digits of precision
|
||||
// with a bounded error that remains bounded upon composition
|
||||
type Histogram struct {
|
||||
mutex sync.Mutex
|
||||
bvs []Bin
|
||||
used int16
|
||||
allocd int16
|
||||
used uint16
|
||||
allocd uint16
|
||||
|
||||
lookup [256][]uint16
|
||||
|
||||
mutex sync.Mutex
|
||||
useLocks bool
|
||||
}
|
||||
|
||||
// New returns a new Histogram
|
||||
func New() *Histogram {
|
||||
return &Histogram{
|
||||
allocd: DEFAULT_HIST_SIZE,
|
||||
used: 0,
|
||||
bvs: make([]Bin, DEFAULT_HIST_SIZE),
|
||||
allocd: DEFAULT_HIST_SIZE,
|
||||
used: 0,
|
||||
bvs: make([]Bin, DEFAULT_HIST_SIZE),
|
||||
useLocks: true,
|
||||
}
|
||||
}
|
||||
|
||||
// New returns a Histogram without locking
|
||||
func NewNoLocks() *Histogram {
|
||||
return &Histogram{
|
||||
allocd: DEFAULT_HIST_SIZE,
|
||||
used: 0,
|
||||
bvs: make([]Bin, DEFAULT_HIST_SIZE),
|
||||
useLocks: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,9 +260,24 @@ func (h *Histogram) Mean() float64 {
|
|||
|
||||
// Reset forgets all bins in the histogram (they remain allocated)
|
||||
func (h *Histogram) Reset() {
|
||||
h.mutex.Lock()
|
||||
if h.useLocks {
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
}
|
||||
for i := 0; i < 256; i++ {
|
||||
if h.lookup[i] != nil {
|
||||
for j := range h.lookup[i] {
|
||||
h.lookup[i][j] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
h.used = 0
|
||||
h.mutex.Unlock()
|
||||
}
|
||||
|
||||
// RecordIntScale records an integer scaler value, returning an error if the
|
||||
// value is out of range.
|
||||
func (h *Histogram) RecordIntScale(val, scale int) error {
|
||||
return h.RecordIntScales(val, scale, 1)
|
||||
}
|
||||
|
||||
// RecordValue records the given value, returning an error if the value is out
|
||||
|
@ -304,14 +313,20 @@ func (h *Histogram) RecordCorrectedValue(v, expectedInterval int64) error {
|
|||
}
|
||||
|
||||
// find where a new bin should go
|
||||
func (h *Histogram) InternalFind(hb *Bin) (bool, int16) {
|
||||
func (h *Histogram) InternalFind(hb *Bin) (bool, uint16) {
|
||||
if h.used == 0 {
|
||||
return false, 0
|
||||
}
|
||||
f2 := hb.fastl2()
|
||||
if h.lookup[f2.l1] != nil {
|
||||
if idx := h.lookup[f2.l1][f2.l2]; idx != 0 {
|
||||
return true, idx - 1
|
||||
}
|
||||
}
|
||||
rv := -1
|
||||
idx := int16(0)
|
||||
l := int16(0)
|
||||
r := h.used - 1
|
||||
idx := uint16(0)
|
||||
l := int(0)
|
||||
r := int(h.used - 1)
|
||||
for l < r {
|
||||
check := (r + l) / 2
|
||||
rv = h.bvs[check].Compare(hb)
|
||||
|
@ -327,7 +342,7 @@ func (h *Histogram) InternalFind(hb *Bin) (bool, int16) {
|
|||
if rv != 0 {
|
||||
rv = h.bvs[l].Compare(hb)
|
||||
}
|
||||
idx = l
|
||||
idx = uint16(l)
|
||||
if rv == 0 {
|
||||
return true, idx
|
||||
}
|
||||
|
@ -339,10 +354,9 @@ func (h *Histogram) InternalFind(hb *Bin) (bool, int16) {
|
|||
}
|
||||
|
||||
func (h *Histogram) InsertBin(hb *Bin, count int64) uint64 {
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
if count == 0 {
|
||||
return 0
|
||||
if h.useLocks {
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
}
|
||||
found, idx := h.InternalFind(hb)
|
||||
if !found {
|
||||
|
@ -363,13 +377,20 @@ func (h *Histogram) InsertBin(hb *Bin, count int64) uint64 {
|
|||
h.bvs[idx].exp = hb.exp
|
||||
h.bvs[idx].count = uint64(count)
|
||||
h.used++
|
||||
for i := idx; i < h.used; i++ {
|
||||
f2 := h.bvs[i].fastl2()
|
||||
if h.lookup[f2.l1] == nil {
|
||||
h.lookup[f2.l1] = make([]uint16, 256)
|
||||
}
|
||||
h.lookup[f2.l1][f2.l2] = uint16(i) + 1
|
||||
}
|
||||
return h.bvs[idx].count
|
||||
}
|
||||
var newval uint64
|
||||
if count < 0 {
|
||||
newval = h.bvs[idx].count - uint64(-count)
|
||||
} else {
|
||||
if count >= 0 {
|
||||
newval = h.bvs[idx].count + uint64(count)
|
||||
} else {
|
||||
newval = h.bvs[idx].count - uint64(-count)
|
||||
}
|
||||
if newval < h.bvs[idx].count { //rolled
|
||||
newval = ^uint64(0)
|
||||
|
@ -378,6 +399,39 @@ func (h *Histogram) InsertBin(hb *Bin, count int64) uint64 {
|
|||
return newval - h.bvs[idx].count
|
||||
}
|
||||
|
||||
// RecordIntScales records n occurrences of the given value, returning an error if
|
||||
// the value is out of range.
|
||||
func (h *Histogram) RecordIntScales(val, scale int, n int64) error {
|
||||
sign := 1
|
||||
if val == 0 {
|
||||
scale = 0
|
||||
} else {
|
||||
if val < 0 {
|
||||
val = 0 - val
|
||||
sign = -1
|
||||
}
|
||||
if val < 10 {
|
||||
val *= 10
|
||||
scale -= 1
|
||||
}
|
||||
for val > 100 {
|
||||
val /= 10
|
||||
scale++
|
||||
}
|
||||
}
|
||||
if scale < -128 {
|
||||
val = 0
|
||||
scale = 0
|
||||
} else if scale > 127 {
|
||||
val = 0xff
|
||||
scale = 0
|
||||
}
|
||||
val *= sign
|
||||
hb := Bin{val: int8(val), exp: int8(scale), count: 0}
|
||||
h.InsertBin(&hb, n)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RecordValues records n occurrences of the given value, returning an error if
|
||||
// the value is out of range.
|
||||
func (h *Histogram) RecordValues(v float64, n int64) error {
|
||||
|
@ -389,11 +443,13 @@ func (h *Histogram) RecordValues(v float64, n int64) error {
|
|||
|
||||
// Approximate mean
|
||||
func (h *Histogram) ApproxMean() float64 {
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
if h.useLocks {
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
}
|
||||
divisor := 0.0
|
||||
sum := 0.0
|
||||
for i := int16(0); i < h.used; i++ {
|
||||
for i := uint16(0); i < h.used; i++ {
|
||||
midpoint := h.bvs[i].Midpoint()
|
||||
cardinality := float64(h.bvs[i].count)
|
||||
divisor += cardinality
|
||||
|
@ -407,10 +463,12 @@ func (h *Histogram) ApproxMean() float64 {
|
|||
|
||||
// Approximate sum
|
||||
func (h *Histogram) ApproxSum() float64 {
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
if h.useLocks {
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
}
|
||||
sum := 0.0
|
||||
for i := int16(0); i < h.used; i++ {
|
||||
for i := uint16(0); i < h.used; i++ {
|
||||
midpoint := h.bvs[i].Midpoint()
|
||||
cardinality := float64(h.bvs[i].count)
|
||||
sum += midpoint * cardinality
|
||||
|
@ -419,10 +477,12 @@ func (h *Histogram) ApproxSum() float64 {
|
|||
}
|
||||
|
||||
func (h *Histogram) ApproxQuantile(q_in []float64) ([]float64, error) {
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
if h.useLocks {
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
}
|
||||
q_out := make([]float64, len(q_in))
|
||||
i_q, i_b := 0, int16(0)
|
||||
i_q, i_b := 0, uint16(0)
|
||||
total_cnt, bin_width, bin_left, lower_cnt, upper_cnt := 0.0, 0.0, 0.0, 0.0, 0.0
|
||||
if len(q_in) == 0 {
|
||||
return q_out, nil
|
||||
|
@ -485,8 +545,10 @@ func (h *Histogram) ApproxQuantile(q_in []float64) ([]float64, error) {
|
|||
|
||||
// ValueAtQuantile returns the recorded value at the given quantile (0..1).
|
||||
func (h *Histogram) ValueAtQuantile(q float64) float64 {
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
if h.useLocks {
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
}
|
||||
q_in := make([]float64, 1)
|
||||
q_in[0] = q
|
||||
q_out, err := h.ApproxQuantile(q_in)
|
||||
|
@ -505,16 +567,20 @@ func (h *Histogram) SignificantFigures() int64 {
|
|||
|
||||
// Equals returns true if the two Histograms are equivalent, false if not.
|
||||
func (h *Histogram) Equals(other *Histogram) bool {
|
||||
h.mutex.Lock()
|
||||
other.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
defer other.mutex.Unlock()
|
||||
if h.useLocks {
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
}
|
||||
if other.useLocks {
|
||||
other.mutex.Lock()
|
||||
defer other.mutex.Unlock()
|
||||
}
|
||||
switch {
|
||||
case
|
||||
h.used != other.used:
|
||||
return false
|
||||
default:
|
||||
for i := int16(0); i < h.used; i++ {
|
||||
for i := uint16(0); i < h.used; i++ {
|
||||
if h.bvs[i].Compare(&other.bvs[i]) != 0 {
|
||||
return false
|
||||
}
|
||||
|
@ -527,8 +593,10 @@ func (h *Histogram) Equals(other *Histogram) bool {
|
|||
}
|
||||
|
||||
func (h *Histogram) CopyAndReset() *Histogram {
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
if h.useLocks {
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
}
|
||||
newhist := &Histogram{
|
||||
allocd: h.allocd,
|
||||
used: h.used,
|
||||
|
@ -537,11 +605,20 @@ func (h *Histogram) CopyAndReset() *Histogram {
|
|||
h.allocd = DEFAULT_HIST_SIZE
|
||||
h.bvs = make([]Bin, DEFAULT_HIST_SIZE)
|
||||
h.used = 0
|
||||
for i := 0; i < 256; i++ {
|
||||
if h.lookup[i] != nil {
|
||||
for j := range h.lookup[i] {
|
||||
h.lookup[i][j] = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
return newhist
|
||||
}
|
||||
func (h *Histogram) DecStrings() []string {
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
if h.useLocks {
|
||||
h.mutex.Lock()
|
||||
defer h.mutex.Unlock()
|
||||
}
|
||||
out := make([]string, h.used)
|
||||
for i, bin := range h.bvs[0:h.used] {
|
||||
var buffer bytes.Buffer
|
||||
|
|
|
@ -267,26 +267,26 @@
|
|||
{
|
||||
"checksumSHA1": "szvY4u7TlXkrQ3PW8wmyJaIFy0U=",
|
||||
"path": "github.com/circonus-labs/circonus-gometrics",
|
||||
"revision": "f8e2e2ff37c349aed537b70c9430ded0ea473248",
|
||||
"revisionTime": "2016-11-01T19:28:51Z"
|
||||
"revision": "d17a8420c36e800fcb46bbd4d2a15b93c68605ea",
|
||||
"revisionTime": "2016-11-09T19:23:37Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "dCnZd/wjQjTnUBTBEDpe0Y2pvTA=",
|
||||
"checksumSHA1": "WUE6oF152uN5FcLmmq+nO3Yl7pU=",
|
||||
"path": "github.com/circonus-labs/circonus-gometrics/api",
|
||||
"revision": "f8e2e2ff37c349aed537b70c9430ded0ea473248",
|
||||
"revisionTime": "2016-11-01T19:28:51Z"
|
||||
"revision": "d17a8420c36e800fcb46bbd4d2a15b93c68605ea",
|
||||
"revisionTime": "2016-11-09T19:23:37Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "B0hN7c1dJ8n3MoZLktuWJoaYxRs=",
|
||||
"checksumSHA1": "beRBHHy2+V6Ht4cACIMmZOCnzgg=",
|
||||
"path": "github.com/circonus-labs/circonus-gometrics/checkmgr",
|
||||
"revision": "f8e2e2ff37c349aed537b70c9430ded0ea473248",
|
||||
"revisionTime": "2016-11-01T19:28:51Z"
|
||||
"revision": "d17a8420c36e800fcb46bbd4d2a15b93c68605ea",
|
||||
"revisionTime": "2016-11-09T19:23:37Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "C4Z7+l5GOpOCW5DcvNYzheGvQRE=",
|
||||
"checksumSHA1": "IP3nkm1BmkAxGYpgeGuUfJYypy8=",
|
||||
"path": "github.com/circonus-labs/circonusllhist",
|
||||
"revision": "d724266ae5270ae8b87a5d2e8081f04e307c3c18",
|
||||
"revisionTime": "2016-05-26T04:38:13Z"
|
||||
"revision": "0e8e86d926b63602c762b8b5647fe14ae2ba6757",
|
||||
"revisionTime": "2016-11-10T01:51:05Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "vcncrPAdKKpLjl5O5lAdrFU6NOc=",
|
||||
|
|
|
@ -200,10 +200,16 @@ is within the object itself.
|
|||
Force activation of metrics which already exist and are not currently active. If check management is enabled, the default behavior is to add new metrics as they are encountered. If the metric already exists in the check, it will **not** be activated. This setting overrides that behavior. By default, this is set to "false".
|
||||
|
||||
* `circonus_check_instance_id`
|
||||
Serves to uniquely identify the metrics coming from this *instance*. It can be used to maintain metric continuity with transient or ephemeral instances as they move around within an infrastructure. By default, this is set to hostname:application name (e.g. "host123:consul").
|
||||
Serves to uniquely identify the metrics coming from this *instance*. It can be used to maintain metric continuity with transient or ephemeral instances as they move around within an infrastructure. By default, this is set to hostname:application name (e.g. "host123:vault").
|
||||
|
||||
* `circonus_check_search_tag`
|
||||
A special tag which, when coupled with the instance id, helps to narrow down the search results when neither a Submission URL or Check ID is provided. By default, this is set to service:app (e.g. "service:consul").
|
||||
A special tag which, when coupled with the instance id, helps to narrow down the search results when neither a Submission URL or Check ID is provided. By default, this is set to service:app (e.g. "service:vault").
|
||||
|
||||
* `circonus_check_display_name`
|
||||
Specifies a name to give a check when it is created. This name is displayed in the Circonus UI Checks list.
|
||||
|
||||
* `circonus_check_tags`
|
||||
Comma separated list of additional tags to add to a check when it is created.
|
||||
|
||||
* `circonus_broker_id`
|
||||
The ID of a specific Circonus Broker to use when creating a new check. The numeric portion of `broker._cid` field in a Broker API object. If metric management is enabled and neither a Submission URL nor Check ID is provided, an attempt will be made to search for an existing check using Instance ID and Search Tag. If one is not found, a new HTTPTRAP check will be created. By default, this is not used and a random Enterprise Broker is selected, or, the default Circonus Public Broker.
|
||||
|
|
Loading…
Reference in New Issue