@sentry/node on appengine 403

Having issues with tracking exceptions and events in a production environment. Everything works fine locally, but I get 403 back from every attempt to track an exception or event. So requests are making it out (no network guards) and afaict the request looks OK, but maybe I’m missing something. I’ve also double checked environment variables and config and they’re all correct (and the same values in development). Any troubleshooting tips would be appreciated.

node: 12.22.1
@sentry/node: 6.3.6
apollo-server: 2.24.0
paltform: appengine (gcr.io/google_appengine/nodejs)
const Sentry = require('@sentry/node')
const { getRevisionSync } = require('../lib/revision')
const revision = getRevisionSync()

const DEFAULT_ENVIRONMENT = 'development'

function initSentry(config) {
	const environment = process.env.NODE_ENV || DEFAULT_ENVIRONMENT
	const dsn = process.env.SENTRY_DSN
	const release = revision[0]

	const initConfig = {
		...config,
		dsn,
		environment,
		release,

		debug: true,

		tracesSampleRate: 1.0,
	}

	console.log('SENTRY INIT')
	console.log(initConfig)
	Sentry.init(initConfig)

	return Sentry
}

module.exports = {
	Sentry,
	initSentry,
}
function sentryPlugin() {
	return {
		requestDidStart() {
			Sentry.captureEvent('requestDidStart')
			return {
				didEncounterErrors(ctx) {
					Sentry.captureEvent('didEncounterError')
					console.log('Sentry Error')
					// If we couldn't parse the operation, don't
					// do anything here
					if (!ctx.operation) {
						return
					}
					for (const err of ctx.errors) {
						// Only report internal server errors,
						// all errors extending ApolloError should be user-facing
						if (err instanceof ApolloError) {
							continue
						}
						// Add scoped report details and send to Sentry
						Sentry.withScope((scope) => {
							// Annotate whether failing operation was query/mutation/subscription
							scope.setTag('kind', ctx.operation.operation)
							// Log query and variables as extras
							// (make sure to strip out sensitive data!)
							scope.setExtra('query', ctx.request.query)
							scope.setExtra('variables', ctx.request.variables)
							if (err.path) {
								// We can also add the path as breadcrumb
								scope.addBreadcrumb({
									category: 'query-path',
									message: err.path.join(' > '),
									level: Sentry.Severity.Debug,
								})
							}
							Sentry.captureException(err)
						})
					}
				},
			}
		},
	}
}

Sample NODE_DEBUG=http log

HTTP 25: createConnection o662766.ingest.sentry.io:443:::::::::::::::::: {
  agent: Agent {
    _events: [Object: null prototype] {
      free: [Function],
      newListener: [Function: maybeEnableKeylog]
    },
    _eventsCount: 2,
    _maxListeners: undefined,
    defaultPort: 443,
    protocol: 'https:',
    options: { keepAlive: false, maxSockets: 30, timeout: 2000, path: null },
    requests: {},
    sockets: { 'o662766.ingest.sentry.io:443::::::::::::::::::': [] },
    freeSockets: {},
    keepAliveMsecs: 1000,
    keepAlive: false,
    maxSockets: 30,
    maxFreeSockets: 256,
    maxTotalSockets: Infinity,
    totalSocketCount: 0,
    maxCachedSessions: 100,
    _sessionCache: { map: [Object], list: [Array] },
    [Symbol(kCapture)]: false
  },
  headers: {
    'Content-Type': 'application/json',
    'X-Sentry-Auth': 'Sentry sentry_version=7, sentry_client=sentry.javascript.node/6.3.6, sentry_key=********************************'
  },
  hostname: 'o662766.ingest.sentry.io',
  method: 'POST',
  path: null,
  port: 443,
  protocol: 'https:',
  _defaultAgent: Agent {
    _events: [Object: null prototype] {
      free: [Function],
      newListener: [Function: maybeEnableKeylog]
    },
    _eventsCount: 2,
    _maxListeners: undefined,
    defaultPort: 443,
    protocol: 'https:',
    options: { path: null },
    requests: {},
    sockets: {},
    freeSockets: {},
    keepAliveMsecs: 1000,
    keepAlive: false,
    maxSockets: Infinity,
    maxFreeSockets: 256,
    maxTotalSockets: Infinity,
    totalSocketCount: 0,
    maxCachedSessions: 100,
    _sessionCache: { map: [Object], list: [Array] },
    [Symbol(kCapture)]: false
  },
  host: 'o662766.ingest.sentry.io',
  keepAlive: false,
  maxSockets: 30,
  timeout: 2000,
  servername: 'o662766.ingest.sentry.io',
  _agentKey: 'o662766.ingest.sentry.io:443::::::::::::::::::'
}
HTTP 25: sockets o662766.ingest.sentry.io:443:::::::::::::::::: 1 1
HTTP 25: write ret = true
HTTP 25: outgoing message end.
HTTP 25: SERVER new http connection
HTTP 25: SERVER socketOnParserExecute 716
HTTP 25: SERVER upgrade or connect GET
HTTP 25: SERVER have listener for upgrade
HTTP 25: AGENT incoming response!
HTTP 25: AGENT socket keep-alive
HTTP 25: CLIENT socket onFree
HTTP 25: agent.on(free) o662766.ingest.sentry.io:443::::::::::::::::::
Sentry Logger [Error]: Error while sending event: SentryError: HTTP Error (403)

Hey kids,

This is a PSA to always check your DSN value completely. I was missing the last character in our production environment and was hard to track down because the string looks correct at a glance.

This topic was automatically closed 15 days after the last reply. New replies are no longer allowed.