All checks were successful
ci / build (push) Successful in 46s
Add push client that sends run summary to a configurable HTTP endpoint on shutdown. Execution context is read from GitHub Actions style environment variables (with Gitea fallbacks). New flag: -push-endpoint <url> Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
105 lines
3.1 KiB
Go
105 lines
3.1 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"log/slog"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
|
|
"edp.buildth.ing/DevFW-CICD/forgejo-runner-resource-collector/internal/collector"
|
|
"edp.buildth.ing/DevFW-CICD/forgejo-runner-resource-collector/internal/output"
|
|
"edp.buildth.ing/DevFW-CICD/forgejo-runner-resource-collector/internal/summary"
|
|
)
|
|
|
|
const (
|
|
defaultInterval = 5 * time.Second
|
|
defaultProcPath = "/proc"
|
|
defaultLogLevel = "info"
|
|
defaultLogFormat = "json"
|
|
defaultTopN = 5
|
|
)
|
|
|
|
func main() {
|
|
// Parse command line flags
|
|
interval := flag.Duration("interval", defaultInterval, "Collection interval (e.g., 5s, 1m)")
|
|
procPath := flag.String("proc-path", defaultProcPath, "Path to proc filesystem")
|
|
logLevel := flag.String("log-level", defaultLogLevel, "Log level: debug, info, warn, error")
|
|
logFormat := flag.String("log-format", defaultLogFormat, "Output format: json, text")
|
|
topN := flag.Int("top", defaultTopN, "Number of top processes to include")
|
|
pushEndpoint := flag.String("push-endpoint", "", "HTTP endpoint to push metrics to (e.g., http://localhost:8080/api/v1/metrics)")
|
|
flag.Parse()
|
|
|
|
// Setup structured logging for application logs
|
|
appLogLevel := output.ParseLogLevel(*logLevel)
|
|
appHandler := slog.NewJSONHandler(os.Stderr, &slog.HandlerOptions{
|
|
Level: appLogLevel,
|
|
})
|
|
appLogger := slog.New(appHandler)
|
|
|
|
// Setup metrics output writer
|
|
metricsWriter := output.NewLoggerWriter(output.LoggerConfig{
|
|
Output: os.Stdout,
|
|
Format: output.ParseLogFormat(*logFormat),
|
|
Level: slog.LevelInfo,
|
|
})
|
|
defer func() { _ = metricsWriter.Close() }()
|
|
|
|
// Create collector
|
|
c := collector.New(collector.Config{
|
|
ProcPath: *procPath,
|
|
Interval: *interval,
|
|
TopN: *topN,
|
|
}, metricsWriter, appLogger)
|
|
|
|
// Attach summary writer to emit run summary on shutdown
|
|
summaryWriter := summary.NewSummaryWriter(os.Stdout, *logFormat)
|
|
c.SetSummaryWriter(summaryWriter)
|
|
|
|
// Setup push client if endpoint is configured
|
|
if *pushEndpoint != "" {
|
|
pushClient := summary.NewPushClient(*pushEndpoint)
|
|
c.SetPushClient(pushClient)
|
|
execCtx := pushClient.ExecutionContext()
|
|
appLogger.Info("push client configured",
|
|
slog.String("endpoint", *pushEndpoint),
|
|
slog.String("organization", execCtx.Organization),
|
|
slog.String("repository", execCtx.Repository),
|
|
slog.String("workflow", execCtx.Workflow),
|
|
slog.String("job", execCtx.Job),
|
|
slog.String("run_id", execCtx.RunID),
|
|
)
|
|
}
|
|
|
|
// Setup signal handling for graceful shutdown
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
defer cancel()
|
|
|
|
sigChan := make(chan os.Signal, 1)
|
|
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
go func() {
|
|
sig := <-sigChan
|
|
appLogger.Info("received signal", slog.String("signal", sig.String()))
|
|
cancel()
|
|
}()
|
|
|
|
// Run collector
|
|
appLogger.Info("starting resource collector",
|
|
slog.Duration("interval", *interval),
|
|
slog.String("proc_path", *procPath),
|
|
slog.String("log_level", *logLevel),
|
|
slog.String("log_format", *logFormat),
|
|
slog.Int("top_n", *topN),
|
|
)
|
|
|
|
if err := c.Run(ctx); err != nil && err != context.Canceled {
|
|
fmt.Fprintf(os.Stderr, "error: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
|
|
appLogger.Info("collector stopped gracefully")
|
|
}
|