backstage: π Bug Report: Opentelemetry setup is not working properly when javascript is bundled.
π Description
The Backstage opentelemetry tutorial works in development but when the backend gets bundled it messes up the order of the code causing certain instrumentations to not be applied
π Expected behavior
All instrumentations from the getNodeAutoInstrumentations() metapackage should be applied after building the backend.
π Actual Behavior with Screenshots
Only certain instrumentations get applied, causing metrics to not be tracked.
Bellow is the bundled code which shows how the imports are being grouped together making the code for the instrumentation get pushed under all of the other imports. This is what is breaking the instrumentations. Per the documentation, the code for the sdk initialization needs to be at the top before all other imports.
'use strict';
var autoInstrumentationsNode = require('@opentelemetry/auto-instrumentations-node');
-----
other imports
-----
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n["default"] = e;
return Object.freeze(n);
}
var Router__default = /*#__PURE__*/_interopDefaultLegacy(Router);
var Docker__default = /*#__PURE__*/_interopDefaultLegacy(Docker);
var esb__default = /*#__PURE__*/_interopDefaultLegacy(esb);
var winston__namespace = /*#__PURE__*/_interopNamespace(winston);
var fetch__default = /*#__PURE__*/_interopDefaultLegacy(fetch);
const sdk = new sdkNode.NodeSDK({
metricReader: new exporterPrometheus.PrometheusExporter({}, () => {
console.log(
`OpenTelemetry prometheus scrape endpoint: http://localhost:${exporterPrometheus.PrometheusExporter.DEFAULT_OPTIONS.port}${exporterPrometheus.PrometheusExporter.DEFAULT_OPTIONS.endpoint}`
);
}),
instrumentations: [autoInstrumentationsNode.getNodeAutoInstrumentations()]
});
sdk.start();
π Reproduction steps
- Follow tutorial shown here. You might need to switch from console metrics exporter to something else, like prometheus, since the default one will spam a lot of logs https://backstage.io/docs/tutorials/setup-opentelemetry
- Add OTEL_LOG_LEVEL=DEBUG environment variable
- Start application in development mode and observe different instrumentations being applied. One of them is @opentelemetry/instrumentation-http
- Build your application and create a container from the built image.
- Add OTEL_LOG_LEVEL=DEBUG environment variable and start looking
- Observe that the @opentelemetry/instrumentation-http instrumentation and lots of other ones are not being applied.
- You can also check your bundled backend inside app/packages/backend/dist/*.cjs.js file which will confirm the problem with the order
π Provide the context for the Bug.
I played around with this a bit and I couldnβt find a solution. The fix would be to somehow inject the instrumentation code at the beginning of the bundled backend application. This is something I have tested by directly editing the bundled backend by setting the configuration at the beginning and restarting the application. After that the instrumentations get applied correctly. There is also an option to copy the instrumentation.ts file inside the Dockerfile to have it there after everything gets build. With this we can than run the node application by specifying the --require option with the path to the instrumentation. I have not managed to get this working, but it could be possible
π₯οΈ Your Environment
No response
π Have you spent some time to check if this bug has been raised before?
- I checked and didnβt find similar issue
π’ Have you read the Code of Conduct?
- I have read the Code of Conduct
Are you willing to submit PR?
No, but Iβm happy to collaborate on a PR with someone else
About this issue
- Original URL
- State: closed
- Created 5 months ago
- Comments: 31 (22 by maintainers)
Managed to get it to work, but it requires changing the docker image and having the instrumentation.ts file outside backend /src folder
I can do a quick POC PR
$
I waited roughly 10 minutes. However For the requires method I did switch to the console exporter as that was the only way to do a quick test without deploying an entire observability stack on my local test k8s cluster. On the local machine dev I have used the OTEL Exporter and just run the OTEL collector from a docker container. Which Exporter I use should not matter though as they should both export all the same data.
I will do some digging and see if I can replicate your results and get the same amount of metrics.
I have tested and done a review on the PR: https://github.com/backstage/backstage/pull/22648/files#
The TL;DR is that moving the
instrumentation.tsfile outside of thesrc/folder seems to break imports.@CasperGN Opened a PR. Works for me, but maybe someone could try to test as well. Or if someone has a better solution or concerns. https://github.com/backstage/backstage/pull/22648
@CasperGN the scaffolder metrics arenβt on OpenTelemetry I think yet - Theyβre still using prom-client I believe.
https://github.com/backstage/backstage/blob/685b693fc0e9ce5d59f5883e1c4a7e43bd51d111/plugins/scaffolder-backend/src/util/metrics.ts#L29-L73
This will all need updating to use
opentelemetry/metricsinstead.