warpzone-sdk 15.0.0.dev12__py3-none-any.whl → 15.0.0.dev14__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,4 @@
1
1
  import asyncio
2
- import logging
3
2
  from contextlib import contextmanager
4
3
  from typing import Callable
5
4
 
@@ -18,16 +17,7 @@ def configure_monitoring():
18
17
  """
19
18
  Configure logging and tracing on Azure Function to
20
19
  - export telemetry to App Insights
21
- - suppress spamming logs
22
20
  """
23
- # disable logging for HTTP calls to avoid log spamming
24
- logging.getLogger("azure.core.pipeline.policies.http_logging_policy").setLevel(
25
- logging.WARNING
26
- )
27
-
28
- # disable logging for Service Bus underlying uAMQP library to avoid log spamming
29
- logging.getLogger("uamqp").setLevel(logging.WARNING)
30
-
31
21
  # configure tracer provider
32
22
  traces.configure_tracing()
33
23
 
warpzone/monitor/logs.py CHANGED
@@ -1,6 +1,7 @@
1
1
  # NOTE: OpenTelemetry logging to Azure is still in EXPERIMENTAL mode!
2
2
  import logging
3
3
  import os
4
+ import threading
4
5
  from logging import StreamHandler
5
6
 
6
7
  from azure.monitor.opentelemetry.exporter import AzureMonitorLogExporter
@@ -27,42 +28,44 @@ _NOISY_LOGGERS = [
27
28
  for _logger_name in _NOISY_LOGGERS:
28
29
  logging.getLogger(_logger_name).setLevel(logging.WARNING)
29
30
 
31
+ _LOGGING_LOCK = threading.Lock()
30
32
  LOGGING_IS_CONFIGURED = False
31
33
 
32
34
 
33
35
  def configure_logging():
34
36
  global LOGGING_IS_CONFIGURED
35
- if LOGGING_IS_CONFIGURED:
36
- # logging should only be set up once
37
- # to avoid duplicated log handling.
38
- # Global variables is the pattern used
39
- # by opentelemetry, so we use the same
40
- return
37
+ with _LOGGING_LOCK:
38
+ if LOGGING_IS_CONFIGURED:
39
+ # logging should only be set up once
40
+ # to avoid duplicated log handling.
41
+ # Global variables is the pattern used
42
+ # by opentelemetry, so we use the same
43
+ return
41
44
 
42
- # set up logger provider based on the Azure Function resource
43
- # (this is make sure App Insights can track the log source correctly)
44
- # (https://learn.microsoft.com/en-us/azure/azure-monitor/app/opentelemetry-enable?tabs=net#set-the-cloud-role-name-and-the-cloud-role-instance)
45
- resource = Resource.create({SERVICE_NAME: os.getenv("WEBSITE_SITE_NAME")})
46
- logs.set_logger_provider(
47
- LoggerProvider(
48
- resource=resource,
45
+ # set up logger provider based on the Azure Function resource
46
+ # (this is make sure App Insights can track the log source correctly)
47
+ # (https://learn.microsoft.com/en-us/azure/azure-monitor/app/opentelemetry-enable?tabs=net#set-the-cloud-role-name-and-the-cloud-role-instance)
48
+ service_name = os.getenv("WEBSITE_SITE_NAME") or "unknown-service"
49
+ resource = Resource.create({SERVICE_NAME: service_name})
50
+ logs.set_logger_provider(
51
+ LoggerProvider(
52
+ resource=resource,
53
+ )
49
54
  )
50
- )
51
55
 
52
- # setup azure monitor log exporter to send telemetry to App Insights
53
- try:
54
- log_exporter = AzureMonitorLogExporter()
55
- except ValueError:
56
- # if no App Insights instrumentation key is set (e.g. when running unit tests),
57
- # the exporter creation will fail. In this case we skip it
58
- logger.warning(
59
- "Cant set up logging to App Insights, as no instrumentation key is set."
60
- )
61
- else:
62
- log_record_processor = BatchLogRecordProcessor(log_exporter)
63
- logs.get_logger_provider().add_log_record_processor(log_record_processor)
56
+ # setup azure monitor log exporter to send telemetry to App Insights
57
+ try:
58
+ log_exporter = AzureMonitorLogExporter()
59
+ except ValueError:
60
+ logger.warning(
61
+ "Cant set up logging to App Insights,"
62
+ " as no connection string is set."
63
+ )
64
+ else:
65
+ log_record_processor = BatchLogRecordProcessor(log_exporter)
66
+ logs.get_logger_provider().add_log_record_processor(log_record_processor)
64
67
 
65
- LOGGING_IS_CONFIGURED = True
68
+ LOGGING_IS_CONFIGURED = True
66
69
 
67
70
 
68
71
  def get_logger(name: str):
@@ -77,5 +80,7 @@ def get_logger(name: str):
77
80
  # add OTEL handler for trace correlation
78
81
  handler = LoggingHandler()
79
82
  logger.addHandler(handler)
83
+ # Don't propagate to root logger to avoid duplicate logs
84
+ logger.propagate = False
80
85
 
81
86
  return logger
@@ -1,5 +1,6 @@
1
1
  import logging
2
2
  import os
3
+ import threading
3
4
  from contextlib import contextmanager
4
5
  from logging import StreamHandler
5
6
 
@@ -16,46 +17,48 @@ logger.addHandler(StreamHandler())
16
17
 
17
18
  tracer = trace.get_tracer(__name__)
18
19
 
20
+ _TRACING_LOCK = threading.Lock()
19
21
  TRACING_IS_CONFIGURED = False
20
22
 
21
23
 
22
24
  def configure_tracing():
23
25
  global TRACING_IS_CONFIGURED
24
- if TRACING_IS_CONFIGURED:
25
- # tracing should only be set up once
26
- # to avoid duplicated trace handling.
27
- # Global variables is the pattern used
28
- # by opentelemetry, so we use the same
29
- return
30
-
31
- # set up tracer provider based on the Azure Function resource
32
- # (this is make sure App Insights can track the trace source correctly)
33
- # (https://learn.microsoft.com/en-us/azure/azure-monitor/app/opentelemetry-enable?tabs=net#set-the-cloud-role-name-and-the-cloud-role-instance).
34
- # We use the ALWAYS ON sampler since otherwise spans will not be
35
- # recording upon creation
36
- # (https://anecdotes.dev/opentelemetry-on-google-cloud-unraveling-the-mystery-f61f044c18be)
37
- resource = Resource.create({SERVICE_NAME: os.getenv("WEBSITE_SITE_NAME")})
38
- trace.set_tracer_provider(
39
- TracerProvider(
40
- sampler=ALWAYS_ON,
41
- resource=resource,
26
+ with _TRACING_LOCK:
27
+ if TRACING_IS_CONFIGURED:
28
+ # tracing should only be set up once
29
+ # to avoid duplicated trace handling.
30
+ # Global variables is the pattern used
31
+ # by opentelemetry, so we use the same
32
+ return
33
+
34
+ # set up tracer provider based on the Azure Function resource
35
+ # (this is make sure App Insights can track the trace source correctly)
36
+ # (https://learn.microsoft.com/en-us/azure/azure-monitor/app/opentelemetry-enable?tabs=net#set-the-cloud-role-name-and-the-cloud-role-instance).
37
+ # We use the ALWAYS ON sampler since otherwise spans will not be
38
+ # recording upon creation
39
+ # (https://anecdotes.dev/opentelemetry-on-google-cloud-unraveling-the-mystery-f61f044c18be)
40
+ service_name = os.getenv("WEBSITE_SITE_NAME") or "unknown-service"
41
+ resource = Resource.create({SERVICE_NAME: service_name})
42
+ trace.set_tracer_provider(
43
+ TracerProvider(
44
+ sampler=ALWAYS_ON,
45
+ resource=resource,
46
+ )
42
47
  )
43
- )
44
48
 
45
- # setup azure monitor trace exporter to send telemetry to App Insights
46
- try:
47
- trace_exporter = AzureMonitorTraceExporter()
48
- except ValueError:
49
- # if no App Insights instrumentation key is set (e.g. when running unit tests),
50
- # the exporter creation will fail. In this case we skip it
51
- logger.warning(
52
- "Cant set up tracing to App Insights, as no instrumentation key is set."
53
- )
54
- else:
55
- span_processor = BatchSpanProcessor(trace_exporter)
56
- trace.get_tracer_provider().add_span_processor(span_processor)
57
-
58
- TRACING_IS_CONFIGURED = True
49
+ # setup azure monitor trace exporter to send telemetry to App Insights
50
+ try:
51
+ trace_exporter = AzureMonitorTraceExporter()
52
+ except ValueError:
53
+ logger.warning(
54
+ "Cant set up tracing to App Insights,"
55
+ " as no connection string is set."
56
+ )
57
+ else:
58
+ span_processor = BatchSpanProcessor(trace_exporter)
59
+ trace.get_tracer_provider().add_span_processor(span_processor)
60
+
61
+ TRACING_IS_CONFIGURED = True
59
62
 
60
63
 
61
64
  @contextmanager
@@ -160,31 +160,22 @@ class WarpzoneDatabaseClient:
160
160
  filters: Optional[dict[str, object]] = None,
161
161
  use_cache: Optional[bool] = True,
162
162
  ) -> pd.DataFrame:
163
- with tracer.start_as_current_span(
164
- "WarpzoneDatabaseClient.query",
165
- attributes={
166
- "table_name": table_name,
167
- "use_cache": use_cache,
168
- "has_filters": filters is not None,
169
- "has_time_interval": time_interval is not None,
170
- },
171
- ):
172
- table_metadata = self.get_table_metadata(table_name)
173
-
174
- match table_metadata.data_type:
175
- case DataType.TIME_SERIES:
176
- df = self._query_time_series(
177
- table_metadata, time_interval, filters, use_cache
163
+ table_metadata = self.get_table_metadata(table_name)
164
+
165
+ match table_metadata.data_type:
166
+ case DataType.TIME_SERIES:
167
+ df = self._query_time_series(
168
+ table_metadata, time_interval, filters, use_cache
169
+ )
170
+ case _:
171
+ if time_interval:
172
+ raise ValueError(
173
+ f"Table {table_name} is not a time series table,"
174
+ " and cannot be queried with a time interval."
178
175
  )
179
- case _:
180
- if time_interval:
181
- raise ValueError(
182
- f"Table {table_name} is not a time series table,"
183
- " and cannot be queried with a time interval."
184
- )
185
- df = self._query_generic(table_metadata, None, filters, use_cache)
186
-
187
- return df
176
+ df = self._query_generic(table_metadata, None, filters, use_cache)
177
+
178
+ return df
188
179
 
189
180
  def list_tables(self):
190
181
  return self._table_client.list_tables()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: warpzone-sdk
3
- Version: 15.0.0.dev12
3
+ Version: 15.0.0.dev14
4
4
  Summary: The main objective of this package is to centralize logic used to interact with Azure Functions, Azure Service Bus and Azure Table Storage
5
5
  Author: Team Enigma
6
6
  Author-email: enigma@energinet.dk
@@ -17,7 +17,7 @@ warpzone/function/__init__.py,sha256=rJOZBpWsUgjMc7YtXMJ1rLGm45KB1AhDJ_Y2ISiSISc
17
17
  warpzone/function/checks.py,sha256=B9YqThymf16ac_fVAYKilv20ru5v9nwXgHlbxYIaG98,1018
18
18
  warpzone/function/functionize.py,sha256=bSV0QvwKbD9Vo3a_8cc1rgV2rzTdMMvidinyXItBfvs,2128
19
19
  warpzone/function/integrations.py,sha256=sDt2BTx6a4mVc-33wTITP9XQVPustwj7rkX4urTyOqo,4018
20
- warpzone/function/monitor.py,sha256=szPn6jYfWcdypZVjqy3Md7SKpKoZ979PZ8px4PFIm5U,2223
20
+ warpzone/function/monitor.py,sha256=xD13d4795a9qgGphOywFl4sOXRQjKypiL2ozQFOseqQ,1862
21
21
  warpzone/function/process.py,sha256=nbUVywM8ChfUwuaqFisgaD98aNRgeZkK4g5sbtuBdRs,2339
22
22
  warpzone/function/processors/__init__.py,sha256=DhIdSWLBcIeSO8IJdxPqGIhgwwnkDN6_Xqwy93BCLeA,46
23
23
  warpzone/function/processors/dependencies.py,sha256=m17BwdKyQEvzCPxpQZpAW5l1uYRIHWmweDz3XJskmpA,1259
@@ -28,8 +28,8 @@ warpzone/function/types.py,sha256=5m2hRrnLC3eqIlAH5-MM9_wKjMZ6lYawZtCOVStyFuY,72
28
28
  warpzone/healthchecks/__init__.py,sha256=9gc_Mt2szs8sDSwy0V4l3JZ6d9hX41xTpZCkDP2qsY4,2108
29
29
  warpzone/healthchecks/model.py,sha256=mM7DnrirLbUpBPPfi82MUPP654D0eOR2_F65TmzsPD0,1187
30
30
  warpzone/monitor/__init__.py,sha256=gXT2cxR4tlZER54zd7D49ZQBVyitLaqj13_cUoILuyM,109
31
- warpzone/monitor/logs.py,sha256=iYGDsaATq6iqcEK4tWDssgw66rkd3gsnNECZmJ8mbME,2889
32
- warpzone/monitor/traces.py,sha256=ARd8IW1BqCRgOXu-A_guOAOGpGvpKhJRTzjJgbAgx5Y,3994
31
+ warpzone/monitor/logs.py,sha256=AO853uEpD9ZZldQsBic5IR9k3GuQPyWafk4pC5fAGio,3084
32
+ warpzone/monitor/traces.py,sha256=2ANxKmO1yca3JFBi68P9HeXQo8WVOOVeT1ev3GLURSY,4107
33
33
  warpzone/servicebus/data/__init__.py,sha256=lnc0uiaGLF0qMi_rWhCpRSFvaj0CJEiMCAl6Yqn1ZiA,21
34
34
  warpzone/servicebus/data/client.py,sha256=zECS3JwedhYnDk8PntYgIYpBF_uu9YN38KzpPFK7CKs,6511
35
35
  warpzone/servicebus/events/__init__.py,sha256=lnc0uiaGLF0qMi_rWhCpRSFvaj0CJEiMCAl6Yqn1ZiA,21
@@ -37,7 +37,7 @@ warpzone/servicebus/events/client.py,sha256=8v8XsF-2RwzKIi_93IzR_eR-BZTGXXHSuV4P
37
37
  warpzone/servicebus/events/triggers.py,sha256=_QuPTBbje7LrBoz0qhhgrtDZOcE6x1S9GNu-WJUQ8bY,2626
38
38
  warpzone/tablestorage/db/__init__.py,sha256=lnc0uiaGLF0qMi_rWhCpRSFvaj0CJEiMCAl6Yqn1ZiA,21
39
39
  warpzone/tablestorage/db/base_client.py,sha256=ropKO6z0UXqBl38NuGYV4VZ_ZFm4w1d84ReOLYoBKLY,2376
40
- warpzone/tablestorage/db/client.py,sha256=w8p3ghtpFnbDQtqqAQTFnC346lLDjBKmi3rRjNgSrz0,7053
40
+ warpzone/tablestorage/db/client.py,sha256=5I_5pUzB9ZVYyj8cf2g9PIuMdXIfaytWsAnDm6EZnyg,6661
41
41
  warpzone/tablestorage/db/table_config.py,sha256=PC45dnr3vVMVr8ktu3GWoH8u3JKJaCRAvMCroUaC1NE,1336
42
42
  warpzone/tablestorage/tables/__init__.py,sha256=l_8wElG1oam39fmXqIXDAnCYqbKXEyX1G0cD6JCCv4s,78
43
43
  warpzone/tablestorage/tables/client.py,sha256=chvmTz5S8M1-IWYgfJHyTCwLZVsVzlchMuCYwHzQhCE,3636
@@ -52,6 +52,6 @@ warpzone/tools/copy.py,sha256=5fddotMZkXZO8avzUbGOhvs0cp8mce95pNpy0oPVjnQ,2596
52
52
  warpzone/transform/__init__.py,sha256=ruGa7tl-v4ndlWpULE1jSGU_a4_iRc3V6eyNr5xKP9E,27
53
53
  warpzone/transform/data.py,sha256=Abb8PcrgMbbNCJkkIUdtrTHdlY0OfXid387qw1nDpFY,2362
54
54
  warpzone/transform/schema.py,sha256=nbSQtDMvXkyqGKuwhuFCF0WsEDsaNyoPYpMKvbsKlv8,2423
55
- warpzone_sdk-15.0.0.dev12.dist-info/METADATA,sha256=C1StbO7xo2v1z8MHH_Xx-SLcYS9iw-jkSamfRPr2MxY,7285
56
- warpzone_sdk-15.0.0.dev12.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
57
- warpzone_sdk-15.0.0.dev12.dist-info/RECORD,,
55
+ warpzone_sdk-15.0.0.dev14.dist-info/METADATA,sha256=C7hvF9-5FlHq-EwoLv65npYpGLZTIEXAsRXo_0Sp_GE,7285
56
+ warpzone_sdk-15.0.0.dev14.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
57
+ warpzone_sdk-15.0.0.dev14.dist-info/RECORD,,