generator.views.events_stream_view
Class to describe an events_stream view.
1"""Class to describe an `events_stream` view.""" 2 3from __future__ import annotations 4 5from copy import deepcopy 6from typing import Any, Iterator, Optional 7 8from . import lookml_utils 9from .view import View, ViewDict 10 11 12class EventsStreamView(View): 13 """A view for querying `events_stream` data, with one row per event.""" 14 15 type: str = "events_stream_view" 16 17 default_measures: list[dict[str, str]] = [ 18 { 19 "name": "event_count", 20 "type": "count", 21 "description": "The number of times the event(s) occurred.", 22 }, 23 # GleanPingViews were previously generated for some `events_stream` views, and those had 24 # `ping_count` measures, so we generate the same measures here to avoid breaking anything. 25 # TODO: Remove this once dashboards have been migrated to use the proper `event_count` measures. 26 { 27 "name": "ping_count", 28 "type": "count", 29 "hidden": "yes", 30 }, 31 ] 32 33 def __init__(self, namespace: str, name: str, tables: list[dict[str, str]]): 34 """Get an instance of an EventsStreamView.""" 35 super().__init__(namespace, name, EventsStreamView.type, tables) 36 37 @classmethod 38 def from_db_views( 39 klass, 40 namespace: str, 41 is_glean: bool, 42 channels: list[dict[str, str]], 43 db_views: dict, 44 ) -> Iterator[EventsStreamView]: 45 """Get EventsStreamViews from db views.""" 46 for view_id in db_views[namespace]: 47 if view_id.endswith("events_stream"): 48 yield EventsStreamView( 49 namespace, 50 view_id, 51 [{"table": f"mozdata.{namespace}.{view_id}"}], 52 ) 53 54 @classmethod 55 def from_dict( 56 klass, namespace: str, name: str, _dict: ViewDict 57 ) -> EventsStreamView: 58 """Get EventsStreamView from a name and dict definition.""" 59 return EventsStreamView(namespace, name, _dict["tables"]) 60 61 def to_lookml(self, v1_name: Optional[str], dryrun) -> dict[str, Any]: 62 """Generate LookML for this view.""" 63 dimensions = lookml_utils._generate_dimensions( 64 self.tables[0]["table"], dryrun=dryrun 65 ) 66 for dimension in dimensions: 67 if dimension["name"] == "event_id": 68 dimension["primary_key"] = "yes" 69 70 measures = self.get_measures(dimensions) 71 72 return { 73 "views": [ 74 { 75 "name": self.name, 76 "sql_table_name": f"`{self.tables[0]['table']}`", 77 "dimensions": [ 78 d for d in dimensions if not lookml_utils._is_dimension_group(d) 79 ], 80 "dimension_groups": [ 81 d for d in dimensions if lookml_utils._is_dimension_group(d) 82 ], 83 "measures": measures, 84 }, 85 ], 86 } 87 88 def get_measures(self, dimensions: list[dict[str, Any]]) -> list[dict[str, str]]: 89 """Get measures for this view.""" 90 measures = deepcopy(EventsStreamView.default_measures) 91 if client_id_dimension := self.get_client_id( 92 dimensions, self.tables[0]["table"] 93 ): 94 measures.append( 95 { 96 "name": "client_count", 97 "type": "count_distinct", 98 "sql": f"${{{client_id_dimension}}}", 99 "description": "The number of clients that completed the event(s).", 100 } 101 ) 102 # GleanPingViews were previously generated for some `events_stream` views, and those had 103 # `clients` measures, so we generate the same measures here to avoid breaking anything. 104 # TODO: Remove this once dashboards have been migrated to use the proper `client_count` measures. 105 measures.append( 106 { 107 "name": "clients", 108 "type": "count_distinct", 109 "sql": f"${{{client_id_dimension}}}", 110 "hidden": "yes", 111 } 112 ) 113 return measures
13class EventsStreamView(View): 14 """A view for querying `events_stream` data, with one row per event.""" 15 16 type: str = "events_stream_view" 17 18 default_measures: list[dict[str, str]] = [ 19 { 20 "name": "event_count", 21 "type": "count", 22 "description": "The number of times the event(s) occurred.", 23 }, 24 # GleanPingViews were previously generated for some `events_stream` views, and those had 25 # `ping_count` measures, so we generate the same measures here to avoid breaking anything. 26 # TODO: Remove this once dashboards have been migrated to use the proper `event_count` measures. 27 { 28 "name": "ping_count", 29 "type": "count", 30 "hidden": "yes", 31 }, 32 ] 33 34 def __init__(self, namespace: str, name: str, tables: list[dict[str, str]]): 35 """Get an instance of an EventsStreamView.""" 36 super().__init__(namespace, name, EventsStreamView.type, tables) 37 38 @classmethod 39 def from_db_views( 40 klass, 41 namespace: str, 42 is_glean: bool, 43 channels: list[dict[str, str]], 44 db_views: dict, 45 ) -> Iterator[EventsStreamView]: 46 """Get EventsStreamViews from db views.""" 47 for view_id in db_views[namespace]: 48 if view_id.endswith("events_stream"): 49 yield EventsStreamView( 50 namespace, 51 view_id, 52 [{"table": f"mozdata.{namespace}.{view_id}"}], 53 ) 54 55 @classmethod 56 def from_dict( 57 klass, namespace: str, name: str, _dict: ViewDict 58 ) -> EventsStreamView: 59 """Get EventsStreamView from a name and dict definition.""" 60 return EventsStreamView(namespace, name, _dict["tables"]) 61 62 def to_lookml(self, v1_name: Optional[str], dryrun) -> dict[str, Any]: 63 """Generate LookML for this view.""" 64 dimensions = lookml_utils._generate_dimensions( 65 self.tables[0]["table"], dryrun=dryrun 66 ) 67 for dimension in dimensions: 68 if dimension["name"] == "event_id": 69 dimension["primary_key"] = "yes" 70 71 measures = self.get_measures(dimensions) 72 73 return { 74 "views": [ 75 { 76 "name": self.name, 77 "sql_table_name": f"`{self.tables[0]['table']}`", 78 "dimensions": [ 79 d for d in dimensions if not lookml_utils._is_dimension_group(d) 80 ], 81 "dimension_groups": [ 82 d for d in dimensions if lookml_utils._is_dimension_group(d) 83 ], 84 "measures": measures, 85 }, 86 ], 87 } 88 89 def get_measures(self, dimensions: list[dict[str, Any]]) -> list[dict[str, str]]: 90 """Get measures for this view.""" 91 measures = deepcopy(EventsStreamView.default_measures) 92 if client_id_dimension := self.get_client_id( 93 dimensions, self.tables[0]["table"] 94 ): 95 measures.append( 96 { 97 "name": "client_count", 98 "type": "count_distinct", 99 "sql": f"${{{client_id_dimension}}}", 100 "description": "The number of clients that completed the event(s).", 101 } 102 ) 103 # GleanPingViews were previously generated for some `events_stream` views, and those had 104 # `clients` measures, so we generate the same measures here to avoid breaking anything. 105 # TODO: Remove this once dashboards have been migrated to use the proper `client_count` measures. 106 measures.append( 107 { 108 "name": "clients", 109 "type": "count_distinct", 110 "sql": f"${{{client_id_dimension}}}", 111 "hidden": "yes", 112 } 113 ) 114 return measures
A view for querying events_stream data, with one row per event.
EventsStreamView(namespace: str, name: str, tables: list[dict[str, str]])
34 def __init__(self, namespace: str, name: str, tables: list[dict[str, str]]): 35 """Get an instance of an EventsStreamView.""" 36 super().__init__(namespace, name, EventsStreamView.type, tables)
Get an instance of an EventsStreamView.
default_measures: list[dict[str, str]] =
[{'name': 'event_count', 'type': 'count', 'description': 'The number of times the event(s) occurred.'}, {'name': 'ping_count', 'type': 'count', 'hidden': 'yes'}]
@classmethod
def
from_db_views( klass, namespace: str, is_glean: bool, channels: list[dict[str, str]], db_views: dict) -> Iterator[EventsStreamView]:
38 @classmethod 39 def from_db_views( 40 klass, 41 namespace: str, 42 is_glean: bool, 43 channels: list[dict[str, str]], 44 db_views: dict, 45 ) -> Iterator[EventsStreamView]: 46 """Get EventsStreamViews from db views.""" 47 for view_id in db_views[namespace]: 48 if view_id.endswith("events_stream"): 49 yield EventsStreamView( 50 namespace, 51 view_id, 52 [{"table": f"mozdata.{namespace}.{view_id}"}], 53 )
Get EventsStreamViews from db views.
@classmethod
def
from_dict( klass, namespace: str, name: str, _dict: generator.views.view.ViewDict) -> EventsStreamView:
55 @classmethod 56 def from_dict( 57 klass, namespace: str, name: str, _dict: ViewDict 58 ) -> EventsStreamView: 59 """Get EventsStreamView from a name and dict definition.""" 60 return EventsStreamView(namespace, name, _dict["tables"])
Get EventsStreamView from a name and dict definition.
def
to_lookml(self, v1_name: Optional[str], dryrun) -> dict[str, typing.Any]:
62 def to_lookml(self, v1_name: Optional[str], dryrun) -> dict[str, Any]: 63 """Generate LookML for this view.""" 64 dimensions = lookml_utils._generate_dimensions( 65 self.tables[0]["table"], dryrun=dryrun 66 ) 67 for dimension in dimensions: 68 if dimension["name"] == "event_id": 69 dimension["primary_key"] = "yes" 70 71 measures = self.get_measures(dimensions) 72 73 return { 74 "views": [ 75 { 76 "name": self.name, 77 "sql_table_name": f"`{self.tables[0]['table']}`", 78 "dimensions": [ 79 d for d in dimensions if not lookml_utils._is_dimension_group(d) 80 ], 81 "dimension_groups": [ 82 d for d in dimensions if lookml_utils._is_dimension_group(d) 83 ], 84 "measures": measures, 85 }, 86 ], 87 }
Generate LookML for this view.
def
get_measures(self, dimensions: list[dict[str, typing.Any]]) -> list[dict[str, str]]:
89 def get_measures(self, dimensions: list[dict[str, Any]]) -> list[dict[str, str]]: 90 """Get measures for this view.""" 91 measures = deepcopy(EventsStreamView.default_measures) 92 if client_id_dimension := self.get_client_id( 93 dimensions, self.tables[0]["table"] 94 ): 95 measures.append( 96 { 97 "name": "client_count", 98 "type": "count_distinct", 99 "sql": f"${{{client_id_dimension}}}", 100 "description": "The number of clients that completed the event(s).", 101 } 102 ) 103 # GleanPingViews were previously generated for some `events_stream` views, and those had 104 # `clients` measures, so we generate the same measures here to avoid breaking anything. 105 # TODO: Remove this once dashboards have been migrated to use the proper `client_count` measures. 106 measures.append( 107 { 108 "name": "clients", 109 "type": "count_distinct", 110 "sql": f"${{{client_id_dimension}}}", 111 "hidden": "yes", 112 } 113 ) 114 return measures
Get measures for this view.