Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/google/cloud/firestore_v1/query_profile.py: 75%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

44 statements  

1# Copyright 2024 Google LLC 

2# 

3# Licensed under the Apache License, Version 2.0 (the "License"); 

4# you may not use this file except in compliance with the License. 

5# You may obtain a copy of the License at 

6# 

7# http://www.apache.org/licenses/LICENSE-2.0 

8# 

9# Unless required by applicable law or agreed to in writing, software 

10# distributed under the License is distributed on an "AS IS" BASIS, 

11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

12# See the License for the specific language governing permissions and 

13# limitations under the License. 

14from __future__ import annotations 

15 

16from typing import Any 

17 

18import datetime 

19 

20from dataclasses import dataclass 

21from google.protobuf.json_format import MessageToDict 

22 

23 

24@dataclass(frozen=True) 

25class ExplainOptions: 

26 """ 

27 Explain options for the query. 

28 Set on a query object using the explain_options attribute at query 

29 construction time. 

30 

31 :type analyze: bool 

32 :param analyze: Optional. Whether to execute this query. When false 

33 (the default), the query will be planned, returning only metrics from the 

34 planning stages. When true, the query will be planned and executed, 

35 returning the full query results along with both planning and execution 

36 stage metrics. 

37 """ 

38 

39 analyze: bool = False 

40 

41 def _to_dict(self): 

42 return {"analyze": self.analyze} 

43 

44 

45@dataclass(frozen=True) 

46class PlanSummary: 

47 """ 

48 Contains planning phase information about a query.` 

49 

50 :type indexes_used: list[dict[str, Any]] 

51 :param indexes_used: The indexes selected for this query. 

52 """ 

53 

54 indexes_used: list[dict[str, Any]] 

55 

56 

57@dataclass(frozen=True) 

58class ExecutionStats: 

59 """ 

60 Execution phase information about a query. 

61 

62 Only available when explain_options.analyze is True. 

63 

64 :type results_returned: int 

65 :param results_returned: Total number of results returned, including 

66 documents, projections, aggregation results, keys. 

67 :type execution_duration: datetime.timedelta 

68 :param execution_duration: Total time to execute the query in the backend. 

69 :type read_operations: int 

70 :param read_operations: Total billable read operations. 

71 :type debug_stats: dict[str, Any] 

72 :param debug_stats: Debugging statistics from the execution of the query. 

73 Note that the debugging stats are subject to change as Firestore evolves 

74 """ 

75 

76 results_returned: int 

77 execution_duration: datetime.timedelta 

78 read_operations: int 

79 debug_stats: dict[str, Any] 

80 

81 

82@dataclass(frozen=True) 

83class ExplainMetrics: 

84 """ 

85 ExplainMetrics contains information about the planning and execution of a query. 

86 

87 When explain_options.analyze is false, only plan_summary is available. 

88 When explain_options.analyze is true, execution_stats is also available. 

89 

90 :type plan_summary: PlanSummary 

91 :param plan_summary: Planning phase information about the query. 

92 :type execution_stats: ExecutionStats 

93 :param execution_stats: Execution phase information about the query. 

94 """ 

95 

96 plan_summary: PlanSummary 

97 

98 @staticmethod 

99 def _from_pb(metrics_pb): 

100 dict_repr = MessageToDict(metrics_pb._pb, preserving_proto_field_name=True) 

101 plan_summary = PlanSummary( 

102 indexes_used=dict_repr.get("plan_summary", {}).get("indexes_used", []) 

103 ) 

104 if "execution_stats" in dict_repr: 

105 stats_dict = dict_repr.get("execution_stats", {}) 

106 execution_stats = ExecutionStats( 

107 results_returned=int(stats_dict.get("results_returned", 0)), 

108 execution_duration=metrics_pb.execution_stats.execution_duration, 

109 read_operations=int(stats_dict.get("read_operations", 0)), 

110 debug_stats=stats_dict.get("debug_stats", {}), 

111 ) 

112 return _ExplainAnalyzeMetrics( 

113 plan_summary=plan_summary, _execution_stats=execution_stats 

114 ) 

115 else: 

116 return ExplainMetrics(plan_summary=plan_summary) 

117 

118 @property 

119 def execution_stats(self) -> ExecutionStats: 

120 raise QueryExplainError( 

121 "execution_stats not available when explain_options.analyze=False." 

122 ) 

123 

124 

125@dataclass(frozen=True) 

126class _ExplainAnalyzeMetrics(ExplainMetrics): 

127 """ 

128 Subclass of ExplainMetrics that includes execution_stats. 

129 Only available when explain_options.analyze is True. 

130 """ 

131 

132 plan_summary: PlanSummary 

133 _execution_stats: ExecutionStats 

134 

135 @property 

136 def execution_stats(self) -> ExecutionStats: 

137 return self._execution_stats 

138 

139 

140class QueryExplainError(Exception): 

141 """ 

142 Error returned when there is a problem accessing query profiling information. 

143 """ 

144 

145 pass