Skip to content

Instantly share code, notes, and snippets.

@JakeChampion
Last active January 25, 2024 19:14
Show Gist options
  • Save JakeChampion/2d03fd6bd4ad31892a3badcb55b5aadb to your computer and use it in GitHub Desktop.
Save JakeChampion/2d03fd6bd4ad31892a3badcb55b5aadb to your computer and use it in GitHub Desktop.
Hono logger for use on Fastly Compute
// @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