Skip to content
Snippets Groups Projects
Unverified Commit 6becc1a7 authored by Thomas Schmidt's avatar Thomas Schmidt Committed by GitHub
Browse files

Add new generic analytics event and bring types to trackSchemaEvent (#46972)

parent 3f8317ad
No related branches found
No related tags found
No related merge requests found
Showing
with 804 additions and 1 deletion
......@@ -12,3 +12,4 @@ enterprise/backend/src/metabase_enterprise/task/truncate_audit_table.clj @noahmo
enterprise/backend/src/metabase_enterprise/internal_user.clj @noahmoss
src/metabase/**/*permissions* @noahmoss
src/metabase/integrations @noahmoss
snowplow/* @metabase/data
......@@ -47,7 +47,7 @@ describeWithSnowplow(
// Snowplow
expectGoodSnowplowEvent({
event: "csv_upload_clicked",
source: "left_nav",
triggered_from: "left_nav",
});
expectGoodSnowplowEvent({
event: testFile.valid ? "csv_upload_successful" : "csv_upload_failed",
......
type AccountEventSchema = {
event: string;
version?: string | null;
link?: string | null;
};
type ValidateEvent<
T extends AccountEventSchema &
Record<Exclude<keyof T, keyof AccountEventSchema>, never>,
> = T;
export type NewUserCreatedEvent = ValidateEvent<{
event: "new_user_created";
}>;
export type NewInstanceCreatedEvent = ValidateEvent<{
event: "new_instance_created";
}>;
export type AccountEvent = NewUserCreatedEvent | NewInstanceCreatedEvent;
type ActionEventSchema = {
event: string;
type: string;
action_id: number;
num_parameters?: number | null;
context?: string | null;
};
type ValidateEvent<
T extends ActionEventSchema &
Record<Exclude<keyof T, keyof ActionEventSchema>, never>,
> = T;
type ActionType = "http" | "query" | "implicit";
export type ActionCreatedEvent = ValidateEvent<{
event: "action_created";
type: ActionType;
action_id: number;
}>;
export type ActionUpdatedEvent = ValidateEvent<{
event: "action_updated";
type: ActionType;
action_id: number;
}>;
export type ActionDeletedEvent = ValidateEvent<{
event: "action_deleted";
type: ActionType;
action_id: number;
}>;
export type ActionExecutedEvent = ValidateEvent<{
event: "action_executed";
type: ActionType;
action_id: number;
}>;
export type ActionEvent =
| ActionCreatedEvent
| ActionUpdatedEvent
| ActionDeletedEvent
| ActionExecutedEvent;
type BrowseDataEventSchema = {
event: string;
model_id?: number | null;
table_id?: number | null;
};
type ValidateEvent<
T extends BrowseDataEventSchema &
Record<Exclude<keyof T, keyof BrowseDataEventSchema>, never>,
> = T;
export type BrowseDataModelClickedEvent = ValidateEvent<{
event: "browse_data_model_clicked";
model_id: number;
}>;
export type BrowseDataTableClickedEvent = ValidateEvent<{
event: "browse_data_table_clicked";
table_id: number;
}>;
export type BrowseDataEvent =
| BrowseDataModelClickedEvent
| BrowseDataTableClickedEvent;
type CleanupEventSchema = {
event: string;
collection_id?: number | null;
total_stale_items_found?: number | null;
cutoff_date?: string | null;
};
type ValidateEvent<
T extends CleanupEventSchema &
Record<Exclude<keyof T, keyof CleanupEventSchema>, never>,
> = T;
export type StaleItemsReadEvent = ValidateEvent<{
event: "stale_items_read";
collection_id: number | null;
total_stale_items_found: number;
cutoff_date: string;
}>;
export type CleanupEvent = StaleItemsReadEvent;
type CsvUploadEventSchema = {
event: string;
model_id?: number | null;
upload_seconds?: number | null;
size_mb: number | null;
num_columns: number | null;
num_rows: number | null;
generated_columns: number | null;
};
type ValidateEvent<
T extends CsvUploadEventSchema &
Record<Exclude<keyof T, keyof CsvUploadEventSchema>, never>,
> = T;
export type CsvUploadSuccessfulEvent = ValidateEvent<{
event: "csv_upload_successful";
model_id: number;
size_mb: number;
num_columns: number;
num_rows: number;
generated_columns: number;
upload_seconds: number;
}>;
export type CsvUploadFailedEvent = ValidateEvent<{
event: "csv_upload_failed";
size_mb: number;
num_columns: number;
num_rows: number;
generated_columns: number;
}>;
export type CsvAppendSuccessfulEvent = ValidateEvent<{
event: "csv_append_successful";
size_mb: number;
num_columns: number;
num_rows: number;
generated_columns: number;
upload_seconds: number;
}>;
export type CsvAppendFailedEvent = ValidateEvent<{
event: "csv_append_failed";
size_mb: number;
num_columns: number;
num_rows: number;
generated_columns: number;
}>;
export type CsvUploadEvent =
| CsvUploadSuccessfulEvent
| CsvUploadFailedEvent
| CsvAppendSuccessfulEvent
| CsvAppendFailedEvent;
type DashboardEventSchema = {
event: string;
dashboard_id: number;
question_id?: number | null;
num_tabs?: number | null;
total_num_tabs?: number | null;
duration_milliseconds?: number | null;
section_layout?: string | null;
full_width?: boolean | null;
dashboard_accessed_via?: string | null;
};
type ValidateEvent<
T extends DashboardEventSchema &
Record<Exclude<keyof T, keyof DashboardEventSchema>, never>,
> = T;
export type DashboardCreatedEvent = ValidateEvent<{
event: "dashboard_created";
dashboard_id: number;
}>;
export type DashboardSavedEvent = ValidateEvent<{
event: "dashboard_saved";
dashboard_id: number;
duration_milliseconds: number;
}>;
export type QuestionAddedToDashboardEvent = ValidateEvent<{
event: "question_added_to_dashboard";
dashboard_id: number;
question_id: number;
}>;
export type AutoApplyFiltersDisabledEvent = ValidateEvent<{
event: "auto_apply_filters_disabled";
dashboard_id: number;
}>;
export type DashboardTabCreatedEvent = ValidateEvent<{
event: "dashboard_tab_created";
dashboard_id: number;
}>;
export type DashboardTabDeletedEvent = ValidateEvent<{
event: "dashboard_tab_deleted";
dashboard_id: number;
}>;
export type DashboardTabDuplicatedEvent = ValidateEvent<{
event: "dashboard_tab_duplicated";
dashboard_id: number;
}>;
export type NewTextCardCreatedEvent = ValidateEvent<{
event: "new_text_card_created";
dashboard_id: number;
}>;
export type NewHeadingCardCreatedEvent = ValidateEvent<{
event: "new_heading_card_created";
dashboard_id: number;
}>;
export type NewLinkCardCreatedEvent = ValidateEvent<{
event: "new_link_card_created";
dashboard_id: number;
}>;
export type NewActionCardCreatedEvent = ValidateEvent<{
event: "new_action_card_created";
dashboard_id: number;
}>;
export type CardSetToHideWhenNoResultsEvent = ValidateEvent<{
event: "card_set_to_hide_when_no_results";
dashboard_id: number;
}>;
export type DashboardPdfExportedEvent = ValidateEvent<{
event: "dashboard_pdf_exported";
dashboard_id: number;
dashboard_accessed_via:
| "internal"
| "public-link"
| "static-embed"
| "interactive-iframe-embed"
| "sdk-embed";
}>;
export type CardMovedToTabEvent = ValidateEvent<{
event: "card_moved_to_tab";
dashboard_id: number;
}>;
export type DashboardCardDuplicatedEvent = ValidateEvent<{
event: "dashboard_card_duplicated";
dashboard_id: number;
}>;
export type DashboardCardReplacedEvent = ValidateEvent<{
event: "dashboard_card_replaced";
dashboard_id: number;
}>;
export type DashboardSectionAddedEvent = ValidateEvent<{
event: "dashboard_section_added";
dashboard_id: number;
section_layout: string;
}>;
export type DashboardWidthToggledEvent = ValidateEvent<{
event: "dashboard_width_toggled";
dashboard_id: number;
full_width: boolean;
}>;
export type DashboardFilterRequiredEvent = ValidateEvent<{
event: "dashboard_filter_required";
dashboard_id: number;
}>;
export type DashboardEvent =
| DashboardCreatedEvent
| DashboardSavedEvent
| QuestionAddedToDashboardEvent
| AutoApplyFiltersDisabledEvent
| DashboardTabCreatedEvent
| DashboardTabDeletedEvent
| DashboardTabDuplicatedEvent
| NewTextCardCreatedEvent
| NewHeadingCardCreatedEvent
| NewLinkCardCreatedEvent
| NewActionCardCreatedEvent
| CardSetToHideWhenNoResultsEvent
| DashboardPdfExportedEvent
| CardMovedToTabEvent
| DashboardCardDuplicatedEvent
| DashboardCardReplacedEvent
| DashboardSectionAddedEvent
| DashboardWidthToggledEvent
| DashboardFilterRequiredEvent;
type DatabaseEventSchema = {
event: string;
database?: string | null;
database_id?: number | null;
error_type?: string | null;
source?: string | null;
dbms_version?: string | null;
};
type ValidateEvent<
T extends DatabaseEventSchema &
Record<Exclude<keyof T, keyof DatabaseEventSchema>, never>,
> = T;
export type DatabaseConnectionSuccessfulEvent = ValidateEvent<{
event: "database_connection_successful";
database: string;
database_id: number;
source: "setup" | "admin";
dbms_version: string;
}>;
export type DatabaseConnectionFailedEvent = ValidateEvent<{
event: "database_connection_failed";
database: string;
database_id: number;
error_type: string;
source: "setup" | "admin";
dbms_version: string;
}>;
export type DatabaseEvent =
| DatabaseConnectionSuccessfulEvent
| DatabaseConnectionFailedEvent;
type DownloadsEventSchema = {
event: string;
resource_type?: string | null;
accessed_via?: string | null;
export_type?: string | null;
};
type ValidateEvent<
T extends DownloadsEventSchema &
Record<Exclude<keyof T, keyof DownloadsEventSchema>, never>,
> = T;
export type DownloadResultsClickedEvent = ValidateEvent<{
event: "download_results_clicked";
resource_type: "question" | "dashcard" | "ad-hoc-question";
accessed_via:
| "internal"
| "public-link"
| "static-embed"
| "interactive-iframe-embed"
| "sdk-embed";
export_type: "csv" | "xlsx" | "json" | "png";
}>;
export type DownloadsEvent = DownloadResultsClickedEvent;
type EmbedFlowParams = {
locked?: number;
enabled?: number;
disabled?: number;
};
type EmbedFlowAppearance = {
background?: boolean;
titled?: boolean;
bordered?: boolean;
theme?: string;
font?: string;
downloads?: boolean | null;
hide_download_button?: boolean | null;
};
type EmbedFlowEventSchema = {
event: string;
artifact: string;
new_embed?: boolean | null;
params?: EmbedFlowParams | null;
first_published_at?: string | null;
language?: string | null;
location?: string | null;
code?: string | null;
appearance?: EmbedFlowAppearance | null;
format?: string | null;
source?: string | null;
time_since_creation?: number | null;
time_since_initial_publication?: number | null;
is_example_dashboard?: boolean | null;
};
type ValidateEvent<
T extends EmbedFlowEventSchema &
Record<Exclude<keyof T, keyof EmbedFlowEventSchema>, never>,
> = T;
type EmbedFlowArtifact = "dashboard" | "question";
export type StaticEmbedDiscardedEvent = ValidateEvent<{
event: "static_embed_discarded";
artifact: EmbedFlowArtifact;
}>;
export type StaticEmbedPublishedEvent = ValidateEvent<{
event: "static_embed_published";
artifact: EmbedFlowArtifact;
params: EmbedFlowParams;
new_embed: boolean;
time_since_creation: number;
time_since_initial_publication: number | null;
is_example_dashboard: boolean;
}>;
export type StaticEmbedUnpublishedEvent = ValidateEvent<{
event: "static_embed_unpublished";
artifact: EmbedFlowArtifact;
time_since_creation: number;
time_since_initial_publication: number | null;
}>;
export type StaticEmbedCodeCopiedEvent = ValidateEvent<{
event: "static_embed_code_copied";
artifact: EmbedFlowArtifact;
language: string;
location: "code_overview" | "code_params" | "code_appearance";
code: "backend" | "view";
appearance: EmbedFlowAppearance;
}>;
export type PublicLinkCopiedEvent = ValidateEvent<{
event: "public_link_copied";
artifact: EmbedFlowArtifact;
format: "csv" | "xlsx" | "json" | "html" | null;
}>;
export type PublicEmbedCodeCopiedEvent = ValidateEvent<{
event: "public_embed_code_copied";
artifact: EmbedFlowArtifact;
source: "public-embed" | "public-share";
}>;
export type PublicLinkRemovedEvent = ValidateEvent<{
event: "public_link_removed";
artifact: EmbedFlowArtifact;
source: "public-embed" | "public-share";
}>;
export type EmbedFlowEvent =
| StaticEmbedDiscardedEvent
| StaticEmbedPublishedEvent
| StaticEmbedUnpublishedEvent
| StaticEmbedCodeCopiedEvent
| PublicLinkCopiedEvent
| PublicEmbedCodeCopiedEvent
| PublicLinkRemovedEvent;
type EmbedShareEventSchema = {
event: string;
authorized_origins_set?: boolean | null;
number_embedded_questions?: number | null;
number_embedded_dashboards?: number | null;
};
type ValidateEvent<
T extends EmbedShareEventSchema &
Record<Exclude<keyof T, keyof EmbedShareEventSchema>, never>,
> = T;
export type EmbeddingEnabledEvent = ValidateEvent<{
event: "embedding_enabled";
authorized_origins_set: boolean;
number_embedded_questions: number;
number_embedded_dashboards: number;
}>;
export type EmbeddingDisabledEvent = ValidateEvent<{
event: "embedding_disabled";
authorized_origins_set: boolean;
number_embedded_questions: number;
number_embedded_dashboards: number;
}>;
export type EmbedShareEvent = EmbeddingEnabledEvent | EmbeddingDisabledEvent;
type EmbeddingHomepageEventSchema = {
event: string;
dismiss_reason?: string | null;
initial_tab?: string | null;
};
type ValidateEvent<
T extends EmbeddingHomepageEventSchema &
Record<Exclude<keyof T, keyof EmbeddingHomepageEventSchema>, never>,
> = T;
export type EmbeddingHomepageDismissedEvent = ValidateEvent<{
event: "embedding_homepage_dismissed";
dismiss_reason:
| "dismissed-done"
| "dismissed-run-into-issues"
| "dismissed-not-interested-now";
}>;
export type EmbeddingHomepageQuickstartClickEvent = ValidateEvent<{
event: "embedding_homepage_quickstart_click";
initial_tab: "static" | "interactive";
}>;
export type EmbeddingHomepageExampleDashboardClickEvent = ValidateEvent<{
event: "embedding_homepage_example_dashboard_click";
initial_tab: "static" | "interactive";
}>;
export type EmbeddingHomepageEvent =
| EmbeddingHomepageDismissedEvent
| EmbeddingHomepageQuickstartClickEvent
| EmbeddingHomepageExampleDashboardClickEvent;
type SimpleEventSchema = {
event: string;
target_id?: number | null;
triggered_from?: string | null;
duration_ms?: number | null;
result?: string | null;
event_detail?: string | null;
};
type ValidateEvent<
T extends SimpleEventSchema &
Record<Exclude<keyof T, keyof SimpleEventSchema>, never>,
> = T;
export type CsvUploadClickedEvent = ValidateEvent<{
event: "csv_upload_clicked";
triggered_from: "left_nav";
}>;
export type SimpleEvent = CsvUploadClickedEvent;
export * from "./account";
export * from "./action";
export * from "./browse_data";
export * from "./cleanup";
export * from "./csv-upload";
export * from "./dashboard";
export * from "./database";
export * from "./downloads";
export * from "./embed-flow";
export * from "./embed-share";
export * from "./embedding-homepage";
export * from "./event";
export * from "./invite";
export * from "./metabot";
export * from "./model";
export * from "./question";
export * from "./serialization";
export * from "./schema";
export * from "./search";
export * from "./settings";
export * from "./setup";
export * from "./timeline";
export * from "./upsell";
type InviteEventSchema = {
event: string;
invited_user_id: number;
source?: string | null;
};
type ValidateEvent<
T extends InviteEventSchema &
Record<Exclude<keyof T, keyof InviteEventSchema>, never>,
> = T;
export type InviteSentEvent = ValidateEvent<{
event: "invite_sent";
invited_user_id: number;
source: "setup" | "admin";
}>;
export type InviteEvent = InviteSentEvent;
type MetabotEventSchema = {
event: string;
entity_type?: string | null;
feedback_type?: string | null;
result_type?: string | null;
prompt_template_versions?: string[] | null;
visualization_type?: string | null;
is_rerun?: boolean | null;
};
type ValidateEvent<
T extends MetabotEventSchema &
Record<Exclude<keyof T, keyof MetabotEventSchema>, never>,
> = T;
export type MetabotQueryRunEvent = ValidateEvent<{
event: "metabot_query_run";
entity_type: "database" | "model" | null;
result_type: "success" | "failure" | "bad-sql";
prompt_template_versions: string[] | null;
visualization_type: string | null;
is_rerun: boolean;
}>;
export type MetabotFeedbackReceivedEvent = ValidateEvent<{
event: "metabot_feedback_received";
entity_type: "database" | "model" | null;
feedback_type:
| "great"
| "wrong_data"
| "incorrect_result"
| "invalid_sql"
| null;
prompt_template_versions: string[] | null;
}>;
export type MetabotEvent = MetabotQueryRunEvent | MetabotFeedbackReceivedEvent;
type ModelEventSchema = {
event: string;
model_id: number;
};
type ValidateEvent<
T extends ModelEventSchema &
Record<Exclude<keyof T, keyof ModelEventSchema>, never>,
> = T;
export type IndexModelEntitiesEnabledEvent = ValidateEvent<{
event: "index_model_entities_enabled";
model_id: number;
}>;
export type ModelEvent = IndexModelEntitiesEnabledEvent;
type QuestionEventSchema = {
event: string;
question_id: number;
type?: string | null;
method?: string | null;
visualization_type?: string | null;
database_id?: number | null;
custom_expressions_used?: string[] | null;
};
type ValidateEvent<
T extends QuestionEventSchema &
Record<Exclude<keyof T, keyof QuestionEventSchema>, never>,
> = T;
export type NewQuestionSavedEvent = ValidateEvent<{
event: "new_question_saved";
question_id: number;
database_id: number | null;
type: "simple_question" | "custom_question" | "native_question";
method: "from_scratch" | "existing_question";
visualization_type: string;
}>;
export type TurnIntoModelClickedEvent = ValidateEvent<{
event: "turn_into_model_clicked";
question_id: number;
}>;
export type NotebookNativePreviewShownEvent = ValidateEvent<{
event: "notebook_native_preview_shown";
question_id: number;
}>;
export type NotebookNativePreviewHiddenEvent = ValidateEvent<{
event: "notebook_native_preview_hidden";
question_id: number;
}>;
export type ColumnCombineViaShortcutEvent = ValidateEvent<{
event: "column_combine_via_shortcut";
question_id: number;
database_id: number | null;
custom_expressions_used: string[];
}>;
export type ColumnCombineViaColumnHeaderEvent = ValidateEvent<{
event: "column_combine_via_column_header";
question_id: number;
database_id: number | null;
custom_expressions_used: string[];
}>;
export type ColumnCombineViaPlusModalEvent = ValidateEvent<{
event: "column_combine_via_plus_modal";
question_id: number;
database_id: number | null;
custom_expressions_used: string[];
}>;
export type ColumnCompareViaShortcutEvent = ValidateEvent<{
event: "column_compare_via_shortcut";
question_id: number;
database_id: number | null;
custom_expressions_used: string[];
}>;
export type ColumnCompareViaColumnHeaderEvent = ValidateEvent<{
event: "column_compare_via_column_header";
question_id: number;
database_id: number | null;
custom_expressions_used: string[];
}>;
export type ColumnCompareViaPlusModalEvent = ValidateEvent<{
event: "column_compare_via_plus_modal";
question_id: number;
database_id: number | null;
custom_expressions_used: string[];
}>;
export type ColumnExtractViaShortcutEvent = ValidateEvent<{
event: "column_extract_via_shortcut";
question_id: number;
database_id: number | null;
custom_expressions_used: string[];
}>;
export type ColumnExtractViaColumnHeaderEvent = ValidateEvent<{
event: "column_extract_via_column_header";
question_id: number;
database_id: number | null;
custom_expressions_used: string[];
}>;
export type ColumnExtractViaPlusModalEvent = ValidateEvent<{
event: "column_extract_via_plus_modal";
question_id: number;
database_id: number | null;
custom_expressions_used: string[];
}>;
export type QuestionEvent =
| NewQuestionSavedEvent
| TurnIntoModelClickedEvent
| NotebookNativePreviewShownEvent
| NotebookNativePreviewHiddenEvent
| ColumnCombineViaShortcutEvent
| ColumnCombineViaColumnHeaderEvent
| ColumnCombineViaPlusModalEvent
| ColumnCompareViaShortcutEvent
| ColumnCompareViaColumnHeaderEvent
| ColumnCompareViaPlusModalEvent
| ColumnExtractViaShortcutEvent
| ColumnExtractViaColumnHeaderEvent
| ColumnExtractViaPlusModalEvent;
import type { AccountEvent } from "./account";
import type { ActionEvent } from "./action";
import type { BrowseDataEvent } from "./browse_data";
import type { CleanupEvent } from "./cleanup";
import type { CsvUploadEvent } from "./csv-upload";
import type { DashboardEvent } from "./dashboard";
import type { DatabaseEvent } from "./database";
import type { DownloadsEvent } from "./downloads";
import type { EmbedFlowEvent } from "./embed-flow";
import type { EmbedShareEvent } from "./embed-share";
import type { EmbeddingHomepageEvent } from "./embedding-homepage";
import type { SimpleEvent } from "./event";
import type { InviteEvent } from "./invite";
import type { MetabotEvent } from "./metabot";
import type { ModelEvent } from "./model";
import type { QuestionEvent } from "./question";
import type { SearchEvent } from "./search";
import type { SerializationEvent } from "./serialization";
import type { SettingsEvent } from "./settings";
import type { SetupEvent } from "./setup";
import type { TimelineEvent } from "./timeline";
import type { UpsellEvent } from "./upsell";
export type SchemaEventMap = {
account: AccountEvent;
action: ActionEvent;
browse_data: BrowseDataEvent;
cleanup: CleanupEvent;
csvupload: CsvUploadEvent;
dashboard: DashboardEvent;
database: DatabaseEvent;
downloads: DownloadsEvent;
embed_flow: EmbedFlowEvent;
embed_share: EmbedShareEvent;
embedding_homepage: EmbeddingHomepageEvent;
event: SimpleEvent;
invite: InviteEvent;
metabot: MetabotEvent;
model: ModelEvent;
question: QuestionEvent;
search: SearchEvent;
serialization: SerializationEvent;
settings: SettingsEvent;
setup: SetupEvent;
timeline: TimelineEvent;
upsell: UpsellEvent;
};
export type SchemaType = keyof SchemaEventMap;
export type SchemaEvent = SchemaEventMap[SchemaType];
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment