Skip to content

Sending sentry data through a serverless function #4704

Closed as not planned
Closed as not planned
@tianhuil

Description

@tianhuil

Problem Statement

A popular strategy for server-side logging is to:

A. Compute the normal request
B. Return the result to the client
C. On the same process, take the telemetry information collected in (A) and send it to the APM (e.g. Sentry).

Because (C) requires an async call to another (possibly distant) server, it can be slow, perhaps even slower than (A). Also, (C) must start after (A) completes as (C) describes the performance of (A).

Ideally, we would execute (B) before beginning (C). This can be done in Express because res.send is just an ordinary command that terminates the communication stream with the client but not the express handler (Stackoverflow). However, this cannot be accomplished in Vercel because it does not support these "fire-and-forget" background tasks:

Vercel does not support streaming responses from Serverless Functions due to an upstream limitation from AWS.
This means that background tasks, also known as "fire-and-forget" is not supported. Once the Serverless Function returns the response payload, it stops processing including any pending background tasks.

Therefore, in a Vercel + Sentry stack, (B) cannot happen until after (C), creating a significant and unnecessary performance penalty. Indeed, the sentry nextjs package has to monkeypatch wrap nextjs's .end to wait until the sentry analytics have returned before returning to the client.

Solution Brainstorm

Proxy Function:

I propose that sentry/nextjs be architected as four steps:

A. Compute the normal request
B. Return the result to the client
C. On the same process, take the telemetry information collected in (A) and send it to a next serverless function (proxy function)
D. The nextjs serverless function sends the data to to APM (e.g. Sentry).

While (B) must occur after (C), (C) is now likely much faster. Indeed, it is likely that it will be sent sent to a function on the same computer, certainly in the same data center. The slow step of crossing to a potentially distant server (D), will no longer block (B), thus improving performance. The new proxy function can be very simple (e.g. takes the body and headers and forwards them to Sentry).

This solution may be useful.

Send and don't wait for acknowledgement

In Step (C) (either with with or without the proxy function), use net.Socket to send the data without waiting for Sentry to acknowledge the result (see this). Instead of completing the full http protocol, just send the header and body and stop listening for a reply. For many analytics applications, "best-effort" may be preferable if there is an accompanying speed boost.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions