@sentry/google-cloud-serverless
Version:
Official Sentry SDK for Google Cloud Functions
71 lines (68 loc) • 3.21 kB
JavaScript
import { URL_PATH, HTTP_REQUEST_METHOD, SENTRY_ORIGIN, SENTRY_SEGMENT_NAME_SOURCE, FAAS_TRIGGER, FAAS_NAME, SENTRY_OP } from '@sentry/conventions/attributes';
import { FUNCTION_GCP } from '@sentry/conventions/op';
import { stripUrlQueryAndFragment, isString, httpRequestToRequestData, getClient, hasSpanStreamingEnabled, SERVERLESS_FUNCTION_SPAN_NAME_FALLBACK, setHttpStatus, debug, handleCallbackErrors } from '@sentry/core';
import { continueTrace, getCurrentScope, startSpanManual, flush, captureException } from '@sentry/node';
import { DEBUG_BUILD } from '../debug-build.js';
import { proxyFunction, domainify, getFunctionName, markEventUnhandled } from '../utils.js';
function wrapHttpFunction(fn, wrapOptions = {}) {
const wrap = (f) => domainify(_wrapHttpFunction(f, wrapOptions));
let overrides;
const emulatorFunc = fn.__emulator_func;
if (emulatorFunc) {
overrides = { __emulator_func: proxyFunction(emulatorFunc, wrap) };
}
return proxyFunction(fn, wrap, overrides);
}
function _wrapHttpFunction(fn, options) {
const flushTimeout = options.flushTimeout || 2e3;
return (req, res) => {
const reqMethod = (req.method || "").toUpperCase();
const reqUrl = stripUrlQueryAndFragment(req.originalUrl || req.url || "");
const sentryTrace = req.headers && isString(req.headers["sentry-trace"]) ? req.headers["sentry-trace"] : void 0;
const baggage = req.headers?.baggage;
return continueTrace({ sentryTrace, baggage }, () => {
const normalizedRequest = httpRequestToRequestData(req);
getCurrentScope().setSDKProcessingMetadata({ normalizedRequest });
const functionName = getFunctionName();
const client = getClient();
const hasSpanStreaming = client && hasSpanStreamingEnabled(client);
const name = hasSpanStreaming ? functionName || SERVERLESS_FUNCTION_SPAN_NAME_FALLBACK : `${reqMethod} ${reqUrl}`;
return startSpanManual(
{
name,
attributes: {
[SENTRY_OP]: FUNCTION_GCP,
[FAAS_NAME]: functionName,
[FAAS_TRIGGER]: "http",
[SENTRY_SEGMENT_NAME_SOURCE]: hasSpanStreaming ? "component" : "route",
[SENTRY_ORIGIN]: "auto.function.serverless.gcp_http",
// The method and path used to be the span name; they stay on the span so that
// information survives the low-cardinality rename.
[HTTP_REQUEST_METHOD]: reqMethod || void 0,
[URL_PATH]: reqUrl || void 0
}
},
(span) => {
const _end = res.end;
res.end = function(chunk, encoding, cb) {
setHttpStatus(span, res.statusCode);
span.end();
flush(flushTimeout).then(null, (e) => {
DEBUG_BUILD && debug.error(e);
}).then(() => {
_end.call(this, chunk, encoding, cb);
});
};
return handleCallbackErrors(
() => fn(req, res),
(err) => {
captureException(err, (scope) => markEventUnhandled(scope, "auto.function.serverless.gcp_http"));
}
);
}
);
});
};
}
export { wrapHttpFunction };
//# sourceMappingURL=http.js.map