chore: Disable anonymous user tracking when feature flag turned on (#40936)
## Description > [!TIP] > _Add a TL;DR when the description is longer than 500 words or extremely technical (helps the content, marketing, and DevRel team)._ > > _Please also include relevant motivation and context. List any dependencies that are required for this change. Add links to Notion, Figma or any other documents that might be relevant to the PR._ Fixes #`Issue Number` _or_ Fixes `Issue URL` > [!WARNING] > _If no issue exists, please create an issue first, and check with the maintainers if the issue is valid._ ## Automation /test sanity ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/15996654359> > Commit: ba524fe2f769b6f8d2c72e0332560dd5e0c0465e > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=15996654359&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.Sanity` > Spec: > <hr>Tue, 01 Jul 2025 11:08:01 UTC <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Introduced a feature flag to control event tracking for anonymous users. * Added the ability to block analytics event tracking for anonymous users when the feature flag is enabled. * **Bug Fixes** * Improved logic to ensure analytics events are not sent for anonymous users if the feature flag is active. * **Chores** * Updated analytics initialization to respect the new tracking preference for anonymous users. * Enhanced tracking initialization flow to conditionally enable or disable analytics based on user status and feature flag. * Added tests to verify analytics initialization respects user tracking preferences. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: jacquesikot <jacquesikot@gmail.com>
This commit is contained in:
parent
be3aef333b
commit
481988daf1
|
|
@ -62,6 +62,8 @@ export const FEATURE_FLAG = {
|
||||||
license_ai_agent_instance_enabled: "license_ai_agent_instance_enabled",
|
license_ai_agent_instance_enabled: "license_ai_agent_instance_enabled",
|
||||||
release_jsobjects_onpageunloadactions_enabled:
|
release_jsobjects_onpageunloadactions_enabled:
|
||||||
"release_jsobjects_onpageunloadactions_enabled",
|
"release_jsobjects_onpageunloadactions_enabled",
|
||||||
|
configure_block_event_tracking_for_anonymous_users:
|
||||||
|
"configure_block_event_tracking_for_anonymous_users",
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type FeatureFlag = keyof typeof FEATURE_FLAG;
|
export type FeatureFlag = keyof typeof FEATURE_FLAG;
|
||||||
|
|
@ -113,6 +115,7 @@ export const DEFAULT_FEATURE_FLAG_VALUE: FeatureFlags = {
|
||||||
release_reactive_actions_enabled: false,
|
release_reactive_actions_enabled: false,
|
||||||
license_ai_agent_instance_enabled: false,
|
license_ai_agent_instance_enabled: false,
|
||||||
release_jsobjects_onpageunloadactions_enabled: false,
|
release_jsobjects_onpageunloadactions_enabled: false,
|
||||||
|
configure_block_event_tracking_for_anonymous_users: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AB_TESTING_EVENT_KEYS = {
|
export const AB_TESTING_EVENT_KEYS = {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import {
|
||||||
take,
|
take,
|
||||||
type TakeEffect,
|
type TakeEffect,
|
||||||
} from "redux-saga/effects";
|
} from "redux-saga/effects";
|
||||||
|
import type { SagaIterator } from "redux-saga";
|
||||||
import type {
|
import type {
|
||||||
ReduxAction,
|
ReduxAction,
|
||||||
ReduxActionWithPromise,
|
ReduxActionWithPromise,
|
||||||
|
|
@ -88,6 +89,7 @@ import {
|
||||||
segmentInitUncertain,
|
segmentInitUncertain,
|
||||||
} from "actions/analyticsActions";
|
} from "actions/analyticsActions";
|
||||||
import { getSegmentState } from "selectors/analyticsSelectors";
|
import { getSegmentState } from "selectors/analyticsSelectors";
|
||||||
|
import { getOrganizationConfig } from "ee/selectors/organizationSelectors";
|
||||||
|
|
||||||
export function* getCurrentUserSaga(action?: {
|
export function* getCurrentUserSaga(action?: {
|
||||||
payload?: { userProfile?: ApiResponse };
|
payload?: { userProfile?: ApiResponse };
|
||||||
|
|
@ -150,7 +152,28 @@ function* getSessionRecordingConfig() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function* initTrackers(currentUser: User) {
|
function shouldTrackUser(
|
||||||
|
currentUser: User,
|
||||||
|
licenseActive: boolean,
|
||||||
|
featureFlag: boolean,
|
||||||
|
): boolean {
|
||||||
|
try {
|
||||||
|
const isAnonymous =
|
||||||
|
currentUser?.isAnonymous || currentUser?.username === "anonymousUser";
|
||||||
|
|
||||||
|
if (!isAnonymous) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const telemetryOn = currentUser?.enableTelemetry ?? false;
|
||||||
|
|
||||||
|
return isAnonymous && (licenseActive || (telemetryOn && !featureFlag));
|
||||||
|
} catch (error) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function* initTrackers(currentUser: User): SagaIterator {
|
||||||
try {
|
try {
|
||||||
const isFFFetched: boolean = yield select(getFeatureFlagsFetched);
|
const isFFFetched: boolean = yield select(getFeatureFlagsFetched);
|
||||||
|
|
||||||
|
|
@ -162,7 +185,21 @@ function* initTrackers(currentUser: User) {
|
||||||
getSessionRecordingConfig,
|
getSessionRecordingConfig,
|
||||||
);
|
);
|
||||||
|
|
||||||
yield call(AnalyticsUtil.initialize, currentUser, sessionRecordingConfig);
|
const featureFlags: FeatureFlags = yield select(selectFeatureFlags);
|
||||||
|
const organizationConfig = yield select(getOrganizationConfig);
|
||||||
|
|
||||||
|
const shouldTrack = shouldTrackUser(
|
||||||
|
currentUser,
|
||||||
|
organizationConfig.license.active,
|
||||||
|
featureFlags.configure_block_event_tracking_for_anonymous_users,
|
||||||
|
);
|
||||||
|
|
||||||
|
yield call(
|
||||||
|
AnalyticsUtil.initialize,
|
||||||
|
currentUser,
|
||||||
|
sessionRecordingConfig,
|
||||||
|
shouldTrack,
|
||||||
|
);
|
||||||
yield put(segmentInitSuccess());
|
yield put(segmentInitSuccess());
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.error(e);
|
log.error(e);
|
||||||
|
|
|
||||||
|
|
@ -30,13 +30,14 @@ let segmentAnalytics: SegmentSingleton | null = null;
|
||||||
async function initialize(
|
async function initialize(
|
||||||
user: User,
|
user: User,
|
||||||
sessionRecordingConfig: SessionRecordingConfig,
|
sessionRecordingConfig: SessionRecordingConfig,
|
||||||
|
shouldTrackUser: boolean,
|
||||||
) {
|
) {
|
||||||
// SentryUtil.init();
|
// SentryUtil.init();
|
||||||
await SmartlookUtil.init();
|
await SmartlookUtil.init();
|
||||||
|
|
||||||
segmentAnalytics = SegmentSingleton.getInstance();
|
segmentAnalytics = SegmentSingleton.getInstance();
|
||||||
|
|
||||||
await segmentAnalytics.init();
|
await segmentAnalytics.init(shouldTrackUser);
|
||||||
|
|
||||||
// Mixpanel needs to be initialized after Segment
|
// Mixpanel needs to be initialized after Segment
|
||||||
await MixpanelSingleton.getInstance().init(sessionRecordingConfig);
|
await MixpanelSingleton.getInstance().init(sessionRecordingConfig);
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ describe("SegmentSingleton", () => {
|
||||||
describe("init", () => {
|
describe("init", () => {
|
||||||
it("should initialize successfully with API key", async () => {
|
it("should initialize successfully with API key", async () => {
|
||||||
const segment = SegmentSingleton.getInstance();
|
const segment = SegmentSingleton.getInstance();
|
||||||
const result = await segment.init();
|
const result = await segment.init(true);
|
||||||
|
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
expect(mockAnalyticsBrowser.load).toHaveBeenCalledWith(
|
expect(mockAnalyticsBrowser.load).toHaveBeenCalledWith(
|
||||||
|
|
@ -73,7 +73,15 @@ describe("SegmentSingleton", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const segment = SegmentSingleton.getInstance();
|
const segment = SegmentSingleton.getInstance();
|
||||||
const result = await segment.init();
|
const result = await segment.init(true);
|
||||||
|
|
||||||
|
expect(result).toBe(true);
|
||||||
|
expect(mockAnalyticsBrowser.load).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not initialize when shouldTrackUser is false", async () => {
|
||||||
|
const segment = SegmentSingleton.getInstance();
|
||||||
|
const result = await segment.init(false);
|
||||||
|
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
expect(mockAnalyticsBrowser.load).not.toHaveBeenCalled();
|
expect(mockAnalyticsBrowser.load).not.toHaveBeenCalled();
|
||||||
|
|
@ -89,7 +97,7 @@ describe("SegmentSingleton", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const segment = SegmentSingleton.getInstance();
|
const segment = SegmentSingleton.getInstance();
|
||||||
const result = await segment.init();
|
const result = await segment.init(true);
|
||||||
|
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
expect(mockAnalyticsBrowser.load).toHaveBeenCalledWith(
|
expect(mockAnalyticsBrowser.load).toHaveBeenCalledWith(
|
||||||
|
|
@ -119,7 +127,7 @@ describe("SegmentSingleton", () => {
|
||||||
const eventData = { test: "data" };
|
const eventData = { test: "data" };
|
||||||
|
|
||||||
segment.track("test-event", eventData);
|
segment.track("test-event", eventData);
|
||||||
await segment.init();
|
await segment.init(true);
|
||||||
|
|
||||||
expect(mockAnalytics.track).toHaveBeenCalledWith("test-event", eventData);
|
expect(mockAnalytics.track).toHaveBeenCalledWith("test-event", eventData);
|
||||||
});
|
});
|
||||||
|
|
@ -127,7 +135,7 @@ describe("SegmentSingleton", () => {
|
||||||
it("should track events directly when initialized", async () => {
|
it("should track events directly when initialized", async () => {
|
||||||
const segment = SegmentSingleton.getInstance();
|
const segment = SegmentSingleton.getInstance();
|
||||||
|
|
||||||
await segment.init();
|
await segment.init(true);
|
||||||
|
|
||||||
const eventData = { test: "data" };
|
const eventData = { test: "data" };
|
||||||
|
|
||||||
|
|
@ -141,7 +149,7 @@ describe("SegmentSingleton", () => {
|
||||||
it("should call analytics identify when initialized", async () => {
|
it("should call analytics identify when initialized", async () => {
|
||||||
const segment = SegmentSingleton.getInstance();
|
const segment = SegmentSingleton.getInstance();
|
||||||
|
|
||||||
await segment.init();
|
await segment.init(true);
|
||||||
|
|
||||||
const userId = "test-user";
|
const userId = "test-user";
|
||||||
const traits = { name: "Test User" };
|
const traits = { name: "Test User" };
|
||||||
|
|
@ -156,7 +164,7 @@ describe("SegmentSingleton", () => {
|
||||||
it("should call analytics reset when initialized", async () => {
|
it("should call analytics reset when initialized", async () => {
|
||||||
const segment = SegmentSingleton.getInstance();
|
const segment = SegmentSingleton.getInstance();
|
||||||
|
|
||||||
await segment.init();
|
await segment.init(true);
|
||||||
|
|
||||||
segment.reset();
|
segment.reset();
|
||||||
|
|
||||||
|
|
@ -169,7 +177,7 @@ describe("SegmentSingleton", () => {
|
||||||
mockAnalyticsBrowser.load.mockRejectedValueOnce(new Error("Init failed"));
|
mockAnalyticsBrowser.load.mockRejectedValueOnce(new Error("Init failed"));
|
||||||
|
|
||||||
const segment = SegmentSingleton.getInstance();
|
const segment = SegmentSingleton.getInstance();
|
||||||
const result = await segment.init();
|
const result = await segment.init(true);
|
||||||
|
|
||||||
expect(result).toBe(false);
|
expect(result).toBe(false);
|
||||||
expect(log.error).toHaveBeenCalledWith(
|
expect(log.error).toHaveBeenCalledWith(
|
||||||
|
|
@ -182,7 +190,7 @@ describe("SegmentSingleton", () => {
|
||||||
it("should not track events after avoidTracking is called", async () => {
|
it("should not track events after avoidTracking is called", async () => {
|
||||||
const segment = SegmentSingleton.getInstance();
|
const segment = SegmentSingleton.getInstance();
|
||||||
|
|
||||||
await segment.init();
|
await segment.init(true);
|
||||||
|
|
||||||
// Track an event before calling avoidTracking
|
// Track an event before calling avoidTracking
|
||||||
segment.track("pre-avoid-event", { data: "value" });
|
segment.track("pre-avoid-event", { data: "value" });
|
||||||
|
|
@ -214,7 +222,7 @@ describe("SegmentSingleton", () => {
|
||||||
segment.avoidTracking();
|
segment.avoidTracking();
|
||||||
|
|
||||||
// Initialize
|
// Initialize
|
||||||
await segment.init();
|
await segment.init(true);
|
||||||
|
|
||||||
// Analytics track should not be called since we're avoiding tracking
|
// Analytics track should not be called since we're avoiding tracking
|
||||||
expect(mockAnalytics.track).not.toHaveBeenCalled();
|
expect(mockAnalytics.track).not.toHaveBeenCalled();
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ class SegmentSingleton {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async init(): Promise<boolean> {
|
public async init(shouldTrackUser: boolean): Promise<boolean> {
|
||||||
const { segment } = getAppsmithConfigs();
|
const { segment } = getAppsmithConfigs();
|
||||||
|
|
||||||
if (!segment.enabled) {
|
if (!segment.enabled) {
|
||||||
|
|
@ -58,6 +58,12 @@ class SegmentSingleton {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!shouldTrackUser) {
|
||||||
|
this.avoidTracking();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.analytics) {
|
if (this.analytics) {
|
||||||
log.warn("Segment is already initialized.");
|
log.warn("Segment is already initialized.");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ public enum FeatureFlagEnum {
|
||||||
release_embed_hide_share_settings_enabled,
|
release_embed_hide_share_settings_enabled,
|
||||||
rollout_datasource_test_rate_limit_enabled,
|
rollout_datasource_test_rate_limit_enabled,
|
||||||
release_gs_all_sheets_options_enabled,
|
release_gs_all_sheets_options_enabled,
|
||||||
|
configure_block_event_tracking_for_anonymous_users,
|
||||||
/**
|
/**
|
||||||
* Feature flag to detect if the git reset optimization is enabled
|
* Feature flag to detect if the git reset optimization is enabled
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import com.appsmith.server.services.ce.AnalyticsServiceCEImpl;
|
||||||
import com.segment.analytics.Analytics;
|
import com.segment.analytics.Analytics;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
|
@ -24,7 +25,8 @@ public class AnalyticsServiceImpl extends AnalyticsServiceCEImpl implements Anal
|
||||||
UserUtils userUtils,
|
UserUtils userUtils,
|
||||||
ProjectProperties projectProperties,
|
ProjectProperties projectProperties,
|
||||||
UserDataRepository userDataRepository,
|
UserDataRepository userDataRepository,
|
||||||
DeploymentProperties deploymentProperties) {
|
DeploymentProperties deploymentProperties,
|
||||||
|
@Lazy FeatureFlagService featureFlagService) {
|
||||||
super(
|
super(
|
||||||
analytics,
|
analytics,
|
||||||
sessionUserService,
|
sessionUserService,
|
||||||
|
|
@ -33,6 +35,7 @@ public class AnalyticsServiceImpl extends AnalyticsServiceCEImpl implements Anal
|
||||||
userUtils,
|
userUtils,
|
||||||
projectProperties,
|
projectProperties,
|
||||||
deploymentProperties,
|
deploymentProperties,
|
||||||
userDataRepository);
|
userDataRepository,
|
||||||
|
featureFlagService);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.appsmith.server.services.ce;
|
package com.appsmith.server.services.ce;
|
||||||
|
|
||||||
import com.appsmith.external.constants.AnalyticsEvents;
|
import com.appsmith.external.constants.AnalyticsEvents;
|
||||||
|
import com.appsmith.external.enums.FeatureFlagEnum;
|
||||||
import com.appsmith.external.helpers.Identifiable;
|
import com.appsmith.external.helpers.Identifiable;
|
||||||
import com.appsmith.external.models.ActionDTO;
|
import com.appsmith.external.models.ActionDTO;
|
||||||
import com.appsmith.external.models.BaseDomain;
|
import com.appsmith.external.models.BaseDomain;
|
||||||
|
|
@ -15,6 +16,7 @@ import com.appsmith.server.helpers.ExchangeUtils;
|
||||||
import com.appsmith.server.helpers.UserUtils;
|
import com.appsmith.server.helpers.UserUtils;
|
||||||
import com.appsmith.server.repositories.UserDataRepository;
|
import com.appsmith.server.repositories.UserDataRepository;
|
||||||
import com.appsmith.server.services.ConfigService;
|
import com.appsmith.server.services.ConfigService;
|
||||||
|
import com.appsmith.server.services.FeatureFlagService;
|
||||||
import com.appsmith.server.services.SessionUserService;
|
import com.appsmith.server.services.SessionUserService;
|
||||||
import com.segment.analytics.Analytics;
|
import com.segment.analytics.Analytics;
|
||||||
import com.segment.analytics.messages.IdentifyMessage;
|
import com.segment.analytics.messages.IdentifyMessage;
|
||||||
|
|
@ -24,6 +26,7 @@ import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.apache.commons.lang3.ObjectUtils;
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Lazy;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
@ -48,6 +51,7 @@ public class AnalyticsServiceCEImpl implements AnalyticsServiceCE {
|
||||||
private final SessionUserService sessionUserService;
|
private final SessionUserService sessionUserService;
|
||||||
private final CommonConfig commonConfig;
|
private final CommonConfig commonConfig;
|
||||||
private final ConfigService configService;
|
private final ConfigService configService;
|
||||||
|
private final FeatureFlagService featureFlagService;
|
||||||
|
|
||||||
private final UserUtils userUtils;
|
private final UserUtils userUtils;
|
||||||
|
|
||||||
|
|
@ -65,11 +69,13 @@ public class AnalyticsServiceCEImpl implements AnalyticsServiceCE {
|
||||||
UserUtils userUtils,
|
UserUtils userUtils,
|
||||||
ProjectProperties projectProperties,
|
ProjectProperties projectProperties,
|
||||||
DeploymentProperties deploymentProperties,
|
DeploymentProperties deploymentProperties,
|
||||||
UserDataRepository userDataRepository) {
|
UserDataRepository userDataRepository,
|
||||||
|
@Lazy FeatureFlagService featureFlagService) {
|
||||||
this.analytics = analytics;
|
this.analytics = analytics;
|
||||||
this.sessionUserService = sessionUserService;
|
this.sessionUserService = sessionUserService;
|
||||||
this.commonConfig = commonConfig;
|
this.commonConfig = commonConfig;
|
||||||
this.configService = configService;
|
this.configService = configService;
|
||||||
|
this.featureFlagService = featureFlagService;
|
||||||
this.userUtils = userUtils;
|
this.userUtils = userUtils;
|
||||||
this.projectProperties = projectProperties;
|
this.projectProperties = projectProperties;
|
||||||
this.deploymentProperties = deploymentProperties;
|
this.deploymentProperties = deploymentProperties;
|
||||||
|
|
@ -319,7 +325,26 @@ public class AnalyticsServiceCEImpl implements AnalyticsServiceCE {
|
||||||
|
|
||||||
Mono<User> userMono = sessionUserService.getCurrentUser().switchIfEmpty(Mono.just(anonymousUser));
|
Mono<User> userMono = sessionUserService.getCurrentUser().switchIfEmpty(Mono.just(anonymousUser));
|
||||||
|
|
||||||
return userMono.flatMap(user -> Mono.zip(
|
return userMono.flatMap(user -> {
|
||||||
|
// if the user is anonymous, check if the feature flag
|
||||||
|
// configure_block_event_tracking_for_anonymous_users is enabled. If yes, then do not send the
|
||||||
|
// analytics event.
|
||||||
|
if (user.isAnonymous()) {
|
||||||
|
return featureFlagService
|
||||||
|
.check(FeatureFlagEnum.configure_block_event_tracking_for_anonymous_users)
|
||||||
|
.flatMap(isDisabled -> {
|
||||||
|
if (isDisabled) {
|
||||||
|
log.debug("Analytics event {} is not sent for anonymous user", eventTag);
|
||||||
|
return Mono.empty();
|
||||||
|
} else {
|
||||||
|
return Mono.just(user);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return Mono.just(user);
|
||||||
|
})
|
||||||
|
.flatMap(user -> Mono.zip(
|
||||||
user.isAnonymous()
|
user.isAnonymous()
|
||||||
? ExchangeUtils.getAnonymousUserIdFromCurrentRequest()
|
? ExchangeUtils.getAnonymousUserIdFromCurrentRequest()
|
||||||
: Mono.just(user.getUsername()),
|
: Mono.just(user.getUsername()),
|
||||||
|
|
@ -363,8 +388,10 @@ public class AnalyticsServiceCEImpl implements AnalyticsServiceCE {
|
||||||
analyticsProperties.remove(FieldName.CLOUD_HOSTED_EXTRA_PROPS);
|
analyticsProperties.remove(FieldName.CLOUD_HOSTED_EXTRA_PROPS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sendEvent(eventTag, username, analyticsProperties).thenReturn(object);
|
return sendEvent(eventTag, username, analyticsProperties);
|
||||||
});
|
})
|
||||||
|
// Return the original object after sending the event
|
||||||
|
.then(Mono.just(object));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user