Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Companion/exporter/collector_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func NewCollectorRunner(ctx context.Context, frmBaseUrl string, collectors ...Co

func (c *CollectorRunner) updateSessionName() {
details := SessionInfo{}
err := retrieveData(c.frmBaseUrl+"/getSessionInfo", &details)
err := retrieveData(c.frmBaseUrl, "/getSessionInfo", &details)
if err != nil {
log.Printf("error reading session name from FRM: %s\n", err)
return
Expand Down
75 changes: 73 additions & 2 deletions Companion/exporter/common.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,35 @@
package exporter

import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"github.com/coder/quartz"
"log"
"net/http"
"net/url"
"regexp"
"strings"
"time"

"github.com/coder/quartz"
)

// Struct for the JSON body of POST requests
type FrmApiRequest struct {
Function string `json:"function"`
Endpoint string `json:"endpoint"`
}

// Reusable HTTP client for HTTPS w/ self-signed certs
// InsecureSkipVerify: true isn't technically "safe," but dedicated servers default to self-signed certs
var tlsClient = &http.Client{
Timeout: 10 * time.Second,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
}

var timeRegex = regexp.MustCompile(`\d\d:\d\d:\d\d`)

var Clock = quartz.NewReal()
Expand All @@ -35,7 +54,7 @@ func parseBool(b bool) float64 {
}
}

func retrieveData(frmAddress string, details any) error {
func retrieveDataViaGET(frmAddress string, details any) error {
resp, err := http.Get(frmAddress)

if err != nil {
Expand All @@ -53,3 +72,55 @@ func retrieveData(frmAddress string, details any) error {
err = decoder.Decode(&details)
return err
}

func retrieveDataViaPOST(frmApiUrl string, endpointName string, details any) error {
reqBody := FrmApiRequest{
Function: "frm",
Endpoint: endpointName,
}
jsonData, err := json.Marshal(reqBody)
if err != nil {
return fmt.Errorf("error marshalling request body: %s\n", err.Error())
}

req, err := http.NewRequest("POST", frmApiUrl, bytes.NewBuffer(jsonData))
if err != nil {
return fmt.Errorf("error creating POST request: %s\n", err.Error())
}
req.Header.Set("Content-Type", "application/json")

resp, err := tlsClient.Do(req)
if err != nil {
return fmt.Errorf("error fetching statistics from FRM: %s\n", err.Error())
}
defer resp.Body.Close()

if resp.StatusCode != 200 {
return fmt.Errorf("non-200 returned when retrieving data: %d", resp.StatusCode)
}

decoder := json.NewDecoder(resp.Body)
err = decoder.Decode(&details)
return err
}

func retrieveData(frmAddress string, endpoint string, details any) error {
u, err := url.Parse(frmAddress)
if err != nil {
return fmt.Errorf("invalid FRM address URL: %s", err)
}

// Check if we're using the Dedicated Server API (1.1)
if strings.HasSuffix(u.Path, "/api/v1") {
// Dedicated server mode.
// frmAddress is "https://host:7777/api/v1"
// endpoint is "/getPower", so we strip the slash
endpointName := strings.TrimPrefix(endpoint, "/")
return retrieveDataViaPOST(frmAddress, endpointName, details)
} else {
// Web server mode.
// frmAddress is "http://host:8080"
// endpoint is "/getPower"
return retrieveDataViaGET(frmAddress+endpoint, details)
}
}
2 changes: 1 addition & 1 deletion Companion/exporter/drone_station_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ func NewDroneStationCollector(endpoint string) *DroneStationCollector {

func (c *DroneStationCollector) Collect(frmAddress string, sessionName string) {
details := []DroneStationDetails{}
err := retrieveData(frmAddress+c.endpoint, &details)
err := retrieveData(frmAddress, c.endpoint, &details)
if err != nil {
c.metricsDropper.DropStaleMetricLabels()
log.Printf("error reading drone station statistics from FRM: %s\n", err)
Expand Down
2 changes: 1 addition & 1 deletion Companion/exporter/extractor_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func NewExtractorCollector(endpoint string) *ExtractorCollector {

func (c *ExtractorCollector) Collect(frmAddress string, sessionName string) {
details := []ExtractorDetails{}
err := retrieveData(frmAddress+c.endpoint, &details)
err := retrieveData(frmAddress, c.endpoint, &details)
if err != nil {
log.Printf("error reading extractor statistics from FRM: %s\n", err)
return
Expand Down
2 changes: 1 addition & 1 deletion Companion/exporter/factory_building_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func NewFactoryBuildingCollector(endpoint string) *FactoryBuildingCollector {

func (c *FactoryBuildingCollector) Collect(frmAddress string, sessionName string) {
details := []BuildingDetail{}
err := retrieveData(frmAddress+c.endpoint, &details)
err := retrieveData(frmAddress, c.endpoint, &details)
if err != nil {
c.metricsDropper.DropStaleMetricLabels()
log.Printf("error reading factory buildings from FRM: %s\n", err)
Expand Down
2 changes: 1 addition & 1 deletion Companion/exporter/factory_building_collector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ var _ = Describe("FactoryBuildingCollector", func() {
Recipe: "Power Shard",
ManuSpeed: 100.0,
CircuitGroupId: 0,
Somersloops: 4,
Somersloops: 4,
PowerInfo: exporter.PowerInfo{
CircuitGroupId: 1,
PowerConsumed: 23,
Expand Down
2 changes: 1 addition & 1 deletion Companion/exporter/fracking_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func NewFrackingCollector(endpoint string) *FrackingCollector {

func (c *FrackingCollector) Collect(frmAddress string, sessionName string) {
details := []FrackingDetails{}
err := retrieveData(frmAddress+c.endpoint, &details)
err := retrieveData(frmAddress, c.endpoint, &details)
if err != nil {
log.Printf("error reading fracking statistics from FRM: %s\n", err)
return
Expand Down
2 changes: 1 addition & 1 deletion Companion/exporter/hypertube_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func NewHypertubeCollector(endpoint string) *HypertubeCollector {

func (c *HypertubeCollector) Collect(frmAddress string, sessionName string) {
details := []HypertubeDetails{}
err := retrieveData(frmAddress+c.endpoint, &details)
err := retrieveData(frmAddress, c.endpoint, &details)
if err != nil {
log.Printf("error reading hypertube statistics from FRM: %s\n", err)
return
Expand Down
2 changes: 1 addition & 1 deletion Companion/exporter/portal_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func NewPortalCollector(endpoint string) *PortalCollector {

func (c *PortalCollector) Collect(frmAddress string, sessionName string) {
details := []PortalDetails{}
err := retrieveData(frmAddress+c.endpoint, &details)
err := retrieveData(frmAddress, c.endpoint, &details)
if err != nil {
log.Printf("error reading portal statistics from FRM: %s\n", err)
return
Expand Down
2 changes: 1 addition & 1 deletion Companion/exporter/power_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ func NewPowerCollector(endpoint string) *PowerCollector {

func (c *PowerCollector) Collect(frmAddress string, sessionName string) {
details := []PowerDetails{}
err := retrieveData(frmAddress+c.endpoint, &details)
err := retrieveData(frmAddress, c.endpoint, &details)
if err != nil {
c.metricsDropper.DropStaleMetricLabels()
log.Printf("error reading power statistics from FRM: %s\n", err)
Expand Down
10 changes: 5 additions & 5 deletions Companion/exporter/power_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ func powerMultiplier(clockspeed float64, sloops float64, slots float64) float64

func MaxParticleAcceleratorPower(recipe string) float64 {
recipes := map[string]float64{
"Dark Matter Crystal": 1500.0,
"Diamonds": 750.0,
"Ficsonium": 1500.0,
"Nuclear Pasta": 1500.0,
"Plutonium Pellet": 750.0,
"Dark Matter Crystal": 1500.0,
"Diamonds": 750.0,
"Ficsonium": 1500.0,
"Nuclear Pasta": 1500.0,
"Plutonium Pellet": 750.0,
"Alternate: Cloudy Diamonds": 750.0,
"Alternate: Dark Matter Crystallization": 1500.0,
"Alternate: Dark Matter Trap": 1500.0,
Expand Down
2 changes: 1 addition & 1 deletion Companion/exporter/production_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func NewProductionCollector(endpoint string) *ProductionCollector {

func (c *ProductionCollector) Collect(frmAddress string, sessionName string) {
details := []ProductionDetails{}
err := retrieveData(frmAddress+c.endpoint, &details)
err := retrieveData(frmAddress, c.endpoint, &details)
if err != nil {
c.metricsDropper.DropStaleMetricLabels()
log.Printf("error reading production statistics from FRM: %s\n", err)
Expand Down
2 changes: 1 addition & 1 deletion Companion/exporter/pump_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func NewPumpCollector(endpoint string) *PumpCollector {

func (c *PumpCollector) Collect(frmAddress string, sessionName string) {
details := []PumpDetails{}
err := retrieveData(frmAddress+c.endpoint, &details)
err := retrieveData(frmAddress, c.endpoint, &details)
if err != nil {
log.Printf("error reading pump statistics from FRM: %s\n", err)
return
Expand Down
6 changes: 3 additions & 3 deletions Companion/exporter/resource_sink_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ func NewResourceSinkCollector(buildingEndpoint, globalResourceEndpoint, globalEx

func (c *ResourceSinkCollector) Collect(frmAddress string, sessionName string) {
buildingDetails := []ResourceSinkDetails{}
err := retrieveData(frmAddress+c.buildingEndpoint, &buildingDetails)
err := retrieveData(frmAddress, c.buildingEndpoint, &buildingDetails)
if err != nil {
log.Printf("error reading resource sink details statistics from FRM: %s\n", err)
return
}

globalResourceDetails := []GlobalSinkDetails{}
err = retrieveData(frmAddress+c.globalResourceEndpoint, &globalResourceDetails)
err = retrieveData(frmAddress, c.globalResourceEndpoint, &globalResourceDetails)
if err != nil {
log.Printf("error reading global resource sink statistics from FRM: %s\n", err)
return
Expand All @@ -55,7 +55,7 @@ func (c *ResourceSinkCollector) Collect(frmAddress string, sessionName string) {
}

globalExplorationDetails := []GlobalSinkDetails{}
err = retrieveData(frmAddress+c.globalExplorationEndpoint, &globalExplorationDetails)
err = retrieveData(frmAddress, c.globalExplorationEndpoint, &globalExplorationDetails)
if err != nil {
log.Printf("error reading global resource sink statistics from FRM: %s\n", err)
return
Expand Down
2 changes: 1 addition & 1 deletion Companion/exporter/train_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func (d *TrainDetails) handleTimingUpdates(trackedTrains map[string]*TrainDetail

func (c *TrainCollector) Collect(frmAddress string, sessionName string) {
details := []TrainDetails{}
err := retrieveData(frmAddress+c.endpoint, &details)
err := retrieveData(frmAddress, c.endpoint, &details)
if err != nil {
c.metricsDropper.DropStaleMetricLabels()
log.Printf("error reading train statistics from FRM: %s\n", err)
Expand Down
2 changes: 1 addition & 1 deletion Companion/exporter/train_station_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func NewTrainStationCollector(endpoint string) *TrainStationCollector {

func (c *TrainStationCollector) Collect(frmAddress string, sessionName string) {
details := []TrainStationDetails{}
err := retrieveData(frmAddress+c.endpoint, &details)
err := retrieveData(frmAddress, c.endpoint, &details)
if err != nil {
log.Printf("error reading train station statistics from FRM: %s\n", err)
return
Expand Down
2 changes: 1 addition & 1 deletion Companion/exporter/vehicle_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ func NewVehicleCollector(endpoint string) *VehicleCollector {

func (c *VehicleCollector) Collect(frmAddress string, sessionName string) {
details := []VehicleDetails{}
err := retrieveData(frmAddress+c.endpoint, &details)
err := retrieveData(frmAddress, c.endpoint, &details)
if err != nil {
c.metricsDropper.DropStaleMetricLabels()
log.Printf("error reading vehicle statistics from FRM: %s\n", err)
Expand Down
2 changes: 1 addition & 1 deletion Companion/exporter/vehicle_station_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func NewVehicleStationCollector(endpoint string) *VehicleStationCollector {

func (c *VehicleStationCollector) Collect(frmAddress string, sessionName string) {
details := []VehicleStationDetails{}
err := retrieveData(frmAddress+c.endpoint, &details)
err := retrieveData(frmAddress, c.endpoint, &details)
if err != nil {
log.Printf("error reading vehicle station statistics from FRM: %s\n", err)
return
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ The [Prometheus metrics server](https://prometheus.io/) allows you to [explore t

`FRM_PORT`: The port of the Ficist Remote Monitoring server. EG: `8080`.

`FRM_HOSTS`: A comma separated list of Ficsit Remote Monitoring servers. If protocol is unspecified, it defaults to http. EG: `http://myserver1.frm.example:8080,myserver2.frm.example:8080,https://myserver3.frm.example:8081`
`FRM_HOSTS`: A comma separated list of Ficsit Remote Monitoring servers. This variable supports two connection modes:
* **Standard FRM Web Server:** Provide the base URL. If protocol is unspecified, it defaults to `http`.
* *Example:* `http://myserver1.frm.example:8080,http://myserver2.frm.example:8080`
* **Dedicated Server API:** Provide the full path to the server's built-in API. This will automatically switch to using the secure `POST` method.
* *Example:* `https://my-dedicated-server.example:7777/api/v1`

`FRM_LOG_STDOUT`: If FRMC should print to stdout rather than a separate logfile. Useful for docker/containerization. default false.

Expand Down
6 changes: 5 additions & 1 deletion readme/readme.tpl.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,11 @@ The [Prometheus metrics server](https://prometheus.io/) allows you to [explore t

`FRM_PORT`: The port of the Ficist Remote Monitoring server. EG: `8080`.

`FRM_HOSTS`: A comma separated list of Ficsit Remote Monitoring servers. If protocol is unspecified, it defaults to http. EG: `http://myserver1.frm.example:8080,myserver2.frm.example:8080,https://myserver3.frm.example:8081`
`FRM_HOSTS`: A comma separated list of Ficsit Remote Monitoring servers. This variable supports two connection modes:
* **Standard FRM Web Server:** Provide the base URL. If protocol is unspecified, it defaults to `http`.
* *Example:* `http://myserver1.frm.example:8080,http://myserver2.frm.example:8080`
* **Dedicated Server API:** Provide the full path to the server's built-in API. This will automatically switch to using the secure `POST` method.
* *Example:* `https://my-dedicated-server.example:7777/api/v1`

`FRM_LOG_STDOUT`: If FRMC should print to stdout rather than a separate logfile. Useful for docker/containerization. default false.

Expand Down
Loading