youtubebeat/vendor/github.com/elastic/beats/metricbeat/module/apache/status/data.go

221 lines
6.9 KiB
Go

// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you 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 status
import (
"bufio"
"regexp"
"strings"
"github.com/elastic/beats/libbeat/common"
s "github.com/elastic/beats/libbeat/common/schema"
c "github.com/elastic/beats/libbeat/common/schema/mapstrstr"
)
var (
scoreboardRegexp = regexp.MustCompile("(Scoreboard):\\s+((_|S|R|W|K|D|C|L|G|I|\\.)+)")
// This should match: "CPUSystem: .01"
matchNumber = regexp.MustCompile("(^[0-9a-zA-Z ]+):\\s+(\\d*\\.?\\d+)")
schema = s.Schema{
"total_accesses": c.Int("Total Accesses"),
"total_kbytes": c.Int("Total kBytes"),
"requests_per_sec": c.Float("ReqPerSec", s.Optional),
"bytes_per_sec": c.Float("BytesPerSec", s.Optional),
"bytes_per_request": c.Float("BytesPerReq", s.Optional),
"workers": s.Object{
"busy": c.Int("BusyWorkers"),
"idle": c.Int("IdleWorkers"),
},
"uptime": s.Object{
"server_uptime": c.Int("ServerUptimeSeconds"),
"uptime": c.Int("Uptime"),
},
"cpu": s.Object{
"load": c.Float("CPULoad", s.Optional),
"user": c.Float("CPUUser"),
"system": c.Float("CPUSystem"),
"children_user": c.Float("CPUChildrenUser"),
"children_system": c.Float("CPUChildrenSystem"),
},
"connections": s.Object{
"total": c.Int("ConnsTotal", s.Optional),
"async": s.Object{
"writing": c.Int("ConnsAsyncWriting", s.Optional),
"keep_alive": c.Int("ConnsAsyncKeepAlive", s.Optional),
"closing": c.Int("ConnsAsyncClosing", s.Optional),
},
},
"load": s.Object{
"1": c.Float("Load1", s.Optional),
"5": c.Float("Load5", s.Optional),
"15": c.Float("Load15", s.Optional),
},
}
// Schema used till apache 2.4.12
schemaOld = s.Schema{
"total_accesses": c.Int("Total Accesses"),
"total_kbytes": c.Int("Total kBytes"),
"requests_per_sec": c.Float("ReqPerSec", s.Optional),
"bytes_per_sec": c.Float("BytesPerSec", s.Optional),
"bytes_per_request": c.Float("BytesPerReq", s.Optional),
"workers": s.Object{
"busy": c.Int("BusyWorkers"),
"idle": c.Int("IdleWorkers"),
},
"uptime": s.Object{
"uptime": c.Int("Uptime"),
},
"cpu": s.Object{
"load": c.Float("CPULoad", s.Optional),
},
"connections": s.Object{
"total": c.Int("ConnsTotal", s.Optional),
"async": s.Object{
"writing": c.Int("ConnsAsyncWriting", s.Optional),
"keep_alive": c.Int("ConnsAsyncKeepAlive", s.Optional),
"closing": c.Int("ConnsAsyncClosing", s.Optional),
},
},
}
)
func applySchema(event common.MapStr, fullEvent map[string]interface{}) error {
applicableSchema := schema
if _, found := fullEvent["ServerUptimeSeconds"]; !found {
applicableSchema = schemaOld
}
_, err := applicableSchema.ApplyTo(event, fullEvent)
return err.Err()
}
// Map body to MapStr
func eventMapping(scanner *bufio.Scanner, hostname string) (common.MapStr, error) {
var (
totalS int
totalR int
totalW int
totalK int
totalD int
totalC int
totalL int
totalG int
totalI int
totalDot int
totalUnderscore int
totalAll int
)
fullEvent := map[string]interface{}{}
// Iterate through all events to gather data
for scanner.Scan() {
if match := matchNumber.FindStringSubmatch(scanner.Text()); len(match) == 3 {
// Total Accesses: 16147
//Total kBytes: 12988
// Uptime: 3229728
// CPULoad: .000408393
// CPUUser: 0
// CPUSystem: .01
// CPUChildrenUser: 0
// CPUChildrenSystem: 0
// ReqPerSec: .00499949
// BytesPerSec: 4.1179
// BytesPerReq: 823.665
// BusyWorkers: 1
// IdleWorkers: 8
// ConnsTotal: 4940
// ConnsAsyncWriting: 527
// ConnsAsyncKeepAlive: 1321
// ConnsAsyncClosing: 2785
// ServerUptimeSeconds: 43
//Load1: 0.01
//Load5: 0.10
//Load15: 0.06
fullEvent[match[1]] = match[2]
} else if match := scoreboardRegexp.FindStringSubmatch(scanner.Text()); len(match) == 4 {
// Scoreboard Key:
// "_" Waiting for Connection, "S" Starting up, "R" Reading Request,
// "W" Sending Reply, "K" Keepalive (read), "D" DNS Lookup,
// "C" Closing connection, "L" Logging, "G" Gracefully finishing,
// "I" Idle cleanup of worker, "." Open slot with no current process
// Scoreboard: _W____........___...............................................................................................................................................................................................................................................
totalUnderscore = strings.Count(match[2], "_")
totalS = strings.Count(match[2], "S")
totalR = strings.Count(match[2], "R")
totalW = strings.Count(match[2], "W")
totalK = strings.Count(match[2], "K")
totalD = strings.Count(match[2], "D")
totalC = strings.Count(match[2], "C")
totalL = strings.Count(match[2], "L")
totalG = strings.Count(match[2], "G")
totalI = strings.Count(match[2], "I")
totalDot = strings.Count(match[2], ".")
totalAll = totalUnderscore + totalS + totalR + totalW + totalK + totalD + totalC + totalL + totalG + totalI + totalDot
} else {
debugf("Unexpected line in apache server-status output: %s", scanner.Text())
}
}
event := common.MapStr{
"hostname": hostname,
"scoreboard": common.MapStr{
"starting_up": totalS,
"reading_request": totalR,
"sending_reply": totalW,
"keepalive": totalK,
"dns_lookup": totalD,
"closing_connection": totalC,
"logging": totalL,
"gracefully_finishing": totalG,
"idle_cleanup": totalI,
"open_slot": totalDot,
"waiting_for_connection": totalUnderscore,
"total": totalAll,
},
}
return event, applySchema(event, fullEvent)
}
/*
func parseMatchFloat(input interface{}, fieldName string) float64 {
var parseString string
if input != nil {
if strings.HasPrefix(input.(string), ".") {
parseString = strings.Replace(input.(string), ".", "0.", 1)
} else {
parseString = input.(string)
}
outputFloat, err := strconv.ParseFloat(parseString, 64)
if err != nil {
logp.Err("Cannot parse string '%s' to float for field '%s'. Error: %+v", input.(string), fieldName, err)
return 0.0
}
return outputFloat
} else {
return 0.0
}
}*/