Last active
January 25, 2024 19:14
-
-
Save JakeChampion/2d03fd6bd4ad31892a3badcb55b5aadb to your computer and use it in GitHub Desktop.
Hono logger for use on Fastly Compute
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @ts-check | |
/* eslint-env serviceworker */ | |
/// <reference types="@fastly/js-compute" /> | |
// You can use this logger like so: | |
// import { Hono } from 'hono' | |
// import { logger } from "./logger.js"; | |
// const app = new Hono() | |
// app.use('*', logger()); | |
import { env } from 'fastly:env'; | |
import {ConfigStore} from 'fastly:config-store'; | |
function humanize (times) { | |
const [delimiter, separator] = [",", "."]; | |
const orderTimes = times.map((v) => v.replaceAll(/(\d)(?=(\d{3})+(?!\d))/g, "$1" + delimiter)); | |
return orderTimes.join(separator); | |
}; | |
function time (start) { | |
const delta = Date.now() - start; | |
return humanize([delta < 1e3 ? delta + "ms" : Math.round(delta / 1e3) + "s"]); | |
}; | |
function colorStatus (status) { | |
const out = { | |
7: `\u001B[35m${status}\u001B[0m`, | |
5: `\u001B[31m${status}\u001B[0m`, | |
4: `\u001B[33m${status}\u001B[0m`, | |
3: `\u001B[36m${status}\u001B[0m`, | |
2: `\u001B[32m${status}\u001B[0m`, | |
1: `\u001B[32m${status}\u001B[0m`, | |
0: `\u001B[33m${status}\u001B[0m` | |
}; | |
const calculateStatus = Math.trunc(status / 100); | |
return out[calculateStatus]; | |
}; | |
function log(prefix, method, url, status = 0, elapsed) { | |
const out = prefix.startsWith("<--") /* Incoming */ ? ` ${prefix} ${method} ${url}` : ` ${prefix} ${method} ${url} ${colorStatus(status)} ${elapsed}`; | |
console.log(out); | |
} | |
function logger() { | |
return async (c, next) => { | |
const { | |
method | |
} = c.req; | |
const url = c.req.url; | |
let start = Date.now(); | |
const FASTLY_SERVICE_VERSION = env('FASTLY_SERVICE_VERSION'); | |
const runningLocally = !FASTLY_SERVICE_VERSION; | |
if (runningLocally || shouldLog()) { | |
log(`<-- (Incoming) FASTLY_SERVICE_VERSION: ${FASTLY_SERVICE_VERSION || 'local'}` /* Incoming */ , method, url); | |
await next(); | |
} else { | |
await next(); | |
} | |
if (runningLocally || shouldLog() || c.error) { | |
log(`--> (Outgoing) FASTLY_SERVICE_VERSION: ${FASTLY_SERVICE_VERSION || 'local'}` /* Outgoing */ , method, url, c.res.status, time(start)); | |
} | |
}; | |
}; | |
// Persist within a request in order to have same logging sample within a request | |
let cachedRandomPercentage; | |
function getRandomPercentage(){ | |
if (typeof cachedRandomPercentage === 'undefined') { | |
cachedRandomPercentage = Math.random() * 100; | |
} | |
return cachedRandomPercentage; | |
} | |
function withinSampleRate(randomPercentage) { | |
try { | |
const config = new ConfigStore('config'); | |
const sampleRateString = config.get('sample_rate'); | |
if (!sampleRateString) return true; // no sampling | |
const sampleRate = parseInt(sampleRateString, 10); // Sample rate in integer % | |
return randomPercentage < sampleRate; | |
} catch { | |
return true; | |
} | |
} | |
function shouldLog() { | |
try { | |
const randomPercentage = getRandomPercentage(); | |
const config = new ConfigStore('config'); | |
return config.get('log') === '1' && withinSampleRate(randomPercentage); | |
} catch { | |
return false; | |
} | |
} | |
export { | |
shouldLog, | |
logger | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment