Add php & server info metrics
This commit is contained in:
parent
08888165fd
commit
64b1e9bf15
|
@ -6,6 +6,7 @@ import (
|
|||
"friendica-exporter/serverinfo"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/sirupsen/logrus"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -97,6 +98,30 @@ var (
|
|||
metricPrefix+"reports_closed",
|
||||
"Number of closed reports.",
|
||||
nil, nil)
|
||||
serverInfoDesc = prometheus.NewDesc(
|
||||
metricPrefix+"server_info",
|
||||
"Contains meta information about Server as labels. Value is always 1.",
|
||||
[]string{"version"}, nil)
|
||||
phpInfoDesc = prometheus.NewDesc(
|
||||
metricPrefix+"php_info",
|
||||
"Contains meta information about PHP as labels. Value is always 1.",
|
||||
[]string{"version"}, nil)
|
||||
phpMemoryLimitDesc = prometheus.NewDesc(
|
||||
metricPrefix+"php_memory_limit_bytes",
|
||||
"Configured PHP memory limit in bytes.",
|
||||
nil, nil)
|
||||
phpMaxUploadSizeDesc = prometheus.NewDesc(
|
||||
metricPrefix+"php_upload_max_size_bytes",
|
||||
"Configured maximum upload size in bytes.",
|
||||
nil, nil)
|
||||
phpMaxPostSizeDesc = prometheus.NewDesc(
|
||||
metricPrefix+"php_post_max_size_bytes",
|
||||
"Configured maximum post size in bytes.",
|
||||
nil, nil)
|
||||
databaseMaxAllowedPacketDesc = prometheus.NewDesc(
|
||||
metricPrefix+"php_post_max_allowed_packet",
|
||||
"Configured maximum allowed packet length to send to or receive from the server.",
|
||||
nil, nil)
|
||||
)
|
||||
|
||||
type friendicaCollector struct {
|
||||
|
@ -148,6 +173,12 @@ func (c *friendicaCollector) Describe(ch chan<- *prometheus.Desc) {
|
|||
ch <- reportsNewest
|
||||
ch <- reportsOpen
|
||||
ch <- reportsClosed
|
||||
ch <- serverInfoDesc
|
||||
ch <- phpInfoDesc
|
||||
ch <- phpMaxUploadSizeDesc
|
||||
ch <- phpMaxPostSizeDesc
|
||||
ch <- phpMemoryLimitDesc
|
||||
ch <- databaseMaxAllowedPacketDesc
|
||||
}
|
||||
|
||||
func (c *friendicaCollector) Collect(ch chan<- prometheus.Metric) {
|
||||
|
@ -212,6 +243,10 @@ func readMetrics(ch chan<- prometheus.Metric, status *serverinfo.ServerInfo) err
|
|||
return err
|
||||
}
|
||||
|
||||
if err := collectPhpMetrics(ch, status); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -532,3 +567,60 @@ func collectPacketsPerDirection(ch chan<- prometheus.Metric, status *serverinfo.
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func collectPhpMetrics(ch chan<- prometheus.Metric, status *serverinfo.ServerInfo) error {
|
||||
|
||||
metric, err := prometheus.NewConstMetric(phpInfoDesc, prometheus.GaugeValue, 1, status.Server.PHP.Version)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating metric for %s: %w", phpInfoDesc, err)
|
||||
}
|
||||
ch <- metric
|
||||
|
||||
metric, err = prometheus.NewConstMetric(serverInfoDesc, prometheus.GaugeValue, 1, status.Server.Version)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating metric for %s: %w", serverInfoDesc, err)
|
||||
}
|
||||
ch <- metric
|
||||
|
||||
metricVal, err := strconv.ParseFloat(status.Server.Database.MaxAllowedPacket, 64)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error converting value to byte for %s: %w", databaseMaxAllowedPacketDesc, err)
|
||||
}
|
||||
metric, err = prometheus.NewConstMetric(databaseMaxAllowedPacketDesc, prometheus.GaugeValue, metricVal)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating metric for %s: %w", databaseMaxAllowedPacketDesc, err)
|
||||
}
|
||||
ch <- metric
|
||||
|
||||
metrics := []struct {
|
||||
desc *prometheus.Desc
|
||||
value string
|
||||
}{
|
||||
{
|
||||
desc: phpMemoryLimitDesc,
|
||||
value: status.Server.PHP.MemoryLimit,
|
||||
},
|
||||
{
|
||||
desc: phpMaxPostSizeDesc,
|
||||
value: status.Server.PHP.PostMaxSize,
|
||||
},
|
||||
{
|
||||
desc: phpMaxUploadSizeDesc,
|
||||
value: status.Server.PHP.UploadMaxFilesize,
|
||||
},
|
||||
}
|
||||
|
||||
for _, m := range metrics {
|
||||
metricVal, err := ConvertMemoryToBytes(m.value)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error converting value to byte for %s: %w", m.desc, err)
|
||||
}
|
||||
metric, err = prometheus.NewConstMetric(m.desc, prometheus.GaugeValue, float64(metricVal))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating metric for %s: %w", m.desc, err)
|
||||
}
|
||||
ch <- metric
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
51
internal/metrics/converter.go
Normal file
51
internal/metrics/converter.go
Normal file
|
@ -0,0 +1,51 @@
|
|||
package metrics
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ConvertMemoryToBytes converts a memory limit string into bytes.
|
||||
// Supported units are: K (Kilobytes), M (Megabytes), G (Gigabytes), case-insensitive.
|
||||
// Anything else is interpreted as bytes.
|
||||
func ConvertMemoryToBytes(memory string) (uint64, error) {
|
||||
// Trim whitespace
|
||||
memory = strings.TrimSpace(memory)
|
||||
|
||||
// Regular expression to match the pattern (number + optional unit)
|
||||
re := regexp.MustCompile(`(?i)^([\d.]+)([KMG]?)$`)
|
||||
matches := re.FindStringSubmatch(memory)
|
||||
if matches == nil {
|
||||
return 0, errors.New("invalid memory format")
|
||||
}
|
||||
|
||||
// Extract the numeric part and unit
|
||||
numberStr := matches[1]
|
||||
unit := strings.ToUpper(matches[2])
|
||||
|
||||
// Parse the number, truncate fractional parts as PHP does
|
||||
number, err := strconv.ParseFloat(numberStr, 64)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("invalid numeric value: %v", err)
|
||||
}
|
||||
numberInt := uint64(number) // Truncate fractional part by casting to uint64
|
||||
|
||||
// Convert to bytes based on the unit
|
||||
var multiplier uint64
|
||||
switch unit {
|
||||
case "K":
|
||||
multiplier = 1024 // Kilobytes
|
||||
case "M":
|
||||
multiplier = 1024 * 1024 // Megabytes
|
||||
case "G":
|
||||
multiplier = 1024 * 1024 * 1024 // Gigabytes
|
||||
default:
|
||||
multiplier = 1 // Bytes
|
||||
}
|
||||
|
||||
// Calculate the result
|
||||
return numberInt * multiplier, nil
|
||||
}
|
124
internal/metrics/converter_test.go
Normal file
124
internal/metrics/converter_test.go
Normal file
|
@ -0,0 +1,124 @@
|
|||
package metrics
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"friendica-exporter/internal/testutil"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestConvertMemoryToBytes(t *testing.T) {
|
||||
tt := []struct {
|
||||
desc string
|
||||
memory string
|
||||
wantErr error
|
||||
wantEqual uint64
|
||||
}{
|
||||
{
|
||||
desc: "1 kilobyte (upper case)",
|
||||
memory: "1K",
|
||||
wantErr: nil,
|
||||
wantEqual: 1024,
|
||||
},
|
||||
{
|
||||
desc: "1 kilobyte (lower case)",
|
||||
memory: "1k",
|
||||
wantErr: nil,
|
||||
wantEqual: 1024,
|
||||
},
|
||||
{
|
||||
desc: "1 megabyte (upper case)",
|
||||
memory: "1M",
|
||||
wantErr: nil,
|
||||
wantEqual: 1048576,
|
||||
},
|
||||
{
|
||||
desc: "1 megabyte (lower case)",
|
||||
memory: "1m",
|
||||
wantErr: nil,
|
||||
wantEqual: 1048576,
|
||||
},
|
||||
{
|
||||
desc: "1 gigabyte (upper case)",
|
||||
memory: "1G",
|
||||
wantErr: nil,
|
||||
wantEqual: 1073741824,
|
||||
},
|
||||
{
|
||||
desc: "1 gigabyte (lower case)",
|
||||
memory: "1g",
|
||||
wantErr: nil,
|
||||
wantEqual: 1073741824,
|
||||
},
|
||||
{
|
||||
desc: "2 Kilobytes",
|
||||
memory: "2K",
|
||||
wantErr: nil,
|
||||
wantEqual: 2048,
|
||||
},
|
||||
{
|
||||
desc: "5 gigabytes",
|
||||
memory: "5g",
|
||||
wantErr: nil,
|
||||
wantEqual: 5368709120,
|
||||
},
|
||||
{
|
||||
desc: "0.5 Megabyte",
|
||||
memory: "0.5M",
|
||||
wantErr: nil,
|
||||
wantEqual: 0,
|
||||
},
|
||||
{
|
||||
desc: "10.7 Kilobytes",
|
||||
memory: "10.7k",
|
||||
wantErr: nil,
|
||||
wantEqual: 10240,
|
||||
},
|
||||
{
|
||||
desc: "12345234 Bytes",
|
||||
memory: "12345234",
|
||||
wantErr: nil,
|
||||
wantEqual: 12345234,
|
||||
},
|
||||
{
|
||||
desc: "Invalid",
|
||||
memory: "invalid",
|
||||
wantErr: errors.New("invalid memory format"),
|
||||
wantEqual: 0,
|
||||
},
|
||||
{
|
||||
desc: "1234X",
|
||||
memory: "1234X",
|
||||
wantErr: errors.New("invalid memory format"),
|
||||
wantEqual: 0,
|
||||
},
|
||||
{
|
||||
desc: "512 Megabytes",
|
||||
memory: "512M",
|
||||
wantErr: nil,
|
||||
wantEqual: 536870912,
|
||||
},
|
||||
{
|
||||
desc: "CopyPasteError",
|
||||
memory: "512M512M",
|
||||
wantErr: errors.New("invalid memory format"),
|
||||
wantEqual: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
tc := tc
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
equal, err := ConvertMemoryToBytes(tc.memory)
|
||||
|
||||
if !testutil.EqualErrorMessage(err, tc.wantErr) {
|
||||
t.Errorf("got error %q, want %q", err, tc.wantErr)
|
||||
}
|
||||
|
||||
if equal != tc.wantEqual {
|
||||
t.Errorf("got equal %v, want %v", equal, tc.wantEqual)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -108,7 +108,7 @@ type Update struct {
|
|||
type PHP struct {
|
||||
Version string `json:"version"`
|
||||
UploadMaxFilesize string `json:"upload_max_filesize"`
|
||||
PostMaxSize string `json:"post_max_filesize"`
|
||||
PostMaxSize string `json:"post_max_size"`
|
||||
MemoryLimit string `json:"memory_limit"`
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue