@dasasian/firebase-structured-logger 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +228 -0
- package/dist/client/breadcrumbs.d.ts +15 -0
- package/dist/client/breadcrumbs.d.ts.map +1 -0
- package/dist/client/breadcrumbs.js +52 -0
- package/dist/client/breadcrumbs.js.map +1 -0
- package/dist/client/errorHandler.d.ts +5 -0
- package/dist/client/errorHandler.d.ts.map +1 -0
- package/dist/client/errorHandler.js +19 -0
- package/dist/client/errorHandler.js.map +1 -0
- package/dist/client/index.d.ts +6 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +16 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/logger.d.ts +40 -0
- package/dist/client/logger.d.ts.map +1 -0
- package/dist/client/logger.js +199 -0
- package/dist/client/logger.js.map +1 -0
- package/dist/client/rateLimiter.d.ts +12 -0
- package/dist/client/rateLimiter.d.ts.map +1 -0
- package/dist/client/rateLimiter.js +80 -0
- package/dist/client/rateLimiter.js.map +1 -0
- package/dist/functions/index.d.ts +12 -0
- package/dist/functions/index.d.ts.map +1 -0
- package/dist/functions/index.js +21 -0
- package/dist/functions/index.js.map +1 -0
- package/dist/functions/logHandler.d.ts +27 -0
- package/dist/functions/logHandler.d.ts.map +1 -0
- package/dist/functions/logHandler.js +137 -0
- package/dist/functions/logHandler.js.map +1 -0
- package/dist/functions/logger.d.ts +32 -0
- package/dist/functions/logger.d.ts.map +1 -0
- package/dist/functions/logger.js +253 -0
- package/dist/functions/logger.js.map +1 -0
- package/dist/functions/requestLogger.d.ts +30 -0
- package/dist/functions/requestLogger.d.ts.map +1 -0
- package/dist/functions/requestLogger.js +45 -0
- package/dist/functions/requestLogger.js.map +1 -0
- package/dist/functions/sourceMapCache.d.ts +9 -0
- package/dist/functions/sourceMapCache.d.ts.map +1 -0
- package/dist/functions/sourceMapCache.js +107 -0
- package/dist/functions/sourceMapCache.js.map +1 -0
- package/dist/functions/symbolicate.d.ts +31 -0
- package/dist/functions/symbolicate.d.ts.map +1 -0
- package/dist/functions/symbolicate.js +112 -0
- package/dist/functions/symbolicate.js.map +1 -0
- package/dist/shared/types.d.ts +36 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +3 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +152 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/installSkills.d.ts +6 -0
- package/dist/tools/installSkills.d.ts.map +1 -0
- package/dist/tools/installSkills.js +89 -0
- package/dist/tools/installSkills.js.map +1 -0
- package/dist/tools/packDeploy.d.ts +15 -0
- package/dist/tools/packDeploy.d.ts.map +1 -0
- package/dist/tools/packDeploy.js +148 -0
- package/dist/tools/packDeploy.js.map +1 -0
- package/dist/tools/uploadSourceMaps.d.ts +9 -0
- package/dist/tools/uploadSourceMaps.d.ts.map +1 -0
- package/dist/tools/uploadSourceMaps.js +120 -0
- package/dist/tools/uploadSourceMaps.js.map +1 -0
- package/package.json +103 -0
- package/skills/logs/SKILL.md +185 -0
- package/skills/query-logs/SKILL.md +93 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# /logs — Logging Validation Skill
|
|
2
|
+
|
|
3
|
+
Validate frontend and backend logging implementation for a given file.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Phase 0 — Detect File Type
|
|
8
|
+
|
|
9
|
+
Identify whether the target file is frontend or backend:
|
|
10
|
+
|
|
11
|
+
**Frontend:** path starts with `src/`, imports from `firebase-structured-logger/client`, uses `logError/logWarn/logInfo/logDebug` or `bc.*`
|
|
12
|
+
**Backend:** path starts with `functions/src/`, imports from `firebase-structured-logger/functions`, uses `initRequestLogger/getLogger/logError/logWarn/logInfo/logDebug`
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Phase 1 — Delegate to Explore Agent
|
|
17
|
+
|
|
18
|
+
**Never analyze directly — always delegate to preserve main conversation context.**
|
|
19
|
+
|
|
20
|
+
Build a task for the Explore agent:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
Read these files:
|
|
24
|
+
1. src/main.tsx (or app entry point) — find initLogger<AppLabels>() call, identify AppLabels type name
|
|
25
|
+
2. The AppLabels type definition file — read all label field names
|
|
26
|
+
3. [TARGET_FILE] — the file to analyze
|
|
27
|
+
|
|
28
|
+
File type: [FRONTEND|BACKEND]
|
|
29
|
+
|
|
30
|
+
Report back:
|
|
31
|
+
- AppLabels type name and all its fields
|
|
32
|
+
- For BACKEND: also note which AppLabels fields appear in request.data or function params
|
|
33
|
+
- Full contents of the target file with line numbers
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Phase 2 — Analyze
|
|
39
|
+
|
|
40
|
+
Using the Explore agent's output, check the target file against the rules below.
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
### Frontend Rules
|
|
45
|
+
|
|
46
|
+
**Imports**
|
|
47
|
+
- Must use `logError/logWarn/logInfo/logDebug` from the project's logger utility (e.g. `src/utils/logger.ts`)
|
|
48
|
+
- Must use `bc` from `firebase-structured-logger/client` for breadcrumbs
|
|
49
|
+
- Never use `console.error()` directly — always use the logger
|
|
50
|
+
|
|
51
|
+
**Error paths**
|
|
52
|
+
- Every `catch` block must call `logError`
|
|
53
|
+
- `logError` accepts `unknown` — never cast with `as Error`
|
|
54
|
+
- Do not pass `errorType` explicitly unless overriding the auto-derived value from `error.name`
|
|
55
|
+
|
|
56
|
+
**Breadcrumbs**
|
|
57
|
+
|
|
58
|
+
Breadcrumbs reconstruct what the user was doing before an error — a session timeline, not just a wrapper around service calls. They belong primarily in components and screens, not service files.
|
|
59
|
+
|
|
60
|
+
UX-layer breadcrumbs to check for (flag if missing):
|
|
61
|
+
- Screen/route changes → `bc.nav('ScreenName')`
|
|
62
|
+
- Modal open/close → `bc.action('open_item_modal', { itemId })`
|
|
63
|
+
- Tab switches → `bc.action('switch_tab', { tab })`
|
|
64
|
+
- Explicit user decisions → `bc.action('merge_chosen')`, `bc.action('discard_changes')`
|
|
65
|
+
- Scan/camera events → `bc.action('barcode_scanned', { barcode })`
|
|
66
|
+
|
|
67
|
+
Service-layer breadcrumbs (secondary — useful but not sufficient on their own):
|
|
68
|
+
- Before a Firestore/API call → `bc.action('save_item', { itemId })`
|
|
69
|
+
- On error → `bc.error('save_failed', { itemId })`
|
|
70
|
+
|
|
71
|
+
**A component file with no UX-layer breadcrumbs is almost certainly missing them. A service file with only service-layer breadcrumbs may be fine.**
|
|
72
|
+
|
|
73
|
+
API:
|
|
74
|
+
- `bc.action(name: string, data?)` — user-initiated operations and decisions
|
|
75
|
+
- `bc.state(name: string, data?)` — significant state changes
|
|
76
|
+
- `bc.nav(screen: string)` — screen/route changes
|
|
77
|
+
- `bc.error(type: string, data?)` — when an error occurs
|
|
78
|
+
|
|
79
|
+
**Label completeness**
|
|
80
|
+
- For each function, check which `AppLabels` fields are in scope as variables
|
|
81
|
+
- Flag any that are not passed to the log call
|
|
82
|
+
|
|
83
|
+
**Rate limiting**
|
|
84
|
+
- Never log inside loops
|
|
85
|
+
- Never log on every keystroke or render
|
|
86
|
+
|
|
87
|
+
**PII**
|
|
88
|
+
- No email, name, address in labels or context
|
|
89
|
+
- `userId` is OK; full user objects are not
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### Backend Rules
|
|
94
|
+
|
|
95
|
+
**Imports**
|
|
96
|
+
- Must import from `firebase-structured-logger/functions`
|
|
97
|
+
- Use `logError/logWarn/logInfo/logDebug` — never `console.log/console.error` directly
|
|
98
|
+
|
|
99
|
+
**`initRequestLogger` — mandatory at function entry**
|
|
100
|
+
- Every `onCall` handler must call `initRequestLogger<AppLabels>(request, { functionName, labels })` as the first line
|
|
101
|
+
- Auto-seeds `userId` and `functionName` — do not pass these manually in labels
|
|
102
|
+
- Any `AppLabels` fields present in `request.data` or function params should be passed in `labels`
|
|
103
|
+
- Flag missing `initRequestLogger` as a critical violation
|
|
104
|
+
|
|
105
|
+
**Error paths**
|
|
106
|
+
- Every `catch` block must call `logError`
|
|
107
|
+
- `logError` accepts `unknown` — never cast with `as Error`
|
|
108
|
+
- Do not pass `errorType` explicitly unless overriding the auto-derived value from `error.name`
|
|
109
|
+
|
|
110
|
+
**Label completeness**
|
|
111
|
+
- For each log call, check which `AppLabels` fields are in scope
|
|
112
|
+
- Fields already seeded via `initRequestLogger` labels do not need repeating
|
|
113
|
+
- Flag any in-scope fields not seeded at entry or passed on the log call
|
|
114
|
+
|
|
115
|
+
**PII**
|
|
116
|
+
- Same rules as frontend
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Output Format
|
|
121
|
+
|
|
122
|
+
Report in three sections:
|
|
123
|
+
|
|
124
|
+
### Violations
|
|
125
|
+
```
|
|
126
|
+
Line <N>: <description>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Missing Logging
|
|
130
|
+
```
|
|
131
|
+
Line <N>: <what should be logged and why>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Label Completeness
|
|
135
|
+
```
|
|
136
|
+
Function <name>: missing labels [<label1>, <label2>] — these entities are in scope
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
If no issues found in a section, write "None."
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Phase 3 — Fix
|
|
144
|
+
|
|
145
|
+
When asked to fix violations found in Phase 2, use the FSL API Reference below. Do not read `firebase-structured-logger` source files — the reference is authoritative.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## FSL API Reference
|
|
150
|
+
|
|
151
|
+
### Frontend
|
|
152
|
+
Import from project logger utility (e.g. `src/utils/logger.ts`):
|
|
153
|
+
```ts
|
|
154
|
+
logError(raw: unknown, labels?: Partial<AppLabels>, context?: Record<string, unknown>, attachments?: Record<string, Blob | File | string>): Promise<void>
|
|
155
|
+
logWarn(message: string, labels?: Partial<AppLabels>, context?: Record<string, unknown>, attachments?: Record<string, Blob | File | string>): Promise<void>
|
|
156
|
+
logInfo(message: string, labels?: Partial<AppLabels>, context?: Record<string, unknown>, attachments?: Record<string, Blob | File | string>): Promise<void>
|
|
157
|
+
logDebug(message: string, labels?: Partial<AppLabels>, context?: Record<string, unknown>, attachments?: Record<string, Blob | File | string>): Promise<void>
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Import `bc` from `firebase-structured-logger/client`:
|
|
161
|
+
```ts
|
|
162
|
+
bc.action(name: string, data?: Record<string, unknown>): void // before operations
|
|
163
|
+
bc.state(name: string, data?: Record<string, unknown>): void // on state changes
|
|
164
|
+
bc.nav(screen: string): void // on navigation
|
|
165
|
+
bc.error(type: string, data?: Record<string, unknown>): void // on errors
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Backend
|
|
169
|
+
Import from `firebase-structured-logger/functions`:
|
|
170
|
+
```ts
|
|
171
|
+
// Call first in every onCall handler — auto-seeds userId and functionName
|
|
172
|
+
initRequestLogger<AppLabels>(request, { functionName: 'myFunc', labels: { organizationId: request.data.organizationId } })
|
|
173
|
+
|
|
174
|
+
logError(raw: unknown, labels?: Record<string, string | undefined>, context?: Record<string, unknown>, attachments?: Record<string, string | Buffer>): void
|
|
175
|
+
logWarn(message: string, labels?: Record<string, string | undefined>, context?: Record<string, unknown>, attachments?: Record<string, string | Buffer>): void
|
|
176
|
+
logInfo(message: string, labels?: Record<string, string | undefined>, context?: Record<string, unknown>, attachments?: Record<string, string | Buffer>): void
|
|
177
|
+
logDebug(message: string, labels?: Record<string, string | undefined>, context?: Record<string, unknown>, attachments?: Record<string, string | Buffer>): void
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Key behaviours
|
|
181
|
+
- `logError` auto-derives `errorType` from `error.name` — only pass explicitly to override (e.g. `{ errorType: 'DatabaseError' }`)
|
|
182
|
+
- `logError` accepts `unknown` — never cast with `as Error`
|
|
183
|
+
- `initRequestLogger` auto-seeds `userId` (from `request.auth.uid`) and `functionName` — do not pass these in labels
|
|
184
|
+
- Every log entry includes `labels.logId` (ULID) — if `attachments` are passed, they are uploaded to GCS at `logAttachments/{logId}/{name}` fire-and-forget; upload failure never blocks the log entry
|
|
185
|
+
- When catching an error, check if there are attachments in scope (images, file snapshots, captured data) that would help reproduce or diagnose it — if so, pass them via `attachments`
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# /query-logs — Cloud Logging Query Skill
|
|
2
|
+
|
|
3
|
+
Query structured logs written by firebase-structured-logger using the firebase-mcp-server.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
The `firebase_functions_logs` MCP tool reads from:
|
|
8
|
+
- **Production**: Google Cloud Logging (default)
|
|
9
|
+
- **Development**: Local JSONL file when `DEV_LOG_FILE` env var is set in the MCP server
|
|
10
|
+
|
|
11
|
+
## Queryable Labels
|
|
12
|
+
|
|
13
|
+
All entries written by firebase-structured-logger include these labels:
|
|
14
|
+
|
|
15
|
+
| Label | Description |
|
|
16
|
+
|-------|-------------|
|
|
17
|
+
| `appId` | Application identifier (e.g. `acme`, `store`) |
|
|
18
|
+
| `userId` | Firebase Auth UID |
|
|
19
|
+
| `screen` | Current screen name |
|
|
20
|
+
| `releaseId` | Git short hash or explicit release ID |
|
|
21
|
+
| `platform` | `ios`, `android`, `macos`, `windows`, `web` |
|
|
22
|
+
| `browser` | `chrome`, `firefox`, `safari`, `edge` |
|
|
23
|
+
| `errorType` | Error class name (e.g. `TypeError`, `NetworkError`) |
|
|
24
|
+
| `errorCategory` | `crash` for unhandled errors |
|
|
25
|
+
| `functionName` | Cloud Function name (server-side logs only) |
|
|
26
|
+
| `logId` | ULID — unique per log entry, used to locate attachments in GCS |
|
|
27
|
+
| `hasAttachments` | `'true'` when attachments were uploaded alongside this entry |
|
|
28
|
+
|
|
29
|
+
App-specific labels are defined in each app's `AppLabels` type.
|
|
30
|
+
|
|
31
|
+
## Common Queries
|
|
32
|
+
|
|
33
|
+
### All errors for a user
|
|
34
|
+
```
|
|
35
|
+
labels.userId="<uid>" severity=ERROR
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Errors on a specific screen
|
|
39
|
+
```
|
|
40
|
+
labels.screen="<screen>" severity=ERROR
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Unhandled crashes
|
|
44
|
+
```
|
|
45
|
+
labels.errorCategory="crash"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Logs from a specific release
|
|
49
|
+
```
|
|
50
|
+
labels.releaseId="<hash>"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Recent errors (last hour)
|
|
54
|
+
```
|
|
55
|
+
severity=ERROR timestamp>="<ISO8601>"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Retrieving Attachments
|
|
59
|
+
|
|
60
|
+
When a log entry has `labels.hasAttachments = "true"`, files were uploaded to GCS alongside it.
|
|
61
|
+
|
|
62
|
+
**Step 1 — Find entries with attachments:**
|
|
63
|
+
```
|
|
64
|
+
labels.hasAttachments="true"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**Step 2 — List attachments for an entry:**
|
|
68
|
+
|
|
69
|
+
Use `firebase_storage_ls` with the path `logAttachments/{logId}/` to see what files are present.
|
|
70
|
+
|
|
71
|
+
**Step 3 — Download and analyze:**
|
|
72
|
+
|
|
73
|
+
Use `firebase_storage_read` with path `logAttachments/{logId}/{filename}` — this downloads the file to `/tmp` and returns a `tempPath`. Then use the `Read` tool on `tempPath` to analyze the content.
|
|
74
|
+
|
|
75
|
+
**Example flow:**
|
|
76
|
+
```
|
|
77
|
+
1. Query logs → find entry with logId "01KJBK2QBC5GJGMYZ5GT1Q5TQ6"
|
|
78
|
+
2. firebase_storage_ls path: "logAttachments/01KJBK2QBC5GJGMYZ5GT1Q5TQ6/"
|
|
79
|
+
3. firebase_storage_read path: "logAttachments/01KJBK2QBC5GJGMYZ5GT1Q5TQ6/photo.jpg"
|
|
80
|
+
4. Read tool on tempPath → analyze image in context of the error
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Only check GCS when `hasAttachments = "true"` — entries without it have no files.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Development (Local JSONL)
|
|
88
|
+
|
|
89
|
+
When running with Firebase Emulator, logs are written to the path configured in `initLogger({ devLogFile })`.
|
|
90
|
+
|
|
91
|
+
Set `DEV_LOG_FILE=/path/to/logs.jsonl` in the MCP server environment to enable local log reading.
|
|
92
|
+
|
|
93
|
+
Each JSONL line is a JSON object matching Cloud Logging structure for query compatibility.
|