"github.com/mackerelio/mackerel-agent/logging" ) // FilesystemInfo XXX type FilesystemInfo struct { PercentUsed string KbUsed float64 KbSize float64 KbAvailable float64 Mount string Label string VolumeName string FsType string } var windowsLogger = logging.GetLogger("windows") // CollectFilesystemValues XXX func CollectFilesystemValues() (map[string]FilesystemInfo, error) { filesystems := make(map[string]FilesystemInfo) drivebuf := make([]byte, 256) r, _, err := GetLogicalDriveStrings.Call( uintptr(len(drivebuf)), uintptr(unsafe.Pointer(&drivebuf[0]))) if r == 0 { return nil, err } drives := []string{}
package mpunicorn import ( "flag" "fmt" "io/ioutil" "os" "strings" mp "github.com/mackerelio/go-mackerel-plugin-helper" "github.com/mackerelio/mackerel-agent/logging" ) var logger = logging.GetLogger("metrics.plugin.unicorn") var graphdef = map[string]mp.Graphs{ "unicorn.memory": { Label: "Unicorn Memory", Unit: "bytes", Metrics: []mp.Metrics{ {Name: "memory_workers", Label: "Workers", Diff: false, Stacked: true}, {Name: "memory_master", Label: "Master", Diff: false, Stacked: true}, {Name: "memory_workeravg", Label: "Worker Average", Diff: false, Stacked: false}, }, }, "unicorn.workers": { Label: "Unicorn Workers", Unit: "integer", Metrics: []mp.Metrics{
"github.com/mackerelio/mackerel-agent/logging" "github.com/mackerelio/mackerel-agent/metrics" "github.com/mackerelio/mackerel-agent/util/windows" ) // FilesystemGenerator XXX type FilesystemGenerator struct { } // NewFilesystemGenerator XXX func NewFilesystemGenerator() (*FilesystemGenerator, error) { return &FilesystemGenerator{}, nil } var logger = logging.GetLogger("metrics.filesystem") // Generate XXX func (g *FilesystemGenerator) Generate() (metrics.Values, error) { filesystems, err := windows.CollectFilesystemValues() if err != nil { return nil, err } ret := make(map[string]float64) for name, values := range filesystems { if matches := regexp.MustCompile(`^(.*):`).FindStringSubmatch(name); matches != nil { device := regexp.MustCompile(`[^A-Za-z0-9_-]`).ReplaceAllString(matches[1], "_") ret["filesystem."+device+".size"] = values.KbSize * 1024 ret["filesystem."+device+".used"] = values.KbUsed * 1024
package agent import ( "sync" "github.com/mackerelio/mackerel-agent/logging" "github.com/mackerelio/mackerel-agent/metrics" ) var logger = logging.GetLogger("agent") func generateValues(generators []metrics.Generator) chan metrics.Values { processed := make(chan metrics.Values) finish := make(chan bool) result := make(chan metrics.Values) go func() { allValues := metrics.Values(make(map[string]float64)) for { select { case values := <-processed: allValues.Merge(values) case <-finish: result <- allValues return } } }() go func() { var wg sync.WaitGroup
package main import ( "encoding/json" "errors" "flag" "fmt" "net/http" "os" mp "github.com/mackerelio/go-mackerel-plugin" "github.com/mackerelio/mackerel-agent/logging" ) var logger = logging.GetLogger("metrics.plugin.elasticsearch") var graphdef = map[string](mp.Graphs){ "elasticsearch.http": mp.Graphs{ Label: "Elasticsearch HTTP", Unit: "integer", Metrics: [](mp.Metrics){ mp.Metrics{Name: "http_opened", Label: "Opened", Diff: true}, }, }, "elasticsearch.indices": mp.Graphs{ Label: "Elasticsearch Indices", Unit: "integer", Metrics: [](mp.Metrics){ mp.Metrics{Name: "total_indexing_index", Label: "Indexing-Index", Diff: true, Stacked: true}, mp.Metrics{Name: "total_indexing_delete", Label: "Indexing-Delete", Diff: true, Stacked: true}, mp.Metrics{Name: "total_get", Label: "Get", Diff: true, Stacked: true},
// KernelGenerator Generates specs about the kernel. // Keys below are expected. // - name: the operating system name ("Linux") // - release: the operating system release ("2.6.32-5-686") // - version: the operating system version ("#1 SMP Sun Sep 23 09:49:36 UTC 2012") // - machine: the machine hardware name ("i686") // - os: the operating system name ("GNU/Linux") type KernelGenerator struct { } // Key XXX func (g *KernelGenerator) Key() string { return "kernel" } var kernelLogger = logging.GetLogger("spec.kernel") // Generate XXX func (g *KernelGenerator) Generate() (interface{}, error) { unameArgs := map[string][]string{ "release": []string{"-r"}, "version": []string{"-v"}, "machine": []string{"-m"}, "os": []string{"-s"}, } results := make(map[string]string, len(unameArgs)+1) for field, args := range unameArgs { out, err := exec.Command("/usr/bin/uname", args...).Output() if err != nil {
"github.com/mackerelio/mackerel-agent/metrics" ) /* collect load average `loadavg5`: load average per 5 minutes retrieved from /proc/loadavg graph: `loadavg5` */ // Loadavg5Generator XXX type Loadavg5Generator struct { } var loadavg5Logger = logging.GetLogger("metrics.loadavg5") // Generate XXX func (g *Loadavg5Generator) Generate() (metrics.Values, error) { contentbytes, err := ioutil.ReadFile("/proc/loadavg") if err != nil { loadavg5Logger.Errorf("Failed (skip these metrics): %s", err) return nil, err } content := string(contentbytes) cols := strings.Split(content, " ") f, err := strconv.ParseFloat(cols[1], 64) if err != nil { loadavg5Logger.Errorf("Failed to parse loadavg5 metrics (skip these metrics): %s", err) return nil, err
package main import ( "flag" "fmt" "os" "regexp" mp "github.com/mackerelio/go-mackerel-plugin-helper" "github.com/mackerelio/mackerel-agent/logging" ) var logger = logging.GetLogger("metrics.plugin.proc-fd") // ProcfdPlugin for fetching metrics type ProcfdPlugin struct { Process string NormalizedProcess string MetricName string } // FetchMetrics fetch the metrics func (p ProcfdPlugin) FetchMetrics() (map[string]interface{}, error) { fds, err := openFd.getNumOpenFileDesc() if err != nil { return nil, err } stat := make(map[string]interface{}) // Compute maximum open file descriptor
package mppostgres import ( "flag" "fmt" "os" "github.com/jmoiron/sqlx" // PostgreSQL Driver _ "github.com/lib/pq" mp "github.com/mackerelio/go-mackerel-plugin-helper" "github.com/mackerelio/mackerel-agent/logging" ) var logger = logging.GetLogger("metrics.plugin.postgres") var graphdef = map[string]mp.Graphs{ "postgres.connections": { Label: "Postgres Connections", Unit: "integer", Metrics: []mp.Metrics{ {Name: "active", Label: "Active", Diff: false, Stacked: true}, {Name: "waiting", Label: "Waiting", Diff: false, Stacked: true}, }, }, "postgres.commits": { Label: "Postgres Commits", Unit: "integer", Metrics: []mp.Metrics{ {Name: "xact_commit", Label: "Xact Commit", Diff: true, Stacked: false}, {Name: "xact_rollback", Label: "Xact Rollback", Diff: true, Stacked: false},
package mpjmxjolokia import ( "encoding/json" "flag" "fmt" "net/http" mp "github.com/mackerelio/go-mackerel-plugin-helper" "github.com/mackerelio/mackerel-agent/logging" ) var logger = logging.GetLogger("metrics.plugin.jmx-jolokia") // JmxJolokiaPlugin mackerel plugin for Jolokia type JmxJolokiaPlugin struct { Target string Tempfile string } // JmxJolokiaResponse response for Jolokia type JmxJolokiaResponse struct { Status uint32 Timestamp uint32 Request map[string]interface{} Value map[string]interface{} Error string } var graphdef = map[string]mp.Graphs{ "jmx.jolokia.memory.heap_memory_usage": {
package main import ( "os" "os/exec" "regexp" "runtime" "strconv" "strings" mp "github.com/mackerelio/go-mackerel-plugin-helper" "github.com/mackerelio/mackerel-agent/logging" ) var logger = logging.GetLogger("metrics.plugin.inode") // InodePlugin plugin type InodePlugin struct{} var dfHeaderPattern = regexp.MustCompile( `^Filesystem\s+`, ) var dfColumnsPattern = regexp.MustCompile( `^(.+?)\s+(?:(?:\d+)\s+(?:\d+)\s+(?:\d+)\s+(?:\d+%)\s+|(?:\d+)\s+)?(\d+)\s+(\d+)\s+(\d+%)\s+(.+)$`, ) var devicePattern = regexp.MustCompile( `^/dev/(.*)$`, )
// CloudGenerator definition type CloudGenerator struct { CloudMetaGenerator } // CloudMetaGenerator interface of metadata generator for each cloud platform type CloudMetaGenerator interface { Generate() (interface{}, error) } // Key is a root key for the generator. func (g *CloudGenerator) Key() string { return "cloud" } var cloudLogger = logging.GetLogger("spec.cloud") var ec2BaseURL, gceMetaURL, digitalOceanBaseURL *url.URL func init() { ec2BaseURL, _ = url.Parse("http://169.254.169.254/latest/meta-data") gceMetaURL, _ = url.Parse("http://metadata.google.internal/computeMetadata/v1/?recursive=true") digitalOceanBaseURL, _ = url.Parse("http://169.254.169.254/metadata/v1") // has not been yet used } var timeout = 100 * time.Millisecond // SuggestCloudGenerator returns suitable CloudGenerator func SuggestCloudGenerator() *CloudGenerator { if isEC2() { return &CloudGenerator{&EC2Generator{ec2BaseURL}}
package checks import ( "fmt" "time" "github.com/mackerelio/mackerel-agent/config" "github.com/mackerelio/mackerel-agent/logging" "github.com/mackerelio/mackerel-agent/util" ) var logger = logging.GetLogger("checks") // Status is a status that is produced by periodical checking. // It is currently compatible with Nagios. type Status string // Current possible statuses, which is taken from command's exit code. // the mapping is given as exitCodeToStatus. const ( StatusUndefined Status = "" StatusOK Status = "OK" StatusWarning Status = "WARNING" StatusCritical Status = "CRITICAL" StatusUnknown Status = "UNKNOWN" ) var exitCodeToStatus = map[int]Status{ 0: StatusOK, 1: StatusWarning, 2: StatusCritical,
"time" "unsafe" "github.com/mackerelio/mackerel-agent/logging" "github.com/mackerelio/mackerel-agent/metrics" "github.com/mackerelio/mackerel-agent/util/windows" ) // DiskGenerator XXX type DiskGenerator struct { Interval time.Duration query syscall.Handle counters []*windows.CounterInfo } var diskLogger = logging.GetLogger("metrics.disk") // NewDiskGenerator XXX func NewDiskGenerator(interval time.Duration) (*DiskGenerator, error) { g := &DiskGenerator{interval, 0, nil} var err error g.query, err = windows.CreateQuery() if err != nil { diskLogger.Criticalf(err.Error()) return nil, err } drivebuf := make([]byte, 256) r, _, err := windows.GetLogicalDriveStrings.Call( uintptr(len(drivebuf)),
package config import ( "fmt" "io/ioutil" "os" "path/filepath" "regexp" "strings" "time" "github.com/BurntSushi/toml" "github.com/mackerelio/mackerel-agent/logging" ) var configLogger = logging.GetLogger("config") // `apibase` and `agentName` are set from build flags var apibase string func getApibase() string { if apibase != "" { return apibase } return "https://mackerel.io" } var agentName string func getAgentName() string { if agentName != "" {
"math" "os" "time" "github.com/Songmu/retry" "github.com/mackerelio/mackerel-agent/agent" "github.com/mackerelio/mackerel-agent/checks" "github.com/mackerelio/mackerel-agent/config" "github.com/mackerelio/mackerel-agent/logging" "github.com/mackerelio/mackerel-agent/mackerel" "github.com/mackerelio/mackerel-agent/metrics" "github.com/mackerelio/mackerel-agent/spec" "github.com/mackerelio/mackerel-agent/util" ) var logger = logging.GetLogger("command") var metricsInterval = 60 * time.Second var retryNum uint = 20 var retryInterval = 3 * time.Second // prepareHost collects specs of the host and sends them to Mackerel server. // A unique host-id is returned by the server if one is not specified. func prepareHost(conf *config.Config, api *mackerel.API) (*mackerel.Host, error) { // XXX this configuration should be moved to under spec/linux os.Setenv("PATH", "/sbin:/usr/sbin:/bin:/usr/bin:"+os.Getenv("PATH")) os.Setenv("LANG", "C") // prevent changing outputs of some command, e.g. ifconfig. doRetry := func(f func() error) { retry.Retry(retryNum, retryInterval, f) }
import ( "fmt" "os/exec" "strconv" "strings" "github.com/mackerelio/mackerel-agent/logging" "github.com/mackerelio/mackerel-agent/metrics" ) // CPUUsageGenerator XXX type CPUUsageGenerator struct { } var cpuUsageLogger = logging.GetLogger("metrics.cpuUsage") var iostatFieldToMetricName = []string{"user", "nice", "system", "interrupt", "idle"} // Generate returns current CPU usage of the host. // Keys below are expected: // - cpu.user.percentage // - cpu.system.percentage // - cpu.idle.percentage func (g *CPUUsageGenerator) Generate() (metrics.Values, error) { // $ iostat -n0 -c2 -d -C // cpu // us ni sy in id // 3 21 4 1 71 // 0 0 4 0 96
"unsafe" "github.com/mackerelio/mackerel-agent/logging" "github.com/mackerelio/mackerel-agent/util/windows" ) // MemoryGenerator collects the host's memory specs. type MemoryGenerator struct { } // Key XXX func (g *MemoryGenerator) Key() string { return "memory" } var memoryLogger = logging.GetLogger("spec.memory") // Generate XXX func (g *MemoryGenerator) Generate() (interface{}, error) { result := make(map[string]interface{}) var memoryStatusEx windows.MEMORY_STATUS_EX memoryStatusEx.Length = uint32(unsafe.Sizeof(memoryStatusEx)) r, _, err := windows.GlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&memoryStatusEx))) if r == 0 { return nil, err } result["total"] = fmt.Sprintf("%dkb", memoryStatusEx.TotalPhys/1024) result["free"] = fmt.Sprintf("%dkb", memoryStatusEx.AvailPhys/1024)
import ( "crypto/md5" "flag" "fmt" "os" "regexp" "strconv" "strings" "time" "github.com/fzzy/radix/redis" mp "github.com/mackerelio/go-mackerel-plugin" "github.com/mackerelio/mackerel-agent/logging" ) var logger = logging.GetLogger("metrics.plugin.redis") type RedisPlugin struct { Host string Port string Socket string Prefix string Timeout int Tempfile string } func (m RedisPlugin) FetchMetrics() (map[string]float64, error) { network := "tcp" target := fmt.Sprintf("%s:%s", m.Host, m.Port) if m.Socket != "" { target = m.Socket
var dfHeaderPattern = regexp.MustCompile( // 1024-blocks or 1k-blocks `^Filesystem\s+(?:1024|1[Kk])-block`, ) // DfColumnSpec XXX type DfColumnSpec struct { Name string IsInt bool // type of collected data true: int64, false: string } var dfColumnsPattern = regexp.MustCompile( `^(.+?)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+%)\s+(.+)$`, ) var logger = logging.GetLogger("util.filesystem") var dfOpt []string func init() { switch runtime.GOOS { case "darwin": dfOpt = []string{"-Pkl"} case "freebsd": dfOpt = []string{"-Pkt", "noprocfs,devfs,fdescfs,nfs,cd9660"} case "netbsd": dfOpt = []string{"-Pkl"} default: dfOpt = []string{"-P"} } }
package spec import ( "github.com/mackerelio/mackerel-agent/logging" "github.com/mackerelio/mackerel-agent/version" ) var logger = logging.GetLogger("spec") // Generator XXX type Generator interface { Key() string Generate() (interface{}, error) } // Collect XXX func Collect(specGenerators []Generator) map[string]interface{} { specs := make(map[string]interface{}) for _, g := range specGenerators { value, err := g.Generate() if err != nil { logger.Errorf("Failed to collect meta in %T (skip this spec): %s", g, err.Error()) continue } specs[g.Key()] = value } specs["agent-version"] = version.VERSION specs["agent-revision"] = version.GITCOMMIT specs["agent-name"] = version.UserAgent() return specs }
"os" "regexp" "github.com/mackerelio/mackerel-agent/logging" ) // CPUGenerator Collects CPU specs type CPUGenerator struct { } // Key XXX func (g *CPUGenerator) Key() string { return "cpu" } var cpuLogger = logging.GetLogger("spec.cpu") // Generate XXX func (g *CPUGenerator) Generate() (interface{}, error) { file, err := os.Open("/proc/cpuinfo") if err != nil { cpuLogger.Errorf("Failed (skip this spec): %s", err) return nil, err } scanner := bufio.NewScanner(file) var results []map[string]interface{} var cur map[string]interface{} for scanner.Scan() { line := scanner.Text()
// allow options like -role=... -role=... type roleFullnamesFlag []string var roleFullnamePattern = regexp.MustCompile(`^[a-zA-Z0-9][-_a-zA-Z0-9]*:\s*[a-zA-Z0-9][-_a-zA-Z0-9]*$`) func (r *roleFullnamesFlag) String() string { return fmt.Sprint(*r) } func (r *roleFullnamesFlag) Set(input string) error { inputRoles := strings.Split(input, ",") *r = append(*r, inputRoles...) return nil } var logger = logging.GetLogger("main") func main() { cli.Run(os.Args[1:]) } func printRetireUsage() { usage := fmt.Sprintf(`Usage of mackerel-agent retire: -conf string Config file path (Configs in this file are over-written by command line options) (default "%s") -force force retirement without prompting -apibase string API base (default "%s") -apikey string
// InterfaceGenerator XXX type InterfaceGenerator struct { Interval time.Duration } var interfaceMetrics = []string{ "rxBytes", "rxPackets", "rxErrors", "rxDrops", "rxFifo", "rxFrame", "rxCompressed", "rxMulticast", "txBytes", "txPackets", "txErrors", "txDrops", "txFifo", "txColls", "txCarrier", "txCompressed", } // metrics for posting to Mackerel var postInterfaceMetricsRegexp = regexp.MustCompile(`^interface\..+\.(rxBytes|txBytes)$`) var interfaceLogger = logging.GetLogger("metrics.interface") // Generate XXX func (g *InterfaceGenerator) Generate() (metrics.Values, error) { prevValues, err := g.collectIntarfacesValues() if err != nil { return nil, err } time.Sleep(g.Interval) currValues, err := g.collectIntarfacesValues() if err != nil { return nil, err }
Pages zero filled: 50848672. Pages reactivated: 1999. Pages purged: 2496610. File-backed pages: 677870. Anonymous pages: 2996150. Pages stored in compressor: 0. Pages occupied by compressor: 0. Decompressions: 0. Compressions: 0. Pageins: 6333901. Pageouts: 353. Swapins: 0. Swapouts: 0. */ var memoryLogger = logging.GetLogger("metrics.memory") var statReg = regexp.MustCompile(`^(.+):\s+([0-9]+)\.$`) // Generate generate metrics values func (g *MemoryGenerator) Generate() (metrics.Values, error) { outBytes, err := exec.Command("vm_stat").Output() if err != nil { memoryLogger.Errorf("Failed (skip these metrics): %s", err) return nil, err } out := string(outBytes) lines := strings.Split(out, "\n") stats := map[string]int64{} for _, line := range lines { if matches := statReg.FindStringSubmatch(line); matches != nil {
package freebsd import ( "github.com/mackerelio/mackerel-agent/logging" "github.com/mackerelio/mackerel-agent/util" ) // FilesystemGenerator XXX type FilesystemGenerator struct { } // Key XXX func (g *FilesystemGenerator) Key() string { return "filesystem" } var logger = logging.GetLogger("spec.filesystem") var dfColumnSpecs = []util.DfColumnSpec{ util.DfColumnSpec{Name: "kb_size", IsInt: true}, util.DfColumnSpec{Name: "kb_used", IsInt: true}, util.DfColumnSpec{Name: "kb_available", IsInt: true}, util.DfColumnSpec{Name: "percent_used", IsInt: false}, util.DfColumnSpec{Name: "mount", IsInt: false}, } // Generate XXX func (g *FilesystemGenerator) Generate() (interface{}, error) { return util.CollectDfValues(dfColumnSpecs) }
// +build linux darwin freebsd netbsd package util import ( "fmt" "os/exec" "time" "github.com/Songmu/timeout" "github.com/mackerelio/mackerel-agent/logging" ) var utilLogger = logging.GetLogger("util") // TimeoutDuration is option of `Runcommand()` set timeout limit of command execution. var TimeoutDuration = 30 * time.Second // TimeoutKillAfter is option of `RunCommand()` set waiting limit to `kill -kill` after terminating the command. var TimeoutKillAfter = 10 * time.Second // RunCommand runs command (in two string) and returns stdout, stderr strings and its exit code. func RunCommand(command, user string) (string, string, int, error) { cmd := exec.Command("/bin/sh", "-c", command) if user != "" { cmd = exec.Command("sudo", "-u", user, "/bin/sh", "-c", command) } tio := &timeout.Timeout{ Cmd: cmd, Duration: TimeoutDuration, KillAfter: TimeoutKillAfter,
"github.com/mackerelio/mackerel-agent/logging" "github.com/mackerelio/mackerel-agent/spec" "github.com/mackerelio/mackerel-agent/util/windows" ) // InterfaceGenerator XXX type InterfaceGenerator struct { } // Key XXX func (g *InterfaceGenerator) Key() string { return "interface" } var interfaceLogger = logging.GetLogger("spec.interface") // Generate XXX func (g *InterfaceGenerator) Generate() ([]spec.NetInterface, error) { var results []spec.NetInterface ifs, err := net.Interfaces() if err != nil { return nil, err } ai, err := windows.GetAdapterList() if err != nil { return nil, err }
import ( "encoding/json" "errors" "flag" "fmt" "net/http" "net/url" "os" "strings" mp "github.com/mackerelio/go-mackerel-plugin" "github.com/mackerelio/mackerel-agent/logging" ) var ( logger = logging.GetLogger("metrics.plugin.solr") coreStatKeys = []string{"numDocs", "deletedDocs", "indexHeapUsageBytes", "version", "segmentCount", "sizeInBytes"} queryHandlerPaths = []string{"/update/json", "/select", "/update/json/docs", "/get", "/update/csv", "/replication", "/update", "/dataimport"} queryHandlerStatKeys = []string{"requests", "errors", "timeouts", "avgRequestsPerSecond", "5minRateReqsPerSecond", "15minRateReqsPerSecond", "avgTimePerRequest", "medianRequestTime", "75thPcRequestTime", "95thPcRequestTime", "99thPcRequestTime", "999thPcRequestTime"} cacheTypes = []string{"filterCache", "perSegFilter", "queryResultCache", "documentCache", "fieldValueCache"} cacheStatKeys = []string{"lookups", "hits", "hitratio", "inserts", "evictions", "size", "warmupTime"} ) // SolrPlugin mackerel plugin for Solr type SolrPlugin struct { Protocol string Host string Port string BaseURL string Cores []string Prefix string
package main import ( "flag" "fmt" "io/ioutil" "os" "os/exec" "strconv" "strings" mp "github.com/mackerelio/go-mackerel-plugin-helper" "github.com/mackerelio/mackerel-agent/logging" ) var logger = logging.GetLogger("metrics.plugin.jvm") // JVMPlugin plugin for JVM type JVMPlugin struct { Target string Lvmid string JstatPath string JavaName string Tempfile string } // # jps // 26547 NettyServer // 6438 Jps func fetchLvmidByAppname(appname, target, jpsPath string) (string, error) { out, err := exec.Command(jpsPath, target).Output()