diff --git a/README.md b/README.md index ed2e1e3..61f34ba 100644 --- a/README.md +++ b/README.md @@ -92,14 +92,25 @@ The `send()` function is asynchronous and returns a `Promise` of type `IncomingM Note that `IncomingMessage` can be `null` if the request was stored because the application was offline. -`IncomingMessage` is the response from the Raygun API - there's nothing in the body, it's just a status code response. -If everything went ok, you'll get a 202 response code. -Otherwise, we throw 401 for incorrect API keys, 403 if you're over your plan limits, or anything in the 500+ range for internal errors. +`IncomingMessage` is the response from the Raygun API - there's nothing in the body, it's just a status code response. If everything went ok, you'll get a 202 response code. +Otherwise, we return 401 for incorrect API keys, 403 if you're over your plan limits, or anything in the 500+ range for internal errors. -We use the nodejs http/https library to make the POST to Raygun, you can see more documentation about that callback here: https://nodejs.org/api/http.html#http_http_request_options_callback +We use the nodejs http/https library to make the POST to Raygun, you can see more documentation about that callback here: https://nodejs.org/api/http.html#http_http_request_options_callback . You can `await` the call to obtain the result, or use `then/catch`. +The default timeout for the transport layer is 5000ms. You can override this value by setting a custom `timeout` (also in ms) when you initialize the Raygun client: + +```typescript +import * as Raygun from 'raygun'; + +const raygunClient = new Raygun.Client().init({ + apiKey: 'YOUR_API_KEY', + ... + timeout: 3000 // defaults to 5000ms +}); +``` + #### Using `await` Use `await` to obtain the `IncomingMessage`, remember to `catch` any possible thrown errors from the `send()` method. @@ -418,7 +429,18 @@ If your application generates and reports large volumes of errors, especially in You can control how often batches are processed and sent by providing a `batchFrequency` option, which is a number in milliseconds. -In a future version the batch transport will likely be enabled by default. +The default timeout for batch transport calls is 5000ms. You can override this value by setting a custom `timeout` (also in ms) when you initialize the Raygun client: + +```typescript +import * as Raygun from 'raygun'; + +const raygunClient = new Raygun.Client().init({ + apiKey: 'YOUR_API_KEY', + batch: true, + batchFrequency: 5000, // defaults to 1000ms (every second) + timeout: 10000 // defaults to 5000ms +}); +``` ### Offline caching diff --git a/lib/raygun.breadcrumbs.express.ts b/lib/raygun.breadcrumbs.express.ts index 7d61404..83932ed 100644 --- a/lib/raygun.breadcrumbs.express.ts +++ b/lib/raygun.breadcrumbs.express.ts @@ -27,7 +27,7 @@ export function addRequestBreadcrumb(request: Request) { }; debug( - `[raygun.breadcrumbs.express.ts] recorded request breadcrumb: ${internalCrumb}`, + `[raygun.breadcrumbs.express.ts] recorded request breadcrumb: ${JSON.stringify(internalCrumb, undefined, 2)}`, ); crumbs.push(internalCrumb); diff --git a/lib/raygun.transport.ts b/lib/raygun.transport.ts index 8ed989a..66c8f8d 100644 --- a/lib/raygun.transport.ts +++ b/lib/raygun.transport.ts @@ -18,6 +18,8 @@ const API_HOST = "api.raygun.io"; const DEFAULT_ENDPOINT = "/entries"; const BATCH_ENDPOINT = "/entries/bulk"; +const debug = require("debug")("raygun"); + export function sendBatch(options: SendOptions): Promise { return send(options, BATCH_ENDPOINT); } @@ -57,12 +59,27 @@ export function send( (response: IncomingMessage) => { // request completed successfully resolve(response); + // destroy the request after successful completion + request.destroy(); + debug( + `[raygun.transport.ts] Request destroyed for message: ${options.message}`, + ); }, ); + if (options.http.timeout) { + debug(`[raygun.transport.ts] Timeout set: ${options.http.timeout}ms`); + request.setTimeout(options.http.timeout, () => { + console.error( + `[Raygun4Node] request timed out while attempting to send error with message: ${options.message}`, + ); + request.destroy(new Error("Request timed out")); + }); + } + request.on("error", function (e) { console.error( - `[Raygun4Node] error ${e.message} occurred while attempting to send error with message: ${options.message}`, + `[Raygun4Node] Error with details "${e.message}" occurred while attempting to send error with message: ${options.message}`, ); // request failed @@ -74,7 +91,7 @@ export function send( }); } catch (e) { console.error( - `[Raygun4Node] error ${e} occurred while attempting to send error with message: ${options.message}`, + `[Raygun4Node] Error "${e}" occurred while attempting to send error with message: ${options.message}`, ); return Promise.reject(e); } diff --git a/lib/raygun.ts b/lib/raygun.ts index 808c084..2470f00 100644 --- a/lib/raygun.ts +++ b/lib/raygun.ts @@ -61,6 +61,7 @@ try { type SendCB = (error: Error | null, items: string[] | undefined) => void; const DEFAULT_BATCH_FREQUENCY = 1000; // ms +const DEFAULT_TIMEOUT = 5000; // ms function emptyCallback() {} @@ -79,6 +80,8 @@ class Raygun { _useSSL: boolean | undefined; + _timeout: number | undefined; + _onBeforeSend: Hook | undefined; _offlineStorage: IOfflineStorage | undefined; @@ -118,6 +121,7 @@ class Raygun { this._port = options.port; this._useSSL = options.useSSL !== false; this._onBeforeSend = options.onBeforeSend; + this._timeout = options.timeout; this._isOffline = options.isOffline; this._groupingKey = options.groupingKey; this._tags = options.tags; @@ -144,6 +148,7 @@ class Raygun { port: this._port, useSSL: !!this._useSSL, apiKey: this._apiKey, + timeout: this._timeout || DEFAULT_TIMEOUT, }, }); } @@ -570,7 +575,8 @@ class Raygun { host: this._host, port: this._port, useSSL: !!this._useSSL, - apiKey, + apiKey: apiKey, + timeout: this._timeout || DEFAULT_TIMEOUT, }, }, }; @@ -583,6 +589,7 @@ class Raygun { port: this._port, useSSL: this._useSSL || false, apiKey: this._apiKey || "", + timeout: this._timeout || DEFAULT_TIMEOUT, }; return { diff --git a/lib/types.ts b/lib/types.ts index 9a1408d..a071013 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -78,6 +78,7 @@ export type HTTPOptions = { host: string | undefined; port: number | undefined; apiKey: string; + timeout?: number; }; // Allow any because users are free to set anything as CustomData @@ -179,6 +180,7 @@ export type RaygunOptions = { host?: string; port?: number; useSSL?: boolean; + timeout?: number; onBeforeSend?: Hook; offlineStorage?: IOfflineStorage; offlineStorageOptions?: OfflineStorageOptions; diff --git a/test/raygun_async_send_test.js b/test/raygun_async_send_test.js index 56db0ca..f4dc414 100644 --- a/test/raygun_async_send_test.js +++ b/test/raygun_async_send_test.js @@ -48,6 +48,24 @@ test("async send complex", {}, function (t) { }); }); +test("async send complex with timeout", {}, function (t) { + t.plan(1); + + let client = new Raygun.Client() + .init({ apiKey: API_KEY, timeout: 5000 }) + .setVersion("1.0.0.0"); + + client + .send(new Error()) + .then((response) => { + t.equal(response.statusCode, 202); + t.end(); + }) + .catch((err) => { + t.fail(err); + }); +}); + test("async send with inner error", {}, function (t) { t.plan(1);