Skip to content

Commit 2cfdbc7

Browse files
celian-garciajmacd
andcommitted
[receiver/azuremonitorreceiver] feat: multi subscriptions support and automatic discovery
Co-authored-by: Joshua MacDonald <[email protected]> Signed-off-by: Célian Garcia <[email protected]>
1 parent e4559ec commit 2cfdbc7

File tree

12 files changed

+1133
-708
lines changed

12 files changed

+1133
-708
lines changed

.chloggen/feat_discovery.yaml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Use this changelog template to create an entry for release notes.
2+
3+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
4+
change_type: breaking
5+
6+
# The name of the component, or a single word describing the area of concern, (e.g. filelogreceiver)
7+
component: receiver/azuremonitorreceiver
8+
9+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
10+
note: "multi subscriptions support and automatic discovery"
11+
12+
# Mandatory: One or more tracking issues related to the change. You can use the PR number here if no issue exists.
13+
issues: [36612]
14+
15+
# (Optional) One or more lines of additional information to render under the primary note.
16+
# These lines will be padded with 2 spaces and then inserted directly into the document.
17+
# Use pipe (|) for multiline entries.
18+
subtext:
19+
20+
# If your change doesn't affect end users or the exported elements of any package,
21+
# you should instead start your pull request title with [chore] or use the "Skip Changelog" label.
22+
# Optional: The change log or logs in which this entry should be included.
23+
# e.g. '[user]' or '[user, api]'
24+
# Include 'user' if the change is relevant to end users.
25+
# Include 'api' if there is a change to a library API.
26+
# Default: '[user]'
27+
change_logs: []

receiver/azuremonitorreceiver/README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ This receiver scrapes Azure Monitor API for resources metrics.
1818

1919
The following settings are required:
2020

21-
- `subscription_id`
21+
- `subscription_ids`: list of subscriptions on which the resource's metrics are collected
22+
- or `discover_subscriptions`: (default = `false`) If set to true, will collect metrics from all subscriptions in the tenant.
2223

2324
The following settings are optional:
2425

@@ -78,7 +79,7 @@ Using [Service Principal](https://learn.microsoft.com/en-us/azure/developer/go/a
7879
```yaml
7980
receivers:
8081
azuremonitor:
81-
subscription_id: "${subscription_id}"
82+
subscription_ids: ["${subscription_id}"]
8283
tenant_id: "${tenant_id}"
8384
client_id: "${client_id}"
8485
client_secret: "${env:CLIENT_SECRET}"
@@ -98,7 +99,7 @@ Using [Azure Workload Identity](https://learn.microsoft.com/en-us/azure/develope
9899
```yaml
99100
receivers:
100101
azuremonitor:
101-
subscription_id: "${subscription_id}"
102+
subscription_ids: ["${subscription_id}"]
102103
auth: "workload_identity"
103104
tenant_id: "${env:AZURE_TENANT_ID}"
104105
client_id: "${env:AZURE_CLIENT_ID}"
@@ -110,7 +111,7 @@ Using [Managed Identity](https://learn.microsoft.com/en-us/azure/developer/go/az
110111
```yaml
111112
receivers:
112113
azuremonitor:
113-
subscription_id: "${subscription_id}"
114+
subscription_ids: ["${subscription_id}"]
114115
auth: "managed_identity"
115116
client_id: "${env:AZURE_CLIENT_ID}"
116117
```
@@ -120,7 +121,7 @@ Using [Environment Variables](https://learn.microsoft.com/en-us/azure/developer/
120121
```yaml
121122
receivers:
122123
azuremonitor:
123-
subscription_id: "${subscription_id}"
124+
subscription_ids: ["${subscription_id}"]
124125
auth: "default_credentials"
125126
```
126127

receiver/azuremonitorreceiver/config.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ const (
2121

2222
var (
2323
// Predefined error responses for configuration validation failures
24-
errMissingTenantID = errors.New(`TenantID" is not specified in config`)
25-
errMissingSubscriptionID = errors.New(`SubscriptionID" is not specified in config`)
26-
errMissingClientID = errors.New(`ClientID" is not specified in config`)
27-
errMissingClientSecret = errors.New(`ClientSecret" is not specified in config`)
28-
errMissingFedTokenFile = errors.New(`FederatedTokenFile is not specified in config`)
29-
errInvalidCloud = errors.New(`Cloud" is invalid`)
24+
errMissingTenantID = errors.New(`"TenantID" is not specified in config`)
25+
errMissingSubscriptionIDs = errors.New(`neither "SubscriptionIDs" nor "DiscoverSubscription" is specified in the config`)
26+
errMissingClientID = errors.New(`"ClientID" is not specified in config`)
27+
errMissingClientSecret = errors.New(`"ClientSecret" is not specified in config`)
28+
errMissingFedTokenFile = errors.New(`"FederatedTokenFile"" is not specified in config`)
29+
errInvalidCloud = errors.New(`"Cloud" is invalid`)
3030

3131
monitorServices = []string{
3232
"Microsoft.EventGrid/eventSubscriptions",
@@ -240,7 +240,8 @@ type Config struct {
240240
scraperhelper.ControllerConfig `mapstructure:",squash"`
241241
MetricsBuilderConfig metadata.MetricsBuilderConfig `mapstructure:",squash"`
242242
Cloud string `mapstructure:"cloud"`
243-
SubscriptionID string `mapstructure:"subscription_id"`
243+
SubscriptionIDs []string `mapstructure:"subscription_ids"`
244+
DiscoverSubscriptions bool `mapstructure:"discover_subscriptions"`
244245
Authentication string `mapstructure:"auth"`
245246
TenantID string `mapstructure:"tenant_id"`
246247
ClientID string `mapstructure:"client_id"`
@@ -266,8 +267,8 @@ const (
266267

267268
// Validate validates the configuration by checking for missing or invalid fields
268269
func (c Config) Validate() (err error) {
269-
if c.SubscriptionID == "" {
270-
err = multierr.Append(err, errMissingSubscriptionID)
270+
if len(c.SubscriptionIDs) == 0 && !c.DiscoverSubscriptions {
271+
err = multierr.Append(err, errMissingSubscriptionIDs)
271272
}
272273

273274
switch c.Authentication {

receiver/azuremonitorreceiver/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2
88
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor v0.11.0
99
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0
10+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions v1.3.0
1011
github.com/google/go-cmp v0.7.0
1112
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/golden v0.122.0
1213
github.com/open-telemetry/opentelemetry-collector-contrib/pkg/pdatatest v0.122.0

receiver/azuremonitorreceiver/go.sum

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

receiver/azuremonitorreceiver/internal/metadata/metrics.go

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -108,16 +108,7 @@ func (mb *MetricsBuilder) updateCapacity(rm pmetric.ResourceMetrics) {
108108
// ResourceMetricsOption applies changes to provided resource metrics.
109109
type ResourceMetricsOption func(ResourceAttributesSettings, pmetric.ResourceMetrics)
110110

111-
// WithAzureMonitorSubscriptionID sets provided value as "azuremonitor.subscription_id" attribute for current resource.
112-
func WithAzureMonitorSubscriptionID(val string) ResourceMetricsOption {
113-
return func(ras ResourceAttributesSettings, rm pmetric.ResourceMetrics) {
114-
if ras.AzureMonitorSubscriptionID.Enabled {
115-
rm.Resource().Attributes().PutStr("azuremonitor.subscription_id", val)
116-
}
117-
}
118-
}
119-
120-
// WithAzuremonitorTenantID sets provided value as "azuremonitor.tenant_id" attribute for current resource.
111+
// WithAzureMonitorTenantID sets provided value as "azuremonitor.tenant_id" attribute for current resource.
121112
func WithAzureMonitorTenantID(val string) ResourceMetricsOption {
122113
return func(ras ResourceAttributesSettings, rm pmetric.ResourceMetrics) {
123114
if ras.AzureMonitorTenantID.Enabled {
@@ -209,6 +200,7 @@ func (mb *MetricsBuilder) addMetric(resourceMetricID, logicalMetricID, unit stri
209200
}
210201

211202
func (mb *MetricsBuilder) AddDataPoint(
203+
subscriptionID,
212204
resourceID,
213205
metric,
214206
aggregation,
@@ -218,7 +210,7 @@ func (mb *MetricsBuilder) AddDataPoint(
218210
val float64,
219211
) {
220212
logicalMetricID := getLogicalMetricID(metric, aggregation)
221-
resourceMetricID := getLogicalResourceMetricID(resourceID, logicalMetricID)
213+
resourceMetricID := getLogicalResourceMetricID(subscriptionID, resourceID, logicalMetricID)
222214

223215
m, exists := mb.getMetric(resourceMetricID)
224216
if !exists {
@@ -232,6 +224,11 @@ func (mb *MetricsBuilder) AddDataPoint(
232224
dp.SetStartTimestamp(mb.startTime)
233225
dp.SetTimestamp(ts)
234226
dp.SetDoubleValue(val)
227+
228+
if mb.resourceAttributesSettings.AzureMonitorSubscriptionID.Enabled {
229+
dp.Attributes().PutStr("azuremonitor.subscription_id", subscriptionID)
230+
}
231+
235232
dp.Attributes().PutStr("azuremonitor.resource_id", resourceID)
236233
for key, value := range attributes {
237234
dp.Attributes().PutStr(key, *value)
@@ -242,8 +239,8 @@ func getLogicalMetricID(metric, aggregation string) string {
242239
return strings.ToLower(fmt.Sprintf("%s%s_%s", metricsPrefix, strings.ReplaceAll(metric, " ", "_"), aggregation))
243240
}
244241

245-
func getLogicalResourceMetricID(resourceID, logicalMetricID string) string {
246-
return fmt.Sprintf("%s/%s", strings.ToLower(resourceID), logicalMetricID)
242+
func getLogicalResourceMetricID(subscriptionID, resourceID, logicalMetricID string) string {
243+
return fmt.Sprintf("%s/%s/%s", strings.ToLower(subscriptionID), strings.ToLower(resourceID), logicalMetricID)
247244
}
248245

249246
func (mb *MetricsBuilder) EmitAllMetrics(ils pmetric.ScopeMetrics) {

receiver/azuremonitorreceiver/internal/metadata/metrics_test.go

Lines changed: 11 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)