Skip to content

Commit

Permalink
test: logs csv export (#666)
Browse files Browse the repository at this point in the history
  • Loading branch information
hughcrt authored Nov 18, 2024
1 parent 67719e1 commit 839e19f
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 7 deletions.
64 changes: 62 additions & 2 deletions e2e/logs.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { expect, test } from "@playwright/test";
import {
expect,
PlaywrightTestArgs,
PlaywrightTestOptions,
test,
} from "@playwright/test";
import { setOrgPro } from "./utils/db";
import fs from "fs";

test.describe.configure({ mode: "serial" });

Expand All @@ -8,7 +15,6 @@ test("make a log public", async ({ page, context }) => {
await context.grantPermissions(["clipboard-read", "clipboard-write"]);

await page.goto("/logs");

await page.waitForLoadState("networkidle");

await page.getByText("xyzTESTxyz").click();
Expand All @@ -23,6 +29,60 @@ test("make a log public", async ({ page, context }) => {
});
});

test("test export csv", async ({ page }) => {
page.on("console", (msg) => {
console.log(msg);
});
await setOrgPro();

await page.goto("/logs?type=llm");
await page.waitForLoadState("networkidle");

const downloadPromise = page.waitForEvent("download");

await page.getByTestId("export-menu").click();
await page.getByTestId("export-csv-button").click();

const file = await downloadPromise;
const path = await file.path();
const content = fs.readFileSync(path, "utf-8");

const expectedHeaders = [
"id",
"projectId",
"isPublic",
"feedback",
"parentFeedback",
"type",
"name",
"createdAt",
"endedAt",
"duration",
"templateVersionId",
"templateSlug",
"cost",
"tokens",
"tags",
"input",
"output",
"error",
"status",
"siblingRunId",
"params",
"metadata",
"user",
"traceId",
"scores",
];
const actualHeaderLine = content.split("\n")[0].trim();
expect(actualHeaderLine).toBe(`"${expectedHeaders.join('","')}"`);

// TODO: check that the content of each column for each row is correct (use json-2-csv to convert the csv to json
// TODO: do the same thing for threads and traces (do not forget to check that children has the right)
});

// TODO: test export-raw-jsonl-button and export-openai-jsonl-button

test("unauthenticated user can access public log URL", async ({ browser }) => {
const context = await browser.newContext();
const page = await context.newPage();
Expand Down
83 changes: 82 additions & 1 deletion e2e/utils/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,90 @@ export async function populateLogs() {
external_user_id: 91823,
feedback: null,
template_version_id: null,
runtime: "langchain-js",
runtime: "langchain-py",
metadata: "{}",
},
{
created_at: "2024-11-14T03:55:51.596Z",
ended_at: "2024-11-14T03:55:52.206Z",
duration: "00:00:00.61",
tags: ["test", "test2"],
project_id: project.id,
status: "success",
name: "My great agent",
error: null,
input: [1, 2, 3, { test: "sdkj", test2: "sdkj" }],
output: "Agent output",
params: {},
type: "agent",
parent_run_id: null,
prompt_tokens: null,
completion_tokens: null,
cost: null,
external_user_id: 91823,
feedback: null,
is_public: false,
template_version_id: null,
runtime: "lunary-py",
metadata: null,
},
{
created_at: "2024-11-14T03:54:11.773Z",
ended_at: "2024-11-14T03:54:12.528Z",
duration: "00:00:00.755",
tags: ["test", "test2"],
project_id: project.id,
status: "success",
name: "My great agent",
error: null,
input: [1, 2, 3, { test: "sdkj", test2: "sdkj" }],
output: "Agent output",
params: {},
type: "agent",
parent_run_id: null,
prompt_tokens: null,
completion_tokens: null,
cost: null,
external_user_id: 91823,
feedback: null,
is_public: false,
template_version_id: null,
runtime: "lunary-py",
metadata: null,
},
{
created_at: "2024-09-28T11:42:37.770Z",
ended_at: "2024-09-28T11:42:40.157Z",
duration: "00:00:02.387",
tags: null,
project_id: project.id,
status: "success",
name: "SupportAgent",
error: null,
input: {
user: {
id: "demo-user-4",
name: "Test User 2",
email: "[email protected]",
},
topic: "billing",
question: "Hi, I would like to cancel my subscription.",
},
output:
"Hello Test User 2,\n\nI understand you'd like to cancel your subscription. I apologize, but I don't actually have access to any billing or account information. I'm Claude, an AI assistant created by Anthropic to be helpful, harmless, and honest.\n\nFor assistance with canceling your subscription, you'll need to contact the customer support team for the specific service you're subscribed to. They'll be able to help you with the cancellation process.\n\nIs there anything else I can assist you with today?",
params: null,
type: "agent",
parent_run_id: "087c446e-ec41-412e-adb7-bea690e13789",
prompt_tokens: null,
completion_tokens: null,
cost: null,
external_user_id: 91823,
feedback: null,
is_public: false,
template_version_id: null,
runtime: "lunary-py",
metadata: null,
},
];
await sql`insert into run ${sql(logs)}`;
}
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@
"@playwright/test": "^1.47.0",
"@types/node": "^22.5.4",
"dotenv": "^16.4.5",
"json-2-csv": "^5.5.6",
"prettier": "^3.3.3",
"tsup": "^8.2.4",
"tsx": "^4.19.0",
"typescript": "^5.5.4"
}
}
}
2 changes: 2 additions & 0 deletions packages/backend/src/api/v1/runs/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ export async function fileExport(
}
}
}
yield "exports";
},
});
ctx.body = stream;
Expand All @@ -183,6 +184,7 @@ export async function fileExport(
yield line + "\n";
}
}
yield "exports";
},
});
ctx.body = stream;
Expand Down
7 changes: 4 additions & 3 deletions packages/frontend/pages/logs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,6 @@ export default function Logs() {
"filters",
parser.withDefault(DEFAULT_CHECK).withOptions({ clearOnDefault: true }),
);
console.log(checks);

const { sortParams } = useSortParams();

Expand Down Expand Up @@ -447,15 +446,15 @@ export default function Logs() {
/>

<Group gap="xs">
<Menu position="bottom-end">
<Menu position="bottom-end" data-testid="export-menu">
<Menu.Target>
<ActionIcon variant="light">
<IconDotsVertical size={12} />
</ActionIcon>
</Menu.Target>
<Menu.Dropdown>
<Menu.Item
// disabled={type === "thread"}
data-testid="export-csv-button"
leftSection={<IconFileExport size={16} />}
{...exportButton({
serializedChecks,
Expand All @@ -469,6 +468,7 @@ export default function Logs() {

{type === "llm" && (
<Menu.Item
data-testid="export-openai-jsonl-button"
color="dimmed"
leftSection={<IconBrandOpenai size={16} />}
{...exportButton({
Expand All @@ -483,6 +483,7 @@ export default function Logs() {
)}

<Menu.Item
data-testid="export-raw-jsonl-button"
color="dimmed"
// disabled={type === "thread"}
leftSection={<IconBraces size={16} />}
Expand Down

0 comments on commit 839e19f

Please sign in to comment.