| 
									
										
										
										
											2018-04-19 07:01:42 +08:00
										 |  |  | /* | 
					
						
							|  |  |  |  * Minio Cloud Storage, (C) 2018 Minio, Inc. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Licensed under the Apache License, Version 2.0 (the "License"); | 
					
						
							|  |  |  |  * you may not use this file except in compliance with the License. | 
					
						
							|  |  |  |  * You may obtain a copy of the License at | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *     http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Unless required by applicable law or agreed to in writing, software | 
					
						
							|  |  |  |  * distributed under the License is distributed on an "AS IS" BASIS, | 
					
						
							|  |  |  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
					
						
							|  |  |  |  * See the License for the specific language governing permissions and | 
					
						
							|  |  |  |  * limitations under the License. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"context" | 
					
						
							|  |  |  | 	"net/http" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-09 11:10:55 +08:00
										 |  |  | 	"github.com/minio/minio/cmd/logger" | 
					
						
							| 
									
										
										
										
											2018-04-19 07:01:42 +08:00
										 |  |  | 	"github.com/prometheus/client_golang/prometheus" | 
					
						
							| 
									
										
										
										
											2018-05-09 11:10:55 +08:00
										 |  |  | 	"github.com/prometheus/client_golang/prometheus/promhttp" | 
					
						
							| 
									
										
										
										
											2018-04-19 07:01:42 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var ( | 
					
						
							|  |  |  | 	httpRequestsDuration = prometheus.NewHistogramVec( | 
					
						
							|  |  |  | 		prometheus.HistogramOpts{ | 
					
						
							|  |  |  | 			Name:    "minio_http_requests_duration_seconds", | 
					
						
							|  |  |  | 			Help:    "Time taken by requests served by current Minio server instance", | 
					
						
							|  |  |  | 			Buckets: []float64{.001, .003, .005, .1, .5, 1}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		[]string{"request_type"}, | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func init() { | 
					
						
							|  |  |  | 	prometheus.MustRegister(httpRequestsDuration) | 
					
						
							| 
									
										
										
										
											2018-05-09 11:10:55 +08:00
										 |  |  | 	prometheus.MustRegister(newMinioCollector()) | 
					
						
							| 
									
										
										
										
											2018-04-19 07:01:42 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-09 11:10:55 +08:00
										 |  |  | // newMinioCollector describes the collector
 | 
					
						
							|  |  |  | // and returns reference of minioCollector
 | 
					
						
							|  |  |  | // It creates the Prometheus Description which is used
 | 
					
						
							|  |  |  | // to define metric and  help string
 | 
					
						
							|  |  |  | func newMinioCollector() *minioCollector { | 
					
						
							|  |  |  | 	return &minioCollector{ | 
					
						
							|  |  |  | 		desc: prometheus.NewDesc("minio_stats", "Statistics exposed by Minio server", nil, nil), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // minioCollector is the Custom Collector
 | 
					
						
							|  |  |  | type minioCollector struct { | 
					
						
							|  |  |  | 	desc *prometheus.Desc | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Describe sends the super-set of all possible descriptors of metrics
 | 
					
						
							|  |  |  | func (c *minioCollector) Describe(ch chan<- *prometheus.Desc) { | 
					
						
							|  |  |  | 	ch <- c.desc | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Collect is called by the Prometheus registry when collecting metrics.
 | 
					
						
							|  |  |  | func (c *minioCollector) Collect(ch chan<- prometheus.Metric) { | 
					
						
							| 
									
										
										
										
											2018-04-19 07:01:42 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-30 12:43:46 +08:00
										 |  |  | 	// Always expose network stats
 | 
					
						
							| 
									
										
										
										
											2018-05-09 11:10:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Network Sent/Received Bytes
 | 
					
						
							|  |  |  | 	ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 		prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName("minio", "network", "sent_bytes_total"), | 
					
						
							|  |  |  | 			"Total number of bytes sent by current Minio server instance", | 
					
						
							|  |  |  | 			nil, nil), | 
					
						
							|  |  |  | 		prometheus.CounterValue, | 
					
						
							|  |  |  | 		float64(globalConnStats.getTotalOutputBytes()), | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 		prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName("minio", "network", "received_bytes_total"), | 
					
						
							|  |  |  | 			"Total number of bytes received by current Minio server instance", | 
					
						
							|  |  |  | 			nil, nil), | 
					
						
							|  |  |  | 		prometheus.CounterValue, | 
					
						
							|  |  |  | 		float64(globalConnStats.getTotalInputBytes()), | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2018-05-16 03:23:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-31 02:30:14 +08:00
										 |  |  | 	// Expose cache stats only if available
 | 
					
						
							|  |  |  | 	cacheObjLayer := newCacheObjectsFn() | 
					
						
							|  |  |  | 	if cacheObjLayer != nil { | 
					
						
							|  |  |  | 		cs := cacheObjLayer.StorageInfo(context.Background()) | 
					
						
							|  |  |  | 		ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 			prometheus.NewDesc( | 
					
						
							|  |  |  | 				prometheus.BuildFQName("minio", "disk", "cache_storage_bytes"), | 
					
						
							|  |  |  | 				"Total cache capacity on current Minio server instance", | 
					
						
							|  |  |  | 				nil, nil), | 
					
						
							|  |  |  | 			prometheus.GaugeValue, | 
					
						
							|  |  |  | 			float64(cs.Total), | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 		ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 			prometheus.NewDesc( | 
					
						
							|  |  |  | 				prometheus.BuildFQName("minio", "disk", "cache_storage_free_bytes"), | 
					
						
							|  |  |  | 				"Total cache available on current Minio server instance", | 
					
						
							|  |  |  | 				nil, nil), | 
					
						
							|  |  |  | 			prometheus.GaugeValue, | 
					
						
							|  |  |  | 			float64(cs.Free), | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-30 12:43:46 +08:00
										 |  |  | 	// Expose disk stats only if applicable
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Fetch disk space info
 | 
					
						
							|  |  |  | 	objLayer := newObjectLayerFn() | 
					
						
							|  |  |  | 	// Service not initialized yet
 | 
					
						
							|  |  |  | 	if objLayer == nil { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-05-31 02:30:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-30 12:43:46 +08:00
										 |  |  | 	s := objLayer.StorageInfo(context.Background()) | 
					
						
							| 
									
										
										
										
											2018-05-31 02:30:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-30 12:43:46 +08:00
										 |  |  | 	// Gateways don't provide disk info
 | 
					
						
							|  |  |  | 	if s.Backend.Type == Unknown { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var totalDisks, offlineDisks int | 
					
						
							|  |  |  | 	// Setting totalDisks to 1 and offlineDisks to 0 in FS mode
 | 
					
						
							| 
									
										
										
										
											2018-08-24 14:35:37 +08:00
										 |  |  | 	if s.Backend.Type == BackendFS { | 
					
						
							| 
									
										
										
										
											2018-05-30 12:43:46 +08:00
										 |  |  | 		totalDisks = 1 | 
					
						
							|  |  |  | 		offlineDisks = 0 | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		offlineDisks = s.Backend.OfflineDisks | 
					
						
							|  |  |  | 		totalDisks = s.Backend.OfflineDisks + s.Backend.OnlineDisks | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-31 02:30:14 +08:00
										 |  |  | 	// Total disk usage by current Minio server instance
 | 
					
						
							| 
									
										
										
										
											2018-05-09 11:10:55 +08:00
										 |  |  | 	ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 		prometheus.NewDesc( | 
					
						
							| 
									
										
										
										
											2018-05-31 02:30:14 +08:00
										 |  |  | 			prometheus.BuildFQName("minio", "disk", "storage_used_bytes"), | 
					
						
							|  |  |  | 			"Total disk storage used by current Minio server instance", | 
					
						
							| 
									
										
										
										
											2018-05-09 11:10:55 +08:00
										 |  |  | 			nil, nil), | 
					
						
							|  |  |  | 		prometheus.GaugeValue, | 
					
						
							| 
									
										
										
										
											2018-05-31 02:30:14 +08:00
										 |  |  | 		float64(s.Used), | 
					
						
							| 
									
										
										
										
											2018-05-09 11:10:55 +08:00
										 |  |  | 	) | 
					
						
							| 
									
										
										
										
											2018-04-19 07:01:42 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-09 11:10:55 +08:00
										 |  |  | 	// Minio Total Disk/Offline Disk
 | 
					
						
							|  |  |  | 	ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 		prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName("minio", "total", "disks"), | 
					
						
							|  |  |  | 			"Total number of disks for current Minio server instance", | 
					
						
							|  |  |  | 			nil, nil), | 
					
						
							|  |  |  | 		prometheus.GaugeValue, | 
					
						
							|  |  |  | 		float64(totalDisks), | 
					
						
							|  |  |  | 	) | 
					
						
							|  |  |  | 	ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 		prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName("minio", "offline", "disks"), | 
					
						
							|  |  |  | 			"Total number of offline disks for current Minio server instance", | 
					
						
							|  |  |  | 			nil, nil), | 
					
						
							|  |  |  | 		prometheus.GaugeValue, | 
					
						
							|  |  |  | 		float64(offlineDisks), | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2018-04-19 07:01:42 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-09 11:10:55 +08:00
										 |  |  | func metricsHandler() http.Handler { | 
					
						
							|  |  |  | 	registry := prometheus.NewRegistry() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-16 03:23:43 +08:00
										 |  |  | 	err := registry.Register(httpRequestsDuration) | 
					
						
							| 
									
										
										
										
											2018-05-09 11:10:55 +08:00
										 |  |  | 	logger.LogIf(context.Background(), err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	err = registry.Register(newMinioCollector()) | 
					
						
							|  |  |  | 	logger.LogIf(context.Background(), err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gatherers := prometheus.Gatherers{ | 
					
						
							|  |  |  | 		prometheus.DefaultGatherer, | 
					
						
							|  |  |  | 		registry, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Delegate http serving to Prometheus client library, which will call collector.Collect.
 | 
					
						
							|  |  |  | 	return promhttp.InstrumentMetricHandler( | 
					
						
							|  |  |  | 		registry, | 
					
						
							|  |  |  | 		promhttp.HandlerFor(gatherers, | 
					
						
							|  |  |  | 			promhttp.HandlerOpts{ | 
					
						
							|  |  |  | 				ErrorHandling: promhttp.ContinueOnError, | 
					
						
							|  |  |  | 			}), | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2018-04-19 07:01:42 +08:00
										 |  |  | } |