cmd/bosun: Azure Monitor Datasource - #2283
Conversation
e22f47c to
1fc3f64
Compare
|
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 |
| return allClients | ||
| } | ||
|
|
||
| func azureLogRequest() autorest.PrepareDecorator { |
There was a problem hiding this comment.
Comment this function and the following, add comment to attribute source of readme from the go azure sdk
There was a problem hiding this comment.
Are these even required long term?
There was a problem hiding this comment.
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) |
| if err != nil { | ||
| slog.Warningf("failure to dump azure request: %v", err) | ||
| } | ||
| dump, _ := httputil.DumpResponse(r, true) |
| }, | ||
| } | ||
|
|
||
| // Tag function for the "az" expression function |
| return azureTags(args[2]) | ||
| } | ||
|
|
||
| // Tag function for the "azmulti" expression function |
There was a problem hiding this comment.
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{}{}} |
There was a problem hiding this comment.
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 { |
| return | ||
| } | ||
|
|
||
| // AzureQuery queries an Azure monitor metric for the given resource and returns a series set tagged by |
There was a problem hiding this 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) |
| 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 |
There was a problem hiding this comment.
expand on comment , link to https://docs.microsoft.com/en-us/rest/api/monitor/filter-syntax
| tg = azureIntervalToTimegrain(interval) | ||
| } | ||
|
|
||
| // Set azure aggregation method |
There was a problem hiding this comment.
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)) |
There was a problem hiding this comment.
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} |
There was a problem hiding this comment.
add metadata for these metrics
| } | ||
| series := make(Series) | ||
| tags := make(opentsdb.TagSet) | ||
| tags["rsg"] = rsg |
| } | ||
| } | ||
| for _, mValue := range *dataContainer.Data { | ||
| exValue := azureExtractMetricValue(&mValue, aggLong) |
| for res := range resCh { | ||
| queryResults = append(queryResults, res) | ||
| } | ||
| // Merge the query results into a single seriesSet |
There was a problem hiding this comment.
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) |
| 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 |
There was a problem hiding this comment.
note case insensitivity in expression docs
| key := strings.ToLower(sp[0]) // Make key case insensitive | ||
| value := sp[1] | ||
| switch key { | ||
| case "name": |
There was a problem hiding this comment.
consts again for name, rsg
| if re.MatchString(ar.Name) { | ||
| return true, nil | ||
| } | ||
| case "rsg", "resourcegroup": |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
add missing None aggregation
There was a problem hiding this comment.
nm, None isn't a field in the sdk
| return string(insights.Maximum), nil | ||
| case "total": | ||
| return string(insights.Total), nil | ||
| case "count": |
There was a problem hiding this comment.
add missing none aggregation here as well
captncraig
left a comment
There was a problem hiding this comment.
Seems pretty good to me. Just finish out todos and comments.
| 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 != "" |
There was a problem hiding this comment.
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?)
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
Fatal feels wrong here. Does this method get invoked every time an expression runs? If azure is down intermittently, could this crash bosun?
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
Are these even required long term?
| F: AzureMultiQuery, | ||
| PrefixEnabled: true, | ||
| }, | ||
| "azmd": { // TODO Finish and document this func |
| F: AzureResourcesByType, | ||
| PrefixEnabled: true, | ||
| }, | ||
| "azrf": { |
There was a problem hiding this comment.
azrf or azfr? Inner function is "FilterResources", so maybe azfr matches better? I kinda hate short names.
There was a problem hiding this comment.
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 |
| return | ||
| } | ||
| } | ||
| st := e.now.Add(time.Duration(-sd)).Format(azTimeFmt) |
There was a problem hiding this comment.
"startTime" and "endTime" would not be unreasonable names.
There was a problem hiding this comment.
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.
7919b3d to
4dce241
Compare
this includes an incomplete azure metadata function with TODOs to be completed in a future commit.
so metrics can be collected
No description provided.