Skip to content

Commit

Permalink
feat: use tslog for logging
Browse files Browse the repository at this point in the history
  • Loading branch information
gowoons committed Aug 1, 2023
1 parent 6200060 commit 4d287ff
Show file tree
Hide file tree
Showing 16 changed files with 69 additions and 28 deletions.
17 changes: 17 additions & 0 deletions package-lock.json

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

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"inquirer": "^9.2.8",
"langchain": "^0.0.103",
"ts-retry": "^4.2.1",
"tslog": "^4.8.2",
"yargs": "^17.7.2"
},
"devDependencies": {
Expand Down
5 changes: 3 additions & 2 deletions src/common/ci/commentOnPR.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { context, getOctokit } from "@actions/github";
import { getToken } from "./utils";
import { logger } from "../utils/logger";

/**
* Publish a comment on the pull request. If the bot has already commented (i.e. a comment with the same sign off exists), update the comment instead of creating a new one.
Expand All @@ -14,7 +15,7 @@ export const commentOnPR = async (comment: string, signOff: string) => {
const { payload, issue } = context;

if (!payload.pull_request) {
console.warn("Not a pull request. Skipping commenting on PR...");
logger.warn("Not a pull request. Skipping commenting on PR...");
return;
}

Expand Down Expand Up @@ -50,7 +51,7 @@ export const commentOnPR = async (comment: string, signOff: string) => {
});
}
} catch (error) {
console.error(`Failed to comment on PR: ${error}`);
logger.error(`Failed to comment on PR: ${error}`);
throw error;
}
};
5 changes: 3 additions & 2 deletions src/common/ci/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { getGitHubEnvVariables } from "../../config";
import { context, getOctokit } from "@actions/github";
import { IFeedback } from "../../review/llm/feedbackProcessor";
import { logger } from "../utils/logger";

export const getRelativePath = (fileName: string, repoName: string): string => {
const repoIndex = fileName.lastIndexOf(repoName);
Expand All @@ -25,7 +26,7 @@ export const getOctokitRepoDetails = () => {
const { payload, issue } = context;

if (!payload.pull_request) {
console.warn("Not a pull request. Skipping commenting on PR...");
logger.warn("Not a pull request. Skipping commenting on PR...");
return;
}
const octokit = getOctokit(githubToken);
Expand Down Expand Up @@ -72,7 +73,7 @@ export const commentOnFile = async (
});
}
} catch (error) {
console.error(
logger.error(
`Failed to comment on PR for feedback: ${data.feedback.details}. Error: ${error}`
);
}
Expand Down
3 changes: 2 additions & 1 deletion src/common/model/AIModel.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { OpenAIChat } from "langchain/llms/openai";
import { retryAsync } from "ts-retry";
import { logger } from "../utils/logger";

interface IAIModel {
modelName: string;
Expand Down Expand Up @@ -36,7 +37,7 @@ class AIModel {
{
maxTry: this.retryCount,
onError: (error) => {
console.error(`Error in callModelJSON`, error);
logger.error(`Error in callModelJSON`, error);
},
onMaxRetryFunc: () => {
throw new Error(
Expand Down
5 changes: 5 additions & 0 deletions src/common/utils/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { Logger } from "tslog";

export const logger = new Logger({
prettyLogTemplate: "{{logLevelName}}\t",
});
4 changes: 3 additions & 1 deletion src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ In CI:
* GITHUB_TOKEN
*/

import { logger } from "./common/utils/logger";

export const openAIApiKey = (): string => {
if (!process.env.OPENAI_API_KEY) {
throw new Error("OPENAI_API_KEY is not set");
Expand All @@ -18,7 +20,7 @@ export const getGitHubEnvVariables = (): Record<string, string> => {
(varName) => !process.env[varName]
);
if (missingVars.length > 0) {
console.error(`Missing environment variables: ${missingVars.join(", ")}`);
logger.error(`Missing environment variables: ${missingVars.join(", ")}`);
throw new Error("One or more GitHub environment variables are not set");
}
return {
Expand Down
9 changes: 5 additions & 4 deletions src/configure/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import fs from "fs";
import path from "path";
import { execSync } from "child_process";
import { logger } from "../common/utils/logger";

export const configure = async () => {
const workflowContent = fs.readFileSync(
Expand All @@ -14,7 +15,7 @@ export const configure = async () => {
const workflowFile = path.join(workflowsDir, "code-review-gpt.yml");
fs.writeFileSync(workflowFile, workflowContent, "utf8");

console.log(`Created GitHub Actions workflow at: ${workflowFile}`);
logger.info(`Created GitHub Actions workflow at: ${workflowFile}`);

const inquirer = await import("inquirer");
const { apiKey } = await inquirer.default.prompt([
Expand All @@ -26,7 +27,7 @@ export const configure = async () => {
]);

if (!apiKey) {
console.log(
logger.error(
"No API key provided. Please manually add the OPENAI_API_KEY secret to your GitHub repository."
);
return;
Expand All @@ -35,11 +36,11 @@ export const configure = async () => {
try {
execSync(`gh auth status || gh auth login`, { stdio: "inherit" });
execSync(`gh secret set OPENAI_API_KEY --body=${apiKey}`);
console.log(
logger.info(
"Successfully added the OPENAI_API_KEY secret to your GitHub repository."
);
} catch (error) {
console.log(
logger.error(
"It seems that the GitHub CLI is not installed or there was an error during authentication. Don't forget to add the OPENAI_API_KEY to the repo settings/Environment/Actions/Repository Secrets manually."
);
}
Expand Down
5 changes: 3 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import dotenv from "dotenv";
import { getYargs } from "./args";
import { logger } from "./common/utils/logger";

dotenv.config();

Expand All @@ -24,12 +25,12 @@ const main = async () => {
await test(argv);
break;
default:
console.error("Unknown command");
logger.error("Unknown command");
process.exit(1);
}
};

main().catch((error) => {
console.error(`Error: ${error}`);
logger.error(`Error: ${error}`);
process.exit(1);
});
9 changes: 7 additions & 2 deletions src/review/llm/askAI.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { openAIApiKey } from "../../config";
import AIModel from "../../common/model/AIModel";
import { createSummary, processFeedbacks, IFeedback } from "./feedbackProcessor";
import {
createSummary,
processFeedbacks,
IFeedback,
} from "./feedbackProcessor";
import { generateMarkdownReport } from "./generateMarkdownReport";
import { logger } from "../../common/utils/logger";

type AskAIResponse = {
markdownReport: string;
Expand All @@ -14,7 +19,7 @@ export const askAI = async (
verbose = true
): Promise<AskAIResponse> => {
if (verbose) {
console.info("Asking the experts...");
logger.error("Asking the experts...");
}

const model = new AIModel({
Expand Down
7 changes: 4 additions & 3 deletions src/review/llm/feedbackProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { maxFeedbackCount } from "../constants";
import { completionPrompt } from "../prompt/prompts";
import PriorityQueue from "./PriorityQueue";
import { formatFeedbacks } from "./generateMarkdownReport";
import { logger } from "../../common/utils/logger";

export interface IFeedback {
fileName: string;
Expand All @@ -17,7 +18,7 @@ const collectAndLogFeedback = async (
const feedbacks = await feedbackPromise;
return feedbacks;
} catch (error) {
console.error(`Error in processing prompt`, error);
logger.error(`Error in processing prompt`, error);
throw error;
}
};
Expand All @@ -35,7 +36,7 @@ const createSummary = async (
const summary = await model.callModel(finalPrompt);

if (verbose) {
console.log(summary);
logger.info(summary);
}

return summary;
Expand Down Expand Up @@ -95,7 +96,7 @@ const processFeedbacks = async (
const bestFeedbacks = await pickBestFeedbacks(feedbacks, maxFeedbackCount);

if (verbose) {
console.log(formatFeedbacks(bestFeedbacks));
logger.info(formatFeedbacks(bestFeedbacks));
}

return bestFeedbacks;
Expand Down
3 changes: 2 additions & 1 deletion src/review/prompt/constructPrompt/constructPrompt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { makeSlimmedFile } from "../makeSlimmedFile";
import { instructionPrompt } from "../prompts";
import { File } from "../../../common/types";
import { ReviewFile } from "../types";
import { logger } from "../../../common/utils/logger";

const getSizeOfReviewFile = (file: ReviewFile): number =>
file.fileName.length + file.fileContent.length;
Expand All @@ -16,7 +17,7 @@ const splitFilesIntoBatches = async (
for (const file of files) {
const currentFileSize = getSizeOfReviewFile(file);
if (currentFileSize > maxBatchSize) {
console.warn(
logger.warn(
`File ${file.fileName} is larger than the max prompt length, consider using a model with a larger context window. Attempting to slim the file...`
);
const slimmedFile = await makeSlimmedFile(file, maxBatchSize);
Expand Down
5 changes: 3 additions & 2 deletions src/review/prompt/makeSlimmedFile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { getLanguageOfFile } from "./getLanguageOfFile";
import { slimmedContextPrompt } from "./prompts";
import { ReviewFile } from "./types";
import { File } from "../../common/types";
import { logger } from "../../common/utils/logger";

export const makeSlimmedFile = async (
file: File,
Expand All @@ -13,7 +14,7 @@ export const makeSlimmedFile = async (
let changedLines: string = file.changedLines;

if (changedLines.length > maxBatchSize) {
console.error(
logger.error(
`The changed lines are ${changedLines.length} which is longer than ${maxBatchSize}. Consider using a model with a larger context window. Slicing the changed lines...`
);
changedLines = changedLines.slice(0, maxBatchSize);
Expand Down Expand Up @@ -49,7 +50,7 @@ export const makeSlimmedFile = async (
.join("\n");

if (context.length > maxBatchSize) {
console.error(
logger.error(
`The context of the changed lines is ${context.length} which is longer than ${maxBatchSize}. Consider using a model with a larger context window. Slicing the context...`
);
context = context.slice(0, maxBatchSize);
Expand Down
5 changes: 3 additions & 2 deletions src/test/load/loadTestCases.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { readFileSync, readdirSync } from "fs";
import path from "path";
import { TestCase } from "../types";
import { logger } from "../../common/utils/logger";

/**
* Load a single test case defined in a JSON file.
Expand All @@ -12,7 +13,7 @@ const loadTestCase = (testCasePath: string): TestCase => {
const fileData = readFileSync(testCasePath, "utf8");
return JSON.parse(fileData) as TestCase;
} catch (error) {
console.error(`Error loading test case: ${testCasePath}`);
logger.error(`Error loading test case: ${testCasePath}`);
throw error;
}
};
Expand All @@ -30,7 +31,7 @@ export const loadTestCases = (testCasesDir: string): TestCase[] => {

return testFiles.map((file) => loadTestCase(path.join(testCasesDir, file)));
} catch (error) {
console.error(`Error loading test cases from: ${testCasesDir}`);
logger.error(`Error loading test cases from: ${testCasesDir}`);
throw error;
}
};
3 changes: 2 additions & 1 deletion src/test/load/loadTestCodeSnippets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import AIModel from "../../common/model/AIModel";
import { generateCodeSnippetsPrompt } from "../constants";
import { TestCase } from "../types";
import { generateHash } from "./hash";
import { logger } from "../../common/utils/logger";

/**
* Generate a code snippet for a test case.
Expand Down Expand Up @@ -51,7 +52,7 @@ const loadOrGenerateCodeSnippet = async (
snippet: { fileName, fileContent, changedLines: fileContent },
};
} catch (error) {
console.info(
logger.info(
`Snippet not found in cache: ${testCase.name}. Generating it...`
);
// If the snippet is not found, generate it
Expand Down
11 changes: 6 additions & 5 deletions src/test/run/runTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
generateTestResultsSummary,
testResult,
} from "./generateTestReport";
import { logger } from "../../common/utils/logger";

/**
* Run a single test case.
Expand All @@ -28,7 +29,7 @@ const runTest = async (
throw new Error(`Test case ${testCase.name} does not have a snippet.`);
}

console.info(chalk.blue(`Running test case ${testCase.name}...`));
logger.info(chalk.blue(`Running test case ${testCase.name}...`));

// First step: run the review on the code snippet.
const prompts = await constructPromptsArray(
Expand Down Expand Up @@ -60,7 +61,7 @@ const runTest = async (
similarity
);

console.log(report);
logger.info(report);

return result;
};
Expand All @@ -84,7 +85,7 @@ export const runTests = async (
return "No test cases found.";
}

console.info(`Running ${testCases.length} test cases...\n`);
logger.info(`Running ${testCases.length} test cases...\n`);

// Keep track of all test results.
const testResults: { [key: string]: testResult } = {};
Expand All @@ -100,12 +101,12 @@ export const runTests = async (
);
testResults[testCase.name] = result;
} catch (error) {
console.error(`Error running test case ${testCase.name}:`, error);
logger.error(`Error running test case ${testCase.name}:`, error);
}
}
const testSummary = generateTestResultsSummary(testResults);

console.info(testSummary);
logger.info(testSummary);

return testSummary;
};

0 comments on commit 4d287ff

Please sign in to comment.