some Honeycomb fixes

We got bit by the "can't run anything after the response finishes" thing

so I'm just forcing the response to wait for Honeycomb submit to finish

I hope this isn't like, just awful for perf lol. but puts to honeycomb seem fast?
This commit is contained in:
Emi Matchu 2020-08-17 01:16:35 -07:00
parent ce028e4956
commit f7997b4dc9
4 changed files with 59 additions and 44 deletions

View file

@ -1,5 +1,25 @@
const beeline = require("honeycomb-beeline")({
writeKey: process.env["HONEYCOMB_WRITE_KEY"],
dataset:
process.env["NODE_ENV"] === "production"
? "Dress to Impress (2020)"
: "Dress to Impress (2020, dev)",
serviceName: "impress-2020-gql-server",
});
const { ApolloServer } = require("../src/server/lib/apollo-server-vercel");
const { config } = require("../src/server");
const server = new ApolloServer(config);
module.exports = server.createHandler();
const serverHandler = server.createHandler();
export default async (req, res) => {
await serverHandler(req, res);
// As a sneaky trick, we require the Honeycomb trace to finish before the
// request formally finishes. This... is technically a slowdown, I'm not sure
// how much of one. Hopefully not too much?
// https://vercel.com/docs/platform/limits#streaming-responses
await beeline.flush();
res.end();
};

View file

@ -1,12 +1,3 @@
require("honeycomb-beeline")({
writeKey: process.env["HONEYCOMB_WRITE_KEY"],
dataset:
process.env["NODE_ENV"] === "production"
? "Dress to Impress (2020)"
: "Dress to Impress (2020, dev)",
serviceName: "impress-2020-gql-server",
});
const { gql, makeExecutableSchema } = require("apollo-server");
import { addBeelineToSchema, beelinePlugin } from "./lib/beeline-graphql";

View file

@ -17,35 +17,37 @@ function graphqlVercel(options) {
);
}
const graphqlHandler = (req, res) => {
const graphqlHandler = async (req, res) => {
if (req.httpMethod === "POST" && !req.body) {
return res.status(500).send("POST body missing.");
res.status(500).write("POST body missing.");
return;
}
runHttpQuery([req, res], {
method: req.method,
options: options,
query: req.method === "POST" && req.body ? req.body : req.query,
request: {
url: req.path,
let result;
try {
result = await runHttpQuery([req, res], {
method: req.method,
headers: new Headers(req.headers),
},
}).then(
({ graphqlResponse, responseInit }) => {
setHeaders(res, new Headers(responseInit.headers)).send(
graphqlResponse
);
},
(error) => {
if ("HttpQueryError" !== error.name) {
console.error(error);
return;
}
setHeaders(res, new Headers(error.headers))
.status(error.statusCode)
.send(error.message);
options: options,
query: req.method === "POST" && req.body ? req.body : req.query,
request: {
url: req.path,
method: req.method,
headers: new Headers(req.headers),
},
});
} catch (error) {
if ("HttpQueryError" !== error.name) {
console.error(error);
return;
}
);
setHeaders(res, new Headers(error.headers))
.status(error.statusCode)
.write(error.message);
return;
}
const { graphqlResponse, responseInit } = result;
setHeaders(res, new Headers(responseInit.headers));
res.write(graphqlResponse);
};
return graphqlHandler;
@ -122,7 +124,7 @@ class ApolloServer extends ApolloServerBase {
}
}
return (req, res) => {
return async (req, res) => {
// Make a request-specific copy of the CORS headers, based on the server
// global CORS headers we've set above.
const requestCorsHeaders = new Headers(corsHeaders);
@ -164,7 +166,8 @@ class ApolloServer extends ApolloServerBase {
);
if (res.method === "OPTIONS") {
setHeaders(res, requestCorsHeadersObject).status(204).send("");
setHeaders(res, requestCorsHeadersObject).status(204);
return;
}
if (this.playgroundOptions && req.method === "GET") {
@ -177,7 +180,7 @@ class ApolloServer extends ApolloServerBase {
...this.playgroundOptions,
};
return setHeaders(
setHeaders(
res,
new Headers({
"Content-Type": "text/html",
@ -185,11 +188,12 @@ class ApolloServer extends ApolloServerBase {
})
)
.status(200)
.send(renderPlaygroundPage(playgroundRenderPageOptions));
.write(renderPlaygroundPage(playgroundRenderPageOptions));
return;
}
}
graphqlVercel(async () => {
await graphqlVercel(async () => {
// In a world where this `createHandler` was async, we might avoid this
// but since we don't want to introduce a breaking change to this API
// (by switching it to `async`), we'll leverage the

View file

@ -18,8 +18,6 @@ export function addBeelineToSchema(schema) {
result = oldResolve(source, args, { ...context, span }, info);
if (result.then) await result;
} catch (error) {
// TODO(matchu): Not sure why this is here, it seems like we should
// re-throw the error, and even then this seems to not be happening?
span.addContext({ "error.message": error.message });
span.addContext({ "error.stacktrace": error.stack });
}
@ -75,8 +73,10 @@ export const beelinePlugin = {
const trace = beeline.startTrace();
return {
didResolveOperation({ operationName }) {
trace.payload["name"] = operationName;
trace.payload["operation_name"] = operationName;
beeline.addContext({
name: operationName,
operation_name: operationName,
});
},
willSendResponse() {
beeline.finishTrace(trace);