diff --git a/analytics/package.json b/analytics/package.json index e966567..81e470c 100644 --- a/analytics/package.json +++ b/analytics/package.json @@ -22,6 +22,7 @@ "dotenv": "^16.4.7", "glob": "^11.0.0", "octokit": "^4.0.2", + "pino": "^9.5.0", "typescript": "^5.7.2" }, "devDependencies": { diff --git a/analytics/pnpm-lock.yaml b/analytics/pnpm-lock.yaml index 25f40df..bff539e 100644 --- a/analytics/pnpm-lock.yaml +++ b/analytics/pnpm-lock.yaml @@ -23,6 +23,9 @@ importers: octokit: specifier: ^4.0.2 version: 4.0.2 + pino: + specifier: ^9.5.0 + version: 9.5.0 typescript: specifier: ^5.7.2 version: 5.7.2 @@ -371,6 +374,10 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -511,6 +518,10 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-redact@3.5.0: + resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} + engines: {node: '>=6'} + fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -663,6 +674,10 @@ packages: resolution: {integrity: sha512-wbqF4uc1YbcldtiBFfkSnquHtECEIpYD78YUXI6ri1Im5OO2NLo6ZVpRdbJpdnpZ05zMrVPssNiEo6JQtea+Qg==} engines: {node: '>= 18'} + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -698,10 +713,23 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + + pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} + + pino@9.5.0: + resolution: {integrity: sha512-xSEmD4pLnV54t0NOUN16yCl7RIB1c5UUOse5HSyEXtBp+FgFQyPeDutc+Q2ZO7/22vImV7VfEjH/1zV2QuqvYw==} + hasBin: true + prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} + process-warning@4.0.0: + resolution: {integrity: sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==} + punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} @@ -709,6 +737,13 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -720,6 +755,10 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + semver@7.6.3: resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} engines: {node: '>=10'} @@ -737,6 +776,13 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + sonic-boom@4.2.0: + resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} + + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -761,6 +807,9 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} + thread-stream@3.1.0: + resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -1214,6 +1263,8 @@ snapshots: argparse@2.0.1: {} + atomic-sleep@1.0.0: {} + balanced-match@1.0.2: {} before-after-hook@3.0.2: {} @@ -1360,6 +1411,8 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-redact@3.5.0: {} + fastq@1.17.1: dependencies: reusify: 1.0.4 @@ -1504,6 +1557,8 @@ snapshots: '@octokit/request-error': 6.1.5 '@octokit/types': 13.6.2 + on-exit-leak-free@2.1.2: {} + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -1538,12 +1593,38 @@ snapshots: picomatch@2.3.1: {} + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-std-serializers@7.0.0: {} + + pino@9.5.0: + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.5.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.0.0 + process-warning: 4.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.0 + thread-stream: 3.1.0 + prelude-ls@1.2.1: {} + process-warning@4.0.0: {} + punycode@2.3.1: {} queue-microtask@1.2.3: {} + quick-format-unescaped@4.0.4: {} + + real-require@0.2.0: {} + resolve-from@4.0.0: {} reusify@1.0.4: {} @@ -1552,6 +1633,8 @@ snapshots: dependencies: queue-microtask: 1.2.3 + safe-stable-stringify@2.5.0: {} + semver@7.6.3: {} shebang-command@2.0.0: @@ -1562,6 +1645,12 @@ snapshots: signal-exit@4.1.0: {} + sonic-boom@4.2.0: + dependencies: + atomic-sleep: 1.0.0 + + split2@4.2.0: {} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -1588,6 +1677,10 @@ snapshots: dependencies: has-flag: 4.0.0 + thread-stream@3.1.0: + dependencies: + real-require: 0.2.0 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 diff --git a/analytics/src/github-storage.ts b/analytics/src/github-storage.ts index cd6845a..17c6393 100644 --- a/analytics/src/github-storage.ts +++ b/analytics/src/github-storage.ts @@ -1,16 +1,16 @@ import "dotenv/config"; - import { readFileSync } from "fs"; import { storeMetricsToRepo } from "./github.js"; +import logger from "./logger.js"; export async function storeInGitHub(file: string, benchmark = false) { if (process.env.DEBUG) { - console.log("DEBUG mode enabled, skipping GitHub storage."); + logger.debug("DEBUG mode enabled, skipping GitHub storage."); return; } if (!process.env.GITHUB_REPOSITORY) { - console.log("GITHUB_REPOSITORY environment variable is not set"); + logger.warn("GITHUB_REPOSITORY environment variable is not set"); return; } diff --git a/analytics/src/github.ts b/analytics/src/github.ts index 3e13905..232cadd 100644 --- a/analytics/src/github.ts +++ b/analytics/src/github.ts @@ -1,11 +1,12 @@ import "dotenv/config"; import { Octokit } from "octokit" +import logger from "./logger.js"; async function obtainOctokit(): Promise { let octokit: Octokit; if (process.env.GITHUB_ACTIONS) { - console.log("Running in GitHub Actions, using @octokit/auth-action"); + logger.debug("Running in GitHub Actions, using @octokit/auth-action"); const { createActionAuth } = await import("@octokit/auth-action"); octokit = new Octokit({ authStrategy: createActionAuth }); } else { @@ -20,7 +21,7 @@ async function obtainOctokit(): Promise { } async function createTag(tag: string, message: string, object_sha: string, owner: string, repo: string) { - console.log(`creating tag ${tag} - "${message}"`); + logger.debug(`creating tag ${tag} - "${message}"`); const octokit = await obtainOctokit(); @@ -36,11 +37,11 @@ async function createTag(tag: string, message: string, object_sha: string, owner } ); - console.log(response); + logger.debug(response); } async function createRef(ref: string, sha: string, owner: string, repo: string) { - console.log(`creating ref ${ref} for metrics tree ${sha}`); + logger.debug(`creating ref ${ref} for metrics tree ${sha}`); const octokit = await obtainOctokit(); @@ -54,11 +55,11 @@ async function createRef(ref: string, sha: string, owner: string, repo: string) } ); - console.log(response); + logger.debug(response); } async function createBlob(content: string, owner: string, repo: string) { - console.log(`creating blob with content: ${content.substring(0, 10)} ...`); + logger.debug(`creating blob with content: ${content.substring(0, 10)} ...`); const octokit = await obtainOctokit(); @@ -72,11 +73,11 @@ async function createBlob(content: string, owner: string, repo: string) { } ); - console.log(response); + logger.debug(response); } async function createTree(metrics: string, owner: string, repo: string): Promise { - console.log(`creating tree at ${owner}/${repo}`); + logger.debug(`creating tree at ${owner}/${repo}`); const octokit = await obtainOctokit(); @@ -96,13 +97,13 @@ async function createTree(metrics: string, owner: string, repo: string): Promise } ); - console.log(response); + logger.debug(response); return response.data.sha; } export async function storeMetricsToRepo(metrics: string, commit_sha: string, owner: string, repo: string) { if (process.env.DEBUG) { - console.log("DEBUG mode enabled, skipping GitHub API calls"); + logger.debug("DEBUG mode enabled, skipping GitHub API calls"); return; } diff --git a/analytics/src/index.ts b/analytics/src/index.ts index cd8ce78..d204cfc 100644 --- a/analytics/src/index.ts +++ b/analytics/src/index.ts @@ -1,23 +1,24 @@ import "dotenv/config"; import { storeInGitHub } from "./github-storage.js"; +import logger from "./logger.js"; if (!process.env.REPOSITORY_PATH) { throw new Error("REPOSITORY_PATH environment variable is not set"); } let metrics_path = "/metrics/metrics.json"; if (!process.env.METRICS_PATH) { - console.warn("Using default METRICS_PATH /metrics/metrics.json") + logger.warn("Using default METRICS_PATH /metrics/metrics.json") } else { metrics_path = process.env.METRICS_PATH; } -console.log(`REPOSITORY_PATH="${process.env.REPOSITORY_PATH}"`); -console.log(`METRICS_PATH="${process.env.METRICS_PATH}"`) +logger.info(`REPOSITORY_PATH="${process.env.REPOSITORY_PATH}"`); +logger.info(`METRICS_PATH="${process.env.METRICS_PATH}"`) const benchmark = Boolean(process.env.BENCHMARK); -console.log(`Perform benchmarking of operations`); +if (benchmark) logger.info(`Perform benchmarking of operations`); storeInGitHub(metrics_path, benchmark).catch((e) => { - console.error(e); + logger.error(e); process.exit(1); }); \ No newline at end of file diff --git a/analytics/src/logger.ts b/analytics/src/logger.ts new file mode 100644 index 0000000..2785977 --- /dev/null +++ b/analytics/src/logger.ts @@ -0,0 +1,13 @@ +import { pino } from 'pino'; + +const logger = pino({ + level: process.env.LOG_LEVEL || 'info', + transport: { + target: 'pino-pretty', + options: { + colorize: process.env.NODE_ENV !== 'production' + } + } +}); + +export default logger; \ No newline at end of file diff --git a/frontend/package.json b/frontend/package.json index b2de1a6..fa132e5 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -24,6 +24,7 @@ "buffer": "^6.0.3", "isomorphic-fetch": "^3.0.0", "octokit": "^4.0.2", + "pino": "^9.5.0", "pretty-bytes": "^6.1.1", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 73b6806..6fcfe5c 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -32,6 +32,9 @@ importers: octokit: specifier: ^4.0.2 version: 4.0.2 + pino: + specifier: ^9.5.0 + version: 9.5.0 pretty-bytes: specifier: ^6.1.1 version: 6.1.1 @@ -1378,6 +1381,10 @@ packages: async@3.2.6: resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -1707,6 +1714,10 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-redact@3.5.0: + resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} + engines: {node: '>=6'} + fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -2154,6 +2165,10 @@ packages: resolution: {integrity: sha512-wbqF4uc1YbcldtiBFfkSnquHtECEIpYD78YUXI6ri1Im5OO2NLo6ZVpRdbJpdnpZ05zMrVPssNiEo6JQtea+Qg==} engines: {node: '>= 18'} + on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -2212,6 +2227,16 @@ packages: resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} engines: {node: '>=12'} + pino-abstract-transport@2.0.0: + resolution: {integrity: sha512-F63x5tizV6WCh4R6RHyi2Ml+M70DNRXt/+HANowMflpgGFMAym/VKm6G7ZOQRjqN7XbGxK1Lg9t6ZrtzOaivMw==} + + pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} + + pino@9.5.0: + resolution: {integrity: sha512-xSEmD4pLnV54t0NOUN16yCl7RIB1c5UUOse5HSyEXtBp+FgFQyPeDutc+Q2ZO7/22vImV7VfEjH/1zV2QuqvYw==} + hasBin: true + pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} @@ -2304,6 +2329,9 @@ packages: resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} engines: {node: ^14.13.1 || >=16.0.0} + process-warning@4.0.0: + resolution: {integrity: sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==} + prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} @@ -2314,6 +2342,9 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + react-dom@19.0.0: resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==} peerDependencies: @@ -2356,6 +2387,10 @@ packages: resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==} engines: {node: '>=0.10.0'} + real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + reflect.getprototypeof@1.0.8: resolution: {integrity: sha512-B5dj6usc5dkk8uFliwjwDHM8To5/QwdKz9JcBZ8Ic4G1f0YmeeJTtE/ZTdgRFPAfxZFiUaPhZ1Jcs4qeagItGQ==} engines: {node: '>= 0.4'} @@ -2423,6 +2458,10 @@ packages: resolution: {integrity: sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==} engines: {node: '>= 0.4'} + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + scheduler@0.25.0: resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==} @@ -2462,6 +2501,9 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} + sonic-boom@4.2.0: + resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==} + sort-object-keys@1.1.3: resolution: {integrity: sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==} @@ -2484,6 +2526,10 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + string.prototype.matchall@4.0.11: resolution: {integrity: sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==} engines: {node: '>= 0.4'} @@ -2533,6 +2579,9 @@ packages: engines: {node: '>=10'} hasBin: true + thread-stream@3.1.0: + resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + tinyglobby@0.2.10: resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==} engines: {node: '>=12.0.0'} @@ -4185,6 +4234,8 @@ snapshots: async@3.2.6: {} + atomic-sleep@1.0.0: {} + available-typed-arrays@1.0.7: dependencies: possible-typed-array-names: 1.0.0 @@ -4632,6 +4683,8 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-redact@3.5.0: {} + fastq@1.17.1: dependencies: reusify: 1.0.4 @@ -5078,6 +5131,8 @@ snapshots: '@octokit/request-error': 6.1.5 '@octokit/types': 13.6.2 + on-exit-leak-free@2.1.2: {} + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -5130,6 +5185,26 @@ snapshots: picomatch@4.0.2: {} + pino-abstract-transport@2.0.0: + dependencies: + split2: 4.2.0 + + pino-std-serializers@7.0.0: {} + + pino@9.5.0: + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.5.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 2.0.0 + pino-std-serializers: 7.0.0 + process-warning: 4.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.2.0 + thread-stream: 3.1.0 + pkg-dir@4.2.0: dependencies: find-up: 4.1.0 @@ -5163,6 +5238,8 @@ snapshots: pretty-bytes@6.1.1: {} + process-warning@4.0.0: {} + prop-types@15.8.1: dependencies: loose-envify: 1.4.0 @@ -5173,6 +5250,8 @@ snapshots: queue-microtask@1.2.3: {} + quick-format-unescaped@4.0.4: {} + react-dom@19.0.0(react@19.0.0): dependencies: react: 19.0.0 @@ -5211,6 +5290,8 @@ snapshots: react@19.0.0: {} + real-require@0.2.0: {} + reflect.getprototypeof@1.0.8: dependencies: call-bind: 1.0.8 @@ -5316,6 +5397,8 @@ snapshots: es-errors: 1.3.0 is-regex: 1.2.0 + safe-stable-stringify@2.5.0: {} + scheduler@0.25.0: {} semver@6.3.1: {} @@ -5355,6 +5438,10 @@ snapshots: slash@3.0.0: {} + sonic-boom@4.2.0: + dependencies: + atomic-sleep: 1.0.0 + sort-object-keys@1.1.3: {} sort-package-json@2.12.0: @@ -5379,6 +5466,8 @@ snapshots: source-map@0.6.1: {} + split2@4.2.0: {} + string.prototype.matchall@4.0.11: dependencies: call-bind: 1.0.8 @@ -5446,6 +5535,10 @@ snapshots: commander: 2.20.3 source-map-support: 0.5.21 + thread-stream@3.1.0: + dependencies: + real-require: 0.2.0 + tinyglobby@0.2.10: dependencies: fdir: 6.4.2(picomatch@4.0.2) diff --git a/frontend/src/components/Metrics.tsx b/frontend/src/components/Metrics.tsx index 4c23777..f3b0e53 100644 --- a/frontend/src/components/Metrics.tsx +++ b/frontend/src/components/Metrics.tsx @@ -1,12 +1,13 @@ import { useState, useEffect } from "react"; import { metricsFromJSON } from "../utils/parse"; -import { getCommitSHA, getMetricsBlob } from "@/utils/github"; +import { getCommitSHA, getMetricsBlob } from "@frontend/utils/github"; import { MetricsTableData } from "@analytics/types"; import { LinearProgress, Stack, Typography, Paper } from "@mui/material"; import Treemap from "./Treemap"; import MetaMetrics from "./MetaMetrics"; import NoMetrics from "./NoMetrics"; import MetricsDataGrid from "./MetricsDataGrid"; +import logger from "@frontend/utils/logger"; type MetricsProps = { owner?: string; @@ -32,17 +33,17 @@ export default function Metrics({ if (!commitSHA) { if (!branch) return; commitSHA = await getCommitSHA(owner, repo, branch); - console.log(commitSHA); + logger.debug("commitSHA:", commitSHA); } try { const [metricsBlob] = await getMetricsBlob(owner, repo, commitSHA, ["metrics.json"]); const parsedData = metricsFromJSON(metricsBlob.content); - console.log("parsedData:", parsedData); + logger.debug("parsedData:", parsedData); setData(parsedData); setSize(metricsBlob.size); } catch (e) { - console.error(e); + logger.error(e); setError(true); } finally { setLoading(false); diff --git a/frontend/src/components/MetricsPage.tsx b/frontend/src/components/MetricsPage.tsx index 7adca3d..04adf8b 100644 --- a/frontend/src/components/MetricsPage.tsx +++ b/frontend/src/components/MetricsPage.tsx @@ -2,10 +2,12 @@ import { Box, Paper, Stack, Typography, Link } from "@mui/material"; import { Link as RouterLink, useParams } from "react-router-dom"; import Metrics from "./Metrics"; import RepoBreadcrumbs from "./RepoBreadcrumbs"; +import logger from "@frontend/utils/logger"; + export default function MetricsPage() { const { owner, repo, commitSHA, branch } = useParams(); - console.log(owner, repo, commitSHA, branch); + logger.debug(owner, repo, commitSHA, branch); const breadcrumbs = [ {owner} diff --git a/frontend/src/components/Repo.tsx b/frontend/src/components/Repo.tsx index 9d1edcb..3739a36 100644 --- a/frontend/src/components/Repo.tsx +++ b/frontend/src/components/Repo.tsx @@ -17,9 +17,10 @@ import { getMetricCommits, ListRefsResponseType, ListBranchesResponseType, -} from "@/utils/github"; +} from "@frontend/utils/github"; import RepoBreadcrumbs from "./RepoBreadcrumbs"; import { Link as RouterLink } from "react-router-dom"; +import logger from "@frontend/utils/logger"; interface RepoParams { owner: string; @@ -37,10 +38,10 @@ export default function Repo({ owner, repo }: RepoParams) { useEffect(() => { async function fetchData() { const branches = await getBranches(owner, repo); - // console.log(branches); + logger.debug("branches:", branches); setBranches(branches); const refs = await getMetricCommits(owner, repo); - // console.log(refs); + logger.debug("refs:", refs); setRefs(refs); } fetchData(); diff --git a/frontend/src/components/Treemap.tsx b/frontend/src/components/Treemap.tsx index 9e75ce6..bdc3bab 100644 --- a/frontend/src/components/Treemap.tsx +++ b/frontend/src/components/Treemap.tsx @@ -1,4 +1,4 @@ -import { configFromFileTree, createFileTree } from "@/utils/treemap_helpers"; +import { configFromFileTree, createFileTree } from "@frontend/utils/treemap_helpers"; import { MetricsTableData } from "@analytics/types"; import { Container } from "@mui/material"; import { useEffect, useState } from "react"; @@ -9,6 +9,7 @@ import { Visualization, Renderer, } from "treemap-renderer"; +import logger from '@frontend/utils/logger'; export default function Treemap({ header, rows }: MetricsTableData) { const fileTree = createFileTree(rows); @@ -31,19 +32,19 @@ export default function Treemap({ header, rows }: MetricsTableData) { canvas.dispose(); // canvas.frameScale = [ 1.0, 1.0 ]; canvas.renderer = visualization.renderer as Renderer; - // console.log("cfg:", config); + logger.debug("cfg:", config); loadConfig(); //debugInit(); }, []); function loadConfig() { - // console.log("loadConfig"); + logger.debug("loadConfig"); if (config && visualization && canvas) { visualization.configuration = config; - // console.log("Visualization:", visualization); - // console.log("Config:", visualization.configuration); - // console.log("Canvas:", canvas); + logger.debug("Visualization:", visualization); + logger.debug("Config:", visualization.configuration); + logger.debug("Canvas:", canvas); canvas.controller.update(); } else { @@ -63,6 +64,8 @@ export default function Treemap({ header, rows }: MetricsTableData) { const width = 1440 / window.devicePixelRatio; const height = 720 / window.devicePixelRatio; + logger.info('Treemap component loaded'); + return (
{ const ref_string = `metrics/${commit_sha}`; - console.log(ref_string); + logger.debug('ref_string', ref_string); const ref = await octokit.rest.git.getRef({ owner, repo, @@ -44,9 +45,12 @@ export async function getMetricsBlob( tree_sha, }); - // response.data.tree.map((object) => { - // console.log(object.path, prettyBytes(object.size!)); - // }); + if (process.env.DEBUG) { + response.data.tree.map((object: { path: string; size?: number }) => { + logger.debug(object.path, prettyBytes(object.size!)); + }); + } + return await Promise.all( files.map(async (file) => { @@ -56,7 +60,7 @@ export async function getMetricsBlob( const file_sha = found_file?.sha; if (!file_sha) { - console.warn(`${file} not found in tree object`); + logger.warn(`${file} not found in tree object`); return { content: "", size: 0 }; } @@ -68,10 +72,10 @@ export async function getMetricsBlob( const blob_string = Buffer.from(blob.data.content, "base64").toString(); if (!blob_string) { - console.warn(`${file} not found in blob object`); + logger.warn(`${file} not found in blob object`); return { content: "", size: 0 }; } - // console.log(blob_string); + logger.debug(blob_string); return { content: blob_string, size: blob.data.size } as MetricsBlob; }) ); diff --git a/frontend/src/utils/logger.ts b/frontend/src/utils/logger.ts new file mode 100644 index 0000000..fa3b4aa --- /dev/null +++ b/frontend/src/utils/logger.ts @@ -0,0 +1,7 @@ +import pino from 'pino'; + +const logger = pino({ + level: import.meta.env.DEBUG ? 'debug' : 'info', +}); + +export default logger; \ No newline at end of file diff --git a/frontend/src/utils/treemap_helpers.ts b/frontend/src/utils/treemap_helpers.ts index fd27abd..dea4c07 100644 --- a/frontend/src/utils/treemap_helpers.ts +++ b/frontend/src/utils/treemap_helpers.ts @@ -1,5 +1,6 @@ import { FileMetrics, Metrics, TreeNode } from "@analytics/types"; import { Configuration, NodeSort } from "treemap-renderer"; +import logger from "@frontend/utils/logger"; interface ValueMapping { weights: keyof Metrics; @@ -29,7 +30,7 @@ export function createFileTree(rows: FileMetrics[]): TreeNode { }, rootNode); }); - // console.log(rootNode); + logger.debug(rootNode); if (rootNode.children.length === 1) { return rootNode.children[0]; } @@ -73,11 +74,11 @@ export function configFromFileTree( } buildEdges(fileTreeRoot); - // console.log("names", names); - // console.log("edges", edges); - // console.log("weights", weights); - // console.log("heights", heights); - // console.log("colors", colors); + logger.debug("names", names); + logger.debug("edges", edges); + logger.debug("weights", weights); + logger.debug("heights", heights); + logger.debug("colors", colors); config.colors = [ { identifier: "emphasis", colorspace: "hex", value: "#00b0ff" }, @@ -193,6 +194,6 @@ export function configFromFileTree( }, ]; - // console.log("Config", JSON.stringify(config, null, 2)); + logger.debug("Config", JSON.stringify(config, null, 2)); return config; } diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index ad91596..ce90b71 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -3,7 +3,11 @@ "baseUrl": "./", "target": "ESNext", "useDefineForClassFields": true, - "lib": ["DOM", "DOM.Iterable", "ESNext"], + "lib": [ + "DOM", + "DOM.Iterable", + "ESNext" + ], "allowJs": false, "skipLibCheck": true, "esModuleInterop": false, @@ -17,14 +21,26 @@ "noEmit": true, "jsx": "react-jsx", "sourceMap": true, - "types": ["vite/client"], + "types": [ + "vite/client" + ], "paths": { - "@/*": ["./src/*"], - "@analytics/*": ["../analytics/src/*"] + "@frontend/*": [ + "./src/*" + ], + "@analytics/*": [ + "../analytics/src/*" + ] } }, - "include": ["src"], - "references": [{ "path": "./tsconfig.node.json" }], + "include": [ + "src" + ], + "references": [ + { + "path": "./tsconfig.node.json" + } + ], "ts-node": { // It is faster to skip typechecking. // Remove if you want ts-node to do typechecking. @@ -36,4 +52,4 @@ "esModuleInterop": true } } -} +} \ No newline at end of file