cloe-logging 0.3.8__py3-none-any.whl → 0.3.10__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.
@@ -2,8 +2,8 @@ import functools
2
2
  import logging
3
3
  import sys
4
4
  import time
5
- from typing import Any
6
5
  from collections.abc import Callable
6
+ from typing import Any
7
7
 
8
8
  from cloe_logging.formatters import DevOpsFormatter
9
9
 
@@ -52,7 +52,7 @@ def build_logger():
52
52
  start = time.time()
53
53
  value = func(*args, **kwargs)
54
54
  end = time.time()
55
- logger.info(f"\n##### END {func.__name__} DURATION [ '{round(end-start)}'s ] #####")
55
+ logger.info(f"\n##### END {func.__name__} DURATION [ '{round(end - start)}'s ] #####")
56
56
  except:
57
57
  logger.error(f"ERROR: {str(sys.exc_info()[1])}")
58
58
  raise
@@ -1,4 +1,4 @@
1
- from .dict_formatter import DictFormatter
2
1
  from .devops_formatter import DevOpsFormatter
2
+ from .dict_formatter import DictFormatter
3
3
 
4
4
  __all__ = ["DictFormatter", "DevOpsFormatter"]
@@ -61,7 +61,7 @@ class DevOpsFormatter(logging.Formatter):
61
61
  if record.levelno == logging.INFO:
62
62
  record_message = record.msg # f"{record.name} -- {record.msg}"
63
63
 
64
- return f"{self.parse_progress(record.msg)}{self.parse_group_start(record.msg)}{record_message}{self.parse_group_end(record.msg)}"
64
+ return f"{self.parse_progress(record.msg)}{self.parse_group_start(record.msg)}{record_message}{self.parse_group_end(record.msg)}" # noqa: E501
65
65
 
66
66
  # Replace the original format with one customized by logging level
67
67
  if record.levelno == logging.DEBUG:
@@ -1,5 +1,5 @@
1
- import logging
2
1
  import json
2
+ import logging
3
3
 
4
4
 
5
5
  class DictFormatter(logging.Formatter):
@@ -1,5 +1,5 @@
1
- from .unity_catalog_handler import UnityCatalogHandler
2
1
  from .log_analytics_handler import LogAnalyticsHandler
3
2
  from .snowflake_handler import SnowflakeHandler
3
+ from .unity_catalog_handler import UnityCatalogHandler
4
4
 
5
5
  __all__ = ["UnityCatalogHandler", "LogAnalyticsHandler", "SnowflakeHandler"]
@@ -3,13 +3,15 @@ import hashlib
3
3
  import hmac
4
4
  import logging
5
5
  import os
6
- from datetime import datetime
6
+ from datetime import UTC, datetime
7
7
 
8
8
  try:
9
9
  import requests
10
+
11
+ _REQUESTS_AVAILABLE = True
10
12
  except ImportError:
11
13
  requests = None # type: ignore
12
- print("Optional dependency 'log_analytics' is not installed. Some functionalities may not be available.")
14
+ _REQUESTS_AVAILABLE = False
13
15
 
14
16
  from cloe_logging.utility.serializer import create_logserializer
15
17
 
@@ -37,7 +39,7 @@ class LogAnalyticsHandler(logging.Handler):
37
39
  test_connectivity: bool = True,
38
40
  column_split_char: str = "|",
39
41
  key_value_split_char: str = ":",
40
- **kwargs, # required to work with the Factory
42
+ **kwargs, # noqa: ARG002 required to work with the Factory
41
43
  ):
42
44
  """Initializes a new instance of the LogAnalyticsHandler class.
43
45
 
@@ -60,6 +62,10 @@ class LogAnalyticsHandler(logging.Handler):
60
62
  raise ValueError(
61
63
  "The workspace_id, shared_key, and log_type must be provided or set as environment variables."
62
64
  )
65
+ if not _REQUESTS_AVAILABLE:
66
+ raise ImportError(
67
+ "Requests library is not installed. Install it with: pip install cloe-logging[log-analytics]"
68
+ )
63
69
  logging.Handler.__init__(self)
64
70
  self.session = requests.Session()
65
71
  formatter = logging.Formatter("timestamp:%(asctime)s | level: %(levelname)-8s | %(message)s")
@@ -99,7 +105,7 @@ class LogAnalyticsHandler(logging.Handler):
99
105
  )
100
106
  self.levelname = "INFO"
101
107
 
102
- def getMessage(self):
108
+ def getMessage(self): # noqa: N802 mimics logging.LogRecord.getMessage
103
109
  return self.msg
104
110
 
105
111
  try:
@@ -154,8 +160,7 @@ class LogAnalyticsHandler(logging.Handler):
154
160
  encoded_hash = base64.b64encode(
155
161
  hmac.new(decoded_key, bytes_to_hash, digestmod=hashlib.sha256).digest(),
156
162
  ).decode()
157
- authorization = f"SharedKey {self.workspace_id}:{encoded_hash}"
158
- return authorization
163
+ return f"SharedKey {self.workspace_id}:{encoded_hash}"
159
164
 
160
165
  def _make_message_compliant(self, input_string):
161
166
  """Encodes the input string as UTF-8 to make it compliant.
@@ -174,8 +179,7 @@ class LogAnalyticsHandler(logging.Handler):
174
179
  Returns:
175
180
  str: The URL of the Azure Log Analytics workspace.
176
181
  """
177
- uri = f"https://{self.workspace_id}.ods.opinsights.azure.com{self.RESOURCE}?api-version=2016-04-01"
178
- return uri
182
+ return f"https://{self.workspace_id}.ods.opinsights.azure.com{self.RESOURCE}?api-version=2016-04-01"
179
183
 
180
184
  def emit(self, record: logging.LogRecord):
181
185
  """Sends the log message to Azure Log Analytics.
@@ -198,7 +202,7 @@ class LogAnalyticsHandler(logging.Handler):
198
202
  log_message_dict = self.serializer.serialize(log_message)
199
203
  compliant_log_message = self._make_message_compliant(str(log_message_dict))
200
204
  content_length = len(compliant_log_message)
201
- rfc1123date = datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT")
205
+ rfc1123date = datetime.now(UTC).strftime("%a, %d %b %Y %H:%M:%S GMT")
202
206
  signature = self._build_signature(rfc1123date, content_length)
203
207
 
204
208
  headers = {
@@ -2,12 +2,16 @@ import logging
2
2
  import os
3
3
 
4
4
  try:
5
- from cloe_util_snowflake_connector.connection_parameters import ConnectionParameters
6
- from cloe_util_snowflake_connector.snowflake_interface import SnowflakeInterface
5
+ from cloe_util_snowflake_connector.connection_parameters import ( # type: ignore[import-not-found]
6
+ ConnectionParameters,
7
+ )
8
+ from cloe_util_snowflake_connector.snowflake_interface import SnowflakeInterface # type: ignore[import-not-found]
9
+
10
+ _SNOWFLAKE_AVAILABLE = True
7
11
  except ImportError:
8
12
  ConnectionParameters = None # type: ignore
9
13
  SnowflakeInterface = None # type: ignore
10
- print("Optional dependency 'snowflake' is not installed. Some functionalities may not be available.")
14
+ _SNOWFLAKE_AVAILABLE = False
11
15
  from cloe_logging.utility.serializer import create_logserializer
12
16
 
13
17
 
@@ -24,7 +28,7 @@ class SnowflakeHandler(logging.Handler):
24
28
  target_table: str = "",
25
29
  column_split_char: str = "|",
26
30
  key_value_split_char: str = ":",
27
- **kwargs, # required to work with the Factory
31
+ **kwargs, # noqa: ARG002 required to work with the Factory
28
32
  ):
29
33
  """Initializes a new instance of the SnowflakeHandler class.
30
34
 
@@ -78,9 +82,12 @@ class SnowflakeHandler(logging.Handler):
78
82
  return hash((self.target_db, self.target_schema, self.target_table))
79
83
 
80
84
  def _get_snowflake_connection(self) -> SnowflakeInterface:
85
+ if not _SNOWFLAKE_AVAILABLE:
86
+ raise ImportError(
87
+ "Snowflake dependencies are not installed. Install them with: pip install cloe-logging[snowflake]"
88
+ )
81
89
  conn_params = ConnectionParameters.init_from_env_variables()
82
- snowflake_conn = SnowflakeInterface(conn_params)
83
- return snowflake_conn
90
+ return SnowflakeInterface(conn_params)
84
91
 
85
92
  def _parse_dict_to_sql_insert(self, input_dict: dict) -> str:
86
93
  """
@@ -95,11 +102,7 @@ class SnowflakeHandler(logging.Handler):
95
102
  """
96
103
  columns = ", ".join(input_dict.keys())
97
104
  values = ", ".join(f"'{str(v)}'" for v in input_dict.values())
98
- sql_statement = (
99
- f"INSERT INTO {self.target_db}.{self.target_schema}.{self.target_table} ({columns}) VALUES ({values})"
100
- )
101
-
102
- return sql_statement
105
+ return f"INSERT INTO {self.target_db}.{self.target_schema}.{self.target_table} ({columns}) VALUES ({values})"
103
106
 
104
107
  def emit(self, record: logging.LogRecord):
105
108
  """Sends the log message to Snowflake.
@@ -3,12 +3,14 @@ import logging
3
3
  from typing import cast
4
4
 
5
5
  try:
6
- from databricks.sdk import WorkspaceClient
7
- from databricks.sdk.service.sql import ExecuteStatementRequestOnWaitTimeout
6
+ from databricks.sdk import WorkspaceClient # type: ignore[import-not-found]
7
+ from databricks.sdk.service.sql import ExecuteStatementRequestOnWaitTimeout # type: ignore[import-not-found]
8
+
9
+ _DATABRICKS_AVAILABLE = True
8
10
  except ImportError:
9
11
  WorkspaceClient = None # type: ignore
10
12
  ExecuteStatementRequestOnWaitTimeout = None # type: ignore
11
- print("Optional dependency 'databricks' is not installed. Some functionalities may not be available.")
13
+ _DATABRICKS_AVAILABLE = False
12
14
 
13
15
  from ..formatters import DictFormatter
14
16
 
@@ -60,9 +62,12 @@ class UnityCatalogHandler(logging.Handler):
60
62
  self.warehouse_id = cast(str, warehouse_id)
61
63
  if not all([self.catalog, self.schema, self.table, self.warehouse_id, self.workspace_url]):
62
64
  raise ValueError(
63
- "You must provide a workspace_url, warehouse_id, catalog, schema, and table to create a DatabricksHandler."
65
+ "You must provide a workspace_url, warehouse_id, catalog,"
66
+ " schema, and table to create a DatabricksHandler."
64
67
  )
65
68
  self.table_identifier = f"{self.catalog}.{self.schema}.{self.table}"
69
+ if not _DATABRICKS_AVAILABLE:
70
+ raise ImportError("Databricks SDK is not installed. Install it with: pip install cloe-logging[databricks]")
66
71
  self.workspace_client = workspace_client or WorkspaceClient(host=self.workspace_url)
67
72
  super().__init__(**kwargs)
68
73
  self.setFormatter(
@@ -136,8 +141,7 @@ class UnityCatalogHandler(logging.Handler):
136
141
  timestamp = split_values[0]
137
142
  casted_timestamp = f"to_timestamp({timestamp}, 'yyyy-MM-dd HH:mm:ss,SSS')"
138
143
  joined_values = ", ".join([casted_timestamp] + split_values[1:])
139
- sql_statement = f"INSERT INTO {self.table_identifier} ({columns}) VALUES ({joined_values})"
140
- return sql_statement
144
+ return f"INSERT INTO {self.table_identifier} ({columns}) VALUES ({joined_values})"
141
145
 
142
146
  def emit(self, record: logging.LogRecord) -> None:
143
147
  """Put a log record into the Queue.
@@ -1,7 +1,8 @@
1
1
  import logging
2
2
  from collections.abc import Callable
3
+ from typing import cast
3
4
 
4
- from cloe_logging.handlers import UnityCatalogHandler, SnowflakeHandler, LogAnalyticsHandler
5
+ from cloe_logging.handlers import LogAnalyticsHandler, SnowflakeHandler, UnityCatalogHandler
5
6
 
6
7
 
7
8
  class LoggerFactory:
@@ -47,18 +48,18 @@ class LoggerFactory:
47
48
  log_format: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
48
49
  **kwargs,
49
50
  ) -> logging.Handler:
50
- HANDLER_FUNCTIONS: dict[str, Callable] = {
51
+ handler_functions: dict[str, Callable] = {
51
52
  "console": LoggerFactory.get_console_handler,
52
53
  "file": LoggerFactory.get_file_handler,
53
54
  "unity_catalog": LoggerFactory.get_unity_catalog_handler,
54
55
  "snowflake": LoggerFactory.get_snowflake_handler,
55
56
  "log_analytics": LoggerFactory.get_log_analytics_handler,
56
57
  }
57
- handler = HANDLER_FUNCTIONS[handler_type](**kwargs, log_format=log_format)
58
- return handler
58
+ handler = handler_functions[handler_type](**kwargs, log_format=log_format)
59
+ return cast(logging.Handler, handler)
59
60
 
60
61
  @staticmethod
61
- def get_console_handler(log_format: str, **kwargs) -> logging.Handler:
62
+ def get_console_handler(log_format: str, **kwargs) -> logging.Handler: # noqa: ARG004
62
63
  handler = logging.StreamHandler()
63
64
  handler.setFormatter(logging.Formatter(log_format))
64
65
  return handler
@@ -70,7 +71,7 @@ class LoggerFactory:
70
71
  mode: str = "a",
71
72
  encoding: str | None = None,
72
73
  delay: bool = False,
73
- **kwargs,
74
+ **kwargs, # noqa: ARG004
74
75
  ) -> logging.Handler:
75
76
  if filename is None:
76
77
  raise ValueError("filename is required for file logger")
@@ -89,7 +90,7 @@ class LoggerFactory:
89
90
  warehouse_id: str,
90
91
  column_split_char: str = DEFAULT_COLUMN_SPLIT_CHAR,
91
92
  key_value_split_char: str = DEFAULT_KEY_VALUE_SPLIT_CHAR,
92
- **kwargs,
93
+ **kwargs, # noqa: ARG003
93
94
  ) -> logging.Handler:
94
95
  return UnityCatalogHandler(
95
96
  catalog=uc_catalog_name,
@@ -110,7 +111,7 @@ class LoggerFactory:
110
111
  target_table: str,
111
112
  column_split_char: str = DEFAULT_COLUMN_SPLIT_CHAR,
112
113
  key_value_split_char: str = DEFAULT_KEY_VALUE_SPLIT_CHAR,
113
- **kwargs,
114
+ **kwargs, # noqa: ARG003
114
115
  ) -> logging.Handler:
115
116
  return SnowflakeHandler(
116
117
  target_db=target_db,
@@ -129,7 +130,7 @@ class LoggerFactory:
129
130
  test_connectivity: bool,
130
131
  column_split_char: str = DEFAULT_COLUMN_SPLIT_CHAR,
131
132
  key_value_split_char: str = DEFAULT_KEY_VALUE_SPLIT_CHAR,
132
- **kwargs,
133
+ **kwargs, # noqa: ARG003
133
134
  ) -> logging.Handler:
134
135
  return LogAnalyticsHandler(
135
136
  workspace_id=workspace_id,
@@ -152,7 +153,7 @@ class LoggerFactory:
152
153
  The logger with the handler added.
153
154
  """
154
155
  if len(logger.handlers) > 0:
155
- if not any([isinstance(h, handler.__class__) for h in logger.handlers]):
156
+ if not any(isinstance(h, handler.__class__) for h in logger.handlers):
156
157
  logger.addHandler(handler)
157
158
  else:
158
159
  logger.addHandler(handler)
@@ -49,7 +49,8 @@ class DictSerializer(LogSerializer):
49
49
  dict: The converted dictionary.
50
50
 
51
51
  Raises:
52
- ValueError: If the log_record is not a string, or if any part of the log_record does not contain the key_value_split_char.
52
+ ValueError: If the log_record is not a string, or if any part of the
53
+ log_record does not contain the key_value_split_char.
53
54
  """
54
55
  if not isinstance(log_record, str):
55
56
  raise ValueError("record must be a string.")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloe-logging
3
- Version: 0.3.8
3
+ Version: 0.3.10
4
4
  Summary: A Standardized Solution for logging to various targets.
5
5
  Author-email: David Achilles <david.achilles@accenture.com>, Ole Steinbrueck <ole.steinbrueck@accenture.com>
6
6
  License: Proprietary
@@ -12,7 +12,7 @@ Classifier: Operating System :: OS Independent
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
14
  Classifier: Topic :: Database
15
- Requires-Python: <3.13,>=3.11
15
+ Requires-Python: <3.14,>=3.11
16
16
  Requires-Dist: pydantic<3.0.0,>=2.7.0
17
17
  Requires-Dist: typing-extensions<5.0.0,>=4.12.2
18
18
  Provides-Extra: databricks
@@ -0,0 +1,17 @@
1
+ cloe_logging/__init__.py,sha256=3rsW-XtJbAaENMtN9ah2qRZyQnZOtqTnkCE_OqXBLNw,74
2
+ cloe_logging/logger_factory.py,sha256=3H_5_Ry-l2ap2-aGe-bkh9lmDcHr0a81qLN8X7mkXaA,5666
3
+ cloe_logging/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ cloe_logging/decorators/__init__.py,sha256=ZFfADCScnpZ3ofxNgle1UybF322cdH9vuIGCx3S9wUU,71
5
+ cloe_logging/decorators/devops_decorator.py,sha256=npuOLa2HLxPlhTN9HMa_EBqyVWQxv8HvlTtaICyfVRw,1961
6
+ cloe_logging/formatters/__init__.py,sha256=1hhmT6qeIGuom63oHrg_2SHQZpLWG2GclMSTmF-fR_g,136
7
+ cloe_logging/formatters/devops_formatter.py,sha256=EeTgN932jGisW1Q_z9RXdd0yvXuOgbN-CuFaSQ3usss,3315
8
+ cloe_logging/formatters/dict_formatter.py,sha256=QGUcCx3KrCAXFGkYD3SY4s13k0OIgSBn6fhijgJ4m0Y,1553
9
+ cloe_logging/handlers/__init__.py,sha256=5RTIz8UooLgVc9h5GnXvI2yF-FkOKiJBfHbSKHKitRE,236
10
+ cloe_logging/handlers/log_analytics_handler.py,sha256=gPTKS0l3EaB7pZWUSr42cOQT99m8Vj0KeQlaNA6UDfI,9199
11
+ cloe_logging/handlers/snowflake_handler.py,sha256=gdFdTlXhi7FHbJJRIhmuFwll6WflgVZ-SxendEfQUxI,5206
12
+ cloe_logging/handlers/unity_catalog_handler.py,sha256=5_-AwlcjCz2Mddk4J0L7Y2iDaTmdISTZsxmnQgnBhcI,7047
13
+ cloe_logging/utility/__init__.py,sha256=wp758l5P1M20bNUbbGojSkBUscFUgRd_TLLdnHgQ_l8,70
14
+ cloe_logging/utility/serializer.py,sha256=a_XNHC3DTPongLXcEBp7UCvVdmdjT-qAQ9ZHubCV0oI,2656
15
+ cloe_logging-0.3.10.dist-info/METADATA,sha256=SONYSRL1RM-_3fPSdyNKs2YBvinc-DV4Ddr5YNj1a-E,2488
16
+ cloe_logging-0.3.10.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
17
+ cloe_logging-0.3.10.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,17 +0,0 @@
1
- cloe_logging/__init__.py,sha256=3rsW-XtJbAaENMtN9ah2qRZyQnZOtqTnkCE_OqXBLNw,74
2
- cloe_logging/logger_factory.py,sha256=az_XcRSrUCge4yG3HXNqFPSPRJ0V8EMKmjPPl54UIms,5541
3
- cloe_logging/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- cloe_logging/decorators/__init__.py,sha256=ZFfADCScnpZ3ofxNgle1UybF322cdH9vuIGCx3S9wUU,71
5
- cloe_logging/decorators/devops_decorator.py,sha256=1jCfNa22lU87u-QPNUt6fVLJOCINhZncYz76UjUh2XE,1959
6
- cloe_logging/formatters/__init__.py,sha256=0FbiRRJbo4zYgNb2QSxY5aGthu8evt9Gex5c_-jxCIs,136
7
- cloe_logging/formatters/devops_formatter.py,sha256=KwarCm_EPpRV-cZk6nGM3GZVNKN39FNOofXfC0KfkQg,3301
8
- cloe_logging/formatters/dict_formatter.py,sha256=PsbNXxdCZxtEC9g-nIukhdQwCcsCfz42EumHPHFt9-4,1553
9
- cloe_logging/handlers/__init__.py,sha256=xgYTK6qXJEgNFPZE6yHXwS1o9bmGuQQZ7so_7BncW7A,236
10
- cloe_logging/handlers/log_analytics_handler.py,sha256=2Z-Hg2mWgvqAbO3nvego9AjDy3PGgzPQOxVWL7x5GAY,9038
11
- cloe_logging/handlers/snowflake_handler.py,sha256=bZR5UIJIlivAJT3IeniVoFXlsQhq5-YDuSUH4qrXeL0,5054
12
- cloe_logging/handlers/unity_catalog_handler.py,sha256=aXIiwDq9tHHheAFMusHhEI9uvYpI39KCscuVntFvNLA,6879
13
- cloe_logging/utility/__init__.py,sha256=wp758l5P1M20bNUbbGojSkBUscFUgRd_TLLdnHgQ_l8,70
14
- cloe_logging/utility/serializer.py,sha256=uPdmpawqM3WXZQVxz63deCalvKJYxRNecxjBQeDzTIY,2639
15
- cloe_logging-0.3.8.dist-info/METADATA,sha256=Q99bSKcf_De64RBjVtSY-Y-T7RmuBPHpWMVSd9E04YM,2487
16
- cloe_logging-0.3.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
17
- cloe_logging-0.3.8.dist-info/RECORD,,