Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add custom_tags to metrics #91

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,18 @@ credentials:
client_id: <secret>
client_secret: <secret>
tenant_id: <secret>
custom_labels:
- name: cost_center
value: 12345s

targets:
- resource: "azure_resource_id"
metrics:
- name: "BytesReceived"
- name: "BytesSent"
custom_labels:
- name: experimental
value: true
- resource: "azure_resource_id"
aggregations:
- Minimum
Expand Down Expand Up @@ -106,6 +112,8 @@ When the metric namespace is specified, it will be added as a prefix of the metr
It can be used to target [custom metrics](https://docs.microsoft.com/en-us/azure/azure-monitor/platform/metrics-custom-overview), such as [guest OS performance counters](https://docs.microsoft.com/en-us/azure/azure-monitor/platform/collect-custom-metrics-guestos-vm-classic).
If not specified, the default metric namespace of the resource will apply.

`custom_tags` specify labels that will be present in all metrics

### Resource group filtering

Resources in a resource group can be filtered using the the following keys:
Expand Down
12 changes: 12 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type Config struct {
ActiveDirectoryAuthorityURL string `yaml:"active_directory_authority_url"`
ResourceManagerURL string `yaml:"resource_manager_url"`
Credentials Credentials `yaml:"credentials"`
CustomLabels []Label `yaml:"custom_labels"`
Targets []Target `yaml:"targets"`
ResourceGroups []ResourceGroup `yaml:"resource_groups"`
ResourceTags []ResourceTag `yaml:"resource_tags"`
Expand Down Expand Up @@ -148,6 +149,7 @@ type Target struct {
Resource string `yaml:"resource"`
MetricNamespace string `yaml:"metric_namespace"`
Metrics []Metric `yaml:"metrics"`
CustomLabels []Label `yaml:"custom_labels"`
Aggregations []string `yaml:"aggregations"`

XXX map[string]interface{} `yaml:",inline"`
Expand All @@ -161,6 +163,7 @@ type ResourceGroup struct {
ResourceNameIncludeRe []Regexp `yaml:"resource_name_include_re"`
ResourceNameExcludeRe []Regexp `yaml:"resource_name_exclude_re"`
Metrics []Metric `yaml:"metrics"`
CustomLabels []Label `yaml:"custom_labels"`
Aggregations []string `yaml:"aggregations"`

XXX map[string]interface{} `yaml:",inline"`
Expand All @@ -173,11 +176,20 @@ type ResourceTag struct {
MetricNamespace string `yaml:"metric_namespace"`
ResourceTypes []string `yaml:"resource_types"`
Metrics []Metric `yaml:"metrics"`
CustomLabels []Label `yaml:"custom_labels"`
Aggregations []string `yaml:"aggregations"`

XXX map[string]interface{} `yaml:",inline"`
}

// Label is a tuple that defines a preometheus label
type Label struct {
Name string `yaml:"name"`
Value string `yaml:"value"`

XXX map[string]interface{} `yaml:",inline"`
}

// Metric defines metric name
type Metric struct {
Name string `yaml:"name"`
Expand Down
4 changes: 3 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ type resourceMeta struct {
metricNamespace string
metrics string
aggregations []string
labels []config.Label
resource AzureResource
}

Expand Down Expand Up @@ -80,7 +81,7 @@ func (c *Collector) extractMetrics(ch chan<- prometheus.Metric, rm resourceMeta,

if len(value.Timeseries) > 0 {
metricValue := value.Timeseries[0].Data[len(value.Timeseries[0].Data)-1]
labels := CreateResourceLabels(rm.resourceURL)
labels := CreateResourceLabels(rm)

if hasAggregation(rm.aggregations, "Total") {
ch <- prometheus.MustNewConstMetric(
Expand Down Expand Up @@ -235,6 +236,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) {
rm.metrics = strings.Join(metrics, ",")
rm.aggregations = filterAggregations(target.Aggregations)
rm.resourceURL = resourceURLFrom(target.Resource, rm.metricNamespace, rm.metrics, rm.aggregations)
rm.labels = append(sc.C.CustomLabels, target.CustomLabels...)
incompleteResources = append(incompleteResources, rm)
}

Expand Down
23 changes: 17 additions & 6 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,21 @@ func GetTimes() (string, string) {
}

// CreateResourceLabels - Returns resource labels for a given resource URL.
func CreateResourceLabels(resourceURL string) map[string]string {
func CreateResourceLabels(rm resourceMeta) map[string]string {
labels := make(map[string]string)
resource := strings.Split(resourceURL, "/")
resource := strings.Split(rm.resourceURL, "/")

labels["resource_group"] = resource[resourceGroupPosition]
labels["resource_name"] = resource[resourceNamePosition]
if len(resource) > 13 {
labels["sub_resource_name"] = resource[subResourceNamePosition]
}

for _, label := range rm.labels {
labelName := "custom_tag_" + cleanLabel(label.Name)
labels[labelName] = label.Value
}

return labels
}

Expand All @@ -73,9 +79,7 @@ func CreateAllResourceLabelsFrom(rm resourceMeta) map[string]string {
labels := make(map[string]string)

for k, v := range rm.resource.Tags {
k = strings.ToLower(k)
k = "tag_" + k
k = invalidLabelChars.ReplaceAllString(k, "_")
k = "tag_" + cleanLabel(k)
labels[k] = v
}

Expand All @@ -93,13 +97,20 @@ func CreateAllResourceLabelsFrom(rm resourceMeta) map[string]string {
// Their tag values are used as label keys.
// To keep coherence with the metric labels, we create "resource_group", "resource_name"
// and "sub_resource_name" by invoking CreateResourceLabels.
resourceLabels := CreateResourceLabels(rm.resourceURL)
resourceLabels := CreateResourceLabels(rm)
for k, v := range resourceLabels {
labels[k] = v
}
return labels
}

func cleanLabel(label string) string {
label = strings.ToLower(label)
label = invalidLabelChars.ReplaceAllString(label, "_")
label = strings.Trim(label, "_")
return label
}

func hasAggregation(aggregations []string, aggregation string) bool {
if len(aggregations) == 0 {
return true
Expand Down
12 changes: 8 additions & 4 deletions utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,25 @@ import (

func TestCreateResourceLabels(t *testing.T) {
var cases = []struct {
url string
rm resourceMeta
want map[string]string
}{
{
"/subscriptions/abc123d4-e5f6-g7h8-i9j10-a1b2c3d4e5f6/resourceGroups/prod-rg-001/providers/Microsoft.Compute/virtualMachines/prod-vm-01/providers/microsoft.insights/metrics",
resourceMeta{
resourceURL: "/subscriptions/abc123d4-e5f6-g7h8-i9j10-a1b2c3d4e5f6/resourceGroups/prod-rg-001/providers/Microsoft.Compute/virtualMachines/prod-vm-01/providers/microsoft.insights/metrics",
},
map[string]string{"resource_group": "prod-rg-001", "resource_name": "prod-vm-01"},
},
{
"/subscriptions/abc123d4-e5f6-g7h8-i9j10-a1b2c3d4e5f6/resourceGroups/prod-rg-002/providers/Microsoft.Sql/servers/sqlprod/databases/prod-db-01/providers/microsoft.insights/metrics",
resourceMeta{
resourceURL: "/subscriptions/abc123d4-e5f6-g7h8-i9j10-a1b2c3d4e5f6/resourceGroups/prod-rg-002/providers/Microsoft.Sql/servers/sqlprod/databases/prod-db-01/providers/microsoft.insights/metrics",
},
map[string]string{"resource_group": "prod-rg-002", "resource_name": "sqlprod", "sub_resource_name": "prod-db-01"},
},
}

for _, c := range cases {
got := CreateResourceLabels(c.url)
got := CreateResourceLabels(c.rm)

if !reflect.DeepEqual(got, c.want) {
t.Errorf("doesn't create expected resource labels\ngot: %v\nwant: %v", got, c.want)
Expand Down