package actions import ( "context" "time" "github.com/dop251/goja" "github.com/dop251/goja_nodejs/console" "github.com/sirupsen/logrus" "github.com/zitadel/zitadel/internal/api/authz" "github.com/zitadel/zitadel/internal/logstore" "github.com/zitadel/zitadel/internal/logstore/record" ) var ( logstoreService *logstore.Service[*record.ExecutionLog] _ console.Printer = (*logger)(nil) ) func SetLogstoreService(svc *logstore.Service[*record.ExecutionLog]) { logstoreService = svc } type logger struct { ctx context.Context started time.Time instanceID string } // newLogger returns a *logger instance that should only be used for a single action run. // The first log call sets the started field for subsequent log calls func newLogger(ctx context.Context, instanceID string) *logger { return &logger{ ctx: ctx, started: time.Time{}, instanceID: instanceID, } } func (l *logger) Log(msg string) { l.log(msg, logrus.InfoLevel, false) } func (l *logger) Warn(msg string) { l.log(msg, logrus.WarnLevel, false) } func (l *logger) Error(msg string) { l.log(msg, logrus.ErrorLevel, false) } func (l *logger) log(msg string, level logrus.Level, last bool) { ts := time.Now() if l.started.IsZero() { l.started = ts } r := &record.ExecutionLog{ LogDate: ts, InstanceID: l.instanceID, Message: msg, LogLevel: level, } if last { r.Took = ts.Sub(l.started) } logstoreService.Handle(l.ctx, r) } func withLogger(ctx context.Context) Option { instance := authz.GetInstance(ctx) instanceID := instance.InstanceID() return func(c *runConfig) { c.logger = newLogger(ctx, instanceID) c.instanceID = instanceID c.modules["zitadel/log"] = func(runtime *goja.Runtime, module *goja.Object) { console.RequireWithPrinter(c.logger)(runtime, module) } } }