UNPKG

log10js

Version:

⚡ Unified LLM data management ⚡

147 lines (128 loc) 3.89 kB
const logger = require("loglevel"); const axios = require("axios"); require("dotenv").config(); const { performance } = require("perf_hooks"); const DEBUG = false; logger.setLevel(DEBUG ? logger.levels.DEBUG : logger.levels.INFO); url = process.env.LOG10_URL; token = process.env.LOG10_TOKEN; orgId = process.env.LOG10_ORG_ID; async function getSessionId() { try { const sessionUrl = url + "/api/sessions"; const res = await axios.post( sessionUrl, { organization_id: orgId, }, { headers: { "x-log10-token": token, "Content-Type": "application/json", }, } ); return res.data.sessionID; } catch (e) { throw new Error("Failed to create LOG10 session: " + e.message); } } // Global variable to store the current sessionID. let sessionIDPromise = getSessionId(); function interceptFunction(fn) { return async function (...args) { const stackTrace = await import("stack-trace"); logger.info(`Calling function: ${fn.name}`); let output = null; try { const completionUrl = url.concat("/api/completions"); const res = await axios.post( completionUrl, { organization_id: orgId, }, { headers: { "x-log10-token": token, "Content-Type": "application/json", }, } ); const completionID = res.data.completionID; console.log(`Log10 completionID: ${completionID}`); const req = JSON.stringify(args[0]); console.log(`args = ${req}`); const sessionID = await sessionIDPromise; // TODO: Make backend handle the translation. let qualname = "Completion.create"; if (fn.name === "createCompletion") { qualname = "Completion.create"; } else if (fn.name === "createChatCompletion") { qualname = "ChatCompletion.create"; } await axios.post( `${completionUrl}/${completionID}`, { status: "started", orig_module: fn.name, orig_qualname: qualname, request: JSON.stringify(args[0]), session_id: sessionID, organization_id: orgId, }, { headers: { "x-log10-token": token, "Content-Type": "application/json", }, } ); const currentStackFrame = stackTrace.get(); const stacktrace = currentStackFrame.map((frame) => ({ file: frame.getFileName(), line: frame.getLineNumber(), lineno: frame.getLineNumber(), name: frame.getFunctionName(), })); const startTime = performance.now(); const output = await fn.apply(this, args); const duration = performance.now() - startTime; console.log(`TIMED BLOCK - OpenAI call duration: ${duration}`); const logRow = { response: JSON.stringify(output.data), status: "finished", duration: Math.round(duration), stacktrace: JSON.stringify(stacktrace), }; await axios.post(`${completionUrl}/${completionID}`, logRow, { headers: { "x-log10-token": token, "Content-Type": "application/json", }, }); return output; } catch (e) { console.error("failed", e); } }; } function log10(constructor) { const wrappedConstructor = class extends constructor { constructor(...args) { super(...args); for (const propertyName of Object.getOwnPropertyNames( constructor.prototype )) { const propertyValue = this[propertyName]; if ( propertyName !== "constructor" && typeof propertyValue === "function" ) { this[propertyName] = interceptFunction(propertyValue); } } } }; return wrappedConstructor; } (module.exports = log10), getSessionId;