Comments (6)
@mderriey Thank you for submitting this issue, but I'm having some trouble reproducing your results. I have a simple app currently that looks like this:
const express = require('express');
let appInsights = require("applicationinsights");
const winston = require('winston');
const logger = winston.createLogger({
transports: [
new winston.transports.Console({
level: 'error',
format: winston.format.simple(),
debugStdout: true,
})
]
});
appInsights.setup("<YOUR-CONNECTION-STRING-HERE>")
.setAutoCollectConsole(true, true)
.start();
class InvariantError extends Error {}
const app = express();
const PORT = 8080;
async function setupRoutes() {
app.get('/', async (req, res) => {
logger.error(`Unhandled error: ${new InvariantError('This does not appear in App Insights')}`);
logger.error(`Unhandled error: ${new Error('This does appear in App Insights')}`);
res.send('Hello World!');
});
}
setupRoutes().then(() => {
app.listen(PORT);
console.log(`Listening on http://localhost:${PORT}`);
});
And I'm seeing both errors' messages parsed and output to ApplicationInsights. Please let me know if this sample produces the same results for you. If not, let me know some more details of the sample application you're testing with and what version of the beta you're using.
from applicationinsights-node.js.
Hey @JacksonWeber, thanks for getting back to me.
I can see two differences between your setup and mine:
- Yours doesn't seem to be using the beta version of the App Insights SDK.
- We don't log errors the same way, I think with your sample the template literal means that the JS runtime converts the
Error
into a string, not the App Insights SDK. Can you please try this way?const express = require('express'); let appInsights = require("applicationinsights"); const winston = require('winston'); const logger = winston.createLogger({ transports: [ new winston.transports.Console({ level: 'error', format: winston.format.simple(), debugStdout: true, }) ] }); appInsights.setup("<YOUR-CONNECTION-STRING-HERE>") .setAutoCollectConsole(true, true) .start(); class InvariantError extends Error {} const app = express(); const PORT = 8080; async function setupRoutes() { app.get('/', async (req, res) => { - logger.error(`Unhandled error: ${new InvariantError('This does not appear in App Insights')}`); - logger.error(`Unhandled error: ${new Error('This does appear in App Insights')}`); + logger.error('Unhandled error', { error: new InvariantError('This does not appear in App Insights') }); + logger.error('Unhandled error', { error: new Error('This does appear in App Insights') })); res.send('Hello World!'); }); } setupRoutes().then(() => { app.listen(PORT); console.log(`Listening on http://localhost:${PORT}`); });
Thanks
from applicationinsights-node.js.
@mderriey Apologies, I had my test app in shim-testing configuration by accident there, thanks!
However, I'm still able to see the message in the InvariantError
in the CustomProperties of ApplicationInsights on version 11 of the Beta package.
I'm using the sample app above just reconfigured to use the beta package properly and enabling the winston instrumentation option and able to see both errors serialized.
Assuming you're using the same logger.error
calls to create Winston logs, can I see how you're initializing/configuring Azure Monitor?
from applicationinsights-node.js.
How weird... 🤔
Assuming you're using the same
logger.error
calls to create Winston logs
We are, yes, except we use the JSON format for the console transport, but that shouldn't have any impact from my understanding given diagnostic-channel-publishers
injects its own transport.
can I see how you're initializing/configuring Azure Monitor?
Sure thing.
Click to expand
import { Resource } from '@opentelemetry/resources'
import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions'
import { useAzureMonitor } from 'applicationinsights'
import { SetTenantAliasAttributeSpanProcessor } from './tracing/set-tenant-alias-attribute-span-processor'
import { TruncateDbStatementAttributeSpanProcessor } from './tracing/truncate-db-statement-attribute-span-processor'
import type { ProxyTracerProvider } from '@opentelemetry/api'
import { trace } from '@opentelemetry/api'
import type { NodeTracerProvider } from '@opentelemetry/sdk-trace-node'
import { registerInstrumentations } from '@opentelemetry/instrumentation'
import type { InstrumentationOptions as ApplicationInsightsInstrumentationOptions } from 'applicationinsights/out/src/types'
import type { InstrumentationOptions as OpenTelemetryInstrumentationOptions } from '@azure/monitor-opentelemetry'
import { instrumentations } from './tracing/instrumentations'
// Default attributes set on the OpenTelemetry traces
const resource = Resource.EMPTY
resource.attributes[SemanticResourceAttributes.SERVICE_NAME] = '<redacted>'
resource.attributes[SemanticResourceAttributes.SERVICE_NAMESPACE] = '<redacted>'
useAzureMonitor({
resource,
instrumentationOptions: {
azureSdk: { enabled: false },
http: { enabled: false },
mongoDb: { enabled: false },
mySql: { enabled: false },
postgreSql: { enabled: false },
redis: { enabled: false },
redis4: { enabled: false },
// NOTE: only winston is enabled
winston: { enabled: true },
console: { enabled: false },
bunyan: { enabled: false },
} satisfies ApplicationInsightsInstrumentationOptions as unknown as OpenTelemetryInstrumentationOptions,
})
const tracerProvider = (trace.getTracerProvider() as ProxyTracerProvider).getDelegate() as NodeTracerProvider
// NOTE: a couple of custom processors
tracerProvider.addSpanProcessor(new SetTenantAliasAttributeSpanProcessor())
tracerProvider.addSpanProcessor(new TruncateDbStatementAttributeSpanProcessor())
registerInstrumentations({
tracerProvider,
// NOTE: these are additional OTel instrumentations like HTTP, Express, Redis, tedious.
instrumentations,
})
When I initially looked into this, I found the problem came from the fact that the custom classes that inherit Error
have their constructor.name
property that is different from Error
, see
ApplicationInsights-node.js/src/shim/logsApi.ts
Lines 121 to 122 in b99d62d
If I run this in my Node.js REPL, that's what I get:
λ node
Welcome to Node.js v20.11.1.
Type ".help" for more information.
> const { InvariantError } = require('./src/util/invariant')
undefined
> new InvariantError().constructor.name
'InvariantError'
I also confirmed that we're using 3.0.0-beta.11:
λ npm ls applicationinsights
<redacted>@1.0.0 <redacted>
`-- [email protected]
I also just tested it again, and the error isn't serialized correctly.
For completeness, here's the TypeScript code:
export function invariant(condition: any, message: string): asserts condition {
if (condition) return
throw new InvariantError(message)
}
export class InvariantError extends Error {}
In a request handler, I added the following bogus invariant assertion:
invariant(1 === 2, 'Boo')
The code that logs these errors is:
logger.error('Unhandled error', {
error: unwrappedError,
})
I put a breakpoint on that line, and evaluated unwrappedError.constructor.name
, which gave back InvariantError
.
Here's the result in the portal:
from applicationinsights-node.js.
I spent some time investigating this and want to note a few things.
I was able to recreate your experience with the error
object being logged as an empty object. However, from messing with the definition of the InvariantError
I was able to get the error to properly be serialized in the customDimensions.
So if I defined my custom error class like:
export class InvariantError extends Error {
constructor(message: string) {
super(message);
Object.setPrototypeOf(this, InvariantError.prototype);
}
};
Adjusting the prototype accordingly so that the object properly identifies as an InvariantError
, I do get an "error": {}
logged in ApplicationInsights. However, I was able to avoid this by setting class properties on the InvariantError
, ex:
export class InvariantError extends Error {
constructor(message: string) {
super();
this.name = "InvariantError";
this.message = message;
Object.setPrototypeOf(this, InvariantError.prototype);
}
};
Hopefully this works as a workaround for the current released version (beta 11), however in testing and investigation I discovered that as a result of #1272, Winston logs will be sent to logger.emit()
exposed by the OpenTelemetry API without first being properly formatted. I have a PR here: #1297 to resolve that issue, and this should be fixed for you in the upcoming release. Tested with custom errors, standard errors, and other objects.
from applicationinsights-node.js.
@JacksonWeber thanks a lot for your investigation.
I'm curious to know why "my" InvariantError
s showed up as empty objects without any additional changes, whereas you had to change the prototype of the object...
Anyway, thanks a lot, we'll test the workaround where we assign properties directly on our error classes instead of relying on the base class constructor.
from applicationinsights-node.js.
Related Issues (20)
- 3.0.0-beta.11 - has no exported member 'Context' HOT 19
- App insights customDimension parsing differently locally vs in Azure. HOT 1
- [Beta] - Nested objects get serialised as "[object Object]" again HOT 11
- [FEATURE] At startup, send all locally stored traces instead of waiting the first batch + some time HOT 8
- Error "body.data.baseData.ver cannot be null or undefined." HOT 12
- Importing Application Insights library in ES6 module import format doesn't work HOT 3
- Invalid metric name: The metric name should be a ASCII string with a length no greater than 255 characters. HOT 2
- @azure/opentelemetry-instrumentation-azure-sdk [ 'Module @azure/core-tracing has been loaded before @azure/opentelemetry-instrumentation-azure-sdk so it might not work, please initialize it before requiring @azure/core-tracing' ] HOT 2
- trackTrace no longer working since this week HOT 1
- TrackEvent no longer reporting Measurements HOT 3
- Unable to integrate with Winston logger HOT 5
- Bunyan logger problems HOT 7
- _APPRESOURCEPREVIEW_ appearing in metrics when upgrading from 2.x to 3.0.1 HOT 5
- customMetrics problems HOT 2
- Upgrade 2.x to 3.0.1 startup warnings HOT 3
- [BUG] Custom proxy with error "Expecting a valid host string in proxy settings, but found" HOT 2
- [BUG] Custom proxy with error "Expecting a valid host string in proxy settings, but found" HOT 1
- "applicationinsights 3.1.0" is not compatible with the "@azure/functions 4.5.0" HOT 1
- Correlation between Frontend and Backend.
- Severitylevel does not work
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from applicationinsights-node.js.