Skip to content

Commit f331394

Browse files
Better error message for AbortError (#604)
* Better error message for `AbortError` * Remove bad change to greeter
1 parent 5dacabc commit f331394

File tree

3 files changed

+95
-9
lines changed

3 files changed

+95
-9
lines changed

packages/restate-sdk/src/endpoint/handlers/generic.ts

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ import {
1717
TerminalError,
1818
} from "../../types/errors.js";
1919
import type {
20-
ProtocolMode,
2120
Endpoint as EndpointManifest,
21+
ProtocolMode,
2222
} from "../discovery.js";
2323
import type { Component, ComponentHandler } from "../components.js";
2424
import { parseUrlComponents } from "../components.js";
@@ -37,6 +37,7 @@ import {
3737
} from "../../logging/console_logger_transport.js";
3838
import {
3939
LoggerContext,
40+
type LoggerTransport,
4041
LogSource,
4142
RestateLogLevel,
4243
} from "../../logging/logger_transport.js";
@@ -83,6 +84,47 @@ const ENDPOINT_MANIFEST_V2 = "application/vnd.restate.endpointmanifest.v2+json";
8384
const ENDPOINT_MANIFEST_V3 = "application/vnd.restate.endpointmanifest.v3+json";
8485
const ENDPOINT_MANIFEST_V4 = "application/vnd.restate.endpointmanifest.v4+json";
8586

87+
export function tryCreateContextualLogger(
88+
loggerTransport: LoggerTransport,
89+
url: string,
90+
headers: Headers,
91+
additionalContext?: { [name: string]: string }
92+
): Logger | undefined {
93+
try {
94+
const path = new URL(url, "https://example.com").pathname;
95+
const parsed = parseUrlComponents(path);
96+
if (parsed.type !== "invoke") {
97+
return undefined;
98+
}
99+
const invocationId = invocationIdFromHeaders(headers);
100+
return createLogger(
101+
loggerTransport,
102+
LogSource.SYSTEM,
103+
new LoggerContext(
104+
invocationId,
105+
parsed.componentName,
106+
parsed.handlerName,
107+
undefined,
108+
undefined,
109+
additionalContext
110+
)
111+
);
112+
} catch (e) {
113+
return undefined;
114+
}
115+
}
116+
117+
function invocationIdFromHeaders(headers: Headers) {
118+
const invocationIdHeader = headers["x-restate-invocation-id"];
119+
const invocationId =
120+
typeof invocationIdHeader === "string"
121+
? invocationIdHeader
122+
: Array.isArray(invocationIdHeader)
123+
? invocationIdHeader[0] ?? "unknown id"
124+
: "unknown id";
125+
return invocationId;
126+
}
127+
86128
/**
87129
* This is an internal API to support 'fetch' like handlers.
88130
* It supports both request-reply mode and bidirectional streaming mode.
@@ -130,8 +172,14 @@ export class GenericHandler implements RestateHandler {
130172
return await this._handle(request, context);
131173
} catch (e) {
132174
const error = ensureError(e);
133-
this.endpoint.rlog.error(
134-
"Error while handling invocation: " + (error.stack ?? error.message)
175+
(
176+
tryCreateContextualLogger(
177+
this.endpoint.loggerTransport,
178+
request.url,
179+
request.headers
180+
) ?? this.endpoint.rlog
181+
).error(
182+
"Error while handling request: " + (error.stack ?? error.message)
135183
);
136184
return this.toErrorResponse(
137185
error instanceof RestateError ? error.code : 500,
@@ -285,7 +333,14 @@ export class GenericHandler implements RestateHandler {
285333
createLogger(
286334
this.endpoint.loggerTransport,
287335
LogSource.JOURNAL,
288-
undefined
336+
new LoggerContext(
337+
invocationIdFromHeaders(headers),
338+
service.name(),
339+
handler.name(),
340+
undefined,
341+
undefined,
342+
additionalContext
343+
)
289344
)
290345
);
291346

packages/restate-sdk/src/endpoint/handlers/lambda.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import type {
2222
RestateRequest,
2323
RestateResponse,
2424
} from "./generic.js";
25+
import { tryCreateContextualLogger } from "./generic.js";
2526
import { WritableStream, type ReadableStream } from "node:stream/web";
2627
import { OnceStream } from "../../utils/streams.js";
2728
import { X_RESTATE_SERVER } from "../../user_agent.js";
@@ -131,7 +132,13 @@ export class LambdaHandler {
131132
} catch (e) {
132133
// unlike in the streaming case, we can actually catch errors in the response body and form a nicer error
133134
const error = ensureError(e);
134-
this.handler.endpoint.rlog.error(
135+
(
136+
tryCreateContextualLogger(
137+
this.handler.endpoint.loggerTransport,
138+
request.url,
139+
request.headers
140+
) ?? this.handler.endpoint.rlog
141+
).error(
135142
"Error while collecting invocation response: " +
136143
(error.stack ?? error.message)
137144
);

packages/restate-sdk/src/endpoint/node_endpoint.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ import type { Http2ServerRequest, Http2ServerResponse } from "http2";
2424
import * as http2 from "http2";
2525
import type { Endpoint } from "./endpoint.js";
2626
import { EndpointBuilder } from "./endpoint.js";
27-
import { GenericHandler } from "./handlers/generic.js";
27+
import {
28+
GenericHandler,
29+
tryCreateContextualLogger,
30+
} from "./handlers/generic.js";
2831
import { Readable, Writable } from "node:stream";
2932
import type { WritableStream } from "node:stream/web";
3033
import { ensureError } from "../types/errors.js";
@@ -155,9 +158,30 @@ function nodeHttp2Handler(
155158
await resp.body.pipeTo(responseWeb);
156159
} catch (e) {
157160
const error = ensureError(e);
158-
endpoint.rlog.error(
159-
"Error while handling connection: " + (error.stack ?? error.message)
160-
);
161+
162+
const logger =
163+
tryCreateContextualLogger(
164+
endpoint.loggerTransport,
165+
request.url,
166+
request.headers
167+
) ?? endpoint.rlog;
168+
if (error.name === "AbortError") {
169+
logger.error(
170+
"Got abort error from connection: " +
171+
error.message +
172+
"\n" +
173+
"This might indicate that:\n" +
174+
"* The restate-server aborted the connection after hitting the 'abort-timeout'\n" +
175+
"* The connection with the restate-server was lost\n" +
176+
"\n" +
177+
"Please check the invocation in the Restate UI for more details."
178+
);
179+
} else {
180+
logger.error(
181+
"Error while handling request: " + (error.stack ?? error.message)
182+
);
183+
}
184+
161185
response.destroy(error);
162186
abortController.abort();
163187
}

0 commit comments

Comments
 (0)