Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(analytics): fix missing events from UI #4026

Merged
merged 8 commits into from Feb 7, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions datahub-web-react/build.gradle
Expand Up @@ -55,6 +55,10 @@ task yarnLint(type: YarnTask, dependsOn: [yarnInstall, yarnGenerate]) {
args = ['run', 'lint']
}

task yarnLintFix(type: YarnTask, dependsOn: [yarnInstall, yarnGenerate]) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice!

args = ['run', 'lint-fix']
}

task yarnBuild(type: YarnTask, dependsOn: [yarnInstall, yarnTest, yarnLint]) {
args = ['run', 'build']
}
Expand Down
3 changes: 3 additions & 0 deletions datahub-web-react/src/app/analytics/event.ts
Expand Up @@ -122,12 +122,15 @@ export interface EntitySectionViewEvent extends BaseEvent {
*/
export const EntityActionType = {
UpdateTags: 'UpdateTags',
UpdateTerms: 'UpdateTerms',
UpdateLinks: 'UpdateLinks',
UpdateOwnership: 'UpdateOwnership',
UpdateDocumentation: 'UpdateDocumentation',
UpdateDescription: 'UpdateDescription',
UpdateProperties: 'UpdateProperties',
UpdateSchemaDescription: 'UpdateSchemaDescription',
UpdateSchemaTags: 'UpdateSchemaTags',
UpdateSchemaTerms: 'UpdateSchemaTerms',
ClickExternalUrl: 'ClickExternalUrl',
};

Expand Down
16 changes: 16 additions & 0 deletions datahub-web-react/src/app/entity/dataset/profile/Documentation.tsx
Expand Up @@ -8,6 +8,8 @@ import {
InstitutionalMemoryUpdate,
} from '../../../../types.generated';
import { useEntityRegistry } from '../../../useEntityRegistry';
import { useEntityData } from '../../shared/EntityContext';
import analytics, { EventType, EntityActionType } from '../../../analytics';

export type Props = {
authenticatedUserUrn?: string;
Expand Down Expand Up @@ -93,6 +95,8 @@ export default function Documentation({
setStagedDocs(newStagedDocs);
};

const { urn, entityType } = useEntityData();

const onSave = async (record: any) => {
const row = await form.validateFields();

Expand All @@ -113,6 +117,12 @@ export default function Documentation({
};
});
updateDocumentation({ elements: updatedInstitutionalMemory });
analytics.event({
type: EventType.EntityActionEvent,
actionType: EntityActionType.UpdateDescription,
entityType,
entityUrn: urn,
});
setEditingIndex(-1);
};

Expand All @@ -130,6 +140,12 @@ export default function Documentation({
description: doc.description,
}));
updateDocumentation({ elements: updatedInstitutionalMemory });
analytics.event({
type: EventType.EntityActionEvent,
actionType: EntityActionType.UpdateDescription,
entityType,
entityUrn: urn,
});
setStagedDocs(newDocs);
};

Expand Down
Expand Up @@ -9,6 +9,8 @@ import UpdateDescriptionModal from '../../../../shared/components/legacy/Descrip
import StripMarkdownText, { removeMarkdown } from '../../../../shared/components/styled/StripMarkdownText';
import MarkdownViewer from '../../../../shared/components/legacy/MarkdownViewer';
import SchemaEditableContext from '../../../../../shared/SchemaEditableContext';
import { useEntityData } from '../../../../shared/EntityContext';
import analytics, { EventType, EntityActionType } from '../../../../../analytics';

const EditIcon = styled(EditOutlined)`
cursor: pointer;
Expand Down Expand Up @@ -89,13 +91,24 @@ export default function DescriptionField({ description, onUpdate, isEdited = fal
const [expanded, setExpanded] = useState(!overLimit);
const isSchemaEditable = React.useContext(SchemaEditableContext);
const onCloseModal = () => setShowAddModal(false);
const { urn, entityType } = useEntityData();

const sendAnalytics = () => {
analytics.event({
type: EventType.EntityActionEvent,
actionType: EntityActionType.UpdateSchemaDescription,
entityType,
entityUrn: urn,
});
};

const onUpdateModal = async (desc: string | null) => {
message.loading({ content: 'Updating...' });
try {
await onUpdate(desc || '');
message.destroy();
message.success({ content: 'Updated!', duration: 2 });
sendAnalytics();
} catch (e: unknown) {
message.destroy();
if (e instanceof Error) message.error({ content: `Update Failed! \n ${e.message || ''}`, duration: 2 });
Expand Down
Expand Up @@ -4,6 +4,7 @@ import { PlusOutlined } from '@ant-design/icons';
import { useGetAuthenticatedUser } from '../../../../useGetAuthenticatedUser';
import { useEntityData } from '../../EntityContext';
import { useAddLinkMutation } from '../../../../../graphql/mutations.generated';
import analytics, { EventType, EntityActionType } from '../../../../analytics';

type AddLinkProps = {
buttonProps?: Record<string, unknown>;
Expand All @@ -13,7 +14,7 @@ type AddLinkProps = {
export const AddLinkModal = ({ buttonProps, refetch }: AddLinkProps) => {
const [isModalVisible, setIsModalVisible] = useState(false);
const user = useGetAuthenticatedUser();
const { urn } = useEntityData();
const { urn, entityType } = useEntityData();
const [addLinkMutation] = useAddLinkMutation();

const [form] = Form.useForm();
Expand All @@ -34,6 +35,12 @@ export const AddLinkModal = ({ buttonProps, refetch }: AddLinkProps) => {
variables: { input: { linkUrl: formData.url, label: formData.label, resourceUrn: urn } },
});
message.success({ content: 'Link Added', duration: 2 });
analytics.event({
type: EventType.EntityActionEvent,
entityType,
entityUrn: urn,
actionType: EntityActionType.UpdateLinks,
});
} catch (e: unknown) {
message.destroy();
if (e instanceof Error) {
Expand Down
Expand Up @@ -7,6 +7,8 @@ import { useRemoveOwnerMutation } from '../../../../../graphql/mutations.generat
import { EntityType, Owner } from '../../../../../types.generated';
import { CustomAvatar } from '../../../../shared/avatar';
import { useEntityRegistry } from '../../../../useEntityRegistry';
import analytics, { EventType, EntityActionType } from '../../../../analytics';
import { useEntityData } from '../../EntityContext';

type Props = {
entityUrn: string;
Expand All @@ -24,6 +26,7 @@ const OwnerTag = styled(Tag)`

export const ExpandedOwner = ({ entityUrn, owner, refetch }: Props) => {
const entityRegistry = useEntityRegistry();
const { entityType } = useEntityData();
const [removeOwnerMutation] = useRemoveOwnerMutation();

let name = '';
Expand All @@ -47,6 +50,12 @@ export const ExpandedOwner = ({ entityUrn, owner, refetch }: Props) => {
},
});
message.success({ content: 'Owner Removed', duration: 2 });
analytics.event({
type: EventType.EntityActionEvent,
actionType: EntityActionType.UpdateOwnership,
entityType,
entityUrn,
});
} catch (e: unknown) {
message.destroy();
if (e instanceof Error) {
Expand Down
Expand Up @@ -18,6 +18,7 @@ import { useEntityRegistry } from '../../../../useEntityRegistry';
import LineageExplorer from '../../../../lineage/LineageExplorer';
import CompactContext from '../../../../shared/CompactContext';
import DynamicTab from '../../tabs/Entity/weaklyTypedAspects/DynamicTab';
import analytics, { EventType } from '../../../../analytics';

type Props<T, U> = {
urn: string;
Expand Down Expand Up @@ -124,6 +125,12 @@ export const EntityProfile = <T, U>({
tabParams?: Record<string, any>;
method?: 'push' | 'replace';
}) => {
analytics.event({
type: EventType.EntitySectionViewEvent,
entityType,
entityUrn: urn,
section: tabName.toLowerCase(),
});
history[method](getEntityPath(entityType, urn, entityRegistry, false, tabName, tabParams));
},
[history, entityType, urn, entityRegistry],
Expand Down
Expand Up @@ -10,6 +10,7 @@ import { IconStyleType } from '../../../../Entity';
import { ANTD_GRAY } from '../../../constants';
import { useEntityData } from '../../../EntityContext';
import { useEntityPath } from '../utils';
import analytics, { EventType, EntityActionType } from '../../../../../analytics';

const LogoContainer = styled.span`
margin-right: 10px;
Expand Down Expand Up @@ -105,6 +106,16 @@ export const EntityHeader = () => {
const entityPath = useEntityPath(entityType, urn);
const externalUrl = entityData?.externalUrl || undefined;
const hasExternalUrl = !!externalUrl;

const sendAnalytics = () => {
analytics.event({
type: EventType.EntityActionEvent,
actionType: EntityActionType.ClickExternalUrl,
entityType,
entityUrn: urn,
});
};

const entityCount = entityData?.entityCount;
const typeIcon = entityRegistry.getIcon(entityType, 12, IconStyleType.ACCENT);
const container = entityData?.container;
Expand Down Expand Up @@ -146,7 +157,11 @@ export const EntityHeader = () => {
<EntityTitle level={3}>{entityData?.name || ' '}</EntityTitle>
</Link>
</MainHeaderContent>
{hasExternalUrl && <ExternalLinkButton href={externalUrl}>View in {platformName}</ExternalLinkButton>}
{hasExternalUrl && (
<ExternalLinkButton href={externalUrl} onClick={sendAnalytics}>
View in {platformName}
</ExternalLinkButton>
)}
<Tooltip title="Copy URN. An URN uniquely identifies an entity on DataHub.">
<Button
icon={copiedUrn ? <CheckOutlined /> : <CopyOutlined />}
Expand Down
Expand Up @@ -8,6 +8,7 @@ import { CorpUser, EntityType, OwnerEntityType, SearchResult } from '../../../..
import { useEntityRegistry } from '../../../../../../useEntityRegistry';
import { useEntityData } from '../../../../EntityContext';
import { CustomAvatar } from '../../../../../../shared/avatar';
import analytics, { EventType, EntityActionType } from '../../../../../../analytics';

type Props = {
visible: boolean;
Expand Down Expand Up @@ -40,7 +41,7 @@ type SelectedActor = {

export const AddOwnerModal = ({ visible, onClose, refetch }: Props) => {
const entityRegistry = useEntityRegistry();
const { urn } = useEntityData();
const { urn, entityType } = useEntityData();
const [selectedActor, setSelectedActor] = useState<SelectedActor | undefined>(undefined);
const [userSearch, { data: userSearchData }] = useGetSearchResultsLazyQuery();
const [groupSearch, { data: groupSearchData }] = useGetSearchResultsLazyQuery();
Expand Down Expand Up @@ -70,6 +71,12 @@ export const AddOwnerModal = ({ visible, onClose, refetch }: Props) => {
},
});
message.success({ content: 'Owner Added', duration: 2 });
analytics.event({
type: EventType.EntityActionEvent,
actionType: EntityActionType.UpdateOwnership,
entityType,
entityUrn: urn,
});
} catch (e: unknown) {
message.destroy();
if (e instanceof Error) {
Expand Down
14 changes: 13 additions & 1 deletion datahub-web-react/src/app/shared/tags/AddTagTermModal.tsx
Expand Up @@ -151,6 +151,7 @@ export default function AddTagTermModal({

let urnToAdd = '';
let input = {};
let actionType = EntityActionType.UpdateSchemaTags;
if (selectedType === EntityType.Tag) {
urnToAdd = `urn:li:tag:${selectedName}`;
input = {
Expand All @@ -159,6 +160,11 @@ export default function AddTagTermModal({
subResource: entitySubresource,
subResourceType: entitySubresource ? SubResourceType.DatasetField : null,
};
if (entitySubresource) {
actionType = EntityActionType.UpdateSchemaTags;
} else {
actionType = EntityActionType.UpdateTags;
}
}
if (selectedType === EntityType.GlossaryTerm) {
urnToAdd = `urn:li:glossaryTerm:${selectedName}`;
Expand All @@ -168,14 +174,20 @@ export default function AddTagTermModal({
subResource: entitySubresource,
subResourceType: entitySubresource ? SubResourceType.DatasetField : null,
};
if (entitySubresource) {
actionType = EntityActionType.UpdateSchemaTerms;
} else {
actionType = EntityActionType.UpdateTerms;
}
}

analytics.event({
type: EventType.EntityActionEvent,
actionType: EntityActionType.UpdateTags,
entityType,
entityUrn,
actionType,
});

mutation({
variables: {
input,
Expand Down
2 changes: 1 addition & 1 deletion datahub-web-react/src/app/shared/tags/TagTermGroup.tsx
Expand Up @@ -117,7 +117,7 @@ export default function TagTermGroup({
const termToRemove = editableGlossaryTerms?.terms?.find((term) => term.term.urn === urnToRemove);
Modal.confirm({
title: `Do you want to remove ${termToRemove?.term.name} term?`,
content: `Are you sure you want to remove the ${termToRemove?.term.name} tag?`,
content: `Are you sure you want to remove the ${termToRemove?.term.name} term?`,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice catch!

onOk() {
if (entityUrn) {
removeTermMutation({
Expand Down
@@ -0,0 +1,14 @@
describe('analytics', () => {
it('can go to a dataset and see analytics in Section Views', () => {
cy.login();

cy.visit("/analytics");
cy.contains("documentation").should('not.exist');

cy.visit("/chart/urn:li:chart:(looker,baz1)");
cy.get("#rc-tabs-0-panel-Dashboards").click({ force: true });

cy.visit("/analytics");
cy.contains("documentation");
});
})