From 78ac846e370f7214dc76257d5cf7c987bd99d830 Mon Sep 17 00:00:00 2001 From: ishabi Date: Fri, 21 Mar 2025 14:45:47 +0100 Subject: [PATCH 1/2] add sdk.event to communicate a login or custom event --- .../dd-trace/src/appsec/sdk/track_event.js | 11 ++++++---- .../dd-trace/src/appsec/telemetry/index.js | 9 +++++++- .../dd-trace/src/appsec/telemetry/user.js | 10 ++++++++- .../test/appsec/sdk/track_event.spec.js | 22 ++++++++++++++++++- .../test/appsec/telemetry/user.spec.js | 11 ++++++++++ 5 files changed, 56 insertions(+), 7 deletions(-) diff --git a/packages/dd-trace/src/appsec/sdk/track_event.js b/packages/dd-trace/src/appsec/sdk/track_event.js index a54829d0a2b..a52c6b408fa 100644 --- a/packages/dd-trace/src/appsec/sdk/track_event.js +++ b/packages/dd-trace/src/appsec/sdk/track_event.js @@ -7,6 +7,7 @@ const waf = require('../waf') const { keepTrace } = require('../../priority_sampler') const addresses = require('../addresses') const { ASM } = require('../../standalone/product') +const { incrementSdkEventMetric } = require('../telemetry') function trackUserLoginSuccessEvent (tracer, user, metadata) { // TODO: better user check here and in _setUser() ? @@ -27,7 +28,7 @@ function trackUserLoginSuccessEvent (tracer, user, metadata) { metadata = { 'usr.login': login, ...metadata } - trackEvent('users.login.success', metadata, 'trackUserLoginSuccessEvent', rootSpan) + trackEvent('users.login.success', 'login_success', metadata, 'trackUserLoginSuccessEvent', rootSpan) runWaf('users.login.success', { id: user.id, login }) } @@ -45,7 +46,7 @@ function trackUserLoginFailureEvent (tracer, userId, exists, metadata) { ...metadata } - trackEvent('users.login.failure', fields, 'trackUserLoginFailureEvent', getRootSpan(tracer)) + trackEvent('users.login.failure', 'login_failure', fields, 'trackUserLoginFailureEvent', getRootSpan(tracer)) runWaf('users.login.failure', { login: userId }) } @@ -56,10 +57,10 @@ function trackCustomEvent (tracer, eventName, metadata) { return } - trackEvent(eventName, metadata, 'trackCustomEvent', getRootSpan(tracer)) + trackEvent(eventName, 'custom', metadata, 'trackCustomEvent', getRootSpan(tracer)) } -function trackEvent (eventName, fields, sdkMethodName, rootSpan) { +function trackEvent (eventName, eventType, fields, sdkMethodName, rootSpan) { if (!rootSpan) { log.warn('[ASM] Root span not available in %s', sdkMethodName) return @@ -79,6 +80,8 @@ function trackEvent (eventName, fields, sdkMethodName, rootSpan) { rootSpan.addTags(tags) keepTrace(rootSpan, ASM) + + incrementSdkEventMetric(eventType) } function runWaf (eventName, user) { diff --git a/packages/dd-trace/src/appsec/telemetry/index.js b/packages/dd-trace/src/appsec/telemetry/index.js index 0593efd97b9..2c0b57f8cc0 100644 --- a/packages/dd-trace/src/appsec/telemetry/index.js +++ b/packages/dd-trace/src/appsec/telemetry/index.js @@ -2,7 +2,7 @@ const { DD_TELEMETRY_REQUEST_METRICS } = require('./common') const { addRaspRequestMetrics, trackRaspMetrics } = require('./rasp') -const { incrementMissingUserId, incrementMissingUserLogin } = require('./user') +const { incrementMissingUserId, incrementMissingUserLogin, incrementSdkEvent } = require('./user') const { addWafRequestMetrics, trackWafMetrics, @@ -107,6 +107,12 @@ function incrementMissingUserIdMetric (framework, eventType) { incrementMissingUserId(framework, eventType) } +function incrementSdkEventMetric (framework, eventType) { + if (!enabled) return + + incrementSdkEvent(framework, eventType) +} + function getRequestMetrics (req) { if (req) { const store = getStore(req) @@ -125,6 +131,7 @@ module.exports = { incrementWafRequestsMetric, incrementMissingUserLoginMetric, incrementMissingUserIdMetric, + incrementSdkEventMetric, getRequestMetrics } diff --git a/packages/dd-trace/src/appsec/telemetry/user.js b/packages/dd-trace/src/appsec/telemetry/user.js index 9f082ae12ec..352b924efdd 100644 --- a/packages/dd-trace/src/appsec/telemetry/user.js +++ b/packages/dd-trace/src/appsec/telemetry/user.js @@ -18,7 +18,15 @@ function incrementMissingUserId (framework, eventType) { }).inc() } +function incrementSdkEvent (eventType) { + appsecMetrics.count('sdk.event', { + event_type: eventType, + sdk_version: 'v2' + }).inc() +} + module.exports = { incrementMissingUserLogin, - incrementMissingUserId + incrementMissingUserId, + incrementSdkEvent } diff --git a/packages/dd-trace/test/appsec/sdk/track_event.spec.js b/packages/dd-trace/test/appsec/sdk/track_event.spec.js index 2e2f4d36329..325c12aefec 100644 --- a/packages/dd-trace/test/appsec/sdk/track_event.spec.js +++ b/packages/dd-trace/test/appsec/sdk/track_event.spec.js @@ -17,6 +17,7 @@ describe('track_event', () => { let getRootSpan let setUserTags let waf + let telemetry let trackUserLoginSuccessEvent, trackUserLoginFailureEvent, trackCustomEvent beforeEach(() => { @@ -42,6 +43,10 @@ describe('track_event', () => { run: sinon.spy() } + telemetry = { + incrementSdkEventMetric: sinon.stub() + } + const trackEvents = proxyquire('../../../src/appsec/sdk/track_event', { '../../log': log, './utils': { @@ -50,7 +55,8 @@ describe('track_event', () => { './set_user': { setUserTags }, - '../waf': waf + '../waf': waf, + '../telemetry': telemetry }) trackUserLoginSuccessEvent = trackEvents.trackUserLoginSuccessEvent @@ -70,6 +76,7 @@ describe('track_event', () => { .to.have.been.calledWithExactly('[ASM] Invalid user provided to trackUserLoginSuccessEvent') expect(setUserTags).to.not.have.been.called expect(rootSpan.addTags).to.not.have.been.called + expect(telemetry.incrementSdkEventMetric).to.not.have.been.called }) it('should log warning when root span is not available', () => { @@ -80,6 +87,7 @@ describe('track_event', () => { expect(log.warn) .to.have.been.calledOnceWithExactly('[ASM] Root span not available in trackUserLoginSuccessEvent') expect(setUserTags).to.not.have.been.called + expect(telemetry.incrementSdkEventMetric).to.not.have.been.called }) it('should call setUser and addTags with metadata', () => { @@ -111,6 +119,7 @@ describe('track_event', () => { [USER_LOGIN]: 'user_id' } }) + expect(telemetry.incrementSdkEventMetric).to.have.been.calledWith('login_success') }) it('should call setUser and addTags without metadata', () => { @@ -134,6 +143,7 @@ describe('track_event', () => { [USER_LOGIN]: 'user_id' } }) + expect(telemetry.incrementSdkEventMetric).to.have.been.calledWith('login_success') }) it('should call waf with user login', () => { @@ -157,6 +167,7 @@ describe('track_event', () => { [USER_LOGIN]: 'user_login' } }) + expect(telemetry.incrementSdkEventMetric).to.have.been.calledWith('login_success') }) }) @@ -172,6 +183,7 @@ describe('track_event', () => { .to.have.been.calledWithExactly('[ASM] Invalid userId provided to trackUserLoginFailureEvent') expect(setUserTags).to.not.have.been.called expect(rootSpan.addTags).to.not.have.been.called + expect(telemetry.incrementSdkEventMetric).to.not.have.been.called }) it('should log warning when root span is not available', () => { @@ -182,6 +194,7 @@ describe('track_event', () => { expect(log.warn) .to.have.been.calledOnceWithExactly('[ASM] Root span not available in %s', 'trackUserLoginFailureEvent') expect(setUserTags).to.not.have.been.called + expect(telemetry.incrementSdkEventMetric).to.not.have.been.called }) it('should call addTags with metadata', () => { @@ -211,6 +224,7 @@ describe('track_event', () => { [USER_LOGIN]: 'user_id' } }) + expect(telemetry.incrementSdkEventMetric).to.have.been.calledWith('login_failure') }) it('should send false `usr.exists` property when the user does not exist', () => { @@ -240,6 +254,7 @@ describe('track_event', () => { [USER_LOGIN]: 'user_id' } }) + expect(telemetry.incrementSdkEventMetric).to.have.been.calledWith('login_failure') }) it('should call addTags without metadata', () => { @@ -262,6 +277,7 @@ describe('track_event', () => { [USER_LOGIN]: 'user_id' } }) + expect(telemetry.incrementSdkEventMetric).to.have.been.calledWith('login_failure') }) }) @@ -277,6 +293,7 @@ describe('track_event', () => { .to.have.been.calledWithExactly('[ASM] Invalid eventName provided to trackCustomEvent') expect(setUserTags).to.not.have.been.called expect(rootSpan.addTags).to.not.have.been.called + expect(telemetry.incrementSdkEventMetric).to.not.have.been.called }) it('should log warning when root span is not available', () => { @@ -287,6 +304,7 @@ describe('track_event', () => { expect(log.warn) .to.have.been.calledOnceWithExactly('[ASM] Root span not available in %s', 'trackCustomEvent') expect(setUserTags).to.not.have.been.called + expect(telemetry.incrementSdkEventMetric).to.not.have.been.called }) it('should call addTags with metadata', () => { @@ -305,6 +323,7 @@ describe('track_event', () => { }) expect(prioritySampler.setPriority) .to.have.been.calledOnceWithExactly(rootSpan, USER_KEEP, ASM) + expect(telemetry.incrementSdkEventMetric).to.have.been.calledWith('custom') }) it('should call addTags without metadata', () => { @@ -318,6 +337,7 @@ describe('track_event', () => { }) expect(prioritySampler.setPriority) .to.have.been.calledOnceWithExactly(rootSpan, USER_KEEP, ASM) + expect(telemetry.incrementSdkEventMetric).to.have.been.calledWith('custom') }) }) }) diff --git a/packages/dd-trace/test/appsec/telemetry/user.spec.js b/packages/dd-trace/test/appsec/telemetry/user.spec.js index 12976fcce88..4c1bf2d64d4 100644 --- a/packages/dd-trace/test/appsec/telemetry/user.spec.js +++ b/packages/dd-trace/test/appsec/telemetry/user.spec.js @@ -49,5 +49,16 @@ describe('Appsec User Telemetry metrics', () => { }) }) }) + + describe('incrementSdkEventMetric', () => { + it('should increment sdk.event metric', () => { + appsecTelemetry.incrementSdkEventMetric('login_success') + + expect(count).to.have.been.calledOnceWithExactly('sdk.event', { + event_type: 'login_success', + sdk_version: 'v2' + }) + }) + }) }) }) From 5c31f8fee8221da5c78381680a16296198518378 Mon Sep 17 00:00:00 2001 From: ishabi Date: Fri, 21 Mar 2025 16:35:23 +0100 Subject: [PATCH 2/2] change sdk version to v1 --- packages/dd-trace/src/appsec/sdk/track_event.js | 16 ++++++++++------ packages/dd-trace/src/appsec/telemetry/user.js | 2 +- .../dd-trace/test/appsec/sdk/track_event.spec.js | 6 +++--- .../dd-trace/test/appsec/telemetry/user.spec.js | 2 +- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/packages/dd-trace/src/appsec/sdk/track_event.js b/packages/dd-trace/src/appsec/sdk/track_event.js index a52c6b408fa..dee32d31bc0 100644 --- a/packages/dd-trace/src/appsec/sdk/track_event.js +++ b/packages/dd-trace/src/appsec/sdk/track_event.js @@ -16,6 +16,8 @@ function trackUserLoginSuccessEvent (tracer, user, metadata) { return } + incrementSdkEventMetric('login_success') + const rootSpan = getRootSpan(tracer) if (!rootSpan) { log.warn('[ASM] Root span not available in trackUserLoginSuccessEvent') @@ -28,7 +30,7 @@ function trackUserLoginSuccessEvent (tracer, user, metadata) { metadata = { 'usr.login': login, ...metadata } - trackEvent('users.login.success', 'login_success', metadata, 'trackUserLoginSuccessEvent', rootSpan) + trackEvent('users.login.success', metadata, 'trackUserLoginSuccessEvent', rootSpan) runWaf('users.login.success', { id: user.id, login }) } @@ -46,9 +48,11 @@ function trackUserLoginFailureEvent (tracer, userId, exists, metadata) { ...metadata } - trackEvent('users.login.failure', 'login_failure', fields, 'trackUserLoginFailureEvent', getRootSpan(tracer)) + trackEvent('users.login.failure', fields, 'trackUserLoginFailureEvent', getRootSpan(tracer)) runWaf('users.login.failure', { login: userId }) + + incrementSdkEventMetric('login_failure') } function trackCustomEvent (tracer, eventName, metadata) { @@ -57,10 +61,12 @@ function trackCustomEvent (tracer, eventName, metadata) { return } - trackEvent(eventName, 'custom', metadata, 'trackCustomEvent', getRootSpan(tracer)) + trackEvent(eventName, metadata, 'trackCustomEvent', getRootSpan(tracer)) + + incrementSdkEventMetric('custom') } -function trackEvent (eventName, eventType, fields, sdkMethodName, rootSpan) { +function trackEvent (eventName, fields, sdkMethodName, rootSpan) { if (!rootSpan) { log.warn('[ASM] Root span not available in %s', sdkMethodName) return @@ -80,8 +86,6 @@ function trackEvent (eventName, eventType, fields, sdkMethodName, rootSpan) { rootSpan.addTags(tags) keepTrace(rootSpan, ASM) - - incrementSdkEventMetric(eventType) } function runWaf (eventName, user) { diff --git a/packages/dd-trace/src/appsec/telemetry/user.js b/packages/dd-trace/src/appsec/telemetry/user.js index 352b924efdd..d4d9d3fa666 100644 --- a/packages/dd-trace/src/appsec/telemetry/user.js +++ b/packages/dd-trace/src/appsec/telemetry/user.js @@ -21,7 +21,7 @@ function incrementMissingUserId (framework, eventType) { function incrementSdkEvent (eventType) { appsecMetrics.count('sdk.event', { event_type: eventType, - sdk_version: 'v2' + sdk_version: 'v1' }).inc() } diff --git a/packages/dd-trace/test/appsec/sdk/track_event.spec.js b/packages/dd-trace/test/appsec/sdk/track_event.spec.js index 325c12aefec..e650e35da1e 100644 --- a/packages/dd-trace/test/appsec/sdk/track_event.spec.js +++ b/packages/dd-trace/test/appsec/sdk/track_event.spec.js @@ -87,7 +87,7 @@ describe('track_event', () => { expect(log.warn) .to.have.been.calledOnceWithExactly('[ASM] Root span not available in trackUserLoginSuccessEvent') expect(setUserTags).to.not.have.been.called - expect(telemetry.incrementSdkEventMetric).to.not.have.been.called + expect(telemetry.incrementSdkEventMetric).to.have.been.calledWith('login_success') }) it('should call setUser and addTags with metadata', () => { @@ -194,7 +194,7 @@ describe('track_event', () => { expect(log.warn) .to.have.been.calledOnceWithExactly('[ASM] Root span not available in %s', 'trackUserLoginFailureEvent') expect(setUserTags).to.not.have.been.called - expect(telemetry.incrementSdkEventMetric).to.not.have.been.called + expect(telemetry.incrementSdkEventMetric).to.have.been.calledWith('login_failure') }) it('should call addTags with metadata', () => { @@ -304,7 +304,7 @@ describe('track_event', () => { expect(log.warn) .to.have.been.calledOnceWithExactly('[ASM] Root span not available in %s', 'trackCustomEvent') expect(setUserTags).to.not.have.been.called - expect(telemetry.incrementSdkEventMetric).to.not.have.been.called + expect(telemetry.incrementSdkEventMetric).to.have.been.calledWith('custom') }) it('should call addTags with metadata', () => { diff --git a/packages/dd-trace/test/appsec/telemetry/user.spec.js b/packages/dd-trace/test/appsec/telemetry/user.spec.js index 4c1bf2d64d4..35f0af60982 100644 --- a/packages/dd-trace/test/appsec/telemetry/user.spec.js +++ b/packages/dd-trace/test/appsec/telemetry/user.spec.js @@ -56,7 +56,7 @@ describe('Appsec User Telemetry metrics', () => { expect(count).to.have.been.calledOnceWithExactly('sdk.event', { event_type: 'login_success', - sdk_version: 'v2' + sdk_version: 'v1' }) }) })