OverviewFilesCommitsIssuesDocsReleasesPeers

ollama_semantic_function_calling / ollamatools-new / keet / node_modules / hypertrace / index.js

122 lines · javascript ref:
const objectState = new Map()
const traceFunctionSymbol = Symbol.for('hypertrace.traceFunction')

class Hypertrace {
  constructor (ctx, opts = { }) {
    if (!ctx) throw new Error('Context required, see hypertrace documentation')

    const { parent, props } = opts
    this.enabled = true
    this.ctx = ctx
    this.className = ctx.constructor.name
    this.props = props || null
    this.parentObject = !parent
      ? null
      : {
          className: parent.className,
          id: parent.objectId,
          props: { ...parent.props },
          ctx: parent.ctx
        }

    const currentObjectState = objectState.get(ctx.constructor) || { id: 0, stacktraceCache: new Map() }
    currentObjectState.id += 1
    this.objectId = currentObjectState.id
    objectState.set(ctx.constructor, currentObjectState)
  }

  setParent (parentTracer) {
    this.parentObject = !parentTracer
      ? null
      : {
          className: parentTracer.className,
          id: parentTracer.objectId,
          props: { ...parentTracer.props },
          ctx: parentTracer.ctx
        }
  }

  trace (id, props) {
    const traceFunction = globalThis[traceFunctionSymbol]
    const shouldTrace = traceFunction
    if (!shouldTrace) return

    const hasTraceIdInArgs = typeof id === 'string'
    if (!hasTraceIdInArgs) {
      props = id
      id = null
    }

    const currentObjectState = objectState.get(this.ctx.constructor)
    let stack = id && currentObjectState.stacktraceCache.get(id)
    const hasCachedStacktrace = !!stack
    if (!hasCachedStacktrace) {
      const errorToGetContext = new Error()
      stack = errorToGetContext.stack
      currentObjectState.stacktraceCache.set(id, stack)
    }

    const callLine = stack.split('\n')[2]
    const re = /.*at (.+) \((?:file:\/:\/)?(.+):(\d+):(\d+)\)/
    const [, functionName, filename, line, column] = callLine.match(re)

    const realFunctionName = functionName.split('.')[0] === this.className // Turn SomeModule.foobar => foobar
      ? functionName.substr(functionName.indexOf('.') + 1)
      : functionName

    const object = {
      className: this.className,
      id: this.objectId,
      props: this.props && { ...this.props },
      ctx: this.ctx
    }
    const caller = {
      functionName: realFunctionName,
      filename,
      line: Number(line),
      column: Number(column),
      props: props && { ...props }
    }

    traceFunction({
      id: id || null,
      object,
      parentObject: this.parentObject,
      caller
    })
  }
}

class NoTracingClass {
  constructor () {
    this.enabled = false
    this.ctx = null
    this.className = null
    this.props = null
    this.parentObject = null
    this.objectId = null
  }

  trace () { /* noop */ }

  setParent () { /* noop */ }
}

const noTracing = new NoTracingClass()

module.exports = {
  setTraceFunction: fn => {
    globalThis[traceFunctionSymbol] = fn
  },
  clearTraceFunction: () => {
    globalThis[traceFunctionSymbol] = undefined
  },
  createTracer: (ctx, opts) => {
    // If the trace function is not set, then the returned class cannot trace.
    // This is done for speed.
    const isTracing = !!globalThis[traceFunctionSymbol]
    if (!isTracing) return noTracing
    return new Hypertrace(ctx, opts)
  }
}