(traceId: string)
| 184 | * id, so it is THIS request's report and not a neighbour's. |
| 185 | */ |
| 186 | const reportFor = (traceId: string): Effect.Effect<FiledReport, string> => |
| 187 | Effect.sync(() => { |
| 188 | const lines = readServerLog().split("\n"); |
| 189 | const correlated = lines.findLastIndex( |
| 190 | (line) => |
| 191 | line.includes('"event":"sentry_before_send_otel_correlation"') && |
| 192 | line.includes(`"sentry_event_id":"${traceId}"`), |
| 193 | ); |
| 194 | if (correlated === -1) return undefined; |
| 195 | const reported = lines |
| 196 | .slice(0, correlated) |
| 197 | .findLastIndex((line) => line.startsWith(REPORT_PREFIX)); |
| 198 | if (reported === -1) return undefined; |
| 199 | const block = [ |
| 200 | lines[reported]!.slice(REPORT_PREFIX.length), |
| 201 | ...lines.slice(reported + 1, correlated), |
| 202 | ]; |
| 203 | const end = block.slice(1).findIndex((line) => STACK_FRAME.test(line)); |
| 204 | return { |
| 205 | headline: block |
| 206 | .slice(0, end === -1 ? 1 : end + 1) |
| 207 | .join("\n") |
| 208 | .trimEnd(), |
| 209 | full: block.join("\n"), |
| 210 | }; |
| 211 | }).pipe( |
| 212 | Effect.filterOrFail( |
| 213 | (report): report is FiledReport => report !== undefined, |
| 214 | () => `no error report joined to trace id ${traceId} in the server log`, |
| 215 | ), |
| 216 | // The log is a file the dev stack appends to; the write lands moments after |
| 217 | // the response. Poll rather than sleep (~20s ceiling). |
| 218 | Effect.retry(Schedule.both(Schedule.spaced("500 millis"), Schedule.recurs(40))), |
| 219 | ); |
| 220 | |
| 221 | scenario( |
| 222 | "Storage · a rejected write is reported without its SQL or the caller's data", |
no test coverage detected