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  }