Skip to content
Merged
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
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ Metrics are collected from the Prism Element v2.0 APIs. Currently, the exporter
- VMs
- Storage Containers

Additionally, the v1 VM API is supported for gathering additional stats not available in the v2 API. The config file for this endpoint is `vm_v1.yaml`.

The response from the API contains a list of entities, each with a set of key-value pairs. The exporter will flatten these key-value pairs and expose them as Prometheus metrics.

`/config` contains a YAML configuration file for each exporter. This is where the metrics to be collected are defined. Any value in the API response can be collected; however, the exporter will only collect metrics that are defined in the configuration file. It is important to note that nested fields in the API response are flattened and exposed like "parent_child", e.g. "stats_num_iops".
Expand Down Expand Up @@ -76,7 +78,7 @@ For both methods, start by cloning the repository and navigating to the repo roo

To build and run the Go binary natively:

1. Download and install Go from [here](https://go.dev/doc/install)
1. Download and install the [Go Programming Language](https://go.dev/doc/install)
2. Export all necessary environment variables
3. `go run cmd/nutanix_exporter/main.go`
4. The exporter will now be running on `localhost:9408`
Expand Down
6 changes: 6 additions & 0 deletions configs/vm_v1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
- name: stats_memory_usage_ppm
help: Memory usage in parts per million (PPM).
- name: stats_hypervisor_cpu_usage_ppm
help: Hypervisor CPU usage in parts per million (PPM).
- name: stats_controller_user_bytes
help: Controller user bytes.
3 changes: 3 additions & 0 deletions internal/prom/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ func (e *Exporter) processEntity(ent map[string]interface{}, isCluster bool) {
// For entity-level metrics, use both cluster name and entity name as labels
if name, ok := ent["name"].(string); ok {
labelValues = []string{e.Cluster.Name, name}
// Check for vmname key if name key is not present (used in VMv1 API)
} else if name, ok := ent["vmName"].(string); ok {
labelValues = []string{e.Cluster.Name, name}
} else {
// Handle case where "name" is missing or not a string
labelValues = []string{e.Cluster.Name, "unknown"}
Expand Down
31 changes: 31 additions & 0 deletions internal/prom/exporters.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ type VmExporter struct {
*Exporter
}

type Vmv1Exporter struct {
*Exporter
}

type StorageContainerExporter struct {
*Exporter
}
Expand Down Expand Up @@ -73,6 +77,15 @@ func NewVMCollector(cluster *nutanix.Cluster, configPath string) *VmExporter {
return exporter
}

func NewVMv1Collector(cluster *nutanix.Cluster, configPath string) *Vmv1Exporter {
labels := []string{"cluster_name", "vm_name"}
exporter := &Vmv1Exporter{
Exporter: NewExporter(cluster, labels),
}
exporter.initMetrics(configPath, labels)
return exporter
}

func NewStorageContainerCollector(cluster *nutanix.Cluster, configPath string) *StorageContainerExporter {
labels := []string{"cluster_name", "container_name"}
exporter := &StorageContainerExporter{
Expand Down Expand Up @@ -155,3 +168,21 @@ func (e *VmExporter) Collect(ch chan<- prometheus.Metric) {
gaugeVec.Collect(ch)
}
}

// Collect
func (e *Vmv1Exporter) Collect(ch chan<- prometheus.Metric) {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

result, err := e.fetchData(ctx, "/v1/vms/")
if err != nil {
slog.Error("Error fetching VM v1 data", "error", err)
return
}

e.updateMetrics(result)

for _, gaugeVec := range e.Metrics {
gaugeVec.Collect(ch)
}
}
1 change: 1 addition & 0 deletions internal/service/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ func (es *ExporterService) refreshClusters() error {
prom.NewClusterCollector(cluster, es.config.ConfigPath+"/cluster.yaml"),
prom.NewHostCollector(cluster, es.config.ConfigPath+"/host.yaml"),
prom.NewVMCollector(cluster, es.config.ConfigPath+"/vm.yaml"),
prom.NewVMv1Collector(cluster, es.config.ConfigPath+"/vm_v1.yaml"),
}

for _, collector := range collectors {
Expand Down