You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
1.7 KiB
Go

package monitor
import (
"log"
"os"
"os/exec"
"path"
"strings"
"time"
)
type Config struct {
ScriptsDir string
CacheTimeout time.Duration
}
type cacheEntry struct {
creationTime time.Time
output string
}
type Service struct {
Config *Config
scriptPaths map[string]string
scriptOutputCache map[string]cacheEntry
}
func NewService(config *Config) *Service {
return &Service{
Config: config,
scriptPaths: map[string]string{},
scriptOutputCache: map[string]cacheEntry{},
}
}
func (s *Service) LoadScripts() error {
entries, err := os.ReadDir(s.Config.ScriptsDir)
if err != nil {
return err
}
s.scriptPaths = map[string]string{}
for _, entry := range entries {
newScriptPath := path.Join(s.Config.ScriptsDir, entry.Name())
s.scriptPaths[entry.Name()] = newScriptPath
}
return nil
}
func (s *Service) InvalidateCache() {
log.Printf("Invalidating monitor cache")
s.scriptOutputCache = map[string]cacheEntry{}
}
func (s *Service) GetOutput(command string) (string, error) {
// check if output is present in cache
if entry, found := s.scriptOutputCache[command]; found {
// check if cached value is expired
if time.Now().Before(entry.creationTime.Add(s.Config.CacheTimeout)) {
log.Printf("Retrieving output of %q from cache", command)
return entry.output, nil
}
}
args := strings.Fields(command)
log.Printf("Running script %q with args %v", args[0], args[1:])
scriptPath := s.scriptPaths[args[0]]
bytes, err := exec.Command(scriptPath, args[1:]...).Output()
if err != nil {
return "", err
}
output := string(bytes)
log.Printf("Caching output of %q", command)
s.scriptOutputCache[command] = cacheEntry{time.Now(), output}
return output, nil
}