Fix date filtering in metric definition views (#921)
This commit is contained in:
Родитель
36a178254d
Коммит
693cf80851
|
@ -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
|
||||||
|
|
Загрузка…
Ссылка в новой задаче