bump(github.com/docker/libcompose) v0.3.0

This commit is contained in:
Tomas Kral
2016-08-22 10:51:22 +02:00
parent 223b4f37fa
commit e341adce0e
57 changed files with 944 additions and 12907 deletions
+23 -2
View File
@@ -46,7 +46,10 @@ func ResponseFormat(h http.Header) Format {
return FmtUnknown
}
const textType = "text/plain"
const (
textType = "text/plain"
jsonType = "application/json"
)
switch mediatype {
case ProtoType:
@@ -63,6 +66,22 @@ func ResponseFormat(h http.Header) Format {
return FmtUnknown
}
return FmtText
case jsonType:
var prometheusAPIVersion string
if params["schema"] == "prometheus/telemetry" && params["version"] != "" {
prometheusAPIVersion = params["version"]
} else {
prometheusAPIVersion = h.Get("X-Prometheus-API-Version")
}
switch prometheusAPIVersion {
case "0.0.2", "":
return fmtJSON2
default:
return FmtUnknown
}
}
return FmtUnknown
@@ -74,6 +93,8 @@ func NewDecoder(r io.Reader, format Format) Decoder {
switch format {
case FmtProtoDelim:
return &protoDecoder{r: r}
case fmtJSON2:
return newJSON2Decoder(r)
}
return &textDecoder{r: r}
}
@@ -111,7 +132,7 @@ func (d *protoDecoder) Decode(v *dto.MetricFamily) error {
return nil
}
// textDecoder implements the Decoder interface for the text protocol.
// textDecoder implements the Decoder interface for the text protcol.
type textDecoder struct {
r io.Reader
p TextParser
+174
View File
@@ -0,0 +1,174 @@
// Copyright 2015 The Prometheus Authors
// 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 expfmt
import (
"encoding/json"
"fmt"
"io"
"sort"
"github.com/golang/protobuf/proto"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/common/model"
)
type json2Decoder struct {
dec *json.Decoder
fams []*dto.MetricFamily
}
func newJSON2Decoder(r io.Reader) Decoder {
return &json2Decoder{
dec: json.NewDecoder(r),
}
}
type histogram002 struct {
Labels model.LabelSet `json:"labels"`
Values map[string]float64 `json:"value"`
}
type counter002 struct {
Labels model.LabelSet `json:"labels"`
Value float64 `json:"value"`
}
func protoLabelSet(base, ext model.LabelSet) ([]*dto.LabelPair, error) {
labels := base.Clone().Merge(ext)
delete(labels, model.MetricNameLabel)
names := make([]string, 0, len(labels))
for ln := range labels {
names = append(names, string(ln))
}
sort.Strings(names)
pairs := make([]*dto.LabelPair, 0, len(labels))
for _, ln := range names {
if !model.LabelNameRE.MatchString(ln) {
return nil, fmt.Errorf("invalid label name %q", ln)
}
lv := labels[model.LabelName(ln)]
pairs = append(pairs, &dto.LabelPair{
Name: proto.String(ln),
Value: proto.String(string(lv)),
})
}
return pairs, nil
}
func (d *json2Decoder) more() error {
var entities []struct {
BaseLabels model.LabelSet `json:"baseLabels"`
Docstring string `json:"docstring"`
Metric struct {
Type string `json:"type"`
Values json.RawMessage `json:"value"`
} `json:"metric"`
}
if err := d.dec.Decode(&entities); err != nil {
return err
}
for _, e := range entities {
f := &dto.MetricFamily{
Name: proto.String(string(e.BaseLabels[model.MetricNameLabel])),
Help: proto.String(e.Docstring),
Type: dto.MetricType_UNTYPED.Enum(),
Metric: []*dto.Metric{},
}
d.fams = append(d.fams, f)
switch e.Metric.Type {
case "counter", "gauge":
var values []counter002
if err := json.Unmarshal(e.Metric.Values, &values); err != nil {
return fmt.Errorf("could not extract %s value: %s", e.Metric.Type, err)
}
for _, ctr := range values {
labels, err := protoLabelSet(e.BaseLabels, ctr.Labels)
if err != nil {
return err
}
f.Metric = append(f.Metric, &dto.Metric{
Label: labels,
Untyped: &dto.Untyped{
Value: proto.Float64(ctr.Value),
},
})
}
case "histogram":
var values []histogram002
if err := json.Unmarshal(e.Metric.Values, &values); err != nil {
return fmt.Errorf("could not extract %s value: %s", e.Metric.Type, err)
}
for _, hist := range values {
quants := make([]string, 0, len(values))
for q := range hist.Values {
quants = append(quants, q)
}
sort.Strings(quants)
for _, q := range quants {
value := hist.Values[q]
// The correct label is "quantile" but to not break old expressions
// this remains "percentile"
hist.Labels["percentile"] = model.LabelValue(q)
labels, err := protoLabelSet(e.BaseLabels, hist.Labels)
if err != nil {
return err
}
f.Metric = append(f.Metric, &dto.Metric{
Label: labels,
Untyped: &dto.Untyped{
Value: proto.Float64(value),
},
})
}
}
default:
return fmt.Errorf("unknown metric type %q", e.Metric.Type)
}
}
return nil
}
// Decode implements the Decoder interface.
func (d *json2Decoder) Decode(v *dto.MetricFamily) error {
if len(d.fams) == 0 {
if err := d.more(); err != nil {
return err
}
}
*v = *d.fams[0]
d.fams = d.fams[1:]
return nil
}
+14 -9
View File
@@ -14,6 +14,7 @@
package expfmt
import (
"bytes"
"fmt"
"io"
"math"
@@ -284,17 +285,21 @@ func labelPairsToText(
return written, nil
}
var (
escape = strings.NewReplacer("\\", `\\`, "\n", `\n`)
escapeWithDoubleQuote = strings.NewReplacer("\\", `\\`, "\n", `\n`, "\"", `\"`)
)
// escapeString replaces '\' by '\\', new line character by '\n', and - if
// includeDoubleQuote is true - '"' by '\"'.
func escapeString(v string, includeDoubleQuote bool) string {
if includeDoubleQuote {
return escapeWithDoubleQuote.Replace(v)
result := bytes.NewBuffer(make([]byte, 0, len(v)))
for _, c := range v {
switch {
case c == '\\':
result.WriteString(`\\`)
case includeDoubleQuote && c == '"':
result.WriteString(`\"`)
case c == '\n':
result.WriteString(`\n`)
default:
result.WriteRune(c)
}
}
return escape.Replace(v)
return result.String()
}
+1 -1
View File
@@ -12,5 +12,5 @@
// limitations under the License.
// Package model contains common data structures that are shared across
// Prometheus components and libraries.
// Prometheus componenets and libraries.
package model
+3 -3
View File
@@ -1,5 +1,5 @@
sudo: false
language: go
go:
- 1.5
- 1.6
- 1.3
- 1.4
- tip
+1 -10
View File
@@ -8,13 +8,4 @@ Maintainers of this repository:
The following individuals have contributed code to this repository
(listed in alphabetical order):
* Armen Baghumian <abaghumian@noggin.com.au>
* Bjoern Rabenstein <beorn@soundcloud.com>
* David Cournapeau <cournape@gmail.com>
* Ji-Hoon, Seol <jihoon.seol@gmail.com>
* Jonas Große Sundrup <cherti@letopolis.de>
* Julius Volz <julius.volz@gmail.com>
* Matthias Rampke <mr@soundcloud.com>
* Nicky Gerritsen <nicky@streamone.nl>
* Rémi Audebert <contact@halfr.net>
* Tobias Schmidt <tobidt@gmail.com>
* Tobias Schmidt <ts@soundcloud.com>
-6
View File
@@ -1,6 +0,0 @@
ci:
! gofmt -l *.go | read nothing
go vet
go test -v ./...
go get github.com/golang/lint/golint
golint *.go
-3
View File
@@ -3,8 +3,5 @@
This procfs package provides functions to retrieve system, kernel and process
metrics from the pseudo-filesystem proc.
*WARNING*: This package is a work in progress. Its API may still break in
backwards-incompatible ways without warnings. Use it at your own risk.
[![GoDoc](https://godoc.org/github.com/prometheus/procfs?status.png)](https://godoc.org/github.com/prometheus/procfs)
[![Build Status](https://travis-ci.org/prometheus/procfs.svg?branch=master)](https://travis-ci.org/prometheus/procfs)
+6 -3
View File
@@ -27,7 +27,10 @@ func NewFS(mountPoint string) (FS, error) {
return FS(mountPoint), nil
}
// Path returns the path of the given subsystem relative to the procfs root.
func (fs FS) Path(p ...string) string {
return path.Join(append([]string{string(fs)}, p...)...)
func (fs FS) stat(p string) (os.FileInfo, error) {
return os.Stat(path.Join(string(fs), p))
}
func (fs FS) open(p string) (*os.File, error) {
return os.Open(path.Join(string(fs), p))
}
-224
View File
@@ -1,224 +0,0 @@
package procfs
import (
"bufio"
"encoding/hex"
"errors"
"fmt"
"io"
"io/ioutil"
"net"
"os"
"strconv"
"strings"
)
// IPVSStats holds IPVS statistics, as exposed by the kernel in `/proc/net/ip_vs_stats`.
type IPVSStats struct {
// Total count of connections.
Connections uint64
// Total incoming packages processed.
IncomingPackets uint64
// Total outgoing packages processed.
OutgoingPackets uint64
// Total incoming traffic.
IncomingBytes uint64
// Total outgoing traffic.
OutgoingBytes uint64
}
// IPVSBackendStatus holds current metrics of one virtual / real address pair.
type IPVSBackendStatus struct {
// The local (virtual) IP address.
LocalAddress net.IP
// The local (virtual) port.
LocalPort uint16
// The transport protocol (TCP, UDP).
Proto string
// The remote (real) IP address.
RemoteAddress net.IP
// The remote (real) port.
RemotePort uint16
// The current number of active connections for this virtual/real address pair.
ActiveConn uint64
// The current number of inactive connections for this virtual/real address pair.
InactConn uint64
// The current weight of this virtual/real address pair.
Weight uint64
}
// NewIPVSStats reads the IPVS statistics.
func NewIPVSStats() (IPVSStats, error) {
fs, err := NewFS(DefaultMountPoint)
if err != nil {
return IPVSStats{}, err
}
return fs.NewIPVSStats()
}
// NewIPVSStats reads the IPVS statistics from the specified `proc` filesystem.
func (fs FS) NewIPVSStats() (IPVSStats, error) {
file, err := os.Open(fs.Path("net/ip_vs_stats"))
if err != nil {
return IPVSStats{}, err
}
defer file.Close()
return parseIPVSStats(file)
}
// parseIPVSStats performs the actual parsing of `ip_vs_stats`.
func parseIPVSStats(file io.Reader) (IPVSStats, error) {
var (
statContent []byte
statLines []string
statFields []string
stats IPVSStats
)
statContent, err := ioutil.ReadAll(file)
if err != nil {
return IPVSStats{}, err
}
statLines = strings.SplitN(string(statContent), "\n", 4)
if len(statLines) != 4 {
return IPVSStats{}, errors.New("ip_vs_stats corrupt: too short")
}
statFields = strings.Fields(statLines[2])
if len(statFields) != 5 {
return IPVSStats{}, errors.New("ip_vs_stats corrupt: unexpected number of fields")
}
stats.Connections, err = strconv.ParseUint(statFields[0], 16, 64)
if err != nil {
return IPVSStats{}, err
}
stats.IncomingPackets, err = strconv.ParseUint(statFields[1], 16, 64)
if err != nil {
return IPVSStats{}, err
}
stats.OutgoingPackets, err = strconv.ParseUint(statFields[2], 16, 64)
if err != nil {
return IPVSStats{}, err
}
stats.IncomingBytes, err = strconv.ParseUint(statFields[3], 16, 64)
if err != nil {
return IPVSStats{}, err
}
stats.OutgoingBytes, err = strconv.ParseUint(statFields[4], 16, 64)
if err != nil {
return IPVSStats{}, err
}
return stats, nil
}
// NewIPVSBackendStatus reads and returns the status of all (virtual,real) server pairs.
func NewIPVSBackendStatus() ([]IPVSBackendStatus, error) {
fs, err := NewFS(DefaultMountPoint)
if err != nil {
return []IPVSBackendStatus{}, err
}
return fs.NewIPVSBackendStatus()
}
// NewIPVSBackendStatus reads and returns the status of all (virtual,real) server pairs from the specified `proc` filesystem.
func (fs FS) NewIPVSBackendStatus() ([]IPVSBackendStatus, error) {
file, err := os.Open(fs.Path("net/ip_vs"))
if err != nil {
return nil, err
}
defer file.Close()
return parseIPVSBackendStatus(file)
}
func parseIPVSBackendStatus(file io.Reader) ([]IPVSBackendStatus, error) {
var (
status []IPVSBackendStatus
scanner = bufio.NewScanner(file)
proto string
localAddress net.IP
localPort uint16
err error
)
for scanner.Scan() {
fields := strings.Fields(string(scanner.Text()))
if len(fields) == 0 {
continue
}
switch {
case fields[0] == "IP" || fields[0] == "Prot" || fields[1] == "RemoteAddress:Port":
continue
case fields[0] == "TCP" || fields[0] == "UDP":
if len(fields) < 2 {
continue
}
proto = fields[0]
localAddress, localPort, err = parseIPPort(fields[1])
if err != nil {
return nil, err
}
case fields[0] == "->":
if len(fields) < 6 {
continue
}
remoteAddress, remotePort, err := parseIPPort(fields[1])
if err != nil {
return nil, err
}
weight, err := strconv.ParseUint(fields[3], 10, 64)
if err != nil {
return nil, err
}
activeConn, err := strconv.ParseUint(fields[4], 10, 64)
if err != nil {
return nil, err
}
inactConn, err := strconv.ParseUint(fields[5], 10, 64)
if err != nil {
return nil, err
}
status = append(status, IPVSBackendStatus{
LocalAddress: localAddress,
LocalPort: localPort,
RemoteAddress: remoteAddress,
RemotePort: remotePort,
Proto: proto,
Weight: weight,
ActiveConn: activeConn,
InactConn: inactConn,
})
}
}
return status, nil
}
func parseIPPort(s string) (net.IP, uint16, error) {
tmp := strings.SplitN(s, ":", 2)
if len(tmp) != 2 {
return nil, 0, fmt.Errorf("invalid IP:Port: %s", s)
}
if len(tmp[0]) != 8 && len(tmp[0]) != 32 {
return nil, 0, fmt.Errorf("invalid IP: %s", tmp[0])
}
ip, err := hex.DecodeString(tmp[0])
if err != nil {
return nil, 0, err
}
port, err := strconv.ParseUint(tmp[1], 16, 16)
if err != nil {
return nil, 0, err
}
return ip, uint16(port), nil
}
-138
View File
@@ -1,138 +0,0 @@
package procfs
import (
"fmt"
"io/ioutil"
"regexp"
"strconv"
"strings"
)
var (
statuslineRE = regexp.MustCompile(`(\d+) blocks .*\[(\d+)/(\d+)\] \[[U_]+\]`)
buildlineRE = regexp.MustCompile(`\((\d+)/\d+\)`)
)
// MDStat holds info parsed from /proc/mdstat.
type MDStat struct {
// Name of the device.
Name string
// activity-state of the device.
ActivityState string
// Number of active disks.
DisksActive int64
// Total number of disks the device consists of.
DisksTotal int64
// Number of blocks the device holds.
BlocksTotal int64
// Number of blocks on the device that are in sync.
BlocksSynced int64
}
// ParseMDStat parses an mdstat-file and returns a struct with the relevant infos.
func (fs FS) ParseMDStat() (mdstates []MDStat, err error) {
mdStatusFilePath := fs.Path("mdstat")
content, err := ioutil.ReadFile(mdStatusFilePath)
if err != nil {
return []MDStat{}, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err)
}
mdStates := []MDStat{}
lines := strings.Split(string(content), "\n")
for i, l := range lines {
if l == "" {
continue
}
if l[0] == ' ' {
continue
}
if strings.HasPrefix(l, "Personalities") || strings.HasPrefix(l, "unused") {
continue
}
mainLine := strings.Split(l, " ")
if len(mainLine) < 3 {
return mdStates, fmt.Errorf("error parsing mdline: %s", l)
}
mdName := mainLine[0]
activityState := mainLine[2]
if len(lines) <= i+3 {
return mdStates, fmt.Errorf(
"error parsing %s: too few lines for md device %s",
mdStatusFilePath,
mdName,
)
}
active, total, size, err := evalStatusline(lines[i+1])
if err != nil {
return mdStates, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err)
}
// j is the line number of the syncing-line.
j := i + 2
if strings.Contains(lines[i+2], "bitmap") { // skip bitmap line
j = i + 3
}
// If device is syncing at the moment, get the number of currently
// synced bytes, otherwise that number equals the size of the device.
syncedBlocks := size
if strings.Contains(lines[j], "recovery") || strings.Contains(lines[j], "resync") {
syncedBlocks, err = evalBuildline(lines[j])
if err != nil {
return mdStates, fmt.Errorf("error parsing %s: %s", mdStatusFilePath, err)
}
}
mdStates = append(mdStates, MDStat{
Name: mdName,
ActivityState: activityState,
DisksActive: active,
DisksTotal: total,
BlocksTotal: size,
BlocksSynced: syncedBlocks,
})
}
return mdStates, nil
}
func evalStatusline(statusline string) (active, total, size int64, err error) {
matches := statuslineRE.FindStringSubmatch(statusline)
if len(matches) != 4 {
return 0, 0, 0, fmt.Errorf("unexpected statusline: %s", statusline)
}
size, err = strconv.ParseInt(matches[1], 10, 64)
if err != nil {
return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err)
}
total, err = strconv.ParseInt(matches[2], 10, 64)
if err != nil {
return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err)
}
active, err = strconv.ParseInt(matches[3], 10, 64)
if err != nil {
return 0, 0, 0, fmt.Errorf("unexpected statusline %s: %s", statusline, err)
}
return active, total, size, nil
}
func evalBuildline(buildline string) (syncedBlocks int64, err error) {
matches := buildlineRE.FindStringSubmatch(buildline)
if len(matches) != 2 {
return 0, fmt.Errorf("unexpected buildline: %s", buildline)
}
syncedBlocks, err = strconv.ParseInt(matches[1], 10, 64)
if err != nil {
return 0, fmt.Errorf("%s in buildline: %s", err, buildline)
}
return syncedBlocks, nil
}
+14 -77
View File
@@ -4,6 +4,7 @@ import (
"fmt"
"io/ioutil"
"os"
"path"
"strconv"
"strings"
)
@@ -23,13 +24,9 @@ func (p Procs) Len() int { return len(p) }
func (p Procs) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p Procs) Less(i, j int) bool { return p[i].PID < p[j].PID }
// Self returns a process for the current process read via /proc/self.
// Self returns a process for the current process.
func Self() (Proc, error) {
fs, err := NewFS(DefaultMountPoint)
if err != nil {
return Proc{}, err
}
return fs.Self()
return NewProc(os.Getpid())
}
// NewProc returns a process for the given pid under /proc.
@@ -38,42 +35,32 @@ func NewProc(pid int) (Proc, error) {
if err != nil {
return Proc{}, err
}
return fs.NewProc(pid)
}
// AllProcs returns a list of all currently available processes under /proc.
// AllProcs returns a list of all currently avaible processes under /proc.
func AllProcs() (Procs, error) {
fs, err := NewFS(DefaultMountPoint)
if err != nil {
return Procs{}, err
}
return fs.AllProcs()
}
// Self returns a process for the current process.
func (fs FS) Self() (Proc, error) {
p, err := os.Readlink(fs.Path("self"))
if err != nil {
return Proc{}, err
}
pid, err := strconv.Atoi(strings.Replace(p, string(fs), "", -1))
if err != nil {
return Proc{}, err
}
return fs.NewProc(pid)
return fs.AllProcs()
}
// NewProc returns a process for the given pid.
func (fs FS) NewProc(pid int) (Proc, error) {
if _, err := os.Stat(fs.Path(strconv.Itoa(pid))); err != nil {
if _, err := fs.stat(strconv.Itoa(pid)); err != nil {
return Proc{}, err
}
return Proc{PID: pid, fs: fs}, nil
}
// AllProcs returns a list of all currently available processes.
// AllProcs returns a list of all currently avaible processes.
func (fs FS) AllProcs() (Procs, error) {
d, err := os.Open(fs.Path())
d, err := fs.open("")
if err != nil {
return Procs{}, err
}
@@ -98,7 +85,7 @@ func (fs FS) AllProcs() (Procs, error) {
// CmdLine returns the command line of a process.
func (p Proc) CmdLine() ([]string, error) {
f, err := os.Open(p.path("cmdline"))
f, err := p.open("cmdline")
if err != nil {
return nil, err
}
@@ -109,39 +96,9 @@ func (p Proc) CmdLine() ([]string, error) {
return nil, err
}
if len(data) < 1 {
return []string{}, nil
}
return strings.Split(string(data[:len(data)-1]), string(byte(0))), nil
}
// Comm returns the command name of a process.
func (p Proc) Comm() (string, error) {
f, err := os.Open(p.path("comm"))
if err != nil {
return "", err
}
defer f.Close()
data, err := ioutil.ReadAll(f)
if err != nil {
return "", err
}
return strings.TrimSpace(string(data)), nil
}
// Executable returns the absolute path of the executable command of a process.
func (p Proc) Executable() (string, error) {
exe, err := os.Readlink(p.path("exe"))
if os.IsNotExist(err) {
return "", nil
}
return exe, err
}
// FileDescriptors returns the currently open file descriptors of a process.
func (p Proc) FileDescriptors() ([]uintptr, error) {
names, err := p.fileDescriptors()
@@ -161,26 +118,6 @@ func (p Proc) FileDescriptors() ([]uintptr, error) {
return fds, nil
}
// FileDescriptorTargets returns the targets of all file descriptors of a process.
// If a file descriptor is not a symlink to a file (like a socket), that value will be the empty string.
func (p Proc) FileDescriptorTargets() ([]string, error) {
names, err := p.fileDescriptors()
if err != nil {
return nil, err
}
targets := make([]string, len(names))
for i, name := range names {
target, err := os.Readlink(p.path("fd", name))
if err == nil {
targets[i] = target
}
}
return targets, nil
}
// FileDescriptorsLen returns the number of currently open file descriptors of
// a process.
func (p Proc) FileDescriptorsLen() (int, error) {
@@ -193,7 +130,7 @@ func (p Proc) FileDescriptorsLen() (int, error) {
}
func (p Proc) fileDescriptors() ([]string, error) {
d, err := os.Open(p.path("fd"))
d, err := p.open("fd")
if err != nil {
return nil, err
}
@@ -207,6 +144,6 @@ func (p Proc) fileDescriptors() ([]string, error) {
return names, nil
}
func (p Proc) path(pa ...string) string {
return p.fs.Path(append([]string{strconv.Itoa(p.PID)}, pa...)...)
func (p Proc) open(pa string) (*os.File, error) {
return p.fs.open(path.Join(strconv.Itoa(p.PID), pa))
}
-55
View File
@@ -1,55 +0,0 @@
package procfs
import (
"fmt"
"io/ioutil"
"os"
)
// ProcIO models the content of /proc/<pid>/io.
type ProcIO struct {
// Chars read.
RChar uint64
// Chars written.
WChar uint64
// Read syscalls.
SyscR uint64
// Write syscalls.
SyscW uint64
// Bytes read.
ReadBytes uint64
// Bytes written.
WriteBytes uint64
// Bytes written, but taking into account truncation. See
// Documentation/filesystems/proc.txt in the kernel sources for
// detailed explanation.
CancelledWriteBytes int64
}
// NewIO creates a new ProcIO instance from a given Proc instance.
func (p Proc) NewIO() (ProcIO, error) {
pio := ProcIO{}
f, err := os.Open(p.path("io"))
if err != nil {
return pio, err
}
defer f.Close()
data, err := ioutil.ReadAll(f)
if err != nil {
return pio, err
}
ioFormat := "rchar: %d\nwchar: %d\nsyscr: %d\nsyscw: %d\n" +
"read_bytes: %d\nwrite_bytes: %d\n" +
"cancelled_write_bytes: %d\n"
_, err = fmt.Sscanf(string(data), ioFormat, &pio.RChar, &pio.WChar, &pio.SyscR,
&pio.SyscW, &pio.ReadBytes, &pio.WriteBytes, &pio.CancelledWriteBytes)
if err != nil {
return pio, err
}
return pio, nil
}
+19 -45
View File
@@ -3,56 +3,29 @@ package procfs
import (
"bufio"
"fmt"
"os"
"regexp"
"strconv"
)
// ProcLimits represents the soft limits for each of the process's resource
// limits. For more information see getrlimit(2):
// http://man7.org/linux/man-pages/man2/getrlimit.2.html.
// limits.
type ProcLimits struct {
// CPU time limit in seconds.
CPUTime int
// Maximum size of files that the process may create.
FileSize int
// Maximum size of the process's data segment (initialized data,
// uninitialized data, and heap).
DataSize int
// Maximum size of the process stack in bytes.
StackSize int
// Maximum size of a core file.
CoreFileSize int
// Limit of the process's resident set in pages.
ResidentSet int
// Maximum number of processes that can be created for the real user ID of
// the calling process.
Processes int
// Value one greater than the maximum file descriptor number that can be
// opened by this process.
OpenFiles int
// Maximum number of bytes of memory that may be locked into RAM.
LockedMemory int
// Maximum size of the process's virtual memory address space in bytes.
AddressSpace int
// Limit on the combined number of flock(2) locks and fcntl(2) leases that
// this process may establish.
FileLocks int
// Limit of signals that may be queued for the real user ID of the calling
// process.
PendingSignals int
// Limit on the number of bytes that can be allocated for POSIX message
// queues for the real user ID of the calling process.
MsqqueueSize int
// Limit of the nice priority set using setpriority(2) or nice(2).
NicePriority int
// Limit of the real-time priority set using sched_setscheduler(2) or
// sched_setparam(2).
CPUTime int
FileSize int
DataSize int
StackSize int
CoreFileSize int
ResidentSet int
Processes int
OpenFiles int
LockedMemory int
AddressSpace int
FileLocks int
PendingSignals int
MsqqueueSize int
NicePriority int
RealtimePriority int
// Limit (in microseconds) on the amount of CPU time that a process
// scheduled under a real-time scheduling policy may consume without making
// a blocking system call.
RealtimeTimeout int
RealtimeTimeout int
}
const (
@@ -66,7 +39,7 @@ var (
// NewLimits returns the current soft limits of the process.
func (p Proc) NewLimits() (ProcLimits, error) {
f, err := os.Open(p.path("limits"))
f, err := p.open("limits")
if err != nil {
return ProcLimits{}, err
}
@@ -87,7 +60,7 @@ func (p Proc) NewLimits() (ProcLimits, error) {
case "Max cpu time":
l.CPUTime, err = parseInt(fields[1])
case "Max file size":
l.FileSize, err = parseInt(fields[1])
l.FileLocks, err = parseInt(fields[1])
case "Max data size":
l.DataSize, err = parseInt(fields[1])
case "Max stack size":
@@ -117,6 +90,7 @@ func (p Proc) NewLimits() (ProcLimits, error) {
case "Max realtime timeout":
l.RealtimeTimeout, err = parseInt(fields[1])
}
if err != nil {
return ProcLimits{}, err
}
+9 -9
View File
@@ -7,15 +7,15 @@ import (
"os"
)
// Originally, this USER_HZ value was dynamically retrieved via a sysconf call
// which required cgo. However, that caused a lot of problems regarding
// Originally, this USER_HZ value was dynamically retrieved via a sysconf call which
// required cgo. However, that caused a lot of problems regarding
// cross-compilation. Alternatives such as running a binary to determine the
// value, or trying to derive it in some other way were all problematic. After
// much research it was determined that USER_HZ is actually hardcoded to 100 on
// all Go-supported platforms as of the time of this writing. This is why we
// decided to hardcode it here as well. It is not impossible that there could
// be systems with exceptions, but they should be very exotic edge cases, and
// in that case, the worst outcome will be two misreported metrics.
// value, or trying to derive it in some other way were all problematic.
// After much research it was determined that USER_HZ is actually hardcoded to
// 100 on all Go-supported platforms as of the time of this writing. This is
// why we decided to hardcode it here as well. It is not impossible that there
// could be systems with exceptions, but they should be very exotic edge cases,
// and in that case, the worst outcome will be two misreported metrics.
//
// See also the following discussions:
//
@@ -91,7 +91,7 @@ type ProcStat struct {
// NewStat returns the current status information of the process.
func (p Proc) NewStat() (ProcStat, error) {
f, err := os.Open(p.path("stat"))
f, err := p.open("stat")
if err != nil {
return ProcStat{}, err
}
+1 -2
View File
@@ -3,7 +3,6 @@ package procfs
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
@@ -26,7 +25,7 @@ func NewStat() (Stat, error) {
// NewStat returns an information about current kernel/system statistics.
func (fs FS) NewStat() (Stat, error) {
f, err := os.Open(fs.Path("stat"))
f, err := fs.open("stat")
if err != nil {
return Stat{}, err
}