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:
parent
ce028e4956
commit
f7997b4dc9
4 changed files with 59 additions and 44 deletions
|
@ -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 { ApolloServer } = require("../src/server/lib/apollo-server-vercel");
|
||||||
const { config } = require("../src/server");
|
const { config } = require("../src/server");
|
||||||
|
|
||||||
const server = new ApolloServer(config);
|
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();
|
||||||
|
};
|
||||||
|
|
|
@ -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");
|
const { gql, makeExecutableSchema } = require("apollo-server");
|
||||||
import { addBeelineToSchema, beelinePlugin } from "./lib/beeline-graphql";
|
import { addBeelineToSchema, beelinePlugin } from "./lib/beeline-graphql";
|
||||||
|
|
||||||
|
|
|
@ -17,35 +17,37 @@ function graphqlVercel(options) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const graphqlHandler = (req, res) => {
|
const graphqlHandler = async (req, res) => {
|
||||||
if (req.httpMethod === "POST" && !req.body) {
|
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], {
|
let result;
|
||||||
method: req.method,
|
try {
|
||||||
options: options,
|
result = await runHttpQuery([req, res], {
|
||||||
query: req.method === "POST" && req.body ? req.body : req.query,
|
|
||||||
request: {
|
|
||||||
url: req.path,
|
|
||||||
method: req.method,
|
method: req.method,
|
||||||
headers: new Headers(req.headers),
|
options: options,
|
||||||
},
|
query: req.method === "POST" && req.body ? req.body : req.query,
|
||||||
}).then(
|
request: {
|
||||||
({ graphqlResponse, responseInit }) => {
|
url: req.path,
|
||||||
setHeaders(res, new Headers(responseInit.headers)).send(
|
method: req.method,
|
||||||
graphqlResponse
|
headers: new Headers(req.headers),
|
||||||
);
|
},
|
||||||
},
|
});
|
||||||
(error) => {
|
} catch (error) {
|
||||||
if ("HttpQueryError" !== error.name) {
|
if ("HttpQueryError" !== error.name) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
setHeaders(res, new Headers(error.headers))
|
|
||||||
.status(error.statusCode)
|
|
||||||
.send(error.message);
|
|
||||||
}
|
}
|
||||||
);
|
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;
|
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
|
// Make a request-specific copy of the CORS headers, based on the server
|
||||||
// global CORS headers we've set above.
|
// global CORS headers we've set above.
|
||||||
const requestCorsHeaders = new Headers(corsHeaders);
|
const requestCorsHeaders = new Headers(corsHeaders);
|
||||||
|
@ -164,7 +166,8 @@ class ApolloServer extends ApolloServerBase {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (res.method === "OPTIONS") {
|
if (res.method === "OPTIONS") {
|
||||||
setHeaders(res, requestCorsHeadersObject).status(204).send("");
|
setHeaders(res, requestCorsHeadersObject).status(204);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.playgroundOptions && req.method === "GET") {
|
if (this.playgroundOptions && req.method === "GET") {
|
||||||
|
@ -177,7 +180,7 @@ class ApolloServer extends ApolloServerBase {
|
||||||
...this.playgroundOptions,
|
...this.playgroundOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
return setHeaders(
|
setHeaders(
|
||||||
res,
|
res,
|
||||||
new Headers({
|
new Headers({
|
||||||
"Content-Type": "text/html",
|
"Content-Type": "text/html",
|
||||||
|
@ -185,11 +188,12 @@ class ApolloServer extends ApolloServerBase {
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.status(200)
|
.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
|
// 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
|
// but since we don't want to introduce a breaking change to this API
|
||||||
// (by switching it to `async`), we'll leverage the
|
// (by switching it to `async`), we'll leverage the
|
||||||
|
|
|
@ -18,8 +18,6 @@ export function addBeelineToSchema(schema) {
|
||||||
result = oldResolve(source, args, { ...context, span }, info);
|
result = oldResolve(source, args, { ...context, span }, info);
|
||||||
if (result.then) await result;
|
if (result.then) await result;
|
||||||
} catch (error) {
|
} 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.message": error.message });
|
||||||
span.addContext({ "error.stacktrace": error.stack });
|
span.addContext({ "error.stacktrace": error.stack });
|
||||||
}
|
}
|
||||||
|
@ -75,8 +73,10 @@ export const beelinePlugin = {
|
||||||
const trace = beeline.startTrace();
|
const trace = beeline.startTrace();
|
||||||
return {
|
return {
|
||||||
didResolveOperation({ operationName }) {
|
didResolveOperation({ operationName }) {
|
||||||
trace.payload["name"] = operationName;
|
beeline.addContext({
|
||||||
trace.payload["operation_name"] = operationName;
|
name: operationName,
|
||||||
|
operation_name: operationName,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
willSendResponse() {
|
willSendResponse() {
|
||||||
beeline.finishTrace(trace);
|
beeline.finishTrace(trace);
|
||||||
|
|
Loading…
Reference in a new issue