From 6e44847ba2b2374dd1930b0854c4ea409c728333 Mon Sep 17 00:00:00 2001 From: Chris Collins Date: Wed, 27 Apr 2022 13:01:44 -0400 Subject: [PATCH 1/2] Configure whether third party logging is enabled with env variable --- .../datahub/graphql/GmsGraphQLEngine.java | 9 ++++-- .../resolvers/config/AppConfigResolver.java | 11 ++++++- .../src/main/resources/app.graphql | 15 ++++++++++ datahub-web-react/src/AppConfigProvider.tsx | 15 +++++++++- .../app/analytics/__tests__/analytics.test.ts | 29 +++++++++++++++++++ .../src/app/analytics/analytics.ts | 25 ++++++++++++++-- datahub-web-react/src/appConfigContext.tsx | 3 ++ datahub-web-react/src/graphql/app.graphql | 3 ++ .../telemetry}/TelemetryConfiguration.java | 6 +++- .../factory/config/ConfigurationProvider.java | 1 + .../factory/graphql/GraphQLEngineFactory.java | 6 ++-- .../src/main/resources/application.yml | 1 + 12 files changed, 114 insertions(+), 10 deletions(-) create mode 100644 datahub-web-react/src/app/analytics/__tests__/analytics.test.ts rename {metadata-service/factories/src/main/java/com/linkedin/gms/factory/config => metadata-io/src/main/java/com/linkedin/metadata/telemetry}/TelemetryConfiguration.java (64%) diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java index 1cd91e38a32e5e..51306b27650814 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java @@ -166,6 +166,7 @@ import com.linkedin.metadata.models.registry.EntityRegistry; import com.linkedin.metadata.recommendation.RecommendationsService; import com.linkedin.metadata.secret.SecretService; +import com.linkedin.metadata.telemetry.TelemetryConfiguration; import com.linkedin.metadata.timeseries.TimeseriesAspectService; import com.linkedin.metadata.version.GitVersion; import com.linkedin.usage.UsageClient; @@ -225,6 +226,7 @@ public class GmsGraphQLEngine { private final AuthenticationConfiguration authenticationConfiguration; private final AuthorizationConfiguration authorizationConfiguration; private final VisualConfiguration visualConfiguration; + private final TelemetryConfiguration telemetryConfiguration; private final DatasetType datasetType; private final CorpUserType corpUserType; @@ -292,6 +294,7 @@ public GmsGraphQLEngine() { null, null, false, + null, null); } @@ -311,7 +314,8 @@ public GmsGraphQLEngine( final AuthorizationConfiguration authorizationConfiguration, final GitVersion gitVersion, final boolean supportsImpactAnalysis, - final VisualConfiguration visualConfiguration + final VisualConfiguration visualConfiguration, + final TelemetryConfiguration telemetryConfiguration ) { this.entityClient = entityClient; @@ -332,6 +336,7 @@ public GmsGraphQLEngine( this.authenticationConfiguration = Objects.requireNonNull(authenticationConfiguration); this.authorizationConfiguration = Objects.requireNonNull(authorizationConfiguration); this.visualConfiguration = visualConfiguration; + this.telemetryConfiguration = telemetryConfiguration; this.datasetType = new DatasetType(entityClient); this.corpUserType = new CorpUserType(entityClient); @@ -569,7 +574,7 @@ private void configureQueryResolvers(final RuntimeWiring.Builder builder) { this.ingestionConfiguration, this.authenticationConfiguration, this.authorizationConfiguration, - supportsImpactAnalysis, this.visualConfiguration)) + supportsImpactAnalysis, this.visualConfiguration, this.telemetryConfiguration)) .dataFetcher("me", new AuthenticatedResolver<>( new MeResolver(this.entityClient))) .dataFetcher("search", new AuthenticatedResolver<>( diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/config/AppConfigResolver.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/config/AppConfigResolver.java index 8fda3c198c482b..cc26bf85dd4753 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/config/AppConfigResolver.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/resolvers/config/AppConfigResolver.java @@ -13,8 +13,10 @@ import com.linkedin.datahub.graphql.generated.PoliciesConfig; import com.linkedin.datahub.graphql.generated.Privilege; import com.linkedin.datahub.graphql.generated.ResourcePrivileges; +import com.linkedin.datahub.graphql.generated.TelemetryConfig; import com.linkedin.datahub.graphql.generated.VisualConfiguration; import com.linkedin.metadata.config.IngestionConfiguration; +import com.linkedin.metadata.telemetry.TelemetryConfiguration; import com.linkedin.metadata.version.GitVersion; import graphql.schema.DataFetcher; import graphql.schema.DataFetchingEnvironment; @@ -34,6 +36,7 @@ public class AppConfigResolver implements DataFetcher get(final DataFetchingEnvironment environmen appConfig.setAuthConfig(authConfig); appConfig.setVisualConfig(_visualConfiguration); + final TelemetryConfig telemetryConfig = new TelemetryConfig(); + telemetryConfig.setEnableThirdPartyLogging(_telemetryConfiguration.isEnableThirdPartyLogging()); + appConfig.setTelemetryConfig(telemetryConfig); + return CompletableFuture.completedFuture(appConfig); } diff --git a/datahub-graphql-core/src/main/resources/app.graphql b/datahub-graphql-core/src/main/resources/app.graphql index a1ce09a6d71a1c..b28e9381dddffd 100644 --- a/datahub-graphql-core/src/main/resources/app.graphql +++ b/datahub-graphql-core/src/main/resources/app.graphql @@ -112,6 +112,11 @@ type AppConfig { Configurations related to visual appearance, allows styling the UI without rebuilding the bundle """ visualConfig: VisualConfiguration! + + """ + Configurations related to tracking users in the app + """ + telemetryConfig: TelemetryConfig! } """ @@ -124,6 +129,16 @@ type VisualConfiguration { logoUrl: String } +""" +Configurations related to tracking users in the app +""" +type TelemetryConfig { + """ + Env variable for whether or not third party logging should be enabled for this instance + """ + enableThirdPartyLogging: Boolean +} + """ Configurations related to Lineage """ diff --git a/datahub-web-react/src/AppConfigProvider.tsx b/datahub-web-react/src/AppConfigProvider.tsx index 2213f2afad2d75..cf0d1426287592 100644 --- a/datahub-web-react/src/AppConfigProvider.tsx +++ b/datahub-web-react/src/AppConfigProvider.tsx @@ -1,5 +1,7 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import './App.less'; +import { THIRD_PARTY_LOGGING_KEY } from './app/analytics/analytics'; +import { checkAuthStatus } from './app/auth/checkAuthStatus'; import { AppConfigContext, DEFAULT_APP_CONFIG } from './appConfigContext'; import { useAppConfigQuery } from './graphql/app.generated'; @@ -10,6 +12,17 @@ const AppConfigProvider = ({ children }: { children: React.ReactNode }) => { refetch(); }; + useEffect(() => { + if (appConfigData && appConfigData.appConfig) { + if (appConfigData.appConfig.telemetryConfig.enableThirdPartyLogging) { + localStorage.setItem(THIRD_PARTY_LOGGING_KEY, 'true'); + checkAuthStatus(); // identify in analyitcs once we receive config response + } else { + localStorage.setItem(THIRD_PARTY_LOGGING_KEY, 'false'); + } + } + }, [appConfigData]); + return ( { + it('should update or create an options object with mixpanel set to the value of what is in localStorage', () => { + // before anything is set in localStorage + let trackingOptions = getMergedTrackingOptions(); + expect(trackingOptions).toMatchObject({ + plugins: { + mixpanel: false, + }, + }); + + localStorage.setItem(THIRD_PARTY_LOGGING_KEY, 'false'); + trackingOptions = getMergedTrackingOptions(); + expect(trackingOptions).toMatchObject({ + plugins: { + mixpanel: false, + }, + }); + + localStorage.setItem(THIRD_PARTY_LOGGING_KEY, 'true'); + trackingOptions = getMergedTrackingOptions(); + expect(trackingOptions).toMatchObject({ + plugins: { + mixpanel: true, + }, + }); + }); +}); diff --git a/datahub-web-react/src/app/analytics/analytics.ts b/datahub-web-react/src/app/analytics/analytics.ts index 11c1e7c6d52298..a66d76a09cf4de 100644 --- a/datahub-web-react/src/app/analytics/analytics.ts +++ b/datahub-web-react/src/app/analytics/analytics.ts @@ -7,6 +7,8 @@ import { getBrowserId } from '../browserId'; const appName = 'datahub-react'; +export const THIRD_PARTY_LOGGING_KEY = 'enableThirdPartyLogging'; + const analytics = Analytics({ app: appName, plugins: plugins.filter((plugin) => plugin.isEnabled).map((plugin) => plugin.plugin), @@ -14,8 +16,19 @@ const analytics = Analytics({ const { NODE_ENV } = process.env; +export function getMergedTrackingOptions(options?: any) { + const isThirdPartyLoggingEnabled = JSON.parse(localStorage.getItem(THIRD_PARTY_LOGGING_KEY) || 'false'); + return { + ...options, + plugins: { + mixpanel: isThirdPartyLoggingEnabled, + amplitude: isThirdPartyLoggingEnabled, + googleAnalytics: isThirdPartyLoggingEnabled, + }, + }; +} + export default { - ...analytics, page: (data?: PageData, options?: any, callback?: (...params: any[]) => any) => { const modifiedData = { ...data, @@ -29,7 +42,8 @@ export default { if (NODE_ENV === 'test') { return null; } - return analytics.page(modifiedData, options, callback); + const trackingOptions = getMergedTrackingOptions(options); + return analytics.page(modifiedData, trackingOptions, callback); }, event: (event: Event, options?: any, callback?: (...params: any[]) => any): Promise => { const eventTypeName = EventType[event.type]; @@ -45,6 +59,11 @@ export default { if (NODE_ENV === 'test') { return Promise.resolve(); } - return analytics.track(eventTypeName, modifiedEvent, options, callback); + const trackingOptions = getMergedTrackingOptions(options); + return analytics.track(eventTypeName, modifiedEvent, trackingOptions, callback); + }, + identify: (userId: string, traits?: any, options?: any, callback?: ((...params: any[]) => any) | undefined) => { + const trackingOptions = getMergedTrackingOptions(options); + return analytics.identify(userId, traits, trackingOptions, callback); }, }; diff --git a/datahub-web-react/src/appConfigContext.tsx b/datahub-web-react/src/appConfigContext.tsx index 0c0b3bde628b66..10e85ecb0657be 100644 --- a/datahub-web-react/src/appConfigContext.tsx +++ b/datahub-web-react/src/appConfigContext.tsx @@ -25,6 +25,9 @@ export const DEFAULT_APP_CONFIG = { authConfig: { tokenAuthEnabled: false, }, + telemetryConfig: { + enableThirdPartyLogging: false, + }, }; export const AppConfigContext = React.createContext<{ diff --git a/datahub-web-react/src/graphql/app.graphql b/datahub-web-react/src/graphql/app.graphql index 40f7cba9d69d50..644e60b8e7c57e 100644 --- a/datahub-web-react/src/graphql/app.graphql +++ b/datahub-web-react/src/graphql/app.graphql @@ -37,6 +37,9 @@ query appConfig { visualConfig { logoUrl } + telemetryConfig { + enableThirdPartyLogging + } } } diff --git a/metadata-service/factories/src/main/java/com/linkedin/gms/factory/config/TelemetryConfiguration.java b/metadata-io/src/main/java/com/linkedin/metadata/telemetry/TelemetryConfiguration.java similarity index 64% rename from metadata-service/factories/src/main/java/com/linkedin/gms/factory/config/TelemetryConfiguration.java rename to metadata-io/src/main/java/com/linkedin/metadata/telemetry/TelemetryConfiguration.java index b78a1cbec5c85b..7d7048096731e9 100644 --- a/metadata-service/factories/src/main/java/com/linkedin/gms/factory/config/TelemetryConfiguration.java +++ b/metadata-io/src/main/java/com/linkedin/metadata/telemetry/TelemetryConfiguration.java @@ -1,4 +1,4 @@ -package com.linkedin.gms.factory.config; +package com.linkedin.metadata.telemetry; import lombok.Data; /** @@ -14,4 +14,8 @@ public class TelemetryConfiguration { * Whether reporting telemetry is enabled */ public boolean enabledIngestion; + /** + * Whether or not third party logging should be enabled for this instance + */ + public boolean enableThirdPartyLogging; } \ No newline at end of file diff --git a/metadata-service/factories/src/main/java/com/linkedin/gms/factory/config/ConfigurationProvider.java b/metadata-service/factories/src/main/java/com/linkedin/gms/factory/config/ConfigurationProvider.java index 00d1679db5c6e9..d3088a21b1a4fb 100644 --- a/metadata-service/factories/src/main/java/com/linkedin/gms/factory/config/ConfigurationProvider.java +++ b/metadata-service/factories/src/main/java/com/linkedin/gms/factory/config/ConfigurationProvider.java @@ -3,6 +3,7 @@ import com.datahub.authentication.AuthenticationConfiguration; import com.datahub.authorization.AuthorizationConfiguration; import com.linkedin.metadata.config.IngestionConfiguration; +import com.linkedin.metadata.telemetry.TelemetryConfiguration; import com.linkedin.gms.factory.spring.YamlPropertySourceFactory; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/metadata-service/factories/src/main/java/com/linkedin/gms/factory/graphql/GraphQLEngineFactory.java b/metadata-service/factories/src/main/java/com/linkedin/gms/factory/graphql/GraphQLEngineFactory.java index 6538f4af21fc78..79d092a376e026 100644 --- a/metadata-service/factories/src/main/java/com/linkedin/gms/factory/graphql/GraphQLEngineFactory.java +++ b/metadata-service/factories/src/main/java/com/linkedin/gms/factory/graphql/GraphQLEngineFactory.java @@ -120,7 +120,8 @@ protected GraphQLEngine getInstance() { _configProvider.getAuthorization(), _gitVersion, _graphService.supportsMultiHop(), - _visualConfiguration + _visualConfiguration, + _configProvider.getTelemetry() ).builder().build(); } return new GmsGraphQLEngine( @@ -139,7 +140,8 @@ protected GraphQLEngine getInstance() { _configProvider.getAuthorization(), _gitVersion, _graphService.supportsMultiHop(), - _visualConfiguration + _visualConfiguration, + _configProvider.getTelemetry() ).builder().build(); } } diff --git a/metadata-service/factories/src/main/resources/application.yml b/metadata-service/factories/src/main/resources/application.yml index e3eb202dddac5a..8afac58a8620bf 100644 --- a/metadata-service/factories/src/main/resources/application.yml +++ b/metadata-service/factories/src/main/resources/application.yml @@ -45,6 +45,7 @@ ingestion: telemetry: enabledCli: ${CLI_TELEMETRY_ENABLED:true} enabledIngestion: ${INGESTION_REPORTING_ENABLED:false} + enableThirdPartyLogging: ${ENABLE_THIRD_PARTY_LOGGING:false} secretService: encryptionKey: ${SECRET_SERVICE_ENCRYPTION_KEY:ENCRYPTION_KEY} From cb02322c1d9a2ad23cdf78fcb3b2967e7fad3aaa Mon Sep 17 00:00:00 2001 From: Chris Collins Date: Fri, 29 Apr 2022 16:23:35 -0400 Subject: [PATCH 2/2] remove extra lines from conflict resolution --- .../java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java index 03811837efa8ae..0b5217aea91f25 100644 --- a/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java +++ b/datahub-graphql-core/src/main/java/com/linkedin/datahub/graphql/GmsGraphQLEngine.java @@ -271,7 +271,6 @@ public class GmsGraphQLEngine { /** * Configures the graph objects that can be browsed. */ - public final List> browsableTypes; public GmsGraphQLEngine( @@ -481,7 +480,6 @@ private void configureQueryResolvers(final RuntimeWiring.Builder builder) { this.ingestionConfiguration, this.authenticationConfiguration, this.authorizationConfiguration, - supportsImpactAnalysis, this.visualConfiguration, this.telemetryConfiguration)) .dataFetcher("me", new MeResolver(this.entityClient)) .dataFetcher("search", new SearchResolver(this.entityClient))