Skip to content

Commit

Permalink
chore: add chunk data
Browse files Browse the repository at this point in the history
  • Loading branch information
mika-f committed Aug 13, 2024
1 parent 03b3116 commit 969298c
Show file tree
Hide file tree
Showing 3 changed files with 150 additions and 72 deletions.
114 changes: 42 additions & 72 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,89 +3,47 @@ package main
import (
"flag"
mp "github.com/mackerelio/go-mackerel-plugin"
"github.com/sch8ill/mclib"
"os"
filepath2 "path/filepath"
"strings"
"github.com/natsuneko-laboratory/mackerel-plugin-minecraft/minecraft"
)

// Mackerel Agent
// MinecraftPlugin Mackerel Agent
type MinecraftPlugin struct {
Prefix string
Server string
SaveData string
}

func (mc MinecraftPlugin) FetchMetrics() (map[string]float64, error) {
client, err := mclib.NewClient(mc.GetServerAddress())
status, err := minecraft.GetServerStatus(mc.GetServerAddress())
if err != nil {
return nil, err
}

res, err := client.StatusPing()
data, err := minecraft.GetSaveDataStats(mc.SaveData)
if err != nil {
return nil, err
}

var overworldSize int64 = 0
var netherSize int64 = 0
var theEndSize int64 = 0
var worldTotalSize int64 = 0

if mc.SaveData != "" {
path, _ := filepath2.Abs(mc.SaveData)
if _, err := os.Stat(path); os.IsNotExist(err) {
return nil, err
}

err = filepath2.Walk(path, func(data string, info os.FileInfo, err error) error {
rel, err := filepath2.Rel(path, data)
if err != nil {
return err
}

if filepath2.Ext(data) == ".mca" {
// Dimension: -1 is Nether
if strings.HasPrefix(rel, "DIM-1/region") {
netherSize += info.Size()
return nil
}

// Dimension: 1 is The End
if strings.HasPrefix(rel, "DIM1/region") {
theEndSize += info.Size()
return nil
}

// Dimension: 0 is Overworld
if strings.HasPrefix(rel, "region") {
overworldSize += info.Size()
return nil
}
}

if filepath2.Ext(data) == ".dat" {
if rel == "level.dat" {
worldTotalSize = info.Size()
}
}

return nil
})

if err != nil {
return nil, err
}
}

return map[string]float64{
"max_players": float64(res.Players.Max),
"online_players": float64(res.Players.Online),
"latency": float64(res.Latency),
"overworld_size": float64(overworldSize),
"nether_size": float64(netherSize),
"the_end_size": float64(theEndSize),
"world_total_size": float64(worldTotalSize),
"max_players": float64(status.MaxPlayers),
"online_players": float64(status.OnlinePlayers),
"latency": float64(status.Latency),
"overworld.size": float64(data.Overworld.SizeInBytes),
"overworld.chunk.x_max": float64(data.Overworld.ChunkX.P * 32),
"overworld.chunk.x_min": float64(data.Overworld.ChunkX.N * 32),
"overworld.chunk.z_max": float64(data.Overworld.ChunkZ.P * 32),
"overworld.chunk.z_min": float64(data.Overworld.ChunkZ.N * 32),
"nether.size": float64(data.Nether.SizeInBytes),
"nether.chunk.x_max": float64(data.Nether.ChunkX.P * 32),
"nether.chunk.x_min": float64(data.Nether.ChunkX.N * 32),
"nether.chunk.z_max": float64(data.Nether.ChunkZ.P * 32),
"nether.chunk.z_min": float64(data.Nether.ChunkZ.N * 32),
"the_end.size": float64(data.EndWorld.SizeInBytes),
"the_end.chunk.x_max": float64(data.EndWorld.ChunkX.P * 32),
"the_end.chunk.x_min": float64(data.EndWorld.ChunkX.N * 32),
"the_end.chunk.z_max": float64(data.EndWorld.ChunkZ.P * 32),
"the_end.chunk.z_min": float64(data.EndWorld.ChunkZ.N * 32),
"world_total_size": float64(0),
}, nil
}

Expand All @@ -98,20 +56,32 @@ func (mc MinecraftPlugin) GraphDefinition() map[string]mp.Graphs {
return map[string]mp.Graphs{
players: {
Label: "Minecraft Server Status",
Unit: "integer",
Unit: mp.UnitFloat,
Metrics: []mp.Metrics{
{Name: "max_players", Label: "Limit"},
{Name: "online_players", Label: "Current Players"},
{Name: "max", Label: "Limit"},
{Name: "online", Label: "Current Players"},
{Name: "latency", Label: "Latency"},
},
},
data: {
Label: "Minecraft Server DataSize",
Unit: "float",
Unit: mp.UnitBytes,
Metrics: []mp.Metrics{
{Name: "overworld_size", Label: "Overworld DataSize"},
{Name: "nether_size", Label: "Nether DataSize"},
{Name: "the_end_size", Label: "TheEnd DataSize"},
{Name: "overworld.size", Label: "Overworld DataSize"},
{Name: "overworld.chunk.x_max", Label: "Overworld Chunk X Max"},
{Name: "overworld.chunk.x_min", Label: "Overworld Chunk X Min"},
{Name: "overworld.chunk.z_max", Label: "Overworld Chunk Z Max"},
{Name: "overworld.chunk.z_min", Label: "Overworld Chunk Z Min"},
{Name: "nether.size", Label: "Nether DataSize"},
{Name: "nether.chunk.x_max", Label: "Nether Chunk X Max"},
{Name: "nether.chunk.x_min", Label: "Nether Chunk X Min"},
{Name: "nether.chunk.z_max", Label: "Nether Chunk Z Max"},
{Name: "nether.chunk.z_min", Label: "Nether Chunk Z Min"},
{Name: "the_end.size", Label: "TheEnd DataSize"},
{Name: "the_end.chunk.x_max", Label: "TheEnd Chunk X Max"},
{Name: "the_end.chunk.x_min", Label: "TheEnd Chunk X Min"},
{Name: "the_end.chunk.z_max", Label: "TheEnd Chunk Z Max"},
{Name: "the_end.chunk.z_min", Label: "TheEnd Chunk Z Min"},
{Name: "world_total_size", Label: "World Total DataSize"},
},
},
Expand Down
79 changes: 79 additions & 0 deletions minecraft/savedata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package minecraft

import (
"os"
filepath2 "path/filepath"
"regexp"
"strconv"
"strings"
)

type Chunk struct {
P int64
N int64
}

type DimensionData struct {
SizeInBytes int64
ChunkX Chunk
ChunkZ Chunk
}

type SaveData struct {
Overworld *DimensionData
Nether *DimensionData
EndWorld *DimensionData
}

func GetSaveDataStats(dir string) (*SaveData, error) {
path, _ := filepath2.Abs(dir)
if _, err := os.Stat(path); os.IsNotExist(err) {
return nil, err
}

data := &SaveData{
Overworld: GetDimensionData(dir, ""),
Nether: GetDimensionData(dir, "DIM-1"),
EndWorld: GetDimensionData(dir, "DIM1"),
}

return data, nil
}

func GetDimensionData(dir string, dimension string) *DimensionData {
var size int64 = 0

path := filepath2.Join(dir, dimension)
chunkX := Chunk{P: 0, N: 0}
chunkZ := Chunk{P: 0, N: 0}
pattern := regexp.MustCompile(`r\.(-?\d+)\.(-?\d+)\.mca$`)

filepath2.Walk(path, func(data string, info os.FileInfo, err error) error {
rel, err := filepath2.Rel(path, data)

// ChunkData
if filepath2.Ext(data) == ".mca" {
if strings.HasPrefix(rel, "region") {
size += info.Size()

matches := pattern.FindAllStringSubmatch(rel, -1)[0]
x, _ := strconv.ParseInt(matches[1], 10, 64)
z, _ := strconv.ParseInt(matches[2], 10, 64)

chunkX.P = max(chunkX.P, x)
chunkX.N = min(chunkX.N, x)

chunkZ.P = max(chunkZ.P, z)
chunkZ.N = min(chunkZ.N, z)
}
}

return nil
})

return &DimensionData{
SizeInBytes: size,
ChunkX: chunkX,
ChunkZ: chunkZ,
}
}
29 changes: 29 additions & 0 deletions minecraft/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package minecraft

import (
"github.com/sch8ill/mclib"
)

type ServerStatus struct {
Latency int
MaxPlayers int
OnlinePlayers int
}

func GetServerStatus(address string) (*ServerStatus, error) {
client, err := mclib.NewClient(address)
if err != nil {
return nil, err
}

res, err := client.StatusPing()
if err != nil {
return nil, err
}

return &ServerStatus{
Latency: res.Latency,
MaxPlayers: res.Players.Max,
OnlinePlayers: res.Players.Online,
}, nil
}

0 comments on commit 969298c

Please sign in to comment.