Skip to content

Local development

Set logLocalDir to ‘../.fsl-logs’ and the emulator writes every entry to .fsl-logs/dev.jsonl instead of Cloud Logging.

The Functions emulator writes the same entries to a local file that production writes to Cloud Logging. The whole loop works before you deploy anything: client, log function, symbolication path and labels.

Add a serve script to functions/package.json:

functions/package.json
"serve": "npm run build && firebase emulators:start --only functions"

Then tell the logger where to write, in your functions entry point:

functions/src/index.ts
import { initLogger } from '@dasasian/firebase-structured-logger/functions'
initLogger({ appId: 'my-app', logLocalDir: '../.fsl-logs' })

logLocalDir is resolved against the emulator’s working directory, functions/, so '../.fsl-logs' is .fsl-logs/ at the repo root.

There is nothing to add. The logger creates the folder when it starts in the emulator, with a .gitignore inside it that holds *, so the folder ignores itself, whatever logLocalDir points at. A .gitignore already there is left alone. fsl logs schema and fsl logs attachments do the same for .fsl-logs/.

Entries go to {logLocalDir}/dev.jsonl. Each emulator start rotates the current file to dev-{timestamp}.jsonl, and rotation also happens when the record limit is hit mid-session.

Option Default Description
logLocalDir none Directory for local log files
logMaxRecordsPerFile 2000 Records per file before rotation
logMaxRotatedFiles 5 Rotated files to keep
functions/src/index.ts
import { initLogger } from '@dasasian/firebase-structured-logger/functions'
initLogger({
appId: 'my-app',
logLocalDir: '../.fsl-logs',
logMaxRecordsPerFile: 5000,
logMaxRotatedFiles: 10,
})

Past logMaxRotatedFiles, the oldest file is deleted.

fsl logs --local reads .fsl-logs/*.jsonl in the current folder with the same flags as a production query:

Terminal window
npx fsl logs --local --where severity=ERROR --group-by labels.screen --select labels.screen,count

The flags are covered in fsl logs. The severity floor in the emulator defaults to DEBUG, so nothing is held back while you develop. See Rate limits and missing logs for what changes in production.

Made by Dasasian