New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Not working with apollo-server-lambda (Apollo GraphQL) #2832
Comments
If there is an issue here, it will be with the Node.js APM agent, and not with the Lambda ext. I'll move it over to the Node.js APM agent repo. |
@wjensen-godaddy A couple details might help with this:
|
|
The log above shows me that there is no We'll have to dig in. If you have a small code repro showing how this is being used that would help immensely. |
I think you should be able to reproduce the issue with this (I was able to using an almost identical setup): serverless.yml service: graph
frameworkVersion: "3"
plugins:
- serverless-esbuild
- serverless-offline
provider:
name: aws
runtime: nodejs14.x
region: us-west-2
environment:
NODE_OPTIONS: "-r elastic-apm-node/start"
ELASTIC_APM_LAMBDA_APM_SERVER: ${env:ELASTIC_APM_LAMBDA_APM_SERVER, ''}
ELASTIC_APM_SECRET_TOKEN: ${env:ELASTIC_APM_SECRET_TOKEN, ''}
ELASTIC_APM_LOG_LEVEL: trace
functions:
graphql:
# this is formatted as <FILENAME>.<HANDLER>
handler: src/index.graphqlHandler
layers:
- arn:aws:lambda:us-west-2:267093732750:layer:elastic-apm-extension-ver-1-0-2-x86_64:1
- arn:aws:lambda:us-west-2:267093732750:layer:elastic-apm-node-ver-3-37-0:1
events:
- http:
path: /graphql
method: post
cors: true
- http:
path: /graphql
method: get
cors: true src/index.ts const { ApolloServer, gql } = require('apollo-server-lambda');
const { ApolloServerPluginLandingPageGraphQLPlayground } = require('apollo-server-core');
// Construct a schema, using GraphQL schema language
const typeDefs = gql`
type Query {
hello: String
}
`;
// Provide resolver functions for your schema fields
const resolvers = {
Query: {
hello: () => 'Hello world!'
}
};
const server = new ApolloServer({
typeDefs,
resolvers,
// By default, the GraphQL Playground interface and GraphQL introspection
// is disabled in "production" (i.e. when `process.env.NODE_ENV` is `production`).
//
// If you'd like to have GraphQL Playground and introspection enabled in production,
// install the Playground plugin and set the `introspection` option explicitly to `true`.
introspection: true,
plugins: [ApolloServerPluginLandingPageGraphQLPlayground()]
});
exports.graphqlHandler = server.createHandler(); |
@wjensen-godaddy Thanks! I will hopefully be able to dig into this soon. However, before then, a thing from your serverless.yml jumps out at me:
It is likely that esbuild's bundling is breaking the APM agent's attempt to instrument modules. The bundling necessarily replaces use of node's core ...
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
...
// node_modules/somemodule/index.js
var require_somemodule = __commonJS({
"node_modules/somemodule/index.js"(exports, module2) {
"use strict";
...
// src/functions/hello/handler.ts
var hello = async (event, context) => {
var _a;
... In this case (assuming the APM agent is even function when bundled itself -- which I don't think it is), the APM agent never "sees" that I just merged this update to the APM agent docs that (among some other things) tries to improve the documentation around using bundlers with the APM agent: #2837 tl;dr: For the APM agent to work, it has to be excluded from the bundle. Plus any modules that you want the APM agent to instrument need to be excluded as well. Esbuild and webpack call this "externals" in their configuration. It looks like the serverless-esbuild plugin has a config option for externals: https://www.serverless.com/plugins/serverless-esbuild#external-dependencies Would you be able to try your example with the following added to the "serverless.yml"?
If not, I'll give this a go when I can get back to this ticket. |
🤦♂️ That was it! Thanks for the help! Since we're using the lambda layers, this config worked (also had to add
|
Thanks for the repro information. I was able to start looking today. Here is my working repo at "v1.0.0": https://github.com/trentm/example-apollo-lambda/tree/v1.0.0 Next I'll try to work closer to what you have and see if I can answer:
|
This was because I was using
I get the |
Found the problem here. The APM agent's Lambda instrumentation was setting After deploying a dev layer of the APM agent with the fix, switching my serverless function to it, and invoking via:
I get transactions with the name (Side note: This isn't using the "GraphQL: " prefix that is discussed in our GraphQL tracing spec... but that is a separate issue.) |
@trentm Awesome! Thank you for such a quick response and fix! |
FYI: |
…low subsequent override by graphql instrumentation (elastic#2865) Before this the Lambda instrumentation was setting `trans.name = ...`, which (via the Transaction.name setter) would set `trans._customName`, which has higher prio than the `trans._defaultName`. Setting `_customName` is intended for the *user* to override. If a Lambda function is using GraphQL, the graphql instrumentation should be able to override the transaction name. Fixes: elastic#2832
The agent seems to think this is a regular HTTP server. All of the requests are being grouped under
POST /staging/{proxy+}
.From reading the documentation, I think our setup is supported, but clearly something isn't working. Thanks for the help!
Lambda extensions:
Apollo packages:
The text was updated successfully, but these errors were encountered: