2 changed files with 222 additions and 7 deletions
@ -0,0 +1,186 @@ |
|||
package stats |
|||
|
|||
import ( |
|||
"crypto/sha256" |
|||
"encoding/hex" |
|||
"sync" |
|||
|
|||
"github.com/prometheus/client_golang/prometheus" |
|||
"github.com/prometheus/client_golang/prometheus/push" |
|||
"github.com/seaweedfs/seaweedfs/weed/pb/master_pb" |
|||
) |
|||
|
|||
const ( |
|||
PushGatewayURL = "http://metrics.seaweedfs.com:9091" |
|||
) |
|||
|
|||
var ( |
|||
ClusterMetrics = prometheus.NewRegistry() |
|||
|
|||
ClusterId = prometheus.NewGauge( |
|||
prometheus.GaugeOpts{ |
|||
Namespace: Namespace, |
|||
Subsystem: "cluster", |
|||
Name: "id", |
|||
Help: "Unique cluster identifier", |
|||
}) |
|||
|
|||
ClusterVolumeCount = prometheus.NewGauge( |
|||
prometheus.GaugeOpts{ |
|||
Namespace: Namespace, |
|||
Subsystem: "cluster", |
|||
Name: "volume_count", |
|||
Help: "Total number of volumes in the cluster", |
|||
}) |
|||
|
|||
ClusterTotalCapacity = prometheus.NewGauge( |
|||
prometheus.GaugeOpts{ |
|||
Namespace: Namespace, |
|||
Subsystem: "cluster", |
|||
Name: "total_capacity_bytes", |
|||
Help: "Total storage capacity in bytes", |
|||
}) |
|||
|
|||
ClusterUsedCapacity = prometheus.NewGauge( |
|||
prometheus.GaugeOpts{ |
|||
Namespace: Namespace, |
|||
Subsystem: "cluster", |
|||
Name: "used_capacity_bytes", |
|||
Help: "Used storage capacity in bytes", |
|||
}) |
|||
|
|||
ClusterVersion = prometheus.NewGauge( |
|||
prometheus.GaugeOpts{ |
|||
Namespace: Namespace, |
|||
Subsystem: "cluster", |
|||
Name: "version", |
|||
Help: "Cluster version", |
|||
}) |
|||
|
|||
ClusterVolumeServerCount = prometheus.NewGauge( |
|||
prometheus.GaugeOpts{ |
|||
Namespace: Namespace, |
|||
Subsystem: "cluster", |
|||
Name: "volume_server_count", |
|||
Help: "Number of volume servers in the cluster", |
|||
}) |
|||
|
|||
ClusterStorageDistribution = prometheus.NewGaugeVec( |
|||
prometheus.GaugeOpts{ |
|||
Namespace: Namespace, |
|||
Subsystem: "cluster", |
|||
Name: "storage_distribution_bytes", |
|||
Help: "Storage distribution by data center and rack", |
|||
}, []string{"datacenter", "rack"}) |
|||
|
|||
ClusterUsedStorageDistribution = prometheus.NewGaugeVec( |
|||
prometheus.GaugeOpts{ |
|||
Namespace: Namespace, |
|||
Subsystem: "cluster", |
|||
Name: "used_storage_distribution_bytes", |
|||
Help: "Used storage distribution by data center and rack", |
|||
}, []string{"datacenter", "rack"}) |
|||
|
|||
pusher *push.Pusher |
|||
) |
|||
|
|||
func init() { |
|||
ClusterMetrics.MustRegister(ClusterId) |
|||
ClusterMetrics.MustRegister(ClusterVolumeCount) |
|||
ClusterMetrics.MustRegister(ClusterTotalCapacity) |
|||
ClusterMetrics.MustRegister(ClusterUsedCapacity) |
|||
ClusterMetrics.MustRegister(ClusterVersion) |
|||
ClusterMetrics.MustRegister(ClusterVolumeServerCount) |
|||
ClusterMetrics.MustRegister(ClusterStorageDistribution) |
|||
ClusterMetrics.MustRegister(ClusterUsedStorageDistribution) |
|||
|
|||
// Initialize the push gateway client
|
|||
pusher = push.New(PushGatewayURL, "seaweedfs_cluster").Gatherer(ClusterMetrics) |
|||
} |
|||
|
|||
var ( |
|||
clusterIdOnce sync.Once |
|||
clusterId string |
|||
) |
|||
|
|||
// GenerateClusterId creates a unique cluster ID based on the first volume server's address
|
|||
func GenerateClusterId(topologyInfo *master_pb.TopologyInfo) string { |
|||
clusterIdOnce.Do(func() { |
|||
if len(topologyInfo.DataCenterInfos) > 0 { |
|||
dc := topologyInfo.DataCenterInfos[0] |
|||
if len(dc.RackInfos) > 0 { |
|||
rack := dc.RackInfos[0] |
|||
if len(rack.DataNodeInfos) > 0 { |
|||
node := rack.DataNodeInfos[0] |
|||
hash := sha256.Sum256([]byte(node.Id)) |
|||
clusterId = hex.EncodeToString(hash[:8]) |
|||
} |
|||
} |
|||
} |
|||
if clusterId == "" { |
|||
clusterId = "unknown" |
|||
} |
|||
}) |
|||
return clusterId |
|||
} |
|||
|
|||
// UpdateClusterMetrics updates all cluster-related metrics
|
|||
func UpdateClusterMetrics(topologyInfo *master_pb.TopologyInfo, volumeSizeLimitMB uint32) { |
|||
// Set cluster ID
|
|||
GenerateClusterId(topologyInfo) // Generate but don't store the ID
|
|||
|
|||
// Set version
|
|||
ClusterVersion.Set(0) // Reset to 0 since we're using a string version
|
|||
|
|||
// Calculate total metrics
|
|||
var totalVolumeCount uint64 |
|||
var totalCapacity uint64 |
|||
var totalUsedCapacity uint64 |
|||
var volumeServerCount uint64 |
|||
|
|||
// Reset all distribution metrics
|
|||
ClusterStorageDistribution.Reset() |
|||
ClusterUsedStorageDistribution.Reset() |
|||
|
|||
for _, dc := range topologyInfo.DataCenterInfos { |
|||
for _, rack := range dc.RackInfos { |
|||
var rackVolumeCount uint64 |
|||
var rackCapacity uint64 |
|||
var rackUsedCapacity uint64 |
|||
|
|||
for _, node := range rack.DataNodeInfos { |
|||
volumeServerCount++ |
|||
for _, diskInfo := range node.DiskInfos { |
|||
rackCapacity += uint64(diskInfo.MaxVolumeCount) * uint64(volumeSizeLimitMB) * 1024 * 1024 |
|||
for _, volumeInfo := range diskInfo.VolumeInfos { |
|||
rackVolumeCount++ |
|||
rackUsedCapacity += volumeInfo.Size |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Update distribution metrics
|
|||
ClusterStorageDistribution.WithLabelValues(dc.Id, rack.Id).Set(float64(rackCapacity)) |
|||
ClusterUsedStorageDistribution.WithLabelValues(dc.Id, rack.Id).Set(float64(rackUsedCapacity)) |
|||
|
|||
// Update total metrics
|
|||
totalVolumeCount += rackVolumeCount |
|||
totalCapacity += rackCapacity |
|||
totalUsedCapacity += rackUsedCapacity |
|||
} |
|||
} |
|||
|
|||
// Update total metrics
|
|||
ClusterVolumeCount.Set(float64(totalVolumeCount)) |
|||
ClusterTotalCapacity.Set(float64(totalCapacity)) |
|||
ClusterUsedCapacity.Set(float64(totalUsedCapacity)) |
|||
ClusterVolumeServerCount.Set(float64(volumeServerCount)) |
|||
} |
|||
|
|||
// PushMetrics sends the current metrics to the push gateway
|
|||
func PushMetrics(clusterId string, enabled bool) error { |
|||
if !enabled || pusher == nil { |
|||
return nil |
|||
} |
|||
return pusher.Push() |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue