From 7c3a466d3b367fe58bcd445e19eb99c2f7fbeef9 Mon Sep 17 00:00:00 2001 From: williams-jack Date: Sun, 4 Aug 2024 23:58:43 -0400 Subject: [PATCH 1/3] feat: logging on worker --- worker/orca_grader/__main__.py | 43 +++++++++++++------ .../common/services/push_results.py | 11 +++-- .../common/services/push_status.py | 9 ++-- worker/orca_grader/config.py | 2 +- worker/orca_grader/container/do_grading.py | 22 +++++++--- 5 files changed, 60 insertions(+), 27 deletions(-) diff --git a/worker/orca_grader/__main__.py b/worker/orca_grader/__main__.py index d5e0a86e..9e217d73 100644 --- a/worker/orca_grader/__main__.py +++ b/worker/orca_grader/__main__.py @@ -2,7 +2,9 @@ import concurrent.futures import json import os +import sys import time +import logging from typing import List, Optional import tempfile from subprocess import CalledProcessError @@ -25,6 +27,7 @@ from orca_grader.common.services.push_status import post_job_status_to_client CONTAINER_WORKING_DIR = '/home/orca-grader' +_LOGGER = logging.getLogger(__name__) def run_local_job(job_path: str, no_container: bool, @@ -40,6 +43,7 @@ def process_jobs_from_db(no_container: bool, retriever = PostgresGradingJobRetriever() with GracefulKiller() as killer: with NonBlockingThreadPoolExecutor(max_workers=2) as futures_executor: + _LOGGER.info("Job loop initialized.") stop_future = futures_executor.submit(killer.wait_for_stop_signal) while True: job_retrieval_future = futures_executor.submit( @@ -56,10 +60,11 @@ def process_jobs_from_db(no_container: bool, updated_db_id = reenqueue_job(grading_job) inform_client_of_reenqueue(grading_job, updated_db_id) + _LOGGER.info(f"Reenqueued job with new database id {updated_db_id}.") if job_retrieval_future in done: if job_retrieval_future.exception(): - print(job_retrieval_future.exception()) + _LOGGER.exception("Failed to retrieve grading job from postgres.") time.sleep(1) continue grading_job = job_retrieval_future.result() @@ -75,7 +80,7 @@ def process_jobs_from_db(no_container: bool, response_url=grading_job['response_url'], key=grading_job['key'] ) - print( + _LOGGER.info( f"Pulled job with key {grading_job['key']} and url {grading_job['response_url']}" ) @@ -90,11 +95,15 @@ def process_jobs_from_db(no_container: bool, if stop_future in done and job_execution_future in not_done: updated_db_id = reenqueue_job(grading_job) inform_client_of_reenqueue(grading_job, updated_db_id) + _LOGGER.info(f"Reenqueued job with new database id {updated_db_id}.") + if job_execution_future in done: if type(job_execution_future.exception()) == InvalidWorkerStateException: + _LOGGER.critical("This worker has entered an invaid state " + "due to some number of issues with the container.") exit(1) - print("Job completed.") + _LOGGER.info("Job completed.") clean_up_unused_images() if stop_future in done: @@ -122,14 +131,10 @@ def run_grading_job(grading_job: GradingJobJSON, no_container: bool, else: handle_grading_job(grading_job, container_sha) except Exception as e: - print(e) - if type(e) == CalledProcessError: - print(e.stdout) - print(e.stderr) - if "response_url" in grading_job: - push_results_with_exception(grading_job, e) - else: - print(e) + _LOGGER.debug(e) + if isinstance(e, CalledProcessError): + _LOGGER.debug("STDERR output of subprocess: {e.stderr}") + push_results_with_exception(grading_job, e) # TODO: Would it be more useful to return the result of the job here? @@ -154,6 +159,10 @@ def handle_grading_job(grading_job: GradingJobJSON, container_sha: str | None = builder.add_docker_volume_mapping( temp_job_file.name, container_job_path ) + builder.add_docker_volume_mapping( + os.path.abspath(APP_CONFIG.logging_filepath), + os.path.join(CONTAINER_WORKING_DIR, APP_CONFIG.logging_filepath) + ) # Allows for new code written to the orca_grader.container # module to be automatically picked up while running # during development. @@ -168,10 +177,9 @@ def handle_grading_job(grading_job: GradingJobJSON, container_sha: str | None = executor = builder.build() result = executor.execute() if result and result.stdout: - # TODO: make this a log statement of some sort. - print(result.stdout.decode()) + print(result.stdout.decode(), file=sys.stderr) if result and result.stderr: - print(result.stderr.decode()) + print(result.stderr.decode(), file=sys.stderr) def inform_client_of_reenqueue(grading_job: GradingJobJSON, @@ -189,6 +197,13 @@ def can_execute_job(grading_job: GradingJobJSON) -> bool: if __name__ == "__main__": + logging.basicConfig(level=logging.DEBUG if APP_CONFIG.environment == 'dev' + else logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s', + handlers=[ + logging.FileHandler(filename=APP_CONFIG.logging_filepath), + logging.StreamHandler() + ]) arg_parser = argparse.ArgumentParser( prog="Orca Grader", description="Pulls a job from a Redis queue and executes a script to autograde." diff --git a/worker/orca_grader/common/services/push_results.py b/worker/orca_grader/common/services/push_results.py index 80e38638..9ad499e0 100644 --- a/worker/orca_grader/common/services/push_results.py +++ b/worker/orca_grader/common/services/push_results.py @@ -1,3 +1,4 @@ +import logging import random import time import requests @@ -7,6 +8,7 @@ from orca_grader.common.services.exceptions import PushResultsFailureException from orca_grader.common.types.grading_job_json_types import GradingJobJSON +_LOGGER = logging.getLogger(__name__) _MAX_RETRIES = 5 # TODO: Update if POST data format changes, or simply remove this comment once solidifed. @@ -20,7 +22,6 @@ def push_results_to_response_url(job_result: GradingJobResult, **job_result.to_json(interpolated_dirs=interpolated_dirs), "key": key } - print(result_as_json) _send_results_with_exponential_backoff(result_as_json, response_url) @@ -32,14 +33,18 @@ def push_results_with_exception(grading_job: GradingJobJSON, def _send_results_with_exponential_backoff(payload: dict, response_url: str, n: int = 1): + if n > 1: + _LOGGER.debug("Attempting to retry sending job status. " + f"Retry attempt {n-1}.") try: res = requests.post(response_url, json=payload) res.raise_for_status() + _LOGGER.debug(f"POSTed response to {response_url} with status code {res.status_code}") return res except HTTPError as e: if not _should_retry(e.response.status_code) or n == _MAX_RETRIES: - print(e) - print(f"{e.request.body}, {e.request.headers}") + _LOGGER.error(f"Could not send response to job client" + f"Status Code: {e.response.status_code}.") raise PushResultsFailureException time.sleep(2**n + (random.randint(0, 1000) / 1000.0)) return _send_results_with_exponential_backoff(payload, response_url, n + 1) diff --git a/worker/orca_grader/common/services/push_status.py b/worker/orca_grader/common/services/push_status.py index 2febcb66..31ec4c91 100644 --- a/worker/orca_grader/common/services/push_status.py +++ b/worker/orca_grader/common/services/push_status.py @@ -1,6 +1,9 @@ +import logging import requests from typing import Optional +_LOGGER = logging.getLogger(__name__) + def post_job_status_to_client(location: str, response_url: str, key: str, id: Optional[int] = None) -> None: @@ -13,7 +16,7 @@ def post_job_status_to_client(location: str, response_url: str, json={"key": key, "status": status} ).raise_for_status() except requests.HTTPError as http_e: - print(http_e) - print(f"{http_e.request.body}, {http_e.request.headers}") + _LOGGER.warning("Could not send job status update to client. " + f"Status Code: {http_e.response.status_code}.") except Exception as e: - print(e) + _LOGGER.warning(f"Encountered error when attempting to update job status with client: {e}") diff --git a/worker/orca_grader/config.py b/worker/orca_grader/config.py index 596cfc04..4a2680e0 100644 --- a/worker/orca_grader/config.py +++ b/worker/orca_grader/config.py @@ -17,6 +17,6 @@ def __init__(self) -> None: enable_diagnostics_val = os.getenv('ENABLE_DIAGNOSTICS', '') or "" self.enable_diagnostics = enable_diagnostics_val.lower() == "true" self.environment = os.getenv("ENVIRONMENT", "DEV").lower() - + self.logging_filepath = f"log/{self.environment}.log" APP_CONFIG = AppConfig() diff --git a/worker/orca_grader/container/do_grading.py b/worker/orca_grader/container/do_grading.py index 4be1daf0..e260778b 100644 --- a/worker/orca_grader/container/do_grading.py +++ b/worker/orca_grader/container/do_grading.py @@ -2,8 +2,10 @@ import os import shutil import traceback +import logging from pathlib import Path from typing import Dict, List, TextIO +from orca_grader.config import APP_CONFIG from orca_grader.common.services.push_results import push_results_to_response_url from orca_grader.container.build_script.preprocess.preprocessor import GradingScriptPreprocessor from orca_grader.container.exec_secret import GradingJobExecutionSecret @@ -19,6 +21,9 @@ ) from orca_grader.container.fs_tree import tree +_LOGGER = logging.getLogger("do_grading" if __name__ != '__main__' else + __name__) + def do_grading(secret: str, grading_job_json: GradingJobJSON) -> GradingJobResult: command_responses: List[GradingScriptCommandResponse] = [] @@ -41,17 +46,16 @@ def do_grading(secret: str, grading_job_json: GradingJobJSON) -> GradingJobResul preprocessor = GradingScriptPreprocessor(secret, commands, code_files, code_file_processor) script: GradingScriptCommand = preprocessor.preprocess_job() - print("****Directories and their files:****") + _LOGGER.debug("****Directories and their files:****") for actual_dir in interpolated_dirs.values(): - print(f"{actual_dir}:") + _LOGGER.debug(f"{actual_dir}:") for line in tree(Path(actual_dir)): - print(line) + _LOGGER.debug(line) output: GradingJobResult = script.execute(command_responses) except PreprocessingException as preprocess_e: output = GradingJobResult(command_responses, [preprocess_e]) except Exception as e: output = GradingJobResult(command_responses, [e]) - print(output.to_json(interpolated_dirs=interpolated_dirs)) reverse_interpolated_dirs = {v: k for k, v in interpolated_dirs.items()} push_results_to_response_url(output, grading_job_json["key"], @@ -77,6 +81,13 @@ def cleanup(secret: str) -> None: if __name__ == "__main__": + logging.basicConfig(level=logging.DEBUG if APP_CONFIG.environment == 'dev' + else logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s', + handlers=[ + logging.FileHandler(filename=APP_CONFIG.logging_filepath), + logging.StreamHandler() + ]) secret = GradingJobExecutionSecret.get_secret() try: file_name = os.getenv('GRADING_JOB_FILE_NAME', 'grading_job.json') @@ -84,8 +95,7 @@ def cleanup(secret: str) -> None: grading_job = get_job_from_input_stream(job_json_fp) do_grading(secret, grading_job) except Exception as e: - traceback.print_tb(e.__traceback__) - output = GradingJobResult([], [e.with_traceback(None)]) + output = GradingJobResult([], [e]) push_results_to_response_url(output, grading_job["key"], grading_job["container_response_url"] From 71ee9962d93901c2a8bf6a6b698f1c3e9c2fede7 Mon Sep 17 00:00:00 2001 From: williams-jack Date: Mon, 5 Aug 2024 00:34:21 -0400 Subject: [PATCH 2/3] feat: logging on orchestrator side --- orchestrator/package.json | 3 +- .../controllers/docker-image-controller.ts | 3 +- .../controllers/grading-queue-controller.ts | 15 +- .../packages/api/src/controllers/utils.ts | 12 +- orchestrator/packages/api/src/index.ts | 4 +- orchestrator/packages/common/src/config.ts | 2 + orchestrator/packages/common/src/index.ts | 2 + orchestrator/packages/common/src/logger.ts | 23 +++ .../common/src/utils/push-status-update.ts | 3 +- .../packages/image-build-service/src/index.ts | 13 +- .../packages/image-build-service/src/utils.ts | 6 +- orchestrator/yarn.lock | 144 +++++++++++++++++- 12 files changed, 203 insertions(+), 27 deletions(-) create mode 100644 orchestrator/packages/common/src/logger.ts diff --git a/orchestrator/package.json b/orchestrator/package.json index f009d8f3..b8bd6e01 100644 --- a/orchestrator/package.json +++ b/orchestrator/package.json @@ -17,7 +17,8 @@ "test": "jest" }, "dependencies": { - "concurrently": "^8.2.2" + "concurrently": "^8.2.2", + "pino": "^9.3.2" }, "devDependencies": { "@types/jest": "^29.5.12", diff --git a/orchestrator/packages/api/src/controllers/docker-image-controller.ts b/orchestrator/packages/api/src/controllers/docker-image-controller.ts index a9c8c702..72d8d149 100644 --- a/orchestrator/packages/api/src/controllers/docker-image-controller.ts +++ b/orchestrator/packages/api/src/controllers/docker-image-controller.ts @@ -2,6 +2,7 @@ import { Request, Response } from "express"; import { errorResponse } from "./utils"; import { graderImageExists, + logger, validations, } from "@codegrade-orca/common"; import { GradingQueueOperationException, enqueueImageBuild, imageIsAwaitingBuild, imageIsBeingBuilt } from "@codegrade-orca/db"; @@ -20,10 +21,10 @@ export const createGraderImage = async (req: Request, res: Response) => { await enqueueImageBuild(req.body); return res.status(200).json({ message: "OK" }); } catch (error) { - console.error(error); if (error instanceof GradingQueueOperationException) { return errorResponse(res, 400, [error.message]); } else { + logger.error(`Could not enqueue image build; ${error}`); return errorResponse(res, 500, [ "An error occured while trying to enqueue the image build request. Please contact an admin.", ]); diff --git a/orchestrator/packages/api/src/controllers/grading-queue-controller.ts b/orchestrator/packages/api/src/controllers/grading-queue-controller.ts index 3a8c1e30..c66328bd 100644 --- a/orchestrator/packages/api/src/controllers/grading-queue-controller.ts +++ b/orchestrator/packages/api/src/controllers/grading-queue-controller.ts @@ -12,6 +12,7 @@ import { filterGradingJobs, getFilterInfo, getGradingQueueStats, + logger, validations, } from "@codegrade-orca/common"; import { @@ -22,6 +23,7 @@ import { getJobStatus } from "@codegrade-orca/db"; import { describeReleaseTiming, reservationWaitingOnRelease } from "../utils/helpers"; +import url export const getGradingJobs = async (req: Request, res: Response) => { if ( @@ -94,7 +96,6 @@ export const getGradingJobs = async (req: Request, res: Response) => { filter_info: filterInfo, }); } catch (err) { - console.error(err); if (err instanceof GradingQueueOperationException) { return errorResponse(res, 400, [err.message]); } @@ -111,20 +112,17 @@ export const createOrUpdateImmediateJob = async ( if (!validations.gradingJobConfig(req.body)) { return errorResponse(res, 400, ["Invalid grading job configuration."]); } - const gradingJobConfig = req.body; - try { - // TODO: Return job id from db operation and in response obj const status = await putJobInQueue(req.body, true); + logger.info(`New job from ${new URL(req.body.response_url).host} sent to ${status.location} with database id ${status.id}.`); return res.status(200).json({ message: "OK", status }); } catch (error) { - console.error(error); if (error instanceof GradingQueueOperationException) { return errorResponse(res, 400, [error.message]); } return errorResponse(res, 500, [ "An error occurred while trying to create an immediate job or update an " + - `existing one for ${gradingJobConfig.collation.type} with ID ${gradingJobConfig.collation.id}.`, + `existing one for ${req.body.collation.type} with ID ${req.body.collation.id}.`, ]); } }; @@ -133,13 +131,11 @@ export const createOrUpdateJob = async (req: Request, res: Response) => { if (!validations.gradingJobConfig(req.body)) { return errorResponse(res, 400, ["The given grading job was invalid."]); } - try { - // TODO: Return job id from db operation and in response obj const status = await putJobInQueue(req.body, false); + logger.info(`New job from ${new URL(req.body.response_url).host} sent to ${status.location} with database id ${status.id}.`); return res.status(200).json({ message: "OK", status }); } catch (err) { - console.error(err); if (err instanceof GradingQueueOperationException) { return errorResponse(res, 400, [err.message]); } else { @@ -170,6 +166,7 @@ export const deleteJob = async (req: Request, res: Response) => { } const deletedJob = await deleteJobInQueue(jobID); const deletedJobConfig = deletedJob.config as object as GradingJobConfig; + logger.info(`Deleted job from ${new URL(deletedJobConfig.response_url).host} with former id ${jobID}.`); notifyClientOfCancelledJob(deletedJobConfig) return res.status(200).json({ message: "OK" }); } catch (err) { diff --git a/orchestrator/packages/api/src/controllers/utils.ts b/orchestrator/packages/api/src/controllers/utils.ts index 169f7f32..4cd28013 100644 --- a/orchestrator/packages/api/src/controllers/utils.ts +++ b/orchestrator/packages/api/src/controllers/utils.ts @@ -1,4 +1,4 @@ -import { GradingJobConfig, GradingJobResult } from "@codegrade-orca/common"; +import { GradingJobConfig, GradingJobResult, logger } from "@codegrade-orca/common"; import { Response } from "express"; export const errorResponse = ( @@ -6,15 +6,21 @@ export const errorResponse = ( status: number, errors: string[], ) => { + if (isClientError(status)) { + logger.warn(errors.join(', ')); + } else { + logger.error(errors.join(', ')); + } return res.status(status).json({ errors: errors }); }; +const isClientError = (statusCode: number): boolean => statusCode > 399 && statusCode < 500; + export const notifyClientOfCancelledJob = (jobConfig: GradingJobConfig) => { const result: GradingJobResult = { shell_responses: [], errors: ["Job cancelled by a course professor or Orca admin."] }; - console.info(jobConfig.response_url); fetch(jobConfig.response_url, { method: "POST", headers: { @@ -23,7 +29,7 @@ export const notifyClientOfCancelledJob = (jobConfig: GradingJobConfig) => { }, body: JSON.stringify({ ...result, key: jobConfig.key }) }).catch((err) => - console.error( + logger.error( `Encountered the following error while attempting to notify client of Job cancellation: ${err}` )); } diff --git a/orchestrator/packages/api/src/index.ts b/orchestrator/packages/api/src/index.ts index 758fe716..a3bc3cd2 100644 --- a/orchestrator/packages/api/src/index.ts +++ b/orchestrator/packages/api/src/index.ts @@ -1,7 +1,7 @@ import { Express } from "express"; import gradingQueueRouter from "./routes/grading-queue"; import { existsSync, mkdirSync } from "fs"; -import { getConfig } from "@codegrade-orca/common"; +import { getConfig, logger } from "@codegrade-orca/common"; import express = require("express"); import cors = require("cors"); import dockerImagesRouter from "./routes/docker-images"; @@ -23,5 +23,5 @@ app.listen(PORT, () => { if (!existsSync(CONFIG.dockerImageFolder)) { mkdirSync(CONFIG.dockerImageFolder); } - console.info(`Server listening on port ${PORT}`); + logger.info(`Server listening on port ${PORT}`); }); diff --git a/orchestrator/packages/common/src/config.ts b/orchestrator/packages/common/src/config.ts index 5ee7acc1..1561700e 100644 --- a/orchestrator/packages/common/src/config.ts +++ b/orchestrator/packages/common/src/config.ts @@ -4,6 +4,7 @@ export interface OrchestratorConfig { api: OrchestratorAPIOptions; dockerImageFolder: string; postgresURL: string; + environment: string; } interface OrchestratorAPIOptions { @@ -16,4 +17,5 @@ export const getConfig = (): OrchestratorConfig => ({ port: process.env.API_PORT ? parseInt(process.env.API_PORT) : 8090, }, dockerImageFolder: join(__dirname, "../../../", "images"), + environment: process.env.ENVIRONMENT?.toLowerCase() || 'dev' }); diff --git a/orchestrator/packages/common/src/index.ts b/orchestrator/packages/common/src/index.ts index 2ce785d2..478dba14 100644 --- a/orchestrator/packages/common/src/index.ts +++ b/orchestrator/packages/common/src/index.ts @@ -1,5 +1,6 @@ import path from "path"; import { getConfig } from "./config"; +import logger from "./logger"; import validations from "./validations"; import { existsSync } from "fs"; @@ -8,6 +9,7 @@ export * from "./types"; export * from "./config"; export * from "./utils"; export { validations }; +export { logger }; export const toMilliseconds = (seconds: number) => seconds * 1_000; export const imageWithSHAExists = (dockerfileSHASum: string): boolean => { diff --git a/orchestrator/packages/common/src/logger.ts b/orchestrator/packages/common/src/logger.ts new file mode 100644 index 00000000..17a57d6b --- /dev/null +++ b/orchestrator/packages/common/src/logger.ts @@ -0,0 +1,23 @@ +import pino, { destination } from "pino"; +import { getConfig } from "./config"; +import path from "path"; + +const transport = pino.transport({ + targets: [ + { + target: 'pino/file', + options: { destination: path.join(__dirname, '../../../', 'logs', `${getConfig().environment}.log`) } + }, + { + target: 'pino/file', + options: { destination: 2 } + } + ] +}); + +const logger = pino({ + level: getConfig().environment === 'production' ? 'info' : 'debug', + timestamp: true, +}, transport); + +export default logger; diff --git a/orchestrator/packages/common/src/utils/push-status-update.ts b/orchestrator/packages/common/src/utils/push-status-update.ts index 6faaf16a..b607d110 100644 --- a/orchestrator/packages/common/src/utils/push-status-update.ts +++ b/orchestrator/packages/common/src/utils/push-status-update.ts @@ -1,3 +1,4 @@ +import logger from "../logger"; import { JobStatus } from "../types"; export const pushStatusUpdate = async (status: JobStatus, responseURL: string, key: string): Promise => { @@ -7,6 +8,6 @@ export const pushStatusUpdate = async (status: JobStatus, responseURL: string, k const body = JSON.stringify({ key, status }); await fetch(responseURL, { body, method: 'POST', headers: { 'Content-Type': 'application/json' } }); } catch (err) { - console.error(`Could not POST status update to ${responseURL}; ${err instanceof Error ? err.message : err}`); + logger.warn(`Could not POST status update to ${responseURL}; ${err instanceof Error ? err.message : err}`); } }; diff --git a/orchestrator/packages/image-build-service/src/index.ts b/orchestrator/packages/image-build-service/src/index.ts index 8a3afd87..5e31f3be 100644 --- a/orchestrator/packages/image-build-service/src/index.ts +++ b/orchestrator/packages/image-build-service/src/index.ts @@ -4,7 +4,8 @@ import { isImageBuildResult, pushStatusUpdate, getConfig, - GraderImageBuildResult + GraderImageBuildResult, + logger } from "@codegrade-orca/common"; import { getNextImageBuild, handleCompletedImageBuild } from "@codegrade-orca/db"; import { createAndStoreGraderImage, removeStaleImageFiles } from "./process-request"; @@ -16,7 +17,7 @@ import { existsSync, rmSync } from "fs"; const LOOP_SLEEP_TIME = 5; // Seconds const main = async () => { - console.info("Cleaning up stale build info..."); + logger.info("Cleaning up stale build info..."); const shaSumJobInfoPairs = await cleanStaleBuildInfo(); shaSumJobInfoPairs.forEach(([originalReq, enqueuedJobs]) => { removeDockerfileIfExists(originalReq.dockerfile_sha_sum); @@ -25,7 +26,7 @@ const main = async () => { ({ response_url, key, ...status }) => pushStatusUpdate(status, response_url, key) ); }); - console.info("Build service initialized."); + logger.info("Build service initialized."); while (true) { let infoAsBuildReq: GraderImageBuildRequest | undefined = undefined; try { @@ -36,7 +37,7 @@ const main = async () => { continue; } - console.info(`Attempting to build image with SHA ${nextBuildReq.dockerfileSHA}.`); + logger.info(`Attempting to build image with SHA ${nextBuildReq.dockerfileSHA}.`); infoAsBuildReq = { dockerfile_sha_sum: nextBuildReq.dockerfileSHA, @@ -49,7 +50,7 @@ const main = async () => { notifyClientOfBuildResult(result, infoAsBuildReq); jobInfo.forEach(({ key, response_url, ...status }) => pushStatusUpdate(status, response_url, key)); - console.info(`Successfully built image with SHA ${nextBuildReq.dockerfileSHA}.`); + logger.info(`Successfully built image with SHA ${nextBuildReq.dockerfileSHA}.`); } catch (err) { if (isImageBuildResult(err) && infoAsBuildReq) { const cancelledJobInfoList = await handleCompletedImageBuild(infoAsBuildReq.dockerfile_sha_sum, false); @@ -59,7 +60,7 @@ const main = async () => { notifyClientOfBuildResult(err, infoAsBuildReq); await cleanUpDockerFiles(infoAsBuildReq.dockerfile_sha_sum); } - console.error(err); + logger.error(`Encountered during image build: ${err}.`); } finally { if (infoAsBuildReq) { await removeImageFromDockerIfExists(infoAsBuildReq.dockerfile_sha_sum); diff --git a/orchestrator/packages/image-build-service/src/utils.ts b/orchestrator/packages/image-build-service/src/utils.ts index 47fad6c8..65fcb88d 100644 --- a/orchestrator/packages/image-build-service/src/utils.ts +++ b/orchestrator/packages/image-build-service/src/utils.ts @@ -1,4 +1,4 @@ -import { GraderImageBuildRequest, GraderImageBuildResult, GradingJobResult, getConfig } from "@codegrade-orca/common"; +import { GraderImageBuildRequest, GraderImageBuildResult, GradingJobResult, getConfig, logger } from "@codegrade-orca/common"; import { CancelJobInfo } from "@codegrade-orca/db/dist/image-builder-operations/handle-completed-image-build"; import { execFile } from "child_process"; import { existsSync, rmSync } from "fs"; @@ -59,7 +59,7 @@ export const sendJobResultForBuildFail = (cancelInfo: CancelJobInfo) => { "Content-Type": "application/json" }, body: JSON.stringify({ ...result, key: cancelInfo.key }) - }).catch((err) => console.error(err)); + }).catch((err) => logger.error(`Could not update client on job result; ${err}`)); } export const notifyClientOfBuildResult = (result: GraderImageBuildResult, originalReq: GraderImageBuildRequest) => { @@ -71,5 +71,5 @@ export const notifyClientOfBuildResult = (result: GraderImageBuildResult, origin "Content-Type": "application/json" }, body: JSON.stringify(result) - }).catch((err) => console.error(err)); + }).catch((err) => logger.error(`Encountered the following error when sending result to ${response_url}: ${err}`)); } diff --git a/orchestrator/yarn.lock b/orchestrator/yarn.lock index ba4d7a69..0035af80 100644 --- a/orchestrator/yarn.lock +++ b/orchestrator/yarn.lock @@ -819,6 +819,13 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -911,6 +918,11 @@ array-flatten@1.1.1: resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== +atomic-sleep@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" + integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== + babel-jest@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5" @@ -976,6 +988,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + binary-extensions@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" @@ -1043,6 +1060,14 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + bytes@3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" @@ -1371,6 +1396,16 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + +events@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" + integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== + execa@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" @@ -1449,6 +1484,11 @@ fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.1.0: resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-redact@^3.1.1: + version "3.5.0" + resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.5.0.tgz#e9ea02f7e57d0cd8438180083e93077e496285e4" + integrity sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A== + fb-watchman@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" @@ -1622,6 +1662,11 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +ieee754@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + ignore-by-default@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" @@ -2377,6 +2422,11 @@ object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== +on-exit-leak-free@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz#fed195c9ebddb7d9e4c3842f93f281ac8dadd3b8" + integrity sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA== + on-finished@2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" @@ -2474,6 +2524,36 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pino-abstract-transport@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pino-abstract-transport/-/pino-abstract-transport-1.2.0.tgz#97f9f2631931e242da531b5c66d3079c12c9d1b5" + integrity sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q== + dependencies: + readable-stream "^4.0.0" + split2 "^4.0.0" + +pino-std-serializers@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-7.0.0.tgz#7c625038b13718dbbd84ab446bd673dc52259e3b" + integrity sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA== + +pino@^9.3.2: + version "9.3.2" + resolved "https://registry.yarnpkg.com/pino/-/pino-9.3.2.tgz#a530d6d28f1d954b6f54416a218cbb616f52f901" + integrity sha512-WtARBjgZ7LNEkrGWxMBN/jvlFiE17LTbBoH0konmBU684Kd0uIiDwBXlcTCW7iJnA6HfIKwUssS/2AC6cDEanw== + dependencies: + atomic-sleep "^1.0.0" + fast-redact "^3.1.1" + on-exit-leak-free "^2.1.0" + pino-abstract-transport "^1.2.0" + pino-std-serializers "^7.0.0" + process-warning "^4.0.0" + quick-format-unescaped "^4.0.3" + real-require "^0.2.0" + safe-stable-stringify "^2.3.1" + sonic-boom "^4.0.1" + thread-stream "^3.0.0" + pirates@^4.0.4: version "4.0.6" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9" @@ -2502,6 +2582,16 @@ prisma@^5.11.0: dependencies: "@prisma/engines" "5.11.0" +process-warning@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/process-warning/-/process-warning-4.0.0.tgz#581e3a7a1fb456c5f4fd239f76bce75897682d5a" + integrity sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A== + prompts@^2.0.1: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" @@ -2540,6 +2630,11 @@ qs@6.11.0: dependencies: side-channel "^1.0.4" +quick-format-unescaped@^4.0.3: + version "4.0.4" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz#93ef6dd8d3453cbc7970dd614fad4c5954d6b5a7" + integrity sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg== + range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -2560,6 +2655,17 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== +readable-stream@^4.0.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.5.2.tgz#9e7fc4c45099baeed934bff6eb97ba6cf2729e09" + integrity sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g== + dependencies: + abort-controller "^3.0.0" + buffer "^6.0.3" + events "^3.3.0" + process "^0.11.10" + string_decoder "^1.3.0" + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -2567,6 +2673,11 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +real-require@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/real-require/-/real-require-0.2.0.tgz#209632dea1810be2ae063a6ac084fee7e33fba78" + integrity sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg== + regenerator-runtime@^0.14.0: version "0.14.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" @@ -2615,11 +2726,16 @@ rxjs@^7.8.1: dependencies: tslib "^2.1.0" -safe-buffer@5.2.1: +safe-buffer@5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-stable-stringify@^2.3.1: + version "2.4.3" + resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" + integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== + "safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -2719,6 +2835,13 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== +sonic-boom@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-4.0.1.tgz#515b7cef2c9290cb362c4536388ddeece07aed30" + integrity sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ== + dependencies: + atomic-sleep "^1.0.0" + source-map-support@0.5.13: version "0.5.13" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.13.tgz#31b24a9c2e73c2de85066c0feb7d44767ed52932" @@ -2737,6 +2860,11 @@ spawn-command@0.0.2: resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2.tgz#9544e1a43ca045f8531aac1a48cb29bdae62338e" integrity sha512-zC8zGoGkmc8J9ndvml8Xksr1Amk9qBujgbF0JAIWO7kXr43w0h/0GJNM/Vustixu+YE8N/MTrQ7N31FvHUACxQ== +split2@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.2.0.tgz#c9c5920904d148bab0b9f67145f245a86aadbfa4" + integrity sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg== + sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" @@ -2771,6 +2899,13 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string_decoder@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -2833,6 +2968,13 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +thread-stream@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/thread-stream/-/thread-stream-3.1.0.tgz#4b2ef252a7c215064507d4ef70c05a5e2d34c4f1" + integrity sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A== + dependencies: + real-require "^0.2.0" + tmpl@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" From d9102491c1851e8ba976862e8db6e542bdaa874a Mon Sep 17 00:00:00 2001 From: williams-jack Date: Mon, 5 Aug 2024 00:35:28 -0400 Subject: [PATCH 3/3] fix: typo causing compile error fix: mkdir for log if not exists by setting opt --- .../api/src/controllers/grading-queue-controller.ts | 1 - orchestrator/packages/common/src/logger.ts | 7 +++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/orchestrator/packages/api/src/controllers/grading-queue-controller.ts b/orchestrator/packages/api/src/controllers/grading-queue-controller.ts index c66328bd..3287a9e2 100644 --- a/orchestrator/packages/api/src/controllers/grading-queue-controller.ts +++ b/orchestrator/packages/api/src/controllers/grading-queue-controller.ts @@ -23,7 +23,6 @@ import { getJobStatus } from "@codegrade-orca/db"; import { describeReleaseTiming, reservationWaitingOnRelease } from "../utils/helpers"; -import url export const getGradingJobs = async (req: Request, res: Response) => { if ( diff --git a/orchestrator/packages/common/src/logger.ts b/orchestrator/packages/common/src/logger.ts index 17a57d6b..1983a216 100644 --- a/orchestrator/packages/common/src/logger.ts +++ b/orchestrator/packages/common/src/logger.ts @@ -1,4 +1,4 @@ -import pino, { destination } from "pino"; +import pino from "pino"; import { getConfig } from "./config"; import path from "path"; @@ -6,7 +6,10 @@ const transport = pino.transport({ targets: [ { target: 'pino/file', - options: { destination: path.join(__dirname, '../../../', 'logs', `${getConfig().environment}.log`) } + options: { + destination: path.join(__dirname, '../../../', 'logs', `${getConfig().environment}.log`), + mkdir: true + } }, { target: 'pino/file',