fresh-logging
Access Log middleware for Deno Fresh.
Installation
First of all, create your fresh app.
Add logging to your import_map.json
.
{
"imports": {
"$logging/": "https://deno.land/x/fresh_logging@1.0.0/"
}
}
Consume the logger in your app’s _middleware.ts
.
import { getLogger } from "$logging/index.ts";
export const handler = [
getLogger(),
// ... other middlewares
];
Note: if includeDuration
option is ON (which is the default behavior), getLogger()
will also count the time taken by all of its subsequent middlewares.
For example, putting getLogger()
at the beginning of your handler
array will count the time taken by all middlewares, while putting it at the very end of
your handler
array will yield the time taken only by the route handler.
Options
getLogger()
accepts an optional object {}
with the following options:
Option | Default Value | Notes |
---|---|---|
format |
LoggingFormat.DEFAULT |
Default format to use, v0.0.1 only supports Common Log Format. |
utcTime |
false |
Whether to log timestamps in UTC or server timezone. |
includeDuration |
true |
Whether to include handler response time. |
resolvers |
{} | Selectively supply customer resolvers for the missing fields. See the next section on limitations for more details. |
logger |
console.info +color -level |
Optionally supply a custom logger function of type (message: string) => string |
Limitations
As of v0.0.1, the following fields are completely omitted (hard-coded to -
):
rfc931
(client identifier): not sure how to obtain thisauthuser
(user identifier): not sure how to obtain this eitherbytes
(response content length): one way I can think of is to useres.clone()
then read its asArrayBuffer
and get thebyteLength
, but that is both time and memory consuming. Until I can find a more efficient way to obtain this piece of information, omission is the decision.
From v0.0.2, a resolvers
option has been added to allow custom resolutions of all the fields, including the missing ones above. For example, the following
code snippet will allow logging the response bytes:
import { getLogger, ResolutionField } from "$logging/index.ts";
export const handler = [
getLogger({
resolvers: {
[ResolutionField.bytes]: async (_req, _ctx, res) => `${(await res.clone().arrayBuffer()).byteLength}`,
},
}),
];
Again, please note that the example above only serves to illustrate how to provide customer resolvers for the missing fields, the actual implementation is sub-optimal. Otherwise, it would have been included as default resolver for that field.
How to use custom logger
Simply provide a function with the signature (message: string) => string
, such as:
import { getLogger } from "$logging/index.ts";
export const handler = [
getLogger({
logger: (message: string) => {
console.debug(message);
return message;
},
}),
];
In combination with a sophisticated logging solution such as https://github.com/onjara/optic, most logging use cases (console/stdout, rotating file, cloud, etc.) can be implemented with relative ease.
A note about versioning
For now, the versions are a.b.c-x.y.z
where a.b.c
is the plugin version and x.y.z
is the supported Turnstile API version. For example, 0.0.1-0
is the
initial release of plugin, which supports Turnstile API v0.
All tags starting with 0.0.
are mutable. Expect breaking changes! Starting from 0.1.
, tags will be immutable. However, still expect breaking
changes. Starting from 1.
, semver will kick in and there will be no breaking changes until 2.
.