mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-02-09 06:26:39 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9404c6cc2 |
@@ -3,8 +3,6 @@
|
||||
package collector
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -15,21 +13,18 @@ import (
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("process", newProcessCollector, "Process")
|
||||
registerCollector("process", NewProcessCollector)
|
||||
}
|
||||
|
||||
var (
|
||||
processWhitelist = kingpin.Flag(
|
||||
"collector.process.whitelist",
|
||||
"Regexp of processes to include. Process name must both match whitelist and not match blacklist to be included.",
|
||||
).Default(".*").String()
|
||||
processBlacklist = kingpin.Flag(
|
||||
"collector.process.blacklist",
|
||||
"Regexp of processes to exclude. Process name must both match whitelist and not match blacklist to be included.",
|
||||
processWhereClause = kingpin.Flag(
|
||||
"collector.process.processes-where",
|
||||
"WQL 'where' clause to use in WMI metrics query. Limits the response to the processes you specify and reduces the size of the response.",
|
||||
).Default("").String()
|
||||
)
|
||||
|
||||
type processCollector struct {
|
||||
// A ProcessCollector is a Prometheus collector for WMI Win32_PerfRawData_PerfProc_Process metrics
|
||||
type ProcessCollector struct {
|
||||
StartTime *prometheus.Desc
|
||||
CPUTimeTotal *prometheus.Desc
|
||||
HandleCount *prometheus.Desc
|
||||
@@ -44,19 +39,18 @@ type processCollector struct {
|
||||
VirtualBytes *prometheus.Desc
|
||||
WorkingSet *prometheus.Desc
|
||||
|
||||
processWhitelistPattern *regexp.Regexp
|
||||
processBlacklistPattern *regexp.Regexp
|
||||
queryWhereClause string
|
||||
}
|
||||
|
||||
// NewProcessCollector ...
|
||||
func newProcessCollector() (Collector, error) {
|
||||
func NewProcessCollector() (Collector, error) {
|
||||
const subsystem = "process"
|
||||
|
||||
if *processWhitelist == ".*" && *processBlacklist == "" {
|
||||
log.Warn("No filters specified for process collector. This will generate a very large number of metrics!")
|
||||
if *processWhereClause == "" {
|
||||
log.Warn("No where-clause specified for process collector. This will generate a very large number of metrics!")
|
||||
}
|
||||
|
||||
return &processCollector{
|
||||
return &ProcessCollector{
|
||||
StartTime: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "start_time"),
|
||||
"Time of process start.",
|
||||
@@ -135,53 +129,66 @@ func newProcessCollector() (Collector, error) {
|
||||
[]string{"process", "process_id", "creating_process_id"},
|
||||
nil,
|
||||
),
|
||||
processWhitelistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *processWhitelist)),
|
||||
processBlacklistPattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *processBlacklist)),
|
||||
queryWhereClause: *processWhereClause,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type perflibProcess struct {
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *ProcessCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collect(ch); err != nil {
|
||||
log.Error("failed collecting process metrics:", desc, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Win32_PerfRawData_PerfProc_Process docs:
|
||||
// - https://msdn.microsoft.com/en-us/library/aa394323(v=vs.85).aspx
|
||||
type Win32_PerfRawData_PerfProc_Process struct {
|
||||
Name string
|
||||
PercentProcessorTime float64 `perflib:"% Processor Time"`
|
||||
PercentPrivilegedTime float64 `perflib:"% Privileged Time"`
|
||||
PercentUserTime float64 `perflib:"% User Time"`
|
||||
CreatingProcessID float64 `perflib:"Creating Process ID"`
|
||||
ElapsedTime float64 `perflib:"Elapsed Time"`
|
||||
HandleCount float64 `perflib:"Handle Count"`
|
||||
IDProcess float64 `perflib:"ID Process"`
|
||||
IODataBytesPerSec float64 `perflib:"IO Data Bytes/sec"`
|
||||
IODataOperationsPerSec float64 `perflib:"IO Data Operations/sec"`
|
||||
IOOtherBytesPerSec float64 `perflib:"IO Other Bytes/sec"`
|
||||
IOOtherOperationsPerSec float64 `perflib:"IO Other Operations/sec"`
|
||||
IOReadBytesPerSec float64 `perflib:"IO Read Bytes/sec"`
|
||||
IOReadOperationsPerSec float64 `perflib:"IO Read Operations/sec"`
|
||||
IOWriteBytesPerSec float64 `perflib:"IO Write Bytes/sec"`
|
||||
IOWriteOperationsPerSec float64 `perflib:"IO Write Operations/sec"`
|
||||
PageFaultsPerSec float64 `perflib:"Page Faults/sec"`
|
||||
PageFileBytesPeak float64 `perflib:"Page File Bytes Peak"`
|
||||
PageFileBytes float64 `perflib:"Page File Bytes"`
|
||||
PoolNonpagedBytes float64 `perflib:"Pool Nonpaged Bytes"`
|
||||
PoolPagedBytes float64 `perflib:"Pool Paged Bytes"`
|
||||
PriorityBase float64 `perflib:"Priority Base"`
|
||||
PrivateBytes float64 `perflib:"Private Bytes"`
|
||||
ThreadCount float64 `perflib:"Thread Count"`
|
||||
VirtualBytesPeak float64 `perflib:"Virtual Bytes Peak"`
|
||||
VirtualBytes float64 `perflib:"Virtual Bytes"`
|
||||
WorkingSetPrivate float64 `perflib:"Working Set - Private"`
|
||||
WorkingSetPeak float64 `perflib:"Working Set Peak"`
|
||||
WorkingSet float64 `perflib:"Working Set"`
|
||||
CreatingProcessID uint32
|
||||
ElapsedTime uint64
|
||||
Frequency_Object uint64
|
||||
HandleCount uint32
|
||||
IDProcess uint32
|
||||
IODataBytesPersec uint64
|
||||
IODataOperationsPersec uint64
|
||||
IOOtherBytesPersec uint64
|
||||
IOOtherOperationsPersec uint64
|
||||
IOReadBytesPersec uint64
|
||||
IOReadOperationsPersec uint64
|
||||
IOWriteBytesPersec uint64
|
||||
IOWriteOperationsPersec uint64
|
||||
PageFaultsPersec uint32
|
||||
PageFileBytes uint64
|
||||
PageFileBytesPeak uint64
|
||||
PercentPrivilegedTime uint64
|
||||
PercentProcessorTime uint64
|
||||
PercentUserTime uint64
|
||||
PoolNonpagedBytes uint32
|
||||
PoolPagedBytes uint32
|
||||
PriorityBase uint32
|
||||
PrivateBytes uint64
|
||||
ThreadCount uint32
|
||||
Timestamp_Object uint64
|
||||
VirtualBytes uint64
|
||||
VirtualBytesPeak uint64
|
||||
WorkingSet uint64
|
||||
WorkingSetPeak uint64
|
||||
WorkingSetPrivate uint64
|
||||
}
|
||||
|
||||
type WorkerProcess struct {
|
||||
AppPoolName string
|
||||
ProcessId uint64
|
||||
ProcessId uint32
|
||||
}
|
||||
|
||||
func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
data := make([]perflibProcess, 0)
|
||||
err := unmarshalObject(ctx.perfObjects["Process"], &data)
|
||||
if err != nil {
|
||||
return err
|
||||
func (c *ProcessCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_PerfProc_Process
|
||||
q := queryAllWhere(&dst, c.queryWhereClause)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var dst_wp []WorkerProcess
|
||||
@@ -190,10 +197,9 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
log.Debugf("Could not query WebAdministration namespace for IIS worker processes: %v. Skipping", err)
|
||||
}
|
||||
|
||||
for _, process := range data {
|
||||
if process.Name == "_Total" ||
|
||||
c.processBlacklistPattern.MatchString(process.Name) ||
|
||||
!c.processWhitelistPattern.MatchString(process.Name) {
|
||||
for _, process := range dst {
|
||||
|
||||
if process.Name == "_Total" {
|
||||
continue
|
||||
}
|
||||
// Duplicate processes are suffixed # and an index number. Remove those.
|
||||
@@ -202,7 +208,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
cpid := strconv.FormatUint(uint64(process.CreatingProcessID), 10)
|
||||
|
||||
for _, wp := range dst_wp {
|
||||
if wp.ProcessId == uint64(process.IDProcess) {
|
||||
if wp.ProcessId == process.IDProcess {
|
||||
processName = strings.Join([]string{processName, wp.AppPoolName}, "_")
|
||||
break
|
||||
}
|
||||
@@ -211,7 +217,8 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.StartTime,
|
||||
prometheus.GaugeValue,
|
||||
process.ElapsedTime,
|
||||
// convert from Windows timestamp (1 jan 1601) to unix timestamp (1 jan 1970)
|
||||
float64(process.ElapsedTime-116444736000000000)/float64(process.Frequency_Object),
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
@@ -220,7 +227,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.HandleCount,
|
||||
prometheus.GaugeValue,
|
||||
process.HandleCount,
|
||||
float64(process.HandleCount),
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
@@ -229,7 +236,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CPUTimeTotal,
|
||||
prometheus.CounterValue,
|
||||
process.PercentPrivilegedTime,
|
||||
float64(process.PercentPrivilegedTime)*ticksToSecondsScaleFactor,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
@@ -239,7 +246,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.CPUTimeTotal,
|
||||
prometheus.CounterValue,
|
||||
process.PercentUserTime,
|
||||
float64(process.PercentUserTime)*ticksToSecondsScaleFactor,
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
@@ -249,7 +256,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.IOBytesTotal,
|
||||
prometheus.CounterValue,
|
||||
process.IOOtherBytesPerSec,
|
||||
float64(process.IOOtherBytesPersec),
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
@@ -259,7 +266,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.IOOperationsTotal,
|
||||
prometheus.CounterValue,
|
||||
process.IOOtherOperationsPerSec,
|
||||
float64(process.IOOtherOperationsPersec),
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
@@ -269,7 +276,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.IOBytesTotal,
|
||||
prometheus.CounterValue,
|
||||
process.IOReadBytesPerSec,
|
||||
float64(process.IOReadBytesPersec),
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
@@ -279,7 +286,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.IOOperationsTotal,
|
||||
prometheus.CounterValue,
|
||||
process.IOReadOperationsPerSec,
|
||||
float64(process.IOReadOperationsPersec),
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
@@ -289,7 +296,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.IOBytesTotal,
|
||||
prometheus.CounterValue,
|
||||
process.IOWriteBytesPerSec,
|
||||
float64(process.IOWriteBytesPersec),
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
@@ -299,7 +306,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.IOOperationsTotal,
|
||||
prometheus.CounterValue,
|
||||
process.IOWriteOperationsPerSec,
|
||||
float64(process.IOWriteOperationsPersec),
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
@@ -309,7 +316,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PageFaultsTotal,
|
||||
prometheus.CounterValue,
|
||||
process.PageFaultsPerSec,
|
||||
float64(process.PageFaultsPersec),
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
@@ -318,7 +325,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PageFileBytes,
|
||||
prometheus.GaugeValue,
|
||||
process.PageFileBytes,
|
||||
float64(process.PageFileBytes),
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
@@ -327,7 +334,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PoolBytes,
|
||||
prometheus.GaugeValue,
|
||||
process.PoolNonpagedBytes,
|
||||
float64(process.PoolNonpagedBytes),
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
@@ -337,7 +344,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PoolBytes,
|
||||
prometheus.GaugeValue,
|
||||
process.PoolPagedBytes,
|
||||
float64(process.PoolPagedBytes),
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
@@ -347,7 +354,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PriorityBase,
|
||||
prometheus.GaugeValue,
|
||||
process.PriorityBase,
|
||||
float64(process.PriorityBase),
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
@@ -356,7 +363,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.PrivateBytes,
|
||||
prometheus.GaugeValue,
|
||||
process.PrivateBytes,
|
||||
float64(process.PrivateBytes),
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
@@ -365,7 +372,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.ThreadCount,
|
||||
prometheus.GaugeValue,
|
||||
process.ThreadCount,
|
||||
float64(process.ThreadCount),
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
@@ -374,7 +381,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.VirtualBytes,
|
||||
prometheus.GaugeValue,
|
||||
process.VirtualBytes,
|
||||
float64(process.VirtualBytes),
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
@@ -383,12 +390,12 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.WorkingSet,
|
||||
prometheus.GaugeValue,
|
||||
process.WorkingSet,
|
||||
float64(process.WorkingSet),
|
||||
processName,
|
||||
pid,
|
||||
cpid,
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
84
collector/terminal_services.go
Normal file
84
collector/terminal_services.go
Normal file
@@ -0,0 +1,84 @@
|
||||
// +build windows
|
||||
|
||||
package collector
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/StackExchange/wmi"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/common/log"
|
||||
)
|
||||
|
||||
func init() {
|
||||
registerCollector("terminal_services", NewTerminalServicesCollector)
|
||||
}
|
||||
|
||||
// A TerminalServicesCollector is a Prometheus collector for WMI
|
||||
// Win32_PerfRawData_LocalSessionManager_TerminalServices & Win32_PerfRawData_TermService_TerminalServicesSession metrics
|
||||
type TerminalServicesCollector struct {
|
||||
Local_session_count *prometheus.Desc
|
||||
}
|
||||
|
||||
// NewTerminalServicesCollector ...
|
||||
func NewTerminalServicesCollector() (Collector, error) {
|
||||
const subsystem = "terminal_services"
|
||||
return &TerminalServicesCollector{
|
||||
Local_session_count: prometheus.NewDesc(
|
||||
prometheus.BuildFQName(Namespace, subsystem, "local_session_count"),
|
||||
"Number of Terminal Services sessions",
|
||||
[]string{"session"},
|
||||
nil,
|
||||
),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Collect sends the metric values for each metric
|
||||
// to the provided prometheus Metric channel.
|
||||
func (c *TerminalServicesCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error {
|
||||
if desc, err := c.collectTSSessionCount(ch); err != nil {
|
||||
log.Error("failed collecting terminal services session count metrics:", desc, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Win32_PerfRawData_LocalSessionManager_TerminalServices struct {
|
||||
ActiveSessions uint32
|
||||
InactiveSessions uint32
|
||||
TotalSessions uint32
|
||||
}
|
||||
|
||||
func (c *TerminalServicesCollector) collectTSSessionCount(ch chan<- prometheus.Metric) (*prometheus.Desc, error) {
|
||||
var dst []Win32_PerfRawData_LocalSessionManager_TerminalServices
|
||||
q := queryAll(&dst)
|
||||
if err := wmi.Query(q, &dst); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(dst) == 0 {
|
||||
return nil, errors.New("WMI query returned empty result set")
|
||||
}
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Local_session_count,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].ActiveSessions),
|
||||
"active",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Local_session_count,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].InactiveSessions),
|
||||
"inactive",
|
||||
)
|
||||
|
||||
ch <- prometheus.MustNewConstMetric(
|
||||
c.Local_session_count,
|
||||
prometheus.GaugeValue,
|
||||
float64(dst[0].TotalSessions),
|
||||
"total",
|
||||
)
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
@@ -5,29 +5,18 @@ The process collector exposes metrics about processes
|
||||
|||
|
||||
-|-
|
||||
Metric name prefix | `process`
|
||||
Data source | Perflib
|
||||
Counters | `Process`
|
||||
Classes | [`Win32_PerfRawData_PerfProc_Process`](https://msdn.microsoft.com/en-us/library/aa394323(v=vs.85).aspx)
|
||||
Enabled by default? | No
|
||||
|
||||
## Flags
|
||||
|
||||
### `--collector.process.whitelist`
|
||||
### `--collector.process.processes-where`
|
||||
|
||||
Regexp of processes to include. Process name must both match whitelist and not
|
||||
match blacklist to be included. Recommended to keep down number of returned
|
||||
metrics.
|
||||
A WMI filter on which processes to include. Recommended to keep down number of returned metrics.
|
||||
|
||||
### `--collector.process.blacklist`
|
||||
`%` is a wildcard, and can be used to match on substrings.
|
||||
|
||||
Regexp of processes to exclude. Process name must both match whitelist and not
|
||||
match blacklist to be included. Recommended to keep down number of returned
|
||||
metrics.
|
||||
|
||||
### Example
|
||||
To match all firefox processes: `--collector.process.whitelist="firefox.+"`.
|
||||
Note that multiple processes with the same name will be disambiguated by
|
||||
Windows by adding a number suffix, such as `firefox#2`. Your regexp must take
|
||||
these suffixes into consideration.
|
||||
Example: `--collector.process.processes-where="Name LIKE 'firefox%'`
|
||||
|
||||
## Metrics
|
||||
|
||||
|
||||
33
exporter.go
33
exporter.go
@@ -265,10 +265,6 @@ func main() {
|
||||
"telemetry.path",
|
||||
"URL path for surfacing collected metrics.",
|
||||
).Default("/metrics").String()
|
||||
maxRequests = kingpin.Flag(
|
||||
"telemetry.max-requests",
|
||||
"Maximum number of concurrent requests. 0 to disable.",
|
||||
).Default("5").Int()
|
||||
enabledCollectors = kingpin.Flag(
|
||||
"collectors.enabled",
|
||||
"Comma-separated list of collectors to use. Use '[defaults]' as a placeholder for all the collectors enabled by default.").
|
||||
@@ -336,16 +332,10 @@ func main() {
|
||||
},
|
||||
}
|
||||
|
||||
http.HandleFunc(*metricsPath, withConcurrencyLimit(*maxRequests, h.ServeHTTP))
|
||||
http.Handle(*metricsPath, h)
|
||||
http.HandleFunc("/health", healthCheck)
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
_, _ = w.Write([]byte(`<html>
|
||||
<head><title>WMI Exporter</title></head>
|
||||
<body>
|
||||
<h1>WMI Exporter</h1>
|
||||
<p><a href="` + *metricsPath + `">Metrics</a></p>
|
||||
</body>
|
||||
</html>`))
|
||||
http.Redirect(w, r, *metricsPath, http.StatusMovedPermanently)
|
||||
})
|
||||
|
||||
log.Infoln("Starting WMI exporter", version.Info())
|
||||
@@ -380,25 +370,6 @@ func keys(m map[string]collector.Collector) []string {
|
||||
return ret
|
||||
}
|
||||
|
||||
func withConcurrencyLimit(n int, next http.HandlerFunc) http.HandlerFunc {
|
||||
if n <= 0 {
|
||||
return next
|
||||
}
|
||||
|
||||
sem := make(chan struct{}, n)
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
select {
|
||||
case sem <- struct{}{}:
|
||||
defer func() { <-sem }()
|
||||
default:
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
_, _ = w.Write([]byte("Too many concurrent requests"))
|
||||
return
|
||||
}
|
||||
next(w, r)
|
||||
}
|
||||
}
|
||||
|
||||
type wmiExporterService struct {
|
||||
stopCh chan<- bool
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user