github.com/anycable/anycable-go@v1.5.1/metrics/custom_printer.go (about) 1 //go:build (darwin && mrb) || (linux && mrb) 2 // +build darwin,mrb linux,mrb 3 4 package metrics 5 6 import ( 7 "fmt" 8 "log/slog" 9 10 "github.com/anycable/anycable-go/mrb" 11 "github.com/mitchellh/go-mruby" 12 ) 13 14 // RubyPrinter contains refs to mruby vm and code 15 type RubyPrinter struct { 16 path string 17 mrbModule *mruby.MrbValue 18 engine *mrb.Engine 19 20 log *slog.Logger 21 } 22 23 // NewCustomPrinter generates log formatter from the provided (as path) 24 // Ruby script 25 func NewCustomPrinter(path string, l *slog.Logger) (*RubyPrinter, error) { 26 return &RubyPrinter{path: path, log: l}, nil 27 } 28 29 // Run initializes the Ruby VM 30 func (p *RubyPrinter) Run(interval int) error { 31 p.engine = mrb.DefaultEngine() 32 33 if err := p.engine.LoadFile(p.path); err != nil { 34 return err 35 } 36 37 mod := p.engine.VM.Module("MetricsFormatter") 38 39 p.mrbModule = mod.MrbValue(p.engine.VM) 40 41 p.log.Info(fmt.Sprintf("Log metrics every %ds using a custom Ruby formatter from %s", interval, p.path)) 42 43 return nil 44 } 45 46 func (p *RubyPrinter) Stop() { 47 } 48 49 // Write prints formatted snapshot to the log 50 func (p *RubyPrinter) Write(m *Metrics) error { 51 snapshot := m.IntervalSnapshot() 52 p.Print(snapshot) 53 return nil 54 } 55 56 // Print calls Ruby script to format the output and prints it to the log 57 func (p *RubyPrinter) Print(snapshot map[string]uint64) { 58 rhash, _ := p.engine.VM.LoadString("{}") 59 60 hash := rhash.Hash() 61 62 for k, v := range snapshot { 63 hash.Set(mruby.String(k), mruby.Int(v)) 64 } 65 66 result, err := p.mrbModule.Call("call", rhash) 67 68 if err != nil { 69 p.log.Error("mruby call failed", "error", err) 70 return 71 } 72 73 p.log.Info(result.String()) 74 }