-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlog10.js
146 lines (128 loc) · 3.8 KB
/
log10.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
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;