Reputation: 684
I'm trying to implement google trace in my MERN project, hosted in google cloud platform.
I've followed the guide and the examples offered by Google, but I can't make it work in any way.
import gCloudTrace from '@google-cloud/trace-agent';
// initialize gcloud trace
if (process.env.NODE_ENV === 'production') {
console.log(`Starting google cloud trace...`);
const tracer = gCloudTrace.start();
console.log(JSON.stringify(tracer,null,2));
};
import express from 'express';
import apiRoute from './api.js';
import indexRoute from './index/indexRoute.js';
try {
// setup
const host = process.env.HOST || '0.0.0.0';
const port = process.env.PORT || 5050;
const app = express();
// routes
app.use('/', indexRoute);
app.use('/api', checkGloblalSettings, apiRoute);
// create and run HTTP server
app.listen(port, host, () => {
console.log(`EXPRESS SERVER HTTP BACKEND UP AND RUNNING ON ${host} : ${port}`);
});
} catch(error) {
globalErrorHandler(error);
};
When I deploy (google app engine, flex env) everything works great, all route works but I can't find any trace in my project. I've double checked gcloud settings: Trace API is enabled, no need to create custom credentials.
Any suggestion?
Upvotes: 0
Views: 1190
Reputation: 684
I finally solved the problem. While the code in the question seems correct, the problem inherently lies in how NodeJS handles ES6 import() instead of require().
Throughout the Google Trace documentation you will find only examples with require(). Here an example:
if (process.env.NODE_ENV === 'production') {
require('@google-cloud/trace-agent').start();
}
const express = require('express');
const got = require('got');
const app = express();
const DISCOVERY_URL = 'https://www.googleapis.com/discovery/v1/apis';
// This incoming HTTP request should be captured by Trace
app.get('/', async (req, res) => {
// This outgoing HTTP request should be captured by Trace
try {
const {body} = await got(DISCOVERY_URL, {responseType: 'json'});
const names = body.items.map(item => item.name);
res.status(200).send(names.join('\n')).end();
} catch (err) {
console.error(err);
res.status(500).end();
}
});
// Start the server
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`App listening on port ${PORT}`);
console.log('Press Ctrl+C to quit.');
});
The fact is that while using require the import order is respected (so if you place require('@ google-cloud/trace-agent').start(); in the first place everything works), using import() the code runs AFTER importing the express module as well, so nothing is tracked.
To solve, I recreated the require syntax (here the documentation), then using require() everything worked perfectly:
import { createRequire } from 'module';
const require = createRequire(import.meta.url);
if (process.env.NODE_ENV === 'production') {
// [START trace_setup_nodejs_implicit]
require('@google-cloud/trace-agent').start({
logLevel: 2,
flushDelaySeconds: 30,
ignoreUrls: ['/_ah/health', '/api/status'],
ignoreMethods: ['OPTIONS'],
samplingRate: 10,
bufferSize: 1000,
onUncaughtException: 'ignore',
});
// [END trace_setup_nodejs_implicit]
};
const express = await require('express');
I hope this can serve others and avoid the headaches it caused me :)
Upvotes: 5