cmd/bosun: Azure Monitor Datasource #2283
Conversation
For review except the metric metadata function which can be ignored for now. Also will vendor later. cc @mhenderson-so . |
DebugResponse bool | ||
} | ||
|
||
// Valid returns if the configuration for the AzureMonitor |
kylebrandt
Jul 31, 2018
Author
Member
fix comment
fix comment
return allClients | ||
} | ||
|
||
func azureLogRequest() autorest.PrepareDecorator { |
kylebrandt
Jul 31, 2018
Author
Member
Comment this function and the following, add comment to attribute source of readme from the go azure sdk
Comment this function and the following, add comment to attribute source of readme from the go azure sdk
captncraig
Jul 31, 2018
Contributor
Are these even required long term?
Are these even required long term?
kylebrandt
Jul 31, 2018
Author
Member
I don't think they hurt, and since the documentation is marking the experimental for now they could be handy. I would probably be better if more datasources had this I think
I don't think they hurt, and since the documentation is marking the experimental for now they could be handy. I would probably be better if more datasources had this I think
if err != nil { | ||
slog.Warningf("failure to dump azure request: %v", err) | ||
} | ||
dump, _ := httputil.DumpRequestOut(r, true) |
kylebrandt
Jul 31, 2018
Author
Member
check + log err
check + log err
if err != nil { | ||
slog.Warningf("failure to dump azure request: %v", err) | ||
} | ||
dump, _ := httputil.DumpResponse(r, true) |
kylebrandt
Jul 31, 2018
Author
Member
check + log err
check + log err
}, | ||
} | ||
|
||
// Tag function for the "az" expression function |
kylebrandt
Jul 31, 2018
Author
Member
comment: azTags is
comment: azTags is
return azureTags(args[2]) | ||
} | ||
|
||
// Tag function for the "azmulti" expression function |
kylebrandt
Jul 31, 2018
Author
Member
comment: azMultiTags is
comment: azMultiTags is
|
||
// azureTags adds tags for the csv argument along with the "name" and "rsg" tags | ||
func azureTags(arg parse.Node) (parse.Tags, error) { | ||
tags := parse.Tags{"name": struct{}{}, "rsg": struct{}{}} |
kylebrandt
Jul 31, 2018
Author
Member
make name and rsg constants and change in all places where referenced
make name and rsg constants and change in all places where referenced
|
||
const azTimeFmt = "2006-01-02T15:04:05" | ||
|
||
func azResourceURI(subscription, resourceGrp, Namespace, Resource string) string { |
kylebrandt
Jul 31, 2018
Author
Member
comment func
comment func
return | ||
} | ||
|
||
// AzureQuery queries an Azure monitor metric for the given resource and returns a series set tagged by |
kylebrandt
Jul 31, 2018
Author
Member
finish this func comment
finish this func comment
// Verify prefix is a defined resource and fetch the collection of clients | ||
cc, clientFound := e.Backends.AzureMonitor[prefix] | ||
if !clientFound { | ||
return r, fmt.Errorf("azure client with name %v not defined", prefix) |
kylebrandt
Jul 31, 2018
Author
Member
... "%v" ...
... "%v" ...
st := e.now.Add(time.Duration(-sd)).Format(azTimeFmt) | ||
en := e.now.Add(time.Duration(-ed)).Format(azTimeFmt) | ||
|
||
// Set Dimensions (tag) keys for metrics that support them by building a filter |
kylebrandt
Jul 31, 2018
Author
Member
expand on comment , link to https://docs.microsoft.com/en-us/rest/api/monitor/filter-syntax
expand on comment , link to https://docs.microsoft.com/en-us/rest/api/monitor/filter-syntax
tg = azureIntervalToTimegrain(interval) | ||
} | ||
|
||
// Set azure aggregation method |
kylebrandt
Jul 31, 2018
Author
Member
Find various "azure" comments and replace with "Azure" (casing)
Find various "azure" comments and replace with "Azure" (casing)
if err != nil { | ||
slog.Errorf("failure to parse remaning reads from azure response") | ||
} else { | ||
collect.Sample("azure.remaining_reads", opentsdb.TagSet{"prefix": prefix}, float64(readsRemaining)) |
kylebrandt
Jul 31, 2018
Author
Member
add comment explaining why this is sampled
add comment explaining why this is sampled
// collectCache is a helper function for collecting metrics on | ||
// the expression cache | ||
func collectCacheHit(cacheName, qType string, hit bool) { | ||
tags := opentsdb.TagSet{"query_type": qType, "name": cacheName} |
kylebrandt
Jul 31, 2018
Author
Member
add metadata for these metrics
add metadata for these metrics
} | ||
series := make(Series) | ||
tags := make(opentsdb.TagSet) | ||
tags["rsg"] = rsg |
kylebrandt
Jul 31, 2018
Author
Member
ref constant here
ref constant here
} | ||
} | ||
for _, mValue := range *dataContainer.Data { | ||
exValue := azureExtractMetricValue(&mValue, aggLong) |
kylebrandt
Jul 31, 2018
Author
Member
add comment
add comment
for res := range resCh { | ||
queryResults = append(queryResults, res) | ||
} | ||
// Merge the query results into a single seriesSet |
kylebrandt
Jul 31, 2018
Author
Member
skip merge if length of set is not gt than 1
skip merge if length of set is not gt than 1
// or tags associated with that resource | ||
func AzureFilterResources(e *State, T miniprofiler.Timer, resources AzureResources, filter string) (r *Results, err error) { | ||
r = new(Results) | ||
bqf, err := boolq.Parse(filter) |
kylebrandt
Jul 31, 2018
Author
Member
add comment
add comment
if len(sp) != 2 { | ||
return false, fmt.Errorf("bad filter, filter must be in k:v format, got %v", filter) | ||
} | ||
key := strings.ToLower(sp[0]) // Make key case insensitive |
kylebrandt
Jul 31, 2018
Author
Member
note case insensitivity in expression docs
note case insensitivity in expression docs
key := strings.ToLower(sp[0]) // Make key case insensitive | ||
value := sp[1] | ||
switch key { | ||
case "name": |
kylebrandt
Jul 31, 2018
Author
Member
consts again for name, rsg
consts again for name, rsg
if re.MatchString(ar.Name) { | ||
return true, nil | ||
} | ||
case "rsg", "resourcegroup": |
kylebrandt
Jul 31, 2018
Author
Member
remove "resourcegroup" alias, no real point, update expr docs to reflect
remove "resourcegroup" alias, no real point, update expr docs to reflect
case string(insights.Maximum): | ||
v = mv.Maximum | ||
case string(insights.Total): | ||
v = mv.Total |
kylebrandt
Jul 31, 2018
Author
Member
add missing None aggregation
add missing None aggregation
kylebrandt
Aug 1, 2018
Author
Member
nm, None isn't a field in the sdk
nm, None isn't a field in the sdk
return string(insights.Maximum), nil | ||
case "total": | ||
return string(insights.Total), nil | ||
case "count": |
kylebrandt
Jul 31, 2018
Author
Member
add missing none aggregation here as well
add missing none aggregation here as well
Seems pretty good to me. Just finish out todos and comments. |
@@ -84,6 +94,7 @@ func (sc *SystemConf) EnabledBackends() EnabledBackends { | |||
b.Influx = sc.InfluxConf.URL != "" | |||
b.Elastic = len(sc.ElasticConf["default"].Hosts) != 0 | |||
b.Annotate = len(sc.AnnotateConf.Hosts) != 0 | |||
b.AzureMonitor = sc.AzureMonitorConf["default"].ClientId != "" |
captncraig
Jul 31, 2018
Contributor
This feels like a weak thing to check. Are they required to have a "default"? Is ClientID required? (assume thats a credential of some kind?)
This feels like a weak thing to check. Are they required to have a "default"? Is ClientID required? (assume thats a credential of some kind?)
kylebrandt
Jul 31, 2018
Author
Member
Agreed will make something better, this is left from my first pass
Agreed will make something better, this is left from my first pass
clients.MetricsClient = insights.NewMetricsClient(conf.SubscriptionId) | ||
clients.MetricDefinitionsClient = insights.NewMetricDefinitionsClient(conf.SubscriptionId) | ||
clients.ResourcesClient = resources.NewClient(conf.SubscriptionId) | ||
if conf.DebugRequest { |
captncraig
Jul 31, 2018
Contributor
Do we really need these debug things long term? I'd probably prefer not having a million different config options if we can avoid it.
Do we really need these debug things long term? I'd probably prefer not having a million different config options if we can avoid it.
kylebrandt
Jul 31, 2018
Author
Member
Just two options. Could help with people debugging issues, in particular since I saw what I think is a bug in the SDK about error being missed.
Just two options. Could help with people debugging issues, in particular since I saw what I think is a bug in the SDK about error being missed.
if err != nil { | ||
// Should not hit this since we check for authorizer errors in Validation | ||
// This is checked before because this method is not called until the an expression is called | ||
slog.Fatal("Azure conf: ", err) |
captncraig
Jul 31, 2018
Contributor
Fatal feels wrong here. Does this method get invoked every time an expression runs? If azure is down intermittently, could this crash bosun?
Fatal feels wrong here. Does this method get invoked every time an expression runs? If azure is down intermittently, could this crash bosun?
kylebrandt
Jul 31, 2018
Author
Member
I don't think this actually make any API calls and is just a validity thing. So it should be caught by Valid() method, but added this here in case I'm wrong.
I don't think this actually make any API calls and is just a validity thing. So it should be caught by Valid() method, but added this here in case I'm wrong.
return allClients | ||
} | ||
|
||
func azureLogRequest() autorest.PrepareDecorator { |
captncraig
Jul 31, 2018
Contributor
Are these even required long term?
Are these even required long term?
F: AzureMultiQuery, | ||
PrefixEnabled: true, | ||
}, | ||
"azmd": { // TODO Finish and document this func |
captncraig
Jul 31, 2018
Contributor
todo
todo
F: AzureResourcesByType, | ||
PrefixEnabled: true, | ||
}, | ||
"azrf": { |
captncraig
Jul 31, 2018
Contributor
azrf or azfr? Inner function is "FilterResources", so maybe azfr matches better? I kinda hate short names.
azrf or azfr? Inner function is "FilterResources", so maybe azfr matches better? I kinda hate short names.
kylebrandt
Aug 1, 2018
Author
Member
I think like azrf because it shares the azr prefix with azrt
I think like azrf because it shares the azr prefix with azrt
} | ||
|
||
// AzureMetricDefinitions fetches metric information for a specific resource and metric tuple | ||
// TODO make this return and not fmt.Printf |
captncraig
Jul 31, 2018
Contributor
todo
todo
return | ||
} | ||
} | ||
st := e.now.Add(time.Duration(-sd)).Format(azTimeFmt) |
captncraig
Jul 31, 2018
Contributor
"startTime" and "endTime" would not be unreasonable names.
"startTime" and "endTime" would not be unreasonable names.
kylebrandt
Jul 31, 2018
Author
Member
When this is done I want to go back and make a method on the State that does since we use it all the time.
When this is done I want to go back and make a method on the State that does since we use it all the time.
this includes an incomplete azure metadata function with TODOs to be completed in a future commit.
so metrics can be collected
No description provided.