mirror of
https://git.friendi.ca/friendica/friendica-exporter.git
synced 2025-06-07 09:54:26 +02:00
Initial Release
This commit is contained in:
commit
76ec4ba39f
31 changed files with 3023 additions and 0 deletions
16
serverinfo/parse.go
Normal file
16
serverinfo/parse.go
Normal file
|
@ -0,0 +1,16 @@
|
|||
package serverinfo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
)
|
||||
|
||||
// ParseJSON reads ServerInfo from a Reader in JSON format.
|
||||
func ParseJSON(r io.Reader) (*ServerInfo, error) {
|
||||
result := ServerInfo{}
|
||||
if err := json.NewDecoder(r).Decode(&result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &result, nil
|
||||
}
|
28
serverinfo/parse_test.go
Normal file
28
serverinfo/parse_test.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
package serverinfo
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestParseJSON(t *testing.T) {
|
||||
inputFiles := []string{
|
||||
"stats.json",
|
||||
}
|
||||
|
||||
for _, inputFile := range inputFiles {
|
||||
inputFile := inputFile
|
||||
t.Run(inputFile, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
reader, err := os.Open("testdata/" + inputFile)
|
||||
if err != nil {
|
||||
t.Fatalf("error opening test data: %s", err)
|
||||
}
|
||||
|
||||
if _, err := ParseJSON(reader); err != nil {
|
||||
t.Errorf("got error %q", err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
122
serverinfo/serverinfo.go
Normal file
122
serverinfo/serverinfo.go
Normal file
|
@ -0,0 +1,122 @@
|
|||
package serverinfo
|
||||
|
||||
// ServerInfo contains the status information about the instance.
|
||||
type ServerInfo struct {
|
||||
Cron Cron `json:"cron"`
|
||||
Worker Worker `json:"worker"`
|
||||
Users Users `json:"users"`
|
||||
Packets Packets `json:"packets"`
|
||||
Reports Reports `json:"reports"`
|
||||
Update Update `json:"update"`
|
||||
Server Server `json:"server"`
|
||||
}
|
||||
|
||||
// DateTimeTimestamp contains a Datetime and a Timestamp
|
||||
type DateTimeTimestamp struct {
|
||||
DateTime string `json:"datetime"`
|
||||
Timestamp int32 `json:"timestamp"`
|
||||
}
|
||||
|
||||
// Cron contains information about the Cronjob
|
||||
type Cron struct {
|
||||
LastExecution DateTimeTimestamp `json:"lastExecution"`
|
||||
}
|
||||
|
||||
// JPM contains the KPI "Jobs per Minute"
|
||||
type JPM struct {
|
||||
OneMinute int64 `json:"1"`
|
||||
ThreeMinutes int64 `json:"3"`
|
||||
FiveMinutes int64 `json:"5"`
|
||||
}
|
||||
|
||||
// WorkerCount contains the count of specific worker tasks, based on their priority
|
||||
type WorkerCount struct {
|
||||
Undefined int64 `json:"0"`
|
||||
Critical int64 `json:"10"`
|
||||
High int64 `json:"20"`
|
||||
Medium int64 `json:"30"`
|
||||
Low int64 `json:"40"`
|
||||
Negligible int64 `json:"50"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
|
||||
// Worker contains information about the worker load
|
||||
type Worker struct {
|
||||
LastExecution DateTimeTimestamp `json:"lastExecution"`
|
||||
JPM JPM `json:"jpm"`
|
||||
Active WorkerCount `json:"active"`
|
||||
Defferd []int64 `json:"defferd"`
|
||||
Total WorkerCount `json:"total"`
|
||||
}
|
||||
|
||||
// Users contains statistics about the users of this node
|
||||
type Users struct {
|
||||
Total int64 `json:"total"`
|
||||
ActiveWeek int64 `json:"activeWeek"`
|
||||
ActiveMonth int64 `json:"activeMonth"`
|
||||
ActiveHalfYear int64 `json:"activeHalfYear"`
|
||||
Pending int64 `json:"pending"`
|
||||
}
|
||||
|
||||
// PostCounts contains contains post and comments statistics
|
||||
type PostCounts struct {
|
||||
Posts int64 `json:"posts"`
|
||||
Comments int64 `json:"comments"`
|
||||
}
|
||||
|
||||
// Posts contains statistics about inbound and outbound posts and comments
|
||||
type Posts struct {
|
||||
Inbound PostCounts `json:"inbound"`
|
||||
Outbound PostCounts `json:"outbound"`
|
||||
}
|
||||
|
||||
// PacketCounts contains statistics of protocol specific packages
|
||||
type PacketCounts struct {
|
||||
ActivityPub int64 `json:"apub"`
|
||||
DFRN int64 `json:"dfrn"`
|
||||
Diaspora int64 `json:"dspr"`
|
||||
OStatus int64 `json:"stat"`
|
||||
Feed int64 `json:"feed"`
|
||||
Mail int64 `json:"mail"`
|
||||
}
|
||||
|
||||
// Packets contains statistics of inbound and outbound packages
|
||||
type Packets struct {
|
||||
Inbound PacketCounts `json:"inbound"`
|
||||
Outbound PacketCounts `json:"outbound"`
|
||||
}
|
||||
|
||||
// Reports contains statistics about Friendica reports
|
||||
type Reports struct {
|
||||
Newest DateTimeTimestamp `json:"newest"`
|
||||
Open int64 `json:"open"`
|
||||
Closed int64 `json:"closed"`
|
||||
}
|
||||
|
||||
// Update contains information about updates
|
||||
type Update struct {
|
||||
Available bool `json:"available"`
|
||||
AvailableVersion string `json:"available_version"`
|
||||
Status int8 `json:"status"`
|
||||
DatabaseStatus int8 `json:"db_status"`
|
||||
}
|
||||
|
||||
// PHP contains information about the PHP used on this node
|
||||
type PHP struct {
|
||||
Version string `json:"version"`
|
||||
UploadMaxFilesize string `json:"upload_max_filesize"`
|
||||
PostMaxSize string `json:"post_max_filesize"`
|
||||
MemoryLimit string `json:"memory_limit"`
|
||||
}
|
||||
|
||||
// Database contains information about the Database used on this node
|
||||
type Database struct {
|
||||
MaxAllowedPacket string `json:"max_allowed_packet"`
|
||||
}
|
||||
|
||||
// Server contains information about this server
|
||||
type Server struct {
|
||||
Version string `json:"version"`
|
||||
PHP PHP `json:"php"`
|
||||
Database Database `json:"database"`
|
||||
}
|
120
serverinfo/testdata/stats.json
vendored
Normal file
120
serverinfo/testdata/stats.json
vendored
Normal file
|
@ -0,0 +1,120 @@
|
|||
{
|
||||
"cron": {
|
||||
"lastExecution": {
|
||||
"datetime": "2024-10-24T16:40:49.000Z",
|
||||
"timestamp": 1729788049
|
||||
}
|
||||
},
|
||||
"worker": {
|
||||
"lastExecution": {
|
||||
"datetime": "2024-10-24T17:18:14.000Z",
|
||||
"timestamp": 1729790294
|
||||
},
|
||||
"jpm": {
|
||||
"1": 116,
|
||||
"3": 39,
|
||||
"5": 23
|
||||
},
|
||||
"active": {
|
||||
"0": 0,
|
||||
"10": 0,
|
||||
"20": 11,
|
||||
"30": 5,
|
||||
"40": 1,
|
||||
"50": 0,
|
||||
"total": 17
|
||||
},
|
||||
"deferred": {
|
||||
"1": 0,
|
||||
"2": 0,
|
||||
"3": 0,
|
||||
"4": 2,
|
||||
"5": 0,
|
||||
"6": 0,
|
||||
"7": 0,
|
||||
"8": 0,
|
||||
"9": 0,
|
||||
"10": 0,
|
||||
"11": 0,
|
||||
"12": 0,
|
||||
"13": 4,
|
||||
"14": 3,
|
||||
"15": 1,
|
||||
"total": 10
|
||||
},
|
||||
"total": {
|
||||
"0": 0,
|
||||
"10": 0,
|
||||
"20": 1336,
|
||||
"30": 12,
|
||||
"40": 61,
|
||||
"50": 0,
|
||||
"total": 1409
|
||||
}
|
||||
},
|
||||
"users": {
|
||||
"total": 743,
|
||||
"activeWeek": 27,
|
||||
"activeMonth": 33,
|
||||
"activeHalfyear": 58,
|
||||
"pending": 0
|
||||
},
|
||||
"posts": {
|
||||
"inbound": {
|
||||
"posts": 4419301,
|
||||
"comments": 4478614
|
||||
},
|
||||
"outbound": {
|
||||
"posts": 64574,
|
||||
"comments": 8494
|
||||
}
|
||||
},
|
||||
"packets": {
|
||||
"inbound": {
|
||||
"apub": 2504751,
|
||||
"dfrn": 43419,
|
||||
"dspr": 132647,
|
||||
"stat": 0,
|
||||
"feed": 245683,
|
||||
"mail": 0,
|
||||
"bsky": 100578,
|
||||
"tmbl": 54
|
||||
},
|
||||
"outbound": {
|
||||
"apub": 442807,
|
||||
"dfrn": 1242,
|
||||
"dspr": 18782,
|
||||
"stat": 0,
|
||||
"feed": 2681,
|
||||
"mail": 0,
|
||||
"bsky": 66,
|
||||
"tmbl": 0
|
||||
}
|
||||
},
|
||||
"reports": {
|
||||
"newest": {
|
||||
"datetime": "2024-02-08T07:54:04.000Z",
|
||||
"timestamp": 1707378844
|
||||
},
|
||||
"open": 2,
|
||||
"closed": 1
|
||||
},
|
||||
"update": {
|
||||
"available": null,
|
||||
"available_version": "2020.09-1",
|
||||
"status": 0,
|
||||
"db_status": 1
|
||||
},
|
||||
"server": {
|
||||
"version": "2024.09-rc",
|
||||
"php": {
|
||||
"version": "8.2.24",
|
||||
"upload_max_filesize": "10G",
|
||||
"post_max_size": "11G",
|
||||
"memory_limit": "8G"
|
||||
},
|
||||
"database": {
|
||||
"max_allowed_packet": "16777216"
|
||||
}
|
||||
}
|
||||
}
|
11
serverinfo/url.go
Normal file
11
serverinfo/url.go
Normal file
|
@ -0,0 +1,11 @@
|
|||
package serverinfo
|
||||
|
||||
import "fmt"
|
||||
|
||||
const (
|
||||
statsPathFormat = "%s/stats?key=%v"
|
||||
)
|
||||
|
||||
func StatsURL(serverUrl string, StatsKey string) string {
|
||||
return fmt.Sprintf(statsPathFormat, serverUrl, StatsKey)
|
||||
}
|
31
serverinfo/url_test.go
Normal file
31
serverinfo/url_test.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package serverinfo
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestStatsURL(t *testing.T) {
|
||||
tt := []struct {
|
||||
desc string
|
||||
serverURL string
|
||||
statsKey string
|
||||
wantURL string
|
||||
}{
|
||||
{
|
||||
desc: "normal",
|
||||
serverURL: "https://friendica.example.com",
|
||||
statsKey: "234/%&/%&/!",
|
||||
wantURL: "https://friendica.example.com/stats?key=234/%&/%&/!",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
tc := tc
|
||||
t.Run(tc.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
url := StatsURL(tc.serverURL, tc.statsKey)
|
||||
if url != tc.wantURL {
|
||||
t.Errorf("got url %q, want %q", url, tc.wantURL)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue