Skip to content

Commit

Permalink
Merge branch 'linkedin:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
shirshanka authored Feb 21, 2022
2 parents fd17a9d + a2d096e commit d36cf07
Show file tree
Hide file tree
Showing 135 changed files with 8,188 additions and 1,006 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ jobs:
uses: actions/setup-java@v1
with:
java-version: 1.8
- uses: actions/setup-python@v2
with:
python-version: 3.9.9
- name: Install Python dependencies
run: ./metadata-ingestion/scripts/install_deps.sh
- name: Build Docs
run: |
./gradlew --info docs-website:build
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.linkedin.datahub.graphql.analytics.resolver.AnalyticsChartTypeResolver;
import com.linkedin.datahub.graphql.analytics.resolver.GetChartsResolver;
import com.linkedin.datahub.graphql.analytics.resolver.GetHighlightsResolver;
import com.linkedin.datahub.graphql.analytics.resolver.GetMetadataAnalyticsResolver;
import com.linkedin.datahub.graphql.analytics.resolver.IsAnalyticsEnabledResolver;
import com.linkedin.datahub.graphql.analytics.service.AnalyticsService;
import com.linkedin.datahub.graphql.generated.AggregationMetadata;
Expand All @@ -26,8 +27,8 @@
import com.linkedin.datahub.graphql.generated.EntityRelationship;
import com.linkedin.datahub.graphql.generated.EntityRelationshipLegacy;
import com.linkedin.datahub.graphql.generated.ForeignKeyConstraint;
import com.linkedin.datahub.graphql.generated.ListDomainsResult;
import com.linkedin.datahub.graphql.generated.InstitutionalMemoryMetadata;
import com.linkedin.datahub.graphql.generated.ListDomainsResult;
import com.linkedin.datahub.graphql.generated.MLFeature;
import com.linkedin.datahub.graphql.generated.MLFeatureProperties;
import com.linkedin.datahub.graphql.generated.MLFeatureTable;
Expand All @@ -45,10 +46,10 @@
import com.linkedin.datahub.graphql.resolvers.AuthenticatedResolver;
import com.linkedin.datahub.graphql.resolvers.MeResolver;
import com.linkedin.datahub.graphql.resolvers.auth.GetAccessTokenResolver;
import com.linkedin.datahub.graphql.resolvers.container.ContainerEntitiesResolver;
import com.linkedin.datahub.graphql.resolvers.browse.BrowsePathsResolver;
import com.linkedin.datahub.graphql.resolvers.browse.BrowseResolver;
import com.linkedin.datahub.graphql.resolvers.config.AppConfigResolver;
import com.linkedin.datahub.graphql.resolvers.container.ContainerEntitiesResolver;
import com.linkedin.datahub.graphql.resolvers.deprecation.UpdateDeprecationResolver;
import com.linkedin.datahub.graphql.resolvers.domain.CreateDomainResolver;
import com.linkedin.datahub.graphql.resolvers.domain.DomainEntitiesResolver;
Expand All @@ -61,18 +62,18 @@
import com.linkedin.datahub.graphql.resolvers.group.ListGroupsResolver;
import com.linkedin.datahub.graphql.resolvers.group.RemoveGroupMembersResolver;
import com.linkedin.datahub.graphql.resolvers.group.RemoveGroupResolver;
import com.linkedin.datahub.graphql.resolvers.group.UpdateUserStatusResolver;
import com.linkedin.datahub.graphql.resolvers.user.UpdateUserStatusResolver;
import com.linkedin.datahub.graphql.resolvers.ingest.execution.CancelIngestionExecutionRequestResolver;
import com.linkedin.datahub.graphql.resolvers.ingest.execution.CreateIngestionExecutionRequestResolver;
import com.linkedin.datahub.graphql.resolvers.ingest.execution.GetIngestionExecutionRequestResolver;
import com.linkedin.datahub.graphql.resolvers.ingest.execution.IngestionSourceExecutionRequestsResolver;
import com.linkedin.datahub.graphql.resolvers.ingest.secret.CreateSecretResolver;
import com.linkedin.datahub.graphql.resolvers.ingest.source.DeleteIngestionSourceResolver;
import com.linkedin.datahub.graphql.resolvers.ingest.secret.DeleteSecretResolver;
import com.linkedin.datahub.graphql.resolvers.ingest.execution.GetIngestionExecutionRequestResolver;
import com.linkedin.datahub.graphql.resolvers.ingest.source.GetIngestionSourceResolver;
import com.linkedin.datahub.graphql.resolvers.ingest.secret.GetSecretValuesResolver;
import com.linkedin.datahub.graphql.resolvers.ingest.execution.IngestionSourceExecutionRequestsResolver;
import com.linkedin.datahub.graphql.resolvers.ingest.source.ListIngestionSourcesResolver;
import com.linkedin.datahub.graphql.resolvers.ingest.secret.ListSecretsResolver;
import com.linkedin.datahub.graphql.resolvers.ingest.source.DeleteIngestionSourceResolver;
import com.linkedin.datahub.graphql.resolvers.ingest.source.GetIngestionSourceResolver;
import com.linkedin.datahub.graphql.resolvers.ingest.source.ListIngestionSourcesResolver;
import com.linkedin.datahub.graphql.resolvers.ingest.source.UpsertIngestionSourceResolver;
import com.linkedin.datahub.graphql.resolvers.load.AspectResolver;
import com.linkedin.datahub.graphql.resolvers.load.EntityRelationshipsResultResolver;
Expand Down Expand Up @@ -116,10 +117,10 @@
import com.linkedin.datahub.graphql.types.SearchableEntityType;
import com.linkedin.datahub.graphql.types.aspect.AspectType;
import com.linkedin.datahub.graphql.types.chart.ChartType;
import com.linkedin.datahub.graphql.types.container.ContainerType;
import com.linkedin.datahub.graphql.types.corpuser.CorpUserType;
import com.linkedin.datahub.graphql.types.common.mappers.OperationMapper;
import com.linkedin.datahub.graphql.types.container.ContainerType;
import com.linkedin.datahub.graphql.types.corpgroup.CorpGroupType;
import com.linkedin.datahub.graphql.types.corpuser.CorpUserType;
import com.linkedin.datahub.graphql.types.dashboard.DashboardType;
import com.linkedin.datahub.graphql.types.dataflow.DataFlowType;
import com.linkedin.datahub.graphql.types.datajob.DataJobType;
Expand Down Expand Up @@ -164,8 +165,15 @@
import org.dataloader.DataLoader;
import org.dataloader.DataLoaderOptions;

import static com.linkedin.datahub.graphql.Constants.*;
import static graphql.Scalars.*;
import static com.linkedin.datahub.graphql.Constants.ANALYTICS_SCHEMA_FILE;
import static com.linkedin.datahub.graphql.Constants.APP_SCHEMA_FILE;
import static com.linkedin.datahub.graphql.Constants.AUTH_SCHEMA_FILE;
import static com.linkedin.datahub.graphql.Constants.GMS_SCHEMA_FILE;
import static com.linkedin.datahub.graphql.Constants.INGESTION_SCHEMA_FILE;
import static com.linkedin.datahub.graphql.Constants.RECOMMENDATIONS_SCHEMA_FILE;
import static com.linkedin.datahub.graphql.Constants.SEARCH_SCHEMA_FILE;
import static com.linkedin.datahub.graphql.Constants.URN_FIELD_NAME;
import static graphql.Scalars.GraphQLLong;

/**
* A {@link GraphQLEngine} configured to provide access to the entities and aspects on the the GMS graph.
Expand Down Expand Up @@ -469,9 +477,10 @@ private void configureAnalyticsResolvers(final RuntimeWiring.Builder builder) {
builder.type("Query", typeWiring -> typeWiring.dataFetcher("isAnalyticsEnabled", new IsAnalyticsEnabledResolver(isAnalyticsEnabled)))
.type("AnalyticsChart", typeWiring -> typeWiring.typeResolver(new AnalyticsChartTypeResolver()));
if (isAnalyticsEnabled) {
builder.type("Query",
typeWiring -> typeWiring.dataFetcher("getAnalyticsCharts", new GetChartsResolver(analyticsService))
.dataFetcher("getHighlights", new GetHighlightsResolver(analyticsService)));
builder.type("Query", typeWiring -> typeWiring.dataFetcher("getAnalyticsCharts",
new GetChartsResolver(analyticsService, entityClient))
.dataFetcher("getHighlights", new GetHighlightsResolver(analyticsService))
.dataFetcher("getMetadataAnalyticsCharts", new GetMetadataAnalyticsResolver(entityClient)));
}
}

Expand Down Expand Up @@ -595,7 +604,8 @@ private void configureMutationResolvers(final RuntimeWiring.Builder builder) {
.dataFetcher("updateDashboard", new AuthenticatedResolver<>(new MutableTypeResolver<>(dashboardType)))
.dataFetcher("updateDataJob", new AuthenticatedResolver<>(new MutableTypeResolver<>(dataJobType)))
.dataFetcher("updateDataFlow", new AuthenticatedResolver<>(new MutableTypeResolver<>(dataFlowType)))
.dataFetcher("updateCorpUserProperties", new AuthenticatedResolver<>(new MutableTypeResolver<>(corpUserType)))
.dataFetcher("updateCorpUserProperties", new MutableTypeResolver<>(corpUserType))
.dataFetcher("updateCorpGroupProperties", new MutableTypeResolver<>(corpGroupType))
.dataFetcher("addTag", new AuthenticatedResolver<>(new AddTagResolver(entityService)))
.dataFetcher("removeTag", new AuthenticatedResolver<>(new RemoveTagResolver(entityService)))
.dataFetcher("addTerm", new AuthenticatedResolver<>(new AddTermResolver(entityService)))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,49 +1,64 @@
package com.linkedin.datahub.graphql.analytics.resolver;

import com.datahub.authentication.Authentication;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.linkedin.datahub.graphql.analytics.service.AnalyticsService;
import com.linkedin.datahub.graphql.analytics.service.AnalyticsUtil;
import com.linkedin.datahub.graphql.generated.AnalyticsChart;
import com.linkedin.datahub.graphql.generated.AnalyticsChartGroup;
import com.linkedin.datahub.graphql.generated.BarChart;
import com.linkedin.datahub.graphql.generated.DateInterval;
import com.linkedin.datahub.graphql.generated.DateRange;
import com.linkedin.datahub.graphql.generated.EntityType;
import com.linkedin.datahub.graphql.generated.NamedBar;
import com.linkedin.datahub.graphql.generated.NamedLine;
import com.linkedin.datahub.graphql.generated.Row;
import com.linkedin.datahub.graphql.generated.TableChart;
import com.linkedin.datahub.graphql.generated.TimeSeriesChart;
import com.linkedin.datahub.graphql.resolvers.ResolverUtils;
import com.linkedin.entity.client.EntityClient;
import com.linkedin.metadata.Constants;
import graphql.schema.DataFetcher;
import graphql.schema.DataFetchingEnvironment;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;


/**
* Retrieves the Charts to be rendered of the Analytics screen of the DataHub application.
*/
@Slf4j
@RequiredArgsConstructor
public final class GetChartsResolver implements DataFetcher<List<AnalyticsChartGroup>> {

private final AnalyticsService _analyticsService;

public GetChartsResolver(final AnalyticsService analyticsService) {
_analyticsService = analyticsService;
}
private final EntityClient _entityClient;

@Override
public final List<AnalyticsChartGroup> get(DataFetchingEnvironment environment) throws Exception {
final AnalyticsChartGroup group = new AnalyticsChartGroup();
group.setTitle("Product Analytics");
group.setCharts(getProductAnalyticsCharts());
return ImmutableList.of(group);
Authentication authentication = ResolverUtils.getAuthentication(environment);
return ImmutableList.of(AnalyticsChartGroup.builder()
.setGroupId("DataHubUsageAnalytics")
.setTitle("DataHub Usage Analytics")
.setCharts(getProductAnalyticsCharts(authentication))
.build(), AnalyticsChartGroup.builder()
.setGroupId("GlobalMetadataAnalytics")
.setTitle("Data Landscape Summary")
.setCharts(getGlobalMetadataAnalyticsCharts(authentication))
.build());
}

/**
* TODO: Config Driven Charts Instead of Hardcoded.
*/
private List<AnalyticsChart> getProductAnalyticsCharts() {
private List<AnalyticsChart> getProductAnalyticsCharts(Authentication authentication) throws Exception {
final List<AnalyticsChart> charts = new ArrayList<>();
final DateTime now = DateTime.now();
final DateTime aWeekAgo = now.minusWeeks(1);
Expand All @@ -59,7 +74,7 @@ private List<AnalyticsChart> getProductAnalyticsCharts() {
DateInterval weeklyInterval = DateInterval.WEEK;

final List<NamedLine> wauTimeseries =
_analyticsService.getTimeseriesChart(AnalyticsService.DATAHUB_USAGE_EVENT_INDEX, twoMonthsDateRange, weeklyInterval,
_analyticsService.getTimeseriesChart(_analyticsService.getUsageIndexName(), twoMonthsDateRange, weeklyInterval,
Optional.empty(), ImmutableMap.of(), Optional.of("browserId"));
charts.add(TimeSeriesChart.builder()
.setTitle(wauTitle)
Expand All @@ -74,7 +89,7 @@ private List<AnalyticsChart> getProductAnalyticsCharts() {
String searchEventType = "SearchEvent";

final List<NamedLine> searchesTimeseries =
_analyticsService.getTimeseriesChart(AnalyticsService.DATAHUB_USAGE_EVENT_INDEX, lastWeekDateRange, dailyInterval,
_analyticsService.getTimeseriesChart(_analyticsService.getUsageIndexName(), lastWeekDateRange, dailyInterval,
Optional.empty(), ImmutableMap.of("type", ImmutableList.of(searchEventType)), Optional.empty());
charts.add(TimeSeriesChart.builder()
.setTitle(searchesTitle)
Expand All @@ -88,35 +103,85 @@ private List<AnalyticsChart> getProductAnalyticsCharts() {
final List<String> columns = ImmutableList.of("Query", "Count");

final List<Row> topSearchQueries =
_analyticsService.getTopNTableChart(AnalyticsService.DATAHUB_USAGE_EVENT_INDEX, Optional.of(lastWeekDateRange),
"query.keyword", ImmutableMap.of("type", ImmutableList.of(searchEventType)), Optional.empty(), 10);
_analyticsService.getTopNTableChart(_analyticsService.getUsageIndexName(), Optional.of(lastWeekDateRange),
"query.keyword", ImmutableMap.of("type", ImmutableList.of(searchEventType)), Optional.empty(), 10,
AnalyticsUtil::buildCellWithSearchLandingPage);
charts.add(TableChart.builder().setTitle(topSearchTitle).setColumns(columns).setRows(topSearchQueries).build());

// Chart 4: Bar Graph Chart
final String sectionViewsTitle = "Section Views across Entity Types";
final List<NamedBar> sectionViewsPerEntityType =
_analyticsService.getBarChart(AnalyticsService.DATAHUB_USAGE_EVENT_INDEX, Optional.of(lastWeekDateRange),
_analyticsService.getBarChart(_analyticsService.getUsageIndexName(), Optional.of(lastWeekDateRange),
ImmutableList.of("entityType.keyword", "section.keyword"),
ImmutableMap.of("type", ImmutableList.of("EntitySectionViewEvent")), Optional.empty());
ImmutableMap.of("type", ImmutableList.of("EntitySectionViewEvent")), Optional.empty(), true);
charts.add(BarChart.builder().setTitle(sectionViewsTitle).setBars(sectionViewsPerEntityType).build());

// Chart 5: Bar Graph Chart
final String actionsByTypeTitle = "Actions by Entity Type";
final List<NamedBar> eventsByEventType =
_analyticsService.getBarChart(AnalyticsService.DATAHUB_USAGE_EVENT_INDEX, Optional.of(lastWeekDateRange),
_analyticsService.getBarChart(_analyticsService.getUsageIndexName(), Optional.of(lastWeekDateRange),
ImmutableList.of("entityType.keyword", "actionType.keyword"),
ImmutableMap.of("type", ImmutableList.of("EntityActionEvent")), Optional.empty());
ImmutableMap.of("type", ImmutableList.of("EntityActionEvent")), Optional.empty(), true);
charts.add(BarChart.builder().setTitle(actionsByTypeTitle).setBars(eventsByEventType).build());

// Chart 6: Table Chart
final String topViewedTitle = "Top Viewed Dataset";
final List<String> columns5 = ImmutableList.of("Dataset", "#Views");

final List<Row> topViewedDatasets =
_analyticsService.getTopNTableChart(AnalyticsService.DATAHUB_USAGE_EVENT_INDEX, Optional.of(lastWeekDateRange),
"dataset_name.keyword", ImmutableMap.of("type", ImmutableList.of("EntityViewEvent")), Optional.empty(), 10);
_analyticsService.getTopNTableChart(_analyticsService.getUsageIndexName(), Optional.of(lastWeekDateRange),
"entityUrn.keyword", ImmutableMap.of("type", ImmutableList.of("EntityViewEvent"), "entityType.keyword",
ImmutableList.of(EntityType.DATASET.name())), Optional.empty(), 10,
AnalyticsUtil::buildCellWithEntityLandingPage);
AnalyticsUtil.hydrateDisplayNameForTable(_entityClient, topViewedDatasets, Constants.DATASET_ENTITY_NAME,
ImmutableSet.of(Constants.DATASET_KEY_ASPECT_NAME), AnalyticsUtil::getDatasetName, authentication);
charts.add(TableChart.builder().setTitle(topViewedTitle).setColumns(columns5).setRows(topViewedDatasets).build());


return charts;
}

private List<AnalyticsChart> getGlobalMetadataAnalyticsCharts(Authentication authentication) throws Exception {
final List<AnalyticsChart> charts = new ArrayList<>();
// Chart 1: Entities per domain
final List<NamedBar> entitiesPerDomain =
_analyticsService.getBarChart(_analyticsService.getAllEntityIndexName(), Optional.empty(),
ImmutableList.of("domains.keyword", "platform.keyword"), Collections.emptyMap(), Optional.empty(), false);
AnalyticsUtil.hydrateDisplayNameForBars(_entityClient, entitiesPerDomain, Constants.DOMAIN_ENTITY_NAME,
ImmutableSet.of(Constants.DOMAIN_PROPERTIES_ASPECT_NAME), AnalyticsUtil::getDomainName, authentication);
AnalyticsUtil.hydrateDisplayNameForSegments(_entityClient, entitiesPerDomain, Constants.DATA_PLATFORM_ENTITY_NAME,
ImmutableSet.of(Constants.DATA_PLATFORM_INFO_ASPECT_NAME), AnalyticsUtil::getPlatformName, authentication);
if (!entitiesPerDomain.isEmpty()) {
charts.add(BarChart.builder().setTitle("Entities per Domain").setBars(entitiesPerDomain).build());
}

// Chart 2: Entities per platform
final List<NamedBar> entitiesPerPlatform =
_analyticsService.getBarChart(_analyticsService.getAllEntityIndexName(), Optional.empty(),
ImmutableList.of("platform.keyword"), Collections.emptyMap(), Optional.empty(), false);
AnalyticsUtil.hydrateDisplayNameForBars(_entityClient, entitiesPerPlatform, Constants.DATA_PLATFORM_ENTITY_NAME,
ImmutableSet.of(Constants.DATA_PLATFORM_INFO_ASPECT_NAME), AnalyticsUtil::getPlatformName, authentication);
if (!entitiesPerPlatform.isEmpty()) {
charts.add(BarChart.builder().setTitle("Entities per Platform").setBars(entitiesPerPlatform).build());
}

// Chart 3: Entities per term
final List<NamedBar> entitiesPerTerm =
_analyticsService.getBarChart(_analyticsService.getAllEntityIndexName(), Optional.empty(),
ImmutableList.of("glossaryTerms.keyword"), Collections.emptyMap(), Optional.empty(), false);
AnalyticsUtil.hydrateDisplayNameForBars(_entityClient, entitiesPerTerm, Constants.GLOSSARY_TERM_ENTITY_NAME,
ImmutableSet.of(Constants.GLOSSARY_TERM_KEY_ASPECT_NAME), AnalyticsUtil::getTermName, authentication);
if (!entitiesPerTerm.isEmpty()) {
charts.add(BarChart.builder().setTitle("Entities per Term").setBars(entitiesPerTerm).build());
}

// Chart 4: Entities per fabric type
final List<NamedBar> entitiesPerEnv =
_analyticsService.getBarChart(_analyticsService.getAllEntityIndexName(), Optional.empty(),
ImmutableList.of("origin.keyword"), Collections.emptyMap(), Optional.empty(), false);
if (entitiesPerEnv.size() > 1) {
charts.add(BarChart.builder().setTitle("Entities per Environment").setBars(entitiesPerEnv).build());
}

return charts;
}
}
Loading

0 comments on commit d36cf07

Please sign in to comment.