github.com/mackerelio/mackerel-agent-plugins@v0.89.3/mackerel-plugin-windows-process-stats/lib/process-stats_windows.go (about)

     1  //go:build windows
     2  
     3  package mpwindowsprocessstats
     4  
     5  import (
     6  	"flag"
     7  	"fmt"
     8  	"os"
     9  	"regexp"
    10  	"sort"
    11  	"strconv"
    12  
    13  	mp "github.com/mackerelio/go-mackerel-plugin-helper"
    14  	"github.com/mackerelio/golib/logging"
    15  	"github.com/yusufpapurcu/wmi"
    16  )
    17  
    18  var logger = logging.GetLogger("metrics.plugin.windows-process-stats")
    19  
    20  type Win32_PerfFormattedData_PerfProc_Process struct {
    21  	ElapsedTime          uint64
    22  	Name                 string
    23  	IDProcess            uint32
    24  	PercentProcessorTime uint64
    25  	WorkingSet           uint64
    26  }
    27  
    28  type WindowsProcessStatsPlugin struct {
    29  	Process string
    30  	Prefix  string
    31  }
    32  
    33  func getProcesses(processName string) ([]Win32_PerfFormattedData_PerfProc_Process, error) {
    34  	var procs []Win32_PerfFormattedData_PerfProc_Process
    35  
    36  	q := wmi.CreateQuery(&procs, "WHERE (Name like '"+processName+"' OR Name like '"+processName+"#%')")
    37  	if err := wmi.Query(q, &procs); err != nil {
    38  		return procs, err
    39  	}
    40  
    41  	sort.Slice(procs, func(i, j int) bool {
    42  		return procs[i].IDProcess < procs[j].IDProcess
    43  	})
    44  	return procs, nil
    45  }
    46  
    47  // FetchMetrics interface for mackerelplugin
    48  func (m WindowsProcessStatsPlugin) FetchMetrics() (map[string]interface{}, error) {
    49  	procs, err := getProcesses(m.Process)
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  	stat := make(map[string]interface{})
    54  	var re = regexp.MustCompile(`#[0-9]+$`)
    55  	for k, v := range procs {
    56  		processName := re.ReplaceAllString(v.Name, "") + "_" + strconv.Itoa(k)
    57  		metricNameCPU := "cpu." + processName + ".percent_processor_time"
    58  		metricNameMemory := "memory." + processName + ".working_set"
    59  		stat[metricNameCPU] = v.PercentProcessorTime
    60  		stat[metricNameMemory] = v.WorkingSet
    61  	}
    62  
    63  	return stat, nil
    64  }
    65  
    66  // GraphDefinition interface for mackerelplugin
    67  func (m WindowsProcessStatsPlugin) GraphDefinition() map[string](mp.Graphs) {
    68  	prefix := m.Prefix
    69  	return map[string](mp.Graphs){
    70  		"cpu.#": mp.Graphs{
    71  			Label: fmt.Sprintf("%s Windows Process Stats CPU", prefix),
    72  			Unit:  "percentage",
    73  			Metrics: []mp.Metrics{
    74  				{Name: "percent_processor_time", Label: "cpu", Diff: false, Stacked: false},
    75  			},
    76  		},
    77  		"memory.#": mp.Graphs{
    78  			Label: fmt.Sprintf("%s Windows Process Stats Memory", prefix),
    79  			Unit:  "bytes",
    80  			Metrics: []mp.Metrics{
    81  				{Name: "working_set", Label: "memory", Diff: false, Stacked: false},
    82  			},
    83  		},
    84  	}
    85  }
    86  
    87  // MetricKeyPrefix interface for mackerelplugin
    88  func (m WindowsProcessStatsPlugin) MetricKeyPrefix() string {
    89  	if m.Prefix == "" {
    90  		return "windows-process-stats-" + m.Process
    91  	}
    92  	return m.Prefix
    93  }
    94  
    95  // Do the plugin
    96  func Do() {
    97  	optProcess := flag.String("process", "", "Process name")
    98  	optMetricKeyPrefix := flag.String("metric-key-prefix", "", "Metric Key Prefix")
    99  	optTempfile := flag.String("tempfile", "", "Temp file name")
   100  	flag.Parse()
   101  
   102  	if *optProcess == "" {
   103  		logger.Warningf("Process name is required")
   104  		flag.PrintDefaults()
   105  		os.Exit(1)
   106  	}
   107  
   108  	var plugin WindowsProcessStatsPlugin
   109  	plugin.Process = *optProcess
   110  	plugin.Prefix = *optMetricKeyPrefix
   111  
   112  	helper := mp.NewMackerelPlugin(plugin)
   113  	helper.Tempfile = *optTempfile
   114  	helper.Run()
   115  }