From b193313f0375cc1d2d011865e50b29c37a0fb360 Mon Sep 17 00:00:00 2001 From: Shivaditya Shivganesh Date: Sat, 23 Nov 2024 20:51:38 -0500 Subject: [PATCH] fix: error handling better logging --- src/adapters/supabase/helpers/comment.ts | 89 ++++++++++---- src/adapters/supabase/helpers/issues.ts | 149 ++++++++++++++++++----- src/adapters/voyage/helpers/embedding.ts | 3 +- src/handlers/add-comments.ts | 15 +-- src/handlers/add-issue.ts | 14 +-- src/handlers/delete-comments.ts | 7 +- src/handlers/delete-issue.ts | 7 +- src/handlers/issue-matching.ts | 3 +- src/handlers/transfer-issue.ts | 6 +- src/handlers/update-comments.ts | 7 +- src/handlers/update-issue.ts | 7 +- 11 files changed, 217 insertions(+), 90 deletions(-) diff --git a/src/adapters/supabase/helpers/comment.ts b/src/adapters/supabase/helpers/comment.ts index 3b1137d..4228fc1 100644 --- a/src/adapters/supabase/helpers/comment.ts +++ b/src/adapters/supabase/helpers/comment.ts @@ -26,30 +26,41 @@ export class Comment extends SuperSupabase { issueId: string ) { //First Check if the comment already exists - const { data, error } = await this.supabase.from("issue_comments").select("*").eq("id", commentNodeId); - if (error) { + const { data: existingData, error: existingError } = await this.supabase.from("issue_comments").select("*").eq("id", commentNodeId); + if (existingError) { this.context.logger.error("Error creating comment"); } - if (data && data.length > 0) { + if (existingData && existingData.length > 0) { this.context.logger.error("Comment already exists"); return; - } else { - //Create the embedding for this comment - const embedding = await this.context.adapters.voyage.embedding.createEmbedding(markdown); - let plaintext: string | null = markdownToPlainText(markdown); - if (isPrivate) { - markdown = null as string | null; - payload = null as Record | null; - plaintext = null as string | null; - } - const { error } = await this.supabase - .from("issue_comments") - .insert([{ id: commentNodeId, markdown, plaintext, author_id: authorId, payload, embedding: embedding, issue_id: issueId }]); - if (error) { - this.context.logger.error("Error creating comment: " + error.message); - } } - this.context.logger.info("Comment created successfully"); + //Create the embedding for this comment + const embedding = await this.context.adapters.voyage.embedding.createEmbedding(markdown); + let plaintext: string | null = markdownToPlainText(markdown); + if (isPrivate) { + markdown = null as string | null; + payload = null as Record | null; + plaintext = null as string | null; + } + const { data, error } = await this.supabase + .from("issue_comments") + .insert([{ id: commentNodeId, markdown, plaintext, author_id: authorId, payload, embedding: embedding, issue_id: issueId }]); + if (error) { + this.context.logger.error("Failed to create comment in database", { + Error: error, + commentData: { + id: commentNodeId, + markdown, + plaintext, + author_id: authorId, + payload, + embedding, + issue_id: issueId, + }, + }); + return; + } + this.context.logger.info(`Comment created successfully with id: ${commentNodeId}`, { data }); } async updateComment( @@ -78,15 +89,42 @@ export class Comment extends SuperSupabase { .update({ markdown, plaintext, embedding: embedding, payload, modified_at: new Date() }) .eq("id", commentNodeId); if (error) { - this.context.logger.error("Error updating comment: " + error.message); + this.context.logger.error("Error updating comment", { + Error: error, + commentData: { + id: commentNodeId, + markdown, + plaintext, + embedding, + payload, + modified_at: new Date(), + }, + }); + return; } + this.context.logger.info("Comment updated successfully with id: " + commentNodeId, { + commentData: { + id: commentNodeId, + markdown, + plaintext, + embedding, + payload, + modified_at: new Date(), + }, + }); } } async getComment(commentNodeId: string): Promise { const { data, error } = await this.supabase.from("issue_comments").select("*").eq("id", commentNodeId); if (error) { - this.context.logger.error("Error getting comment", error); + this.context.logger.error("Error getting comment", { + Error: error, + commentData: { + id: commentNodeId, + }, + }); + return null; } return data; } @@ -94,7 +132,14 @@ export class Comment extends SuperSupabase { async deleteComment(commentNodeId: string) { const { error } = await this.supabase.from("issue_comments").delete().eq("id", commentNodeId); if (error) { - this.context.logger.error("Error deleting comment: " + error.message); + this.context.logger.error("Error deleting comment", { + Error: error, + commentData: { + id: commentNodeId, + }, + }); + return; } + this.context.logger.info("Comment deleted successfully with id: " + commentNodeId); } } diff --git a/src/adapters/supabase/helpers/issues.ts b/src/adapters/supabase/helpers/issues.ts index d00781c..3e9b0e2 100644 --- a/src/adapters/supabase/helpers/issues.ts +++ b/src/adapters/supabase/helpers/issues.ts @@ -29,10 +29,28 @@ export class Issues extends SuperSupabase { //First Check if the issue already exists const { data, error } = await this.supabase.from("issues").select("*").eq("id", issueNodeId); if (error) { - throw new Error("Error creating issue: " + error.message); + this.context.logger.error("Error creating issue", { + Error: error, + issueData: { + id: issueNodeId, + payload, + isPrivate, + markdown, + authorId, + }, + }); + return; } if (data && data.length > 0) { - this.context.logger.info("Issue already exists"); + this.context.logger.info("Issue already exists", { + issueData: { + id: issueNodeId, + payload, + isPrivate, + markdown, + authorId, + }, + }); return; } else { const embedding = await this.context.adapters.voyage.embedding.createEmbedding(markdown, "document"); @@ -44,10 +62,28 @@ export class Issues extends SuperSupabase { } const { error } = await this.supabase.from("issues").insert([{ id: issueNodeId, payload, markdown, plaintext, author_id: authorId, embedding }]); if (error) { - throw new Error("Error creating issue: " + error.message); + this.context.logger.error("Error creating issue: " + error.message, { + Error: error, + issueData: { + id: issueNodeId, + payload, + isPrivate, + markdown, + authorId, + }, + }); + return; } } - this.context.logger.info("Issue created successfully"); + this.context.logger.info("Issue created successfully with id: " + issueNodeId, { + issueData: { + id: issueNodeId, + payload, + isPrivate, + markdown, + authorId, + }, + }); } async updateIssue(markdown: string | null, issueNodeId: string, payload: Record | null, isPrivate: boolean, authorId: number) { @@ -59,53 +95,100 @@ export class Issues extends SuperSupabase { plaintext = null; } const issues = await this.getIssue(issueNodeId); - if (!issues) { - this.context.logger.info("Issue does not exist, creating a new one"); - await this.createIssue(issueNodeId, payload, isPrivate, markdown, authorId); - } else { - const { error } = await this.supabase.from("issues").update({ markdown, plaintext, embedding, payload, modified_at: new Date() }).eq("id", issueNodeId); - if (error) { - throw new Error("Error updating issue: " + error.message); + try { + if (!issues) { + this.context.logger.info("Issue not found, creating new issue with id: " + issueNodeId); + await this.createIssue(issueNodeId, payload, isPrivate, markdown, authorId); + } else { + const { error } = await this.supabase.from("issues").update({ markdown, plaintext, embedding, payload, modified_at: new Date() }).eq("id", issueNodeId); + if (error) { + this.context.logger.error("Error updating issue", { + Error: error, + issueData: { + id: issueNodeId, + payload, + isPrivate, + markdown, + authorId, + }, + }); + } } + } catch (error) { + this.context.logger.error("Error updating issue", { + Error: error, + issueData: { + id: issueNodeId, + payload, + isPrivate, + markdown, + authorId, + }, + }); } } async deleteIssue(issueNodeId: string) { const { error } = await this.supabase.from("issues").delete().eq("id", issueNodeId); if (error) { - throw new Error("Error deleting issue: " + error.message); + this.context.logger.error("Error deleting issue: " + error.message, { + Error: error, + issueData: { + id: issueNodeId, + }, + }); + return; } + this.context.logger.info("Issue deleted successfully with id: " + issueNodeId, { + issueData: { + id: issueNodeId, + }, + }); } async getIssue(issueNodeId: string): Promise { - const { data, error } = await this.supabase - .from("issues") // Provide the second type argument - .select("*") - .eq("id", issueNodeId) - .returns(); + const { data, error } = await this.supabase.from("issues").select("*").eq("id", issueNodeId).returns(); if (error || !data || data.length === 0) { - if (error) { - this.context.logger.error("Error getting issue", error); - } else { - this.context.logger.error("Error getting issue: No data found"); - } + this.context.logger.error("Error getting issue", { + Error: error, + issueData: { + id: issueNodeId, + }, + }); return null; } return data; } - async findSimilarIssues(markdown: string, threshold: number, currentId: string): Promise { - const embedding = await this.context.adapters.voyage.embedding.createEmbedding(markdown, "query"); - const { data, error } = await this.supabase.rpc("find_similar_issues", { - current_id: currentId, - query_embedding: embedding, - threshold: threshold, - top_k: 5, - }); - if (error) { - this.context.logger.error("Error finding similar issues", error); + async findSimilarIssues(markdown: string, threshold: number, currentId: string): Promise { + try { + const embedding = await this.context.adapters.voyage.embedding.createEmbedding(markdown, "query"); + const { data, error } = await this.supabase.rpc("find_similar_issues", { + current_id: currentId, + query_embedding: embedding, + threshold, + top_k: 5, + }); + + if (error) { + this.context.logger.error("Error finding similar issues", { + Error: error, + markdown, + threshold, + currentId, + }); + return []; + } + + return data; + } catch (error) { + this.context.logger.error("Error finding similar issues", { + Error: error, + markdown, + threshold, + currentId, + }); return []; } - return data; } } diff --git a/src/adapters/voyage/helpers/embedding.ts b/src/adapters/voyage/helpers/embedding.ts index a891792..d3076f8 100644 --- a/src/adapters/voyage/helpers/embedding.ts +++ b/src/adapters/voyage/helpers/embedding.ts @@ -2,7 +2,6 @@ import { VoyageAIClient } from "voyageai"; import { Context } from "../../../types"; import { SuperVoyage } from "./voyage"; import { EmbedRequestInputType } from "voyageai/api/types/EmbedRequestInputType"; -const VECTOR_SIZE = 1024; export class Embedding extends SuperVoyage { protected context: Context; @@ -14,7 +13,7 @@ export class Embedding extends SuperVoyage { async createEmbedding(text: string | null, inputType: EmbedRequestInputType = "document"): Promise { if (text === null) { - return new Array(VECTOR_SIZE).fill(0); + throw new Error("Text is null"); } else { const response = await this.client.embed({ input: text, diff --git a/src/handlers/add-comments.ts b/src/handlers/add-comments.ts index 0b2644b..b3ccf5d 100644 --- a/src/handlers/add-comments.ts +++ b/src/handlers/add-comments.ts @@ -8,9 +8,10 @@ export async function addComments(context: Context) { adapters: { supabase }, } = context; const { payload } = context as { payload: CommentPayload }; - const markdown = payload.comment.body; - const authorId = payload.comment.user?.id || -1; - const nodeId = payload.comment.node_id; + const comment = payload.comment; + const markdown = comment.body; + const authorId = comment.user?.id || -1; + const nodeId = comment.node_id; const isPrivate = payload.repository.private; const issueId = payload.issue.node_id; @@ -22,16 +23,16 @@ export async function addComments(context: Context) { logger.error("Comment is on a pull request"); } if ((await supabase.issue.getIssue(issueId)) === null) { + logger.info("Parent issue not found, creating new issue"); await addIssue(context); } await supabase.comment.createComment(markdown, nodeId, authorId, payload, isPrivate, issueId); - logger.ok(`Created Comment with id: ${nodeId}`); - logger.ok(`Successfully created comment!`); + logger.ok(`Successfully created comment!`, comment); } catch (error) { if (error instanceof Error) { - logger.error(`Error creating comment:`, { error: error, stack: error.stack }); + logger.error(`Error creating comment:`, { error: error, stack: error.stack, comment: comment }); } else { - logger.error(`Error creating comment:`, { err: error, error: new Error() }); + logger.error(`Error creating comment:`, { err: error, comment: comment }); } } logger.debug(`Exiting addComments`); diff --git a/src/handlers/add-issue.ts b/src/handlers/add-issue.ts index c897021..ea61e21 100644 --- a/src/handlers/add-issue.ts +++ b/src/handlers/add-issue.ts @@ -8,9 +8,10 @@ export async function addIssue(context: Context) { adapters: { supabase }, } = context; const { payload } = context as { payload: IssuePayload }; - const markdown = payload.issue.body + " " + payload.issue.title || null; - const authorId = payload.issue.user?.id || -1; - const nodeId = payload.issue.node_id; + const issue = payload.issue; + const markdown = issue.body + " " + issue.title || null; + const authorId = issue.user?.id || -1; + const nodeId = issue.node_id; const isPrivate = payload.repository.private; try { @@ -20,16 +21,15 @@ export async function addIssue(context: Context) { } const cleanedIssue = removeFootnotes(markdown); await supabase.issue.createIssue(nodeId, payload, isPrivate, cleanedIssue, authorId); + logger.ok(`Successfully created issue!`, issue); } catch (error) { if (error instanceof Error) { - logger.error(`Error creating issue:`, { error: error, stack: error.stack }); + logger.error(`Error creating issue:`, { error: error, issue: issue }); throw error; } else { - logger.error(`Error creating issue:`, { err: error, error: new Error() }); + logger.error(`Error creating issue:`, { err: error, issue: issue }); throw error; } } - - logger.ok(`Successfully created issue!`); logger.debug(`Exiting addIssue`); } diff --git a/src/handlers/delete-comments.ts b/src/handlers/delete-comments.ts index 8c9e394..8122e1b 100644 --- a/src/handlers/delete-comments.ts +++ b/src/handlers/delete-comments.ts @@ -11,16 +11,15 @@ export async function deleteComment(context: Context) { try { await supabase.comment.deleteComment(nodeId); + logger.ok(`Successfully deleted comment! ${payload.comment.id}`, payload.comment); } catch (error) { if (error instanceof Error) { - logger.error(`Error deleting comment:`, { error: error, stack: error.stack }); + logger.error(`Error deleting comment:`, { error: error, stack: error.stack, comment: payload.comment }); throw error; } else { - logger.error(`Error deleting comment:`, { err: error, error: new Error() }); + logger.error(`Error deleting comment:`, { err: error, error: new Error(), comment: payload.comment }); throw error; } } - - logger.ok(`Successfully deleted comment!`); logger.debug(`Exiting deleteComments`); } diff --git a/src/handlers/delete-issue.ts b/src/handlers/delete-issue.ts index b392c69..38e201a 100644 --- a/src/handlers/delete-issue.ts +++ b/src/handlers/delete-issue.ts @@ -11,16 +11,15 @@ export async function deleteIssues(context: Context) { try { await supabase.issue.deleteIssue(nodeId); + logger.ok(`Successfully deleted issue! ${payload.issue.id}`, payload.issue); } catch (error) { if (error instanceof Error) { - logger.error(`Error deleting issue:`, { error: error, stack: error.stack }); + logger.error(`Error deleting issue:`, { error: error, stack: error.stack, issue: payload.issue }); throw error; } else { - logger.error(`Error deleting issue:`, { err: error, error: new Error() }); + logger.error(`Error deleting issue:`, { err: error, issue: payload.issue }); throw error; } } - - logger.ok(`Successfully deleted issue!`); logger.debug(`Exiting deleteIssue`); } diff --git a/src/handlers/issue-matching.ts b/src/handlers/issue-matching.ts index f2e866a..b2ede21 100644 --- a/src/handlers/issue-matching.ts +++ b/src/handlers/issue-matching.ts @@ -134,8 +134,7 @@ export async function issueMatching(context: Context) { } } - logger.ok(`Successfully created issue comment!`); - logger.debug(`Exiting issueMatching handler`); + logger.ok(`Exiting issueMatching handler!`, { similarIssues: similarIssues || "No similar issues found" }); } /** diff --git a/src/handlers/transfer-issue.ts b/src/handlers/transfer-issue.ts index bf92d47..a9998f2 100644 --- a/src/handlers/transfer-issue.ts +++ b/src/handlers/transfer-issue.ts @@ -20,13 +20,15 @@ export async function issueTransfer(context: Context) { try { await supabase.issue.deleteIssue(nodeId); await supabase.issue.createIssue(newIssueNodeId, new_issue, isPrivate, markdown, authorId); + logger.ok(`Successfully transferred issue!`, new_issue); } catch (error) { if (error instanceof Error) { - logger.error(`Error transferring issue:`, { error: error, stack: error.stack }); + logger.error(`Error transferring issue:`, { error: error, stack: error.stack, issue: new_issue }); throw error; } else { - logger.error(`Error transferring issue:`, { err: error, error: new Error() }); + logger.error(`Error transferring issue:`, { err: error, error: new Error(), issue: new_issue }); throw error; } } + logger.debug(`Exiting issueTransfer`); } diff --git a/src/handlers/update-comments.ts b/src/handlers/update-comments.ts index 1a8ff22..bc5fdf5 100644 --- a/src/handlers/update-comments.ts +++ b/src/handlers/update-comments.ts @@ -23,19 +23,20 @@ export async function updateComment(context: Context) { logger.error("Comment is on a pull request"); } if ((await supabase.issue.getIssue(issueId)) === null) { + logger.info("Parent issue not found, creating new issue"); await addIssue(context); } await supabase.comment.updateComment(markdown, nodeId, authorId, payload, isPrivate, issueId); + logger.ok(`Successfully updated comment! ${payload.comment.id}`, payload.comment); } catch (error) { if (error instanceof Error) { - logger.error(`Error updating comment:`, { error: error, stack: error.stack }); + logger.error(`Error updating comment:`, { error: error, stack: error.stack, comment: payload.comment }); throw error; } else { - logger.error(`Error updating comment:`, { err: error, error: new Error() }); + logger.error(`Error updating comment:`, { err: error, comment: payload.comment }); throw error; } } - logger.ok(`Successfully updated comment!`); logger.debug(`Exiting updateComment`); } diff --git a/src/handlers/update-issue.ts b/src/handlers/update-issue.ts index 8fe8fad..5c1b797 100644 --- a/src/handlers/update-issue.ts +++ b/src/handlers/update-issue.ts @@ -22,16 +22,15 @@ export async function updateIssue(context: Context) { //clean issue by removing footnotes const cleanedIssue = removeFootnotes(markdown); await supabase.issue.updateIssue(cleanedIssue, nodeId, payloadObject, isPrivate, authorId); + logger.ok(`Successfully updated issue! ${payload.issue.id}`, payload.issue); } catch (error) { if (error instanceof Error) { - logger.error(`Error updating issue:`, { error: error, stack: error.stack }); + logger.error(`Error updating issue:`, { error: error, stack: error.stack, issue: payload.issue }); throw error; } else { - logger.error(`Error updating issue:`, { err: error, error: new Error() }); + logger.error(`Error updating issue:`, { err: error, issue: payload.issue }); throw error; } } - - logger.ok(`Successfully updated issue!`); logger.debug(`Exiting updateIssue`); }