From 96d43d511c4fa128ccf665a5d8b334e76ec4c2f0 Mon Sep 17 00:00:00 2001 From: Josh Creek <8179928+jcreek@users.noreply.github.com> Date: Sat, 26 Apr 2025 16:07:02 +0100 Subject: [PATCH] build(*): Add logging --- .env.example | 7 +- package.json | 5 +- partykit/src/server.ts | 5 +- pnpm-lock.yaml | 223 ++++++++++++++++++++++++++++++++++++++++ src/lib/server/ai.ts | 20 ++-- src/lib/utils/logger.ts | 34 ++++++ 6 files changed, 282 insertions(+), 12 deletions(-) create mode 100644 src/lib/utils/logger.ts diff --git a/.env.example b/.env.example index 1c827ee..4adcbb6 100644 --- a/.env.example +++ b/.env.example @@ -9,4 +9,9 @@ PARTYKIT_BASE_URL=wss://your-partykit-project.partykit.dev # For local development: # VITE_PARTYKIT_BASE_URL=ws://127.0.0.1:1999 -# PARTYKIT_BASE_URL=ws://127.0.0.1:1999 \ No newline at end of file +# PARTYKIT_BASE_URL=ws://127.0.0.1:1999 + + +# Logging config: +VITE_AXIOM_DATASET="" +VITE_AXIOM_TOKEN="" \ No newline at end of file diff --git a/package.json b/package.json index 082e740..55c0a10 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,10 @@ }, "packageManager": "pnpm@9.15.4+sha512.b2dc20e2fc72b3e18848459b37359a32064663e5627a51e4c74b2c29dd8e8e0491483c3abb40789cfd578bf362fb6ba8261b05f0387d76792ed6e23ea3b1b6a0", "dependencies": { + "@axiomhq/winston": "^1.3.1", "@azure/ai-projects": "1.0.0-beta.5", - "@azure/identity": "^4.9.0" + "@azure/identity": "^4.9.0", + "ts-debounce": "^4.0.0", + "winston": "^3.17.0" } } diff --git a/partykit/src/server.ts b/partykit/src/server.ts index 7f6932b..94f5620 100644 --- a/partykit/src/server.ts +++ b/partykit/src/server.ts @@ -1,13 +1,12 @@ import type * as Party from "partykit/server"; +import logger from "../../src/lib/utils/logger"; export default class Server implements Party.Server { constructor(readonly room: Party.Room) {} onConnect(conn: Party.Connection, ctx: Party.ConnectionContext) { // Log connection details - console.log( - `Connected:\n id: ${conn.id}\n room: ${this.room.id}\n url: ${new URL(ctx.request.url).pathname}` - ); + logger.info(`Connected:\n id: ${conn.id}\n room: ${this.room.id}\n url: ${new URL(ctx.request.url).pathname}`); } onMessage(message: string, sender: Party.Connection) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e1a7120..12218b0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,12 +8,21 @@ importers: .: dependencies: + '@axiomhq/winston': + specifier: ^1.3.1 + version: 1.3.1 '@azure/ai-projects': specifier: 1.0.0-beta.5 version: 1.0.0-beta.5 '@azure/identity': specifier: ^4.9.0 version: 4.9.0 + ts-debounce: + specifier: ^4.0.0 + version: 4.0.0 + winston: + specifier: ^3.17.0 + version: 3.17.0 devDependencies: '@cucumber/cucumber': specifier: ^9.2.2 @@ -106,6 +115,14 @@ packages: resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} + '@axiomhq/js@1.3.1': + resolution: {integrity: sha512-Ytf5V3wKz8FKNiqJxnqZmUhjgJ7TItKUoyHVNE/H2V9dN1ozD6NNnsueenOjKdA48cm2sGRyP432nworst18aA==} + engines: {node: '>=16'} + + '@axiomhq/winston@1.3.1': + resolution: {integrity: sha512-Nad/PkMIkFp7VxJHnZQTg6co9QpTPQDRPeC+/G7BfvXjISQ5+AY+BxNV3h8St7Bs9tLLAufx+gtyG+fgS47x0Q==} + engines: {node: '>=16'} + '@azure-rest/core-client@2.3.5': resolution: {integrity: sha512-vC8sDkT1xH7jx9erJWQqznMhfPY9k+mrM+4R/rAeb+F+KQCohYYmOEAQmT9CEQxStJ3erjbtpN3GMjAS5tdiYg==} engines: {node: '>=18.0.0'} @@ -174,6 +191,10 @@ packages: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} + '@colors/colors@1.6.0': + resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} + engines: {node: '>=0.1.90'} + '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} @@ -226,6 +247,9 @@ packages: '@cucumber/tag-expressions@5.0.1': resolution: {integrity: sha512-N43uWud8ZXuVjza423T9ZCIJsaZhFekmakt7S9bvogTxqdVGbRobjR663s0+uW0Rz9e+Pa8I6jUuWtoBLQD2Mw==} + '@dabh/diagnostics@2.0.3': + resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} + '@esbuild/aix-ppc64@0.24.2': resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} engines: {node: '>=18'} @@ -918,6 +942,9 @@ packages: '@types/node@22.14.1': resolution: {integrity: sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==} + '@types/triple-beam@1.3.5': + resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} + '@types/uuid@8.3.4': resolution: {integrity: sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==} @@ -1027,6 +1054,9 @@ packages: assertion-error-formatter@3.0.0: resolution: {integrity: sha512-6YyAVLrEze0kQ7CmJfUgrLHb+Y7XghmL2Ie7ijVa2Y9ynP3LV+VDiwFk62Dn0qtqbmY0BT0ss6p1xxpiF2PYbQ==} + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -1097,13 +1127,28 @@ packages: resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} engines: {node: '>=6'} + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@3.2.1: + resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + + colorspace@1.1.4: + resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==} + combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -1198,6 +1243,9 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + enabled@2.0.0: + resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} + enhanced-resolve@5.18.1: resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} engines: {node: '>=10.13.0'} @@ -1338,6 +1386,12 @@ packages: picomatch: optional: true + fecha@4.2.3: + resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} + + fetch-retry@6.0.0: + resolution: {integrity: sha512-BUFj1aMubgib37I3v4q78fYo63Po7t4HUPTpQ6/QE6yK6cIQrP+W43FYToeTEyg5m2Y7eFUtijUuAv/PDlWuag==} + figures@3.2.0: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} engines: {node: '>=8'} @@ -1361,6 +1415,9 @@ packages: flatted@3.3.3: resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + fn.name@1.1.0: + resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} + follow-redirects@1.15.9: resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} engines: {node: '>=4.0'} @@ -1501,6 +1558,9 @@ packages: resolution: {integrity: sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==} engines: {node: '>=10'} + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + is-docker@3.0.0: resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -1592,6 +1652,9 @@ packages: knuth-shuffle-seeded@1.0.6: resolution: {integrity: sha512-9pFH0SplrfyKyojCLxZfMcvkhf5hH0d+UwR9nTVJ/DDQJGuzcXjTwB7TP7sDfehSudlGGaOLblmEWqv04ERVWg==} + kuler@2.0.0: + resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} + lazy-ass@1.6.0: resolution: {integrity: sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==} engines: {node: '> 0.8'} @@ -1708,6 +1771,10 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + logform@2.7.0: + resolution: {integrity: sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==} + engines: {node: '>= 12.0.0'} + lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} @@ -1806,6 +1873,9 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + one-time@1.0.0: + resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} + onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} @@ -1998,6 +2068,10 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + readdirp@4.1.2: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} @@ -2054,6 +2128,10 @@ packages: safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + seed-random@2.2.0: resolution: {integrity: sha512-34EQV6AAHQGhoc0tn/96a9Fsi6v2xdqe/dMUwljGRaFOzR3EgRmECvD0O8vi8X+/uQ50LGHfkNu/Eue5TPKZkQ==} @@ -2081,6 +2159,9 @@ packages: signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + sirv@3.0.1: resolution: {integrity: sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A==} engines: {node: '>=18'} @@ -2099,6 +2180,9 @@ packages: split@0.3.3: resolution: {integrity: sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==} + stack-trace@0.0.10: + resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} + stackframe@1.3.4: resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} @@ -2118,6 +2202,9 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -2166,6 +2253,9 @@ packages: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} + text-hex@1.0.0: + resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} + thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -2198,12 +2288,19 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} + triple-beam@1.4.1: + resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} + engines: {node: '>= 14.0.0'} + ts-api-utils@2.1.0: resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} engines: {node: '>=18.12'} peerDependencies: typescript: '>=4.8.4' + ts-debounce@4.0.0: + resolution: {integrity: sha512-+1iDGY6NmOGidq7i7xZGA4cm8DAa6fqdYcvO5Z6yBevH++Bdo9Qt/mN0TzHUgcCcKv1gmh9+W5dHqz8pMWbCbg==} + ts-node@10.9.2: resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} hasBin: true @@ -2256,6 +2353,10 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + uuid@11.1.0: + resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} + hasBin: true + uuid@8.3.2: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true @@ -2329,6 +2430,14 @@ packages: engines: {node: '>= 8'} hasBin: true + winston-transport@4.9.0: + resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==} + engines: {node: '>= 12.0.0'} + + winston@3.17.0: + resolution: {integrity: sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==} + engines: {node: '>= 12.0.0'} + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -2373,6 +2482,16 @@ snapshots: '@jridgewell/gen-mapping': 0.3.8 '@jridgewell/trace-mapping': 0.3.25 + '@axiomhq/js@1.3.1': + dependencies: + fetch-retry: 6.0.0 + uuid: 11.1.0 + + '@axiomhq/winston@1.3.1': + dependencies: + '@axiomhq/js': 1.3.1 + winston-transport: 4.9.0 + '@azure-rest/core-client@2.3.5': dependencies: '@azure/abort-controller': 2.1.2 @@ -2494,6 +2613,8 @@ snapshots: '@colors/colors@1.5.0': optional: true + '@colors/colors@1.6.0': {} + '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 @@ -2595,6 +2716,12 @@ snapshots: '@cucumber/tag-expressions@5.0.1': {} + '@dabh/diagnostics@2.0.3': + dependencies: + colorspace: 1.1.4 + enabled: 2.0.0 + kuler: 2.0.0 + '@esbuild/aix-ppc64@0.24.2': optional: true @@ -3074,6 +3201,8 @@ snapshots: dependencies: undici-types: 6.21.0 + '@types/triple-beam@1.3.5': {} + '@types/uuid@8.3.4': {} '@types/uuid@9.0.1': {} @@ -3200,6 +3329,8 @@ snapshots: pad-right: 0.2.2 repeat-string: 1.6.1 + async@3.2.6: {} + asynckit@0.4.0: {} axios@1.8.4(debug@4.4.0): @@ -3271,12 +3402,33 @@ snapshots: clsx@2.1.1: {} + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + color-convert@2.0.1: dependencies: color-name: 1.1.4 + color-name@1.1.3: {} + color-name@1.1.4: {} + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + + color@3.2.1: + dependencies: + color-convert: 1.9.3 + color-string: 1.9.1 + + colorspace@1.1.4: + dependencies: + color: 3.2.1 + text-hex: 1.0.0 + combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -3344,6 +3496,8 @@ snapshots: emoji-regex@8.0.0: {} + enabled@2.0.0: {} + enhanced-resolve@5.18.1: dependencies: graceful-fs: 4.2.11 @@ -3570,6 +3724,10 @@ snapshots: optionalDependencies: picomatch: 4.0.2 + fecha@4.2.3: {} + + fetch-retry@6.0.0: {} + figures@3.2.0: dependencies: escape-string-regexp: 1.0.5 @@ -3594,6 +3752,8 @@ snapshots: flatted@3.3.3: {} + fn.name@1.1.0: {} + follow-redirects@1.15.9(debug@4.4.0): optionalDependencies: debug: 4.4.0(supports-color@8.1.1) @@ -3722,6 +3882,8 @@ snapshots: ini@2.0.0: {} + is-arrayish@0.3.2: {} + is-docker@3.0.0: {} is-extglob@2.1.1: {} @@ -3813,6 +3975,8 @@ snapshots: dependencies: seed-random: 2.2.0 + kuler@2.0.0: {} + lazy-ass@1.6.0: {} levn@0.4.1: @@ -3895,6 +4059,15 @@ snapshots: lodash@4.17.21: {} + logform@2.7.0: + dependencies: + '@colors/colors': 1.6.0 + '@types/triple-beam': 1.3.5 + fecha: 4.2.3 + ms: 2.1.3 + safe-stable-stringify: 2.5.0 + triple-beam: 1.4.1 + lower-case@2.0.2: dependencies: tslib: 2.8.1 @@ -3975,6 +4148,10 @@ snapshots: dependencies: wrappy: 1.0.2 + one-time@1.0.0: + dependencies: + fn.name: 1.1.0 + onetime@5.1.2: dependencies: mimic-fn: 2.1.0 @@ -4096,6 +4273,12 @@ snapshots: queue-microtask@1.2.3: {} + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + readdirp@4.1.2: {} reflect-metadata@0.1.13: {} @@ -4160,6 +4343,8 @@ snapshots: safe-buffer@5.2.1: {} + safe-stable-stringify@2.5.0: {} + seed-random@2.2.0: {} semver@7.5.3: @@ -4178,6 +4363,10 @@ snapshots: signal-exit@3.0.7: {} + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + sirv@3.0.1: dependencies: '@polka/url': 1.0.0-next.29 @@ -4197,6 +4386,8 @@ snapshots: dependencies: through: 2.3.8 + stack-trace@0.0.10: {} + stackframe@1.3.4: {} start-server-and-test@2.0.11: @@ -4224,6 +4415,10 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -4284,6 +4479,8 @@ snapshots: tapable@2.2.1: {} + text-hex@1.0.0: {} + thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -4311,10 +4508,14 @@ snapshots: totalist@3.0.1: {} + triple-beam@1.4.1: {} + ts-api-utils@2.1.0(typescript@5.8.3): dependencies: typescript: 5.8.3 + ts-debounce@4.0.0: {} + ts-node@10.9.2(@types/node@22.14.1)(typescript@5.8.3): dependencies: '@cspotcode/source-map-support': 0.8.1 @@ -4367,6 +4568,8 @@ snapshots: util-deprecate@1.0.2: {} + uuid@11.1.0: {} + uuid@8.3.2: {} uuid@9.0.0: {} @@ -4412,6 +4615,26 @@ snapshots: dependencies: isexe: 2.0.0 + winston-transport@4.9.0: + dependencies: + logform: 2.7.0 + readable-stream: 3.6.2 + triple-beam: 1.4.1 + + winston@3.17.0: + dependencies: + '@colors/colors': 1.6.0 + '@dabh/diagnostics': 2.0.3 + async: 3.2.6 + is-stream: 2.0.1 + logform: 2.7.0 + one-time: 1.0.0 + readable-stream: 3.6.2 + safe-stable-stringify: 2.5.0 + stack-trace: 0.0.10 + triple-beam: 1.4.1 + winston-transport: 4.9.0 + word-wrap@1.2.5: {} wrappy@1.0.2: {} diff --git a/src/lib/server/ai.ts b/src/lib/server/ai.ts index c1be2ff..ff424b4 100644 --- a/src/lib/server/ai.ts +++ b/src/lib/server/ai.ts @@ -1,7 +1,9 @@ import { client, agent, toolResources } from '../agent/services/agentService'; +import logger from '../utils/logger'; import { RunStreamEvent, ErrorEvent, type ThreadRunOutput } from '@azure/ai-projects'; import { PARTYKIT_BASE_URL } from '$env/static/private'; import type { OpenAIResponse } from '../utils/types'; +import { json } from 'stream/consumers'; function sanitizeForPrompt(input: string): string { return input @@ -222,7 +224,7 @@ async function processRunStream( ): Promise { for await (const evt of stream) { // if (!evt.event.includes('delta')) { - // console.log('▶️ Stream event:', evt.event); + // logger.info('▶️ Stream event:', evt.event); // } if (evt.event === RunStreamEvent.ThreadRunRequiresAction) { @@ -306,7 +308,9 @@ export async function gradeSubmissionWithAgent( }); initialStream = await runInvoker.stream(); } catch (err) { - console.error('Failed to start run:', err); + logger.error(`Failed to start run on thread ${thread.id}:`, err); + logger.info('Task:', task); + logger.info('Submission', submission); return fallbackGrade(submission, task); } @@ -315,7 +319,7 @@ export async function gradeSubmissionWithAgent( try { finalRun = await processRunStream(thread.id, initialStream, roomId); } catch (err) { - console.error('Agent streaming failed:', err); + logger.error(`Agent streaming failed on thread ${thread.id}:`, err); return fallbackGrade(submission, task); } @@ -340,7 +344,8 @@ export async function gradeSubmissionWithAgent( } return parsed; } catch (parseErr) { - console.error('JSON parse failed, returning fallback:', parseErr); + logger.error(`JSON parse failed, returning fallback on thread ${thread.id}:`, parseErr); + logger.info('JSON', jsonText); return { ...fallbackGrade(submission, task), reasoning: raw }; } } @@ -362,7 +367,7 @@ export async function resumeAgentWithHumanReview( }); stream = await runInvoker.stream(); } catch (err) { - console.error('Failed to start run:', err); + logger.error(`Failed to start run on thread ${threadId}:`, err); return fallbackGrade('', ''); } @@ -370,7 +375,7 @@ export async function resumeAgentWithHumanReview( try { finalRun = await processRunStream(threadId, stream, roomId); } catch (err) { - console.error('Agent streaming failed:', err); + logger.error(`Agent streaming failed on thread ${threadId}:`, err); return fallbackGrade('', ''); } @@ -386,7 +391,8 @@ export async function resumeAgentWithHumanReview( const parsed = JSON.parse(jsonText) as OpenAIResponse; return parsed; } catch (parseErr) { - console.error('JSON parse failed, returning fallback:', parseErr); + logger.error(`JSON parse failed, returning fallback on thread ${threadId}:`, parseErr); + logger.info('JSON', jsonText); return { ...fallbackGrade('', ''), reasoning: raw }; } } diff --git a/src/lib/utils/logger.ts b/src/lib/utils/logger.ts new file mode 100644 index 0000000..201ba43 --- /dev/null +++ b/src/lib/utils/logger.ts @@ -0,0 +1,34 @@ +import { createLogger, transports, format } from 'winston'; +import { WinstonTransport as AxiomTransport } from '@axiomhq/winston'; +import { VITE_AXIOM_DATASET, VITE_AXIOM_TOKEN } from '$env/static/private'; + +const axiomTransport = new AxiomTransport({ + dataset: VITE_AXIOM_DATASET, + token: VITE_AXIOM_TOKEN +}); + +const logger = createLogger({ + level: 'info', + defaultMeta: { service: 'automated-assessment-feedback-agent' }, + format: format.combine( + format.errors({ stack: true }), // Captures error stack traces + format.timestamp(), + format.json() // Formats logs as JSON for structured logging + ), + transports: [ + new transports.Console({ + format: format.combine( + format.colorize(), + format.printf(({ timestamp, level, message, stack }) => { + // Stack traces will be included in error messages automatically + return `${timestamp} [${level.toUpperCase()}]: ${message}${stack ? `\n${stack}` : ''}`; + }) + ) + }), + axiomTransport + ], + exceptionHandlers: [axiomTransport], // Logs uncaught exceptions + rejectionHandlers: [axiomTransport] // Logs unhandled promise rejections +}); + +export default logger;