Use wrapper

This commit is contained in:
Adria Navarro 2024-02-19 16:08:34 +01:00
parent a84474bd62
commit 598ebccc2c
2 changed files with 53 additions and 109 deletions

View File

@ -1,62 +1,16 @@
import vm from "vm"
import env from "../environment"
import { setJSRunner, setOnErrorLog } from "@budibase/string-templates"
import { context, logging, timers } from "@budibase/backend-core"
import { logging } from "@budibase/backend-core"
import tracer from "dd-trace"
import { serializeError } from "serialize-error"
type TrackerFn = <T>(f: () => T) => T
import { BuiltInVM } from "./vm"
export function init() {
setJSRunner((js: string, ctx: vm.Context) => {
return tracer.trace("runJS", {}, span => {
const perRequestLimit = env.JS_PER_REQUEST_TIMEOUT_MS
let track: TrackerFn = f => f()
if (perRequestLimit) {
const bbCtx = tracer.trace("runJS.getCurrentContext", {}, span =>
context.getCurrentContext()
)
if (bbCtx) {
if (!bbCtx.jsExecutionTracker) {
span?.addTags({
createdExecutionTracker: true,
})
bbCtx.jsExecutionTracker = tracer.trace(
"runJS.createExecutionTimeTracker",
{},
span => timers.ExecutionTimeTracker.withLimit(perRequestLimit)
)
}
span?.addTags({
js: {
limitMS: bbCtx.jsExecutionTracker.limitMs,
elapsedMS: bbCtx.jsExecutionTracker.elapsedMS,
},
})
// We call checkLimit() here to prevent paying the cost of creating
// a new VM context below when we don't need to.
tracer.trace("runJS.checkLimitAndBind", {}, span => {
bbCtx.jsExecutionTracker!.checkLimit()
track = bbCtx.jsExecutionTracker!.track.bind(
bbCtx.jsExecutionTracker
)
})
}
}
ctx = {
...ctx,
alert: undefined,
setInterval: undefined,
setTimeout: undefined,
}
vm.createContext(ctx)
return track(() =>
vm.runInNewContext(js, ctx, {
timeout: env.JS_PER_INVOCATION_TIMEOUT_MS,
})
)
const vm = new BuiltInVM(ctx, span)
return vm.execute(js)
})
})

View File

@ -1,75 +1,65 @@
import vm from "vm"
import env from "../../environment"
import { setOnErrorLog } from "@budibase/string-templates"
import { context, logging, timers } from "@budibase/backend-core"
import tracer from "dd-trace"
import { serializeError } from "serialize-error"
import { context, timers } from "@budibase/backend-core"
import tracer, { Span } from "dd-trace"
import { VM } from "@budibase/types"
type TrackerFn = <T>(f: () => T) => T
export class BuiltInVM implements VM {
private ctx: vm.Context
private span?: Span
constructor(ctx: vm.Context) {
constructor(ctx: vm.Context, span?: Span) {
this.ctx = ctx
if (env.LOG_JS_ERRORS) {
setOnErrorLog((error: Error) => {
logging.logWarn(JSON.stringify(serializeError(error)))
})
}
this.span = span
}
execute(code: string) {
return tracer.trace("runJS", {}, span => {
const perRequestLimit = env.JS_PER_REQUEST_TIMEOUT_MS
let track: TrackerFn = f => f()
if (perRequestLimit) {
const bbCtx = tracer.trace("runJS.getCurrentContext", {}, span =>
context.getCurrentContext()
)
if (bbCtx) {
if (!bbCtx.jsExecutionTracker) {
span?.addTags({
createdExecutionTracker: true,
})
bbCtx.jsExecutionTracker = tracer.trace(
"runJS.createExecutionTimeTracker",
{},
span => timers.ExecutionTimeTracker.withLimit(perRequestLimit)
)
}
span?.addTags({
js: {
limitMS: bbCtx.jsExecutionTracker.limitMs,
elapsedMS: bbCtx.jsExecutionTracker.elapsedMS,
},
})
// We call checkLimit() here to prevent paying the cost of creating
// a new VM context below when we don't need to.
tracer.trace("runJS.checkLimitAndBind", {}, span => {
bbCtx.jsExecutionTracker!.checkLimit()
track = bbCtx.jsExecutionTracker!.track.bind(
bbCtx.jsExecutionTracker
)
})
}
}
this.ctx = {
...this.ctx,
alert: undefined,
setInterval: undefined,
setTimeout: undefined,
}
vm.createContext(this.ctx)
return track(() =>
vm.runInNewContext(code, this.ctx, {
timeout: env.JS_PER_INVOCATION_TIMEOUT_MS,
})
const perRequestLimit = env.JS_PER_REQUEST_TIMEOUT_MS
let track: TrackerFn = f => f()
if (perRequestLimit) {
const bbCtx = tracer.trace("runJS.getCurrentContext", {}, span =>
context.getCurrentContext()
)
})
if (bbCtx) {
if (!bbCtx.jsExecutionTracker) {
this.span?.addTags({
createdExecutionTracker: true,
})
bbCtx.jsExecutionTracker = tracer.trace(
"runJS.createExecutionTimeTracker",
{},
span => timers.ExecutionTimeTracker.withLimit(perRequestLimit)
)
}
this.span?.addTags({
js: {
limitMS: bbCtx.jsExecutionTracker.limitMs,
elapsedMS: bbCtx.jsExecutionTracker.elapsedMS,
},
})
// We call checkLimit() here to prevent paying the cost of creating
// a new VM context below when we don't need to.
tracer.trace("runJS.checkLimitAndBind", {}, span => {
bbCtx.jsExecutionTracker!.checkLimit()
track = bbCtx.jsExecutionTracker!.track.bind(bbCtx.jsExecutionTracker)
})
}
}
this.ctx = {
...this.ctx,
alert: undefined,
setInterval: undefined,
setTimeout: undefined,
}
vm.createContext(this.ctx)
return track(() =>
vm.runInNewContext(code, this.ctx, {
timeout: env.JS_PER_INVOCATION_TIMEOUT_MS,
})
)
}
}