Instant Stripe-level observability for your Next.js project.
Flytrap Logs is a collection of packages to add Stripe-inspired canonical logging to your Next.js project. Works both manually and automatically through our plugin.
@useflytrap/logs
: Used for constructing the Stripe-inspired canonical log lines.@useflytrap/logs-transform
A code-transform for automatically instrumenting your Next.js Route Handlers and Server Actions
With Flytrap Logs, each request / Server Action will be accompanied with a log that will be structured and something like this:
{
"method": "POST",
"type": "request",
"path": "/api/v1/captures",
"req": "{ 'hello': 'world' }",
"req_headers": {
"accept": "*/*",
"accept-encoding": "gzip, deflate, br",
"accept-language": "sv-SE,sv;q=0.9",
"user-agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 17_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4.1 Mobile/15E148 Safari/604.1",
"x-forwarded-host": "www.useflytrap.com",
"x-forwarded-port": "443",
"x-forwarded-proto": "https",
"x-matched-path": "/api/v1/captures",
},
"res": {
"message": "Invalid public API key."
},
"res_headers": {
"content-type": "application/json"
},
"http_status": 401,
"duration": 80,
"auth_type": "api_key",
"project_id": "proj_01hsw5hj47fwst6xs4axx78x8h",
"key_id": "pk_MIIBIjANGpt",
"permissions_used": [
"capture"
]
}
- Stripe-inspired observability for your Next.js project
- Easily add context to your canonical log lines
- Saves requests, responses, headers
- Optional encryption for log fields
- Fully type-safe logging
- Identify users, API keys etc in your logs easily
- Install the Flytrap Logs SDK
$ npm install @useflytrap/logs
- Create a logging file (
logging.ts
)
import { PermissionedApiKey } from "@/types"
import { createFlytrapLogger } from "@useflytrap/logs"
export type AdditionalLogContext = {
team_id: string
project_id: string
auth_type: "api_key" | "dashboard"
permissions_used: PermissionedApiKey["permissions"]
build_id: string
key_id: string
}
export const {
addContext,
flushAsync,
flush,
catchUncaughtAction,
catchUncaughtRoute,
response,
nextResponse,
json,
nextJson,
redirect,
nextRedirect,
parseJson,
parseText,
} = createFlytrapLogger<AdditionalLogContext>({
publicKey:
"pk_MIIBI...",
encryption: {
enabled: true,
},
})
This is our example logging definition for our production site. Let's unpack what's going on here.
- We're defining our
AdditionalLogContext
type. This will give us auto-complete throughout our code-base when usingaddContext
to add context to our canonical log lines. - We're enabling encryption, and providing a public key to encrypt the values with. By default, sensitive values such as request payloads, headers, response payloads and errors (containing stacktraces) are encrypted when encryption is enabled.
- We're exporting the functions that will be needed throughout our codebase (eg.
addContext
,response
,json
). These will be used throughout our code-base to add context to our canonical log.
For instance, instead of return Response.json({ success: true })
, we would have return json({ success: true })
.
We recommend to use our code-transform @useflytrap/logs-transform
, which will automatically do everything for you.
- (Optional) Setup Flytrap Logs code transform
If you have a large code-base already, you probably don't want to change it just for our tool. Because of this, we have created a Flytrap Logs plugin, which automatically changes the code at runtime, so you don't have to do anything.
- Simply install the
@useflytrap/logs-transform
package
$ npm install @useflytrap/logs-transform
- Add the plugin to your Next.js config
// next.config.mjs
import { webpack } from "@useflytrap/logs-transform"
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
webpack(config) {
config.plugins = config.plugins ?? []
config.infrastructureLogging = { level: 'error' }
config.plugins.push(webpack({
// here goes the plugin options
}))
return config
},
}
export default nextConfig
- (Optional) Manually use core SDK functions
If you don't want to use the code-transform, you can manually use the core SDK functions. Here are the changes you should make:
- Server Actions using the
catchUncaughtAction
wrapper
"use server"
export async function foo() {
// ... your code here ...
}
// becomes:
export const foo = catchUncaughtAction(() => {
// ... your code here ...
}, {
path: "@/actions/foo" // 👈 whichever path to distinguish this action from others
}
- Route Handlers using the
catchUncaughtRoute
wrapper
export async function POST() {
// ... your code here ...
}
// becomes:
export const POST = catchUncaughtRoute(() => {}, {
path: "/api/v1/user",
method: "POST",
})
Response.json()
->json()
Response.redirect()
->redirect()
new Response()
->response()
NextResponse.json()
->nextJson()
NextResponse.redirect()
->nextRedirect()
new NextResponse()
->nextResponse()
req.json()
->parseJson(req)
req.text()
->parseText(req)
- Et voila! Enjoy your canonical logging setup
Try making a request, and you should see requests & server actions get logged in the console. If you want to send them to an API, you can change the flushMethod
to 'api'
in your logging.ts
, and define logsEndpoint
with your API endpoint.
If you want automatically set-up dashboards for your Route Handlers, Server Actions that look like this 👇, you can integrate our Logs SDK with the Flytrap Logs Dashboard.
- Sign up on Flytrap
- Create a project, select the "Logs" product during the onboarding
- Create your
logging.ts
file, and add thepublicKey
from your onboarding there. - Set the
flushMethod
in yourlogging.ts
file to'api'
- Clone this repository
- Enable Corepack using
corepack enable
(usenpm i -g corepack
for Node.js < 16.10) - Install dependencies using
pnpm install
- Run the tests using
pnpm dev
Made with ❤️ in Helsinki
Published under MIT License.