From 92dd0ed3f3c0aaaa667d350c78cfd888ed46ff83 Mon Sep 17 00:00:00 2001 From: Lukas Stracke Date: Fri, 30 Sep 2022 11:44:27 +0200 Subject: [PATCH] fix(node): Only set `DeviceContext.boot_time` if `os.uptime()` is valid (#5859) When creating the `DeviceContext` in the Node SDK `Context` integration, we calculate the boot time based on `os.uptime`. However, as reported in #5856, `os.uptime` might not always be available or return undefined (I couldn't figure out which of the two cases actually was responsible). This patch fixes this bug by simply not setting the boot time in case we don't get a valid up time. It also adds two basic tests for this behaviour. I opted to not set the boot time instead of e.g. defaulting to `0` for uptime because IMO this creates a false boot time that probably causes more confusion than not having it. --- packages/node/src/integrations/context.ts | 14 ++++++++++-- .../node/test/integrations/context.test.ts | 22 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 packages/node/test/integrations/context.test.ts diff --git a/packages/node/src/integrations/context.ts b/packages/node/src/integrations/context.ts index 73fa8fa40c03..c0991720d76e 100644 --- a/packages/node/src/integrations/context.ts +++ b/packages/node/src/integrations/context.ts @@ -189,10 +189,20 @@ function getAppContext(): AppContext { return { app_start_time, app_memory }; } -function getDeviceContext(deviceOpt: DeviceContextOptions | true): DeviceContext { +/** + * Gets device information from os + */ +export function getDeviceContext(deviceOpt: DeviceContextOptions | true): DeviceContext { const device: DeviceContext = {}; - device.boot_time = new Date(Date.now() - os.uptime() * 1000).toISOString(); + // os.uptime or its return value seem to be undefined in certain environments (e.g. Azure functions). + // Hence, we only set boot time, if we get a valid uptime value. + // @see https://github.com/getsentry/sentry-javascript/issues/5856 + const uptime = os.uptime && os.uptime(); + if (typeof uptime === 'number') { + device.boot_time = new Date(Date.now() - uptime * 1000).toISOString(); + } + device.arch = os.arch(); if (deviceOpt === true || deviceOpt.memory) { diff --git a/packages/node/test/integrations/context.test.ts b/packages/node/test/integrations/context.test.ts new file mode 100644 index 000000000000..519e101187ff --- /dev/null +++ b/packages/node/test/integrations/context.test.ts @@ -0,0 +1,22 @@ +import * as os from 'os'; + +import { getDeviceContext } from '../../src/integrations/context'; + +describe('Context', () => { + describe('getDeviceContext', () => { + afterAll(() => { + jest.clearAllMocks(); + }); + + it('returns boot time if os.uptime is defined and returns a valid uptime', () => { + const deviceCtx = getDeviceContext({}); + expect(deviceCtx.boot_time).toEqual(expect.any(String)); + }); + + it('returns no boot time if os.uptime() returns undefined', () => { + jest.spyOn(os, 'uptime').mockReturnValue(undefined as unknown as number); + const deviceCtx = getDeviceContext({}); + expect(deviceCtx.boot_time).toBeUndefined(); + }); + }); +});