Skip to content

Commit 66153e2

Browse files
committed
Add stub blob collector for azure
1 parent 84088c7 commit 66153e2

File tree

5 files changed

+88
-1
lines changed

5 files changed

+88
-1
lines changed

docs/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@
1111
- [Providers](metrics/providers.md)
1212
- **AWS:** [EC2](metrics/aws/ec2.md), [S3](metrics/aws/s3.md), [RDS](metrics/aws/rds.md), [ELB](metrics/aws/elb.md), [NAT Gateway](metrics/aws/natgateway.md), [VPC](metrics/aws/vpc.md)
1313
- **GCP:** [GKE](metrics/gcp/gke.md), [GCS](metrics/gcp/gcs.md), [Cloud SQL](metrics/gcp/cloudsql.md), [CLB](metrics/gcp/clb.md), [VPC](metrics/gcp/vpc.md)
14-
- **Azure:** [AKS](metrics/azure/aks.md)
14+
- **Azure:** [AKS](metrics/azure/aks.md), [Blob](metrics/azure/blob.md)
1515
- [Deploying](deploying/aws/README.md) - Run the exporter
1616
- [AWS](deploying/aws/README.md) — IRSA, Helm, cross-account access

docs/metrics/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@
2020
## Azure Services
2121

2222
- **[AKS](./azure/aks.md)** - Azure Kubernetes Service VM instances and managed disks
23+
- **[Blob](./azure/blob.md)** - Azure Blob Storage (stub; Cost Management integration planned)

docs/metrics/azure/blob.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Azure Blob Storage metrics
2+
3+
## Status
4+
5+
The `BLOB` service is registered when you pass `BLOB` in `--azure.services`. The collector is a **stub**: it does not call Azure APIs for cost data yet and emits **no** `cloudcost_azure_blob_*` cost gauges.
6+
7+
## Planned behavior (see issue #54):
8+
9+
### Metric shape (AWS S3 and GCP GCS in this repo)
10+
11+
- **Storage rate:** Same naming pattern as S3 and GCS: `storage_by_location_usd_per_gibyte_hour` under the service subsystem (here `azure_blob``cloudcost_azure_blob_storage_by_location_usd_per_gibyte_hour`). Implemented today as `cloudcost_aws_s3_*` in `pkg/aws/s3/s3.go` and `cloudcost_gcp_gcs_*` in `pkg/google/metrics/metrics.go`.
12+
- **Operations rate (optional):** S3 and GCS also define `operation_by_location_usd_per_krequest` (`pkg/aws/s3/s3.go`, `pkg/google/metrics/metrics.go`). A Blob collector may expose an analogous gauge only if the chosen Azure dataset supports it.
13+
- **Labels:** S3 uses `region` and `class` for storage (and `tier` for operations); GCS uses `location` and `storage_class` (and operation class labels for ops). Azure label sets would follow whatever dimensions the Cost Management query returns; the above collectors show the cross-cloud “by location + storage class/tier” pattern only.
14+
15+
### Azure Cost Management
16+
17+
- **Query API:** Azure documentation mentions `POST https://management.azure.com/{scope}/providers/Microsoft.CostManagement/query` and states that `{scope}` includes **`/subscriptions/{subscriptionId}/`** for subscription scope. Sample responses in that snapshot include cost columns such as **`PreTaxCost`** alongside dimensions like **`ResourceLocation`** in example filters.
18+
- **Permissions:** Azure documentation states that you must have **Cost Management permissions at the appropriate scope** to use Cost Management APIs (the captured article links to Microsoft’s assign-access documentation for details). No specific Azure role name is asserted here.
19+
20+
### Provider operational metrics
21+
22+
- **`cloudcost_exporter_collector_*` with `collector="azure_blob"`** — same mechanism as other Azure collectors (e.g. `azure_aks`) via `pkg/azure/azure.go` and the shared gatherer pattern.
23+
24+
## Cost metrics
25+
26+
None yet.

pkg/azure/azure.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/prometheus/client_golang/prometheus"
1313

1414
"github.com/grafana/cloudcost-exporter/pkg/azure/aks"
15+
"github.com/grafana/cloudcost-exporter/pkg/azure/blob"
1516
"github.com/grafana/cloudcost-exporter/pkg/azure/client"
1617
"github.com/grafana/cloudcost-exporter/pkg/collectormetrics"
1718
"github.com/grafana/cloudcost-exporter/pkg/provider"
@@ -101,6 +102,14 @@ func New(ctx context.Context, config *Config) (*Azure, error) {
101102
return nil, err
102103
}
103104
collectors = append(collectors, collector)
105+
case "BLOB":
106+
collector, err := blob.New(&blob.Config{
107+
Logger: logger,
108+
})
109+
if err != nil {
110+
return nil, err
111+
}
112+
collectors = append(collectors, collector)
104113
default:
105114
logger.LogAttrs(ctx, slog.LevelInfo, "unknown service", slog.String("service", svc))
106115
}

pkg/azure/blob/blob.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package blob
2+
3+
import (
4+
"context"
5+
"log/slog"
6+
7+
"github.com/grafana/cloudcost-exporter/pkg/provider"
8+
"github.com/prometheus/client_golang/prometheus"
9+
)
10+
11+
const subsystem = "azure_blob"
12+
13+
// Collector implements provider.Collector for Azure Blob Storage cost metrics.
14+
// Cost Management integration is not implemented yet; Collect emits no cost series.
15+
type Collector struct {
16+
logger *slog.Logger
17+
}
18+
19+
// Config holds settings for the blob collector.
20+
type Config struct {
21+
Logger *slog.Logger
22+
}
23+
24+
// New builds a blob collector. It does not call Azure APIs.
25+
func New(cfg *Config) (*Collector, error) {
26+
return &Collector{
27+
logger: cfg.Logger.With("collector", "blob"),
28+
}, nil
29+
}
30+
31+
// Collect satisfies provider.Collector. No Prometheus samples are sent until Cost Management is wired in.
32+
func (c *Collector) Collect(ctx context.Context, _ chan<- prometheus.Metric) error {
33+
c.logger.LogAttrs(ctx, slog.LevelInfo, "collecting metrics")
34+
return nil
35+
}
36+
37+
// Describe satisfies provider.Collector. No metric descriptors until cost gauges are implemented.
38+
func (c *Collector) Describe(_ chan<- *prometheus.Desc) error {
39+
return nil
40+
}
41+
42+
// Name returns the collector subsystem name for operational metrics.
43+
func (c *Collector) Name() string {
44+
return subsystem
45+
}
46+
47+
// Register satisfies provider.Collector.
48+
func (c *Collector) Register(_ provider.Registry) error {
49+
c.logger.LogAttrs(context.Background(), slog.LevelInfo, "registering collector")
50+
return nil
51+
}

0 commit comments

Comments
 (0)