Fix date filtering in metric definition views (#921)

This commit is contained in:
Anna Scholtz 2024-03-19 15:43:59 -07:00 коммит произвёл GitHub
Родитель 36a178254d
Коммит 693cf80851
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
30 изменённых файлов: 91 добавлений и 23 удалений

Просмотреть файл

@ -3,6 +3,7 @@
.. include:: ../README.md .. include:: ../README.md
.. include:: ../architecture/namespaces_yaml.md .. include:: ../architecture/namespaces_yaml.md
""" """
__docformat__ = "restructuredtext" __docformat__ = "restructuredtext"
import warnings import warnings

Просмотреть файл

@ -1,6 +1,5 @@
"""Run lookml_generator cli.""" """Run lookml_generator cli."""
from . import cli from . import cli

Просмотреть файл

@ -1,4 +1,5 @@
"""All possible dashboard types.""" """All possible dashboard types."""
from .dashboard import Dashboard # noqa: F401 from .dashboard import Dashboard # noqa: F401
from .operational_monitoring_dashboard import OperationalMonitoringDashboard from .operational_monitoring_dashboard import OperationalMonitoringDashboard

Просмотреть файл

@ -1,4 +1,5 @@
"""Generic dashboard type.""" """Generic dashboard type."""
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass, field from dataclasses import dataclass, field

Просмотреть файл

@ -1,4 +1,5 @@
"""Class to describe Operational Monitoring Dashboard.""" """Class to describe Operational Monitoring Dashboard."""
from __future__ import annotations from __future__ import annotations
from typing import Any, Dict, List from typing import Any, Dict, List
@ -129,10 +130,13 @@ class OperationalMonitoringDashboard(Dashboard):
kwargs["elements"].append( kwargs["elements"].append(
{ {
"title": title, "title": title,
"metric": summary["metric"] "metric": (
if metric_group is None summary["metric"]
else ", ".join( if metric_group is None
f'"{m}"' for m in metric_groups[metric_group] else ", ".join(
f'"{m}"'
for m in metric_groups[metric_group]
)
), ),
"statistic": summary["statistic"], "statistic": summary["statistic"],
"explore": explore, "explore": explore,
@ -153,10 +157,13 @@ class OperationalMonitoringDashboard(Dashboard):
kwargs["elements"].append( kwargs["elements"].append(
{ {
"title": f"{title} - By {self.group_by_dimension}", "title": f"{title} - By {self.group_by_dimension}",
"metric": summary["metric"] "metric": (
if metric_group is None summary["metric"]
else ", ".join( if metric_group is None
f'"{m}"' for m in metric_groups[metric_group] else ", ".join(
f'"{m}"'
for m in metric_groups[metric_group]
)
), ),
"statistic": summary["statistic"], "statistic": summary["statistic"],
"explore": explore, "explore": explore,

Просмотреть файл

@ -1,4 +1,5 @@
"""All possible explore types.""" """All possible explore types."""
from .explore import Explore # noqa: F401 isort:skip from .explore import Explore # noqa: F401 isort:skip
from .client_counts_explore import ClientCountsExplore from .client_counts_explore import ClientCountsExplore
from .events_explore import EventsExplore from .events_explore import EventsExplore

Просмотреть файл

@ -1,4 +1,5 @@
"""Client Counts explore type.""" """Client Counts explore type."""
from __future__ import annotations from __future__ import annotations
from pathlib import Path from pathlib import Path

Просмотреть файл

@ -1,4 +1,5 @@
"""An explore for Events Views.""" """An explore for Events Views."""
from __future__ import annotations from __future__ import annotations
from pathlib import Path from pathlib import Path

Просмотреть файл

@ -1,4 +1,5 @@
"""Generic explore type.""" """Generic explore type."""
from __future__ import annotations from __future__ import annotations
from dataclasses import dataclass, field from dataclasses import dataclass, field

Просмотреть файл

@ -1,4 +1,5 @@
"""Funnel Analysis explore type.""" """Funnel Analysis explore type."""
from __future__ import annotations from __future__ import annotations
from pathlib import Path from pathlib import Path

Просмотреть файл

@ -1,4 +1,5 @@
"""Growth Accounting explore type.""" """Growth Accounting explore type."""
from __future__ import annotations from __future__ import annotations
from pathlib import Path from pathlib import Path

Просмотреть файл

@ -1,4 +1,5 @@
"""Metric Hub metrics explore type.""" """Metric Hub metrics explore type."""
from __future__ import annotations from __future__ import annotations
from pathlib import Path from pathlib import Path

Просмотреть файл

@ -1,4 +1,5 @@
"""Operational Monitoring Explore type.""" """Operational Monitoring Explore type."""
from __future__ import annotations from __future__ import annotations
from pathlib import Path from pathlib import Path

Просмотреть файл

@ -1,4 +1,5 @@
"""Ping explore type.""" """Ping explore type."""
from __future__ import annotations from __future__ import annotations
from pathlib import Path from pathlib import Path

Просмотреть файл

@ -1,4 +1,5 @@
"""Table explore type.""" """Table explore type."""
from __future__ import annotations from __future__ import annotations
from pathlib import Path from pathlib import Path

Просмотреть файл

@ -1,4 +1,5 @@
"""An updated lkml parser to handle explore queries.""" """An updated lkml parser to handle explore queries."""
from typing import List, Union from typing import List, Union
from lkml.keys import KEYS_WITH_NAME_FIELDS from lkml.keys import KEYS_WITH_NAME_FIELDS

Просмотреть файл

@ -1,4 +1,5 @@
"""Generate lookml from namespaces.""" """Generate lookml from namespaces."""
import logging import logging
from pathlib import Path from pathlib import Path
from typing import Dict, Iterable, Optional from typing import Dict, Iterable, Optional

Просмотреть файл

@ -1,4 +1,5 @@
"""Generate namespaces.yaml.""" """Generate namespaces.yaml."""
import fnmatch import fnmatch
import json import json
import re import re
@ -241,12 +242,16 @@ def _get_glean_apps(
channels = [ channels = [
{ {
"channel": channel.get("app_channel"), "channel": channel.get("app_channel"),
"dataset": channel.get("app_name").replace("-", "_") "dataset": (
if channel.get("app_channel") == "release" channel.get("app_name").replace("-", "_")
else channel.get("bq_dataset_family"), if channel.get("app_channel") == "release"
"source_dataset": channel.get("bq_dataset_family") else channel.get("bq_dataset_family")
if channel.get("app_channel") == "release" ),
else channel.get("bq_dataset_family") + "_stable", "source_dataset": (
channel.get("bq_dataset_family")
if channel.get("app_channel") == "release"
else channel.get("bq_dataset_family") + "_stable"
),
} }
for channel in variants for channel in variants
if not channel.get("deprecated") if not channel.get("deprecated")

Просмотреть файл

@ -1,4 +1,5 @@
"""Utils for operational monitoring.""" """Utils for operational monitoring."""
from multiprocessing.pool import ThreadPool from multiprocessing.pool import ThreadPool
from typing import Any, Dict, List, Optional, Tuple from typing import Any, Dict, List, Optional, Tuple

Просмотреть файл

@ -1,4 +1,5 @@
"""All available Looker views.""" """All available Looker views."""
from .client_counts_view import ClientCountsView from .client_counts_view import ClientCountsView
from .events_view import EventsView from .events_view import EventsView
from .funnel_analysis_view import FunnelAnalysisView from .funnel_analysis_view import FunnelAnalysisView

Просмотреть файл

@ -1,4 +1,5 @@
"""Class to describe a Client Counts View.""" """Class to describe a Client Counts View."""
from __future__ import annotations from __future__ import annotations
from copy import deepcopy from copy import deepcopy

Просмотреть файл

@ -1,4 +1,5 @@
"""Class to describe an Events view.""" """Class to describe an Events view."""
from __future__ import annotations from __future__ import annotations
from copy import deepcopy from copy import deepcopy

Просмотреть файл

@ -19,6 +19,7 @@ That lets us find out whether the user completed those funnel steps:
The `funnel_analysis` view has some nice dimensions to hide these details from the end user, The `funnel_analysis` view has some nice dimensions to hide these details from the end user,
e.g. `completed_funnel_step_N`. We can then count those users across dimensions. e.g. `completed_funnel_step_N`. We can then count those users across dimensions.
""" """
from __future__ import annotations from __future__ import annotations
from textwrap import dedent from textwrap import dedent

Просмотреть файл

@ -1,4 +1,5 @@
"""Class to describe a Growth Accounting View.""" """Class to describe a Growth Accounting View."""
from __future__ import annotations from __future__ import annotations
from copy import deepcopy from copy import deepcopy

Просмотреть файл

@ -1,4 +1,5 @@
"""Utils for generating lookml.""" """Utils for generating lookml."""
import re import re
import tarfile import tarfile
import urllib.request import urllib.request

Просмотреть файл

@ -105,18 +105,30 @@ class MetricDefinitionsView(View):
f"base_{d['name']} AS {d['name']},\n" f"base_{d['name']} AS {d['name']},\n"
for d in base_view_lkml["views"][0]["dimensions"] for d in base_view_lkml["views"][0]["dimensions"]
if d["name"] not in ignore_base_fields and "hidden" not in d if d["name"] not in ignore_base_fields and "hidden" not in d
] + [
f"base_{d['sql'].replace('${TABLE}.', '')} AS {d['sql'].replace('${TABLE}.', '')},\n"
for d in base_view_lkml["views"][0]["dimension_groups"]
if d["name"] not in ignore_base_fields and "hidden" not in d
] ]
base_view_fields = [ base_view_fields = [
f"{d['name']},\n" f"{d['name']},\n"
for d in base_view_lkml["views"][0]["dimensions"] for d in base_view_lkml["views"][0]["dimensions"]
if d["name"] not in ignore_base_fields and "hidden" not in d if d["name"] not in ignore_base_fields and "hidden" not in d
] + [
f"{d['sql'].replace('${TABLE}.', '')},\n"
for d in base_view_lkml["views"][0]["dimension_groups"]
if d["name"] not in ignore_base_fields and "hidden" not in d
] ]
selected_fields = [ selected_fields = [
f"{d['name'].replace('__', '.')} AS base_{d['name']},\n" f"{d['name'].replace('__', '.')} AS base_{d['name']},\n"
for d in base_view_lkml["views"][0]["dimensions"] for d in base_view_lkml["views"][0]["dimensions"]
if d["name"] not in ignore_base_fields and "hidden" not in d if d["name"] not in ignore_base_fields and "hidden" not in d
] + [
f"{d['sql'].replace('${TABLE}.', '').replace('__', '.')} AS base_{d['sql'].replace('${TABLE}.', '')},\n"
for d in base_view_lkml["views"][0]["dimension_groups"]
if d["name"] not in ignore_base_fields and "hidden" not in d
] ]
client_id_join = ( client_id_join = (
@ -132,17 +144,30 @@ class MetricDefinitionsView(View):
{"".join(selected_fields)} {"".join(selected_fields)}
FROM FROM
{base_table} {base_table}
WHERE
submission_date BETWEEN
COALESCE(
SAFE_CAST(
{{% date_start {data_source_definition.submission_date_column or "submission_date"} %}} AS DATE),
CURRENT_DATE()) AND
COALESCE(
SAFE_CAST(
{{% date_end {data_source_definition.submission_date_column or "submission_date"} %}} AS DATE
), CURRENT_DATE())
) base ) base
ON ON
base.base_submission_date = m.{data_source_definition.submission_date_column or "submission_date"} base.base_submission_date = m.{data_source_definition.submission_date_column or "submission_date"}
{client_id_join} {client_id_join}
WHERE base.base_submission_date BETWEEN WHERE base.base_submission_date BETWEEN
COALESCE(
SAFE_CAST( SAFE_CAST(
{{% date_start {data_source_definition.submission_date_column or "submission_date"} %}} AS DATE {{% date_start {data_source_definition.submission_date_column or "submission_date"} %}} AS DATE
) AND ), CURRENT_DATE()) AND
COALESCE(
SAFE_CAST( SAFE_CAST(
{{% date_end {data_source_definition.submission_date_column or "submission_date"} %}} AS DATE {{% date_end {data_source_definition.submission_date_column or "submission_date"} %}} AS DATE
) AND ), CURRENT_DATE())
AND
base.base_sample_id < {{% parameter sampling %}} base.base_sample_id < {{% parameter sampling %}}
""" """
@ -192,13 +217,17 @@ class MetricDefinitionsView(View):
} }
AS m AS m
{join_base_view} {join_base_view}
{'AND' if join_base_view else 'WHERE'} m.submission_date BETWEEN {'AND' if join_base_view else 'WHERE'}
m.{data_source_definition.submission_date_column or "submission_date"}
BETWEEN
COALESCE(
SAFE_CAST( SAFE_CAST(
{{% date_start {data_source_definition.submission_date_column or "submission_date"} %}} AS DATE {{% date_start {data_source_definition.submission_date_column or "submission_date"} %}} AS DATE
) AND ), CURRENT_DATE()) AND
COALESCE(
SAFE_CAST( SAFE_CAST(
{{% date_end {data_source_definition.submission_date_column or "submission_date"} %}} AS DATE {{% date_end {data_source_definition.submission_date_column or "submission_date"} %}} AS DATE
) ), CURRENT_DATE())
GROUP BY GROUP BY
{"".join(base_view_fields)} {"".join(base_view_fields)}
client_id, client_id,
@ -382,9 +411,11 @@ class MetricDefinitionsView(View):
elif statistic_slug == "client_count": elif statistic_slug == "client_count":
measures.append( measures.append(
{ {
"name": f"{dimension['name']}_{statistic_slug}_sampled" "name": (
if sampling f"{dimension['name']}_{statistic_slug}_sampled"
else f"{dimension['name']}_{statistic_slug}", if sampling
else f"{dimension['name']}_{statistic_slug}"
),
"type": "count_distinct", "type": "count_distinct",
"label": f"{dimension['label']} Client Count", "label": f"{dimension['label']} Client Count",
"group_label": "Statistics", "group_label": "Statistics",

Просмотреть файл

@ -1,4 +1,5 @@
"""Class to describe an Operational Monitoring View.""" """Class to describe an Operational Monitoring View."""
from __future__ import annotations from __future__ import annotations
from typing import Any, Dict, List, Optional, Union from typing import Any, Dict, List, Optional, Union

Просмотреть файл

@ -1,4 +1,5 @@
"""Class to describe a Ping View.""" """Class to describe a Ping View."""
from __future__ import annotations from __future__ import annotations
from collections import defaultdict from collections import defaultdict

Просмотреть файл

@ -1,4 +1,5 @@
"""Class to describe a Table View.""" """Class to describe a Table View."""
from __future__ import annotations from __future__ import annotations
from collections import defaultdict from collections import defaultdict

Просмотреть файл

@ -1,4 +1,5 @@
"""Generic class to describe Looker views.""" """Generic class to describe Looker views."""
from __future__ import annotations from __future__ import annotations
from typing import Any, Dict, Iterator, List, Optional, Set, TypedDict from typing import Any, Dict, Iterator, List, Optional, Set, TypedDict