Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/google/cloud/logging_v2/handlers/_monitored_resources.py: 49%

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

121 statements  

1# Copyright 2021 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. 

14 

15import functools 

16import logging 

17import os 

18 

19from google.cloud.logging_v2.resource import Resource 

20from google.cloud.logging_v2._helpers import retrieve_metadata_server 

21 

22_GAE_SERVICE_ENV = "GAE_SERVICE" 

23_GAE_VERSION_ENV = "GAE_VERSION" 

24_GAE_INSTANCE_ENV = "GAE_INSTANCE" 

25_GAE_ENV_VARS = [_GAE_SERVICE_ENV, _GAE_VERSION_ENV, _GAE_INSTANCE_ENV] 

26"""Environment variables set in App Engine environment.""" 

27 

28_CLOUD_RUN_SERVICE_ID = "K_SERVICE" 

29_CLOUD_RUN_REVISION_ID = "K_REVISION" 

30_CLOUD_RUN_CONFIGURATION_ID = "K_CONFIGURATION" 

31_CLOUD_RUN_SERVICE_ENV_VARS = [ 

32 _CLOUD_RUN_SERVICE_ID, 

33 _CLOUD_RUN_REVISION_ID, 

34 _CLOUD_RUN_CONFIGURATION_ID, 

35] 

36_CLOUD_RUN_JOB_ID = "CLOUD_RUN_JOB" 

37_CLOUD_RUN_EXECUTION_ID = "CLOUD_RUN_EXECUTION" 

38_CLOUD_RUN_TASK_INDEX = "CLOUD_RUN_TASK_INDEX" 

39_CLOUD_RUN_TASK_ATTEMPT = "CLOUD_RUN_TASK_ATTEMPT" 

40_CLOUD_RUN_JOB_ENV_VARS = [ 

41 _CLOUD_RUN_JOB_ID, 

42 _CLOUD_RUN_EXECUTION_ID, 

43 _CLOUD_RUN_TASK_INDEX, 

44 _CLOUD_RUN_TASK_ATTEMPT, 

45] 

46"""Environment variables set in Cloud Run environment.""" 

47 

48_FUNCTION_TARGET = "FUNCTION_TARGET" 

49_FUNCTION_SIGNATURE = "FUNCTION_SIGNATURE_TYPE" 

50_FUNCTION_NAME = "FUNCTION_NAME" 

51_FUNCTION_REGION = "FUNCTION_REGION" 

52_FUNCTION_ENTRY = "ENTRY_POINT" 

53_FUNCTION_ENV_VARS = [_FUNCTION_TARGET, _FUNCTION_SIGNATURE, _CLOUD_RUN_SERVICE_ID] 

54_LEGACY_FUNCTION_ENV_VARS = [_FUNCTION_NAME, _FUNCTION_REGION, _FUNCTION_ENTRY] 

55"""Environment variables set in Cloud Functions environments.""" 

56 

57 

58_REGION_ID = "instance/region" 

59_ZONE_ID = "instance/zone" 

60_GCE_INSTANCE_ID = "instance/id" 

61"""Attribute in metadata server for compute region and instance.""" 

62 

63_GKE_CLUSTER_NAME = "instance/attributes/cluster-name" 

64"""Attribute in metadata server when in GKE environment.""" 

65 

66_GKE_CLUSTER_LOCATION = "instance/attributes/cluster-location" 

67"""Attribute in metadata server when in GKE environment.""" 

68 

69_PROJECT_NAME = "project/project-id" 

70"""Attribute in metadata server when in GKE environment.""" 

71 

72_GAE_RESOURCE_TYPE = "gae_app" 

73"""Resource type for App Engine environment.""" 

74 

75_CLOUD_RUN_JOB_RESOURCE_TYPE = "cloud_run_job" 

76"""Resource type for Cloud Run Jobs.""" 

77 

78_GAE_TRACE_ID_LABEL = "appengine.googleapis.com/trace_id" 

79"""Extra trace label to be added on App Engine environments""" 

80 

81_CLOUD_RUN_JOBS_EXECUTION_NAME_LABEL = "run.googleapis.com/execution_name" 

82_CLOUD_RUN_JOBS_TASK_INDEX_LABEL = "run.googleapis.com/task_index" 

83_CLOUD_RUN_JOBS_TASK_ATTEMPT_LABEL = "run.googleapis.com/task_attempt" 

84"""Extra labels for Cloud Run environments to be recognized by Cloud Run Jobs web UI.""" 

85 

86 

87def _create_functions_resource(): 

88 """Create a standardized Cloud Functions resource. 

89 Returns: 

90 google.cloud.logging.Resource 

91 """ 

92 project = retrieve_metadata_server(_PROJECT_NAME) 

93 region = retrieve_metadata_server(_REGION_ID) 

94 if _FUNCTION_NAME in os.environ: 

95 function_name = os.environ.get(_FUNCTION_NAME) 

96 elif _CLOUD_RUN_SERVICE_ID in os.environ: 

97 function_name = os.environ.get(_CLOUD_RUN_SERVICE_ID) 

98 else: 

99 function_name = "" 

100 resource = Resource( 

101 type="cloud_function", 

102 labels={ 

103 "project_id": project if project else "", 

104 "function_name": function_name if function_name else "", 

105 "region": region.split("/")[-1] if region else "", 

106 }, 

107 ) 

108 return resource 

109 

110 

111def _create_kubernetes_resource(): 

112 """Create a standardized Kubernetes resource. 

113 Returns: 

114 google.cloud.logging.Resource 

115 """ 

116 location = retrieve_metadata_server(_GKE_CLUSTER_LOCATION) 

117 cluster_name = retrieve_metadata_server(_GKE_CLUSTER_NAME) 

118 project = retrieve_metadata_server(_PROJECT_NAME) 

119 

120 resource = Resource( 

121 type="k8s_container", 

122 labels={ 

123 "project_id": project if project else "", 

124 "location": location if location else "", 

125 "cluster_name": cluster_name if cluster_name else "", 

126 }, 

127 ) 

128 return resource 

129 

130 

131def _create_compute_resource(): 

132 """Create a standardized Compute Engine resource. 

133 Returns: 

134 google.cloud.logging.Resource 

135 """ 

136 instance = retrieve_metadata_server(_GCE_INSTANCE_ID) 

137 zone = retrieve_metadata_server(_ZONE_ID) 

138 project = retrieve_metadata_server(_PROJECT_NAME) 

139 resource = Resource( 

140 type="gce_instance", 

141 labels={ 

142 "project_id": project if project else "", 

143 "instance_id": instance if instance else "", 

144 "zone": zone if zone else "", 

145 }, 

146 ) 

147 return resource 

148 

149 

150def _create_cloud_run_service_resource(): 

151 """Create a standardized Cloud Run service resource. 

152 Returns: 

153 google.cloud.logging.Resource 

154 """ 

155 region = retrieve_metadata_server(_REGION_ID) 

156 project = retrieve_metadata_server(_PROJECT_NAME) 

157 resource = Resource( 

158 type="cloud_run_revision", 

159 labels={ 

160 "project_id": project if project else "", 

161 "service_name": os.environ.get(_CLOUD_RUN_SERVICE_ID, ""), 

162 "revision_name": os.environ.get(_CLOUD_RUN_REVISION_ID, ""), 

163 "location": region.split("/")[-1] if region else "", 

164 "configuration_name": os.environ.get(_CLOUD_RUN_CONFIGURATION_ID, ""), 

165 }, 

166 ) 

167 return resource 

168 

169 

170def _create_cloud_run_job_resource(): 

171 """Create a standardized Cloud Run job resource. 

172 Returns: 

173 google.cloud.logging.Resource 

174 """ 

175 region = retrieve_metadata_server(_REGION_ID) 

176 project = retrieve_metadata_server(_PROJECT_NAME) 

177 resource = Resource( 

178 type=_CLOUD_RUN_JOB_RESOURCE_TYPE, 

179 labels={ 

180 "project_id": project if project else "", 

181 "job_name": os.environ.get(_CLOUD_RUN_JOB_ID, ""), 

182 "location": region.split("/")[-1] if region else "", 

183 }, 

184 ) 

185 return resource 

186 

187 

188def _create_app_engine_resource(): 

189 """Create a standardized App Engine resource. 

190 Returns: 

191 google.cloud.logging.Resource 

192 """ 

193 zone = retrieve_metadata_server(_ZONE_ID) 

194 project = retrieve_metadata_server(_PROJECT_NAME) 

195 resource = Resource( 

196 type=_GAE_RESOURCE_TYPE, 

197 labels={ 

198 "project_id": project if project else "", 

199 "module_id": os.environ.get(_GAE_SERVICE_ENV, ""), 

200 "version_id": os.environ.get(_GAE_VERSION_ENV, ""), 

201 "zone": zone if zone else "", 

202 }, 

203 ) 

204 return resource 

205 

206 

207def _create_global_resource(project): 

208 """Create a global resource. 

209 Args: 

210 project (str): The project ID to pass on to the resource 

211 Returns: 

212 google.cloud.logging.Resource 

213 """ 

214 return Resource(type="global", labels={"project_id": project if project else ""}) 

215 

216 

217def detect_resource(project=""): 

218 """Return the default monitored resource based on the local environment. 

219 If GCP resource not found, defaults to `global`. 

220 

221 Args: 

222 project (str): The project ID to pass on to the resource (if needed) 

223 Returns: 

224 google.cloud.logging.Resource: The default resource based on the environment 

225 """ 

226 gke_cluster_name = retrieve_metadata_server(_GKE_CLUSTER_NAME) 

227 gce_instance_name = retrieve_metadata_server(_GCE_INSTANCE_ID) 

228 

229 if all([env in os.environ for env in _GAE_ENV_VARS]): 

230 # App Engine Flex or Standard 

231 return _create_app_engine_resource() 

232 elif gke_cluster_name is not None: 

233 # Kubernetes Engine 

234 return _create_kubernetes_resource() 

235 elif all([env in os.environ for env in _LEGACY_FUNCTION_ENV_VARS]) or all( 

236 [env in os.environ for env in _FUNCTION_ENV_VARS] 

237 ): 

238 # Cloud Functions 

239 return _create_functions_resource() 

240 elif all([env in os.environ for env in _CLOUD_RUN_SERVICE_ENV_VARS]): 

241 # Cloud Run 

242 return _create_cloud_run_service_resource() 

243 elif all([env in os.environ for env in _CLOUD_RUN_JOB_ENV_VARS]): 

244 # Cloud Run 

245 return _create_cloud_run_job_resource() 

246 elif gce_instance_name is not None: 

247 # Compute Engine 

248 return _create_compute_resource() 

249 else: 

250 # use generic global resource 

251 return _create_global_resource(project) 

252 

253 

254@functools.lru_cache(maxsize=None) 

255def _get_environmental_labels(resource_type): 

256 """Builds a dictionary of labels to be inserted into a LogRecord of the given resource type. 

257 This function should only build a dict of items that are consistent across multiple logging statements 

258 of the same resource type, such as environment variables. Th 

259 

260 Returns: 

261 dict: 

262 A dict representation of labels and the values of those labels 

263 """ 

264 labels = {} 

265 environ_vars = { 

266 _CLOUD_RUN_JOB_RESOURCE_TYPE: { 

267 _CLOUD_RUN_JOBS_EXECUTION_NAME_LABEL: _CLOUD_RUN_EXECUTION_ID, 

268 _CLOUD_RUN_JOBS_TASK_INDEX_LABEL: _CLOUD_RUN_TASK_INDEX, 

269 _CLOUD_RUN_JOBS_TASK_ATTEMPT_LABEL: _CLOUD_RUN_TASK_ATTEMPT, 

270 } 

271 } 

272 

273 if resource_type in environ_vars: 

274 for key, env_var in environ_vars[resource_type].items(): 

275 val = os.environ.get(env_var, "") 

276 if val: 

277 labels[key] = val 

278 

279 return labels 

280 

281 

282def add_resource_labels(resource: Resource, record: logging.LogRecord): 

283 """Returns additional labels to be appended on to a LogRecord object based on the 

284 local environment. Defaults to an empty dictionary if none apply. This is only to be 

285 used for CloudLoggingHandler, as the structured logging daemon already does this. 

286 

287 Args: 

288 resource (google.cloud.logging.Resource): Resource based on the environment 

289 record (logging.LogRecord): A LogRecord object representing a log record 

290 Returns: 

291 Dict[str, str]: New labels to append to the labels of the LogRecord 

292 """ 

293 if not resource: 

294 return None 

295 

296 # Get environmental labels from the resource type 

297 labels = _get_environmental_labels(resource.type) 

298 

299 # Add labels from log record 

300 if resource.type == _GAE_RESOURCE_TYPE and record._trace is not None: 

301 labels[_GAE_TRACE_ID_LABEL] = record._trace 

302 

303 return labels