cloe-logging 0.3.9__py3-none-any.whl → 0.3.11__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.
@@ -9,8 +9,8 @@ class DevOpsFormatter(logging.Formatter):
9
9
  info_format = "%(message)s" # "%(name)s -- %(message)s"
10
10
  section_format = "%(name)s -- %(message)s"
11
11
 
12
- def __init__(self, fmt="%(levelno)s: %(msg)s", section_info=False):
13
- super().__init__(fmt=fmt)
12
+ def __init__(self, fmt="%(levelno)s: %(msg)s", datefmt=None, section_info=False):
13
+ super().__init__(fmt=fmt, datefmt=datefmt)
14
14
  self._section_info = section_info
15
15
 
16
16
  def parse_progress(self, message: str) -> str:
@@ -7,9 +7,11 @@ 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,6 +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 = ":",
42
+ datefmt: str | None = None,
40
43
  **kwargs, # noqa: ARG002 required to work with the Factory
41
44
  ):
42
45
  """Initializes a new instance of the LogAnalyticsHandler class.
@@ -48,6 +51,7 @@ class LogAnalyticsHandler(logging.Handler):
48
51
  column_split_char (str, optional): The character used to split columns in the log message. Defaults to "|".
49
52
  key_value_split_char (str, optional): The character used to split keys and values in the log message.
50
53
  Defaults to ":".
54
+ datefmt (str, optional): The format of the date/time in log messages. If None, uses the default format.
51
55
  test_connectivity (bool, optional): Whether to test connectivity to Azure Log Analytics when initializing
52
56
  the handler. Defaults to True.
53
57
  """
@@ -60,9 +64,13 @@ class LogAnalyticsHandler(logging.Handler):
60
64
  raise ValueError(
61
65
  "The workspace_id, shared_key, and log_type must be provided or set as environment variables."
62
66
  )
67
+ if not _REQUESTS_AVAILABLE:
68
+ raise ImportError(
69
+ "Requests library is not installed. Install it with: pip install cloe-logging[log-analytics]"
70
+ )
63
71
  logging.Handler.__init__(self)
64
72
  self.session = requests.Session()
65
- formatter = logging.Formatter("timestamp:%(asctime)s | level: %(levelname)-8s | %(message)s")
73
+ formatter = logging.Formatter("timestamp:%(asctime)s | level: %(levelname)-8s | %(message)s", datefmt=datefmt)
66
74
  self.setFormatter(formatter)
67
75
  self.serializer = create_logserializer()
68
76
  self.serializer.column_split_char = self.column_split_char
@@ -6,10 +6,12 @@ try:
6
6
  ConnectionParameters,
7
7
  )
8
8
  from cloe_util_snowflake_connector.snowflake_interface import SnowflakeInterface # type: ignore[import-not-found]
9
+
10
+ _SNOWFLAKE_AVAILABLE = True
9
11
  except ImportError:
10
12
  ConnectionParameters = None # type: ignore
11
13
  SnowflakeInterface = None # type: ignore
12
- print("Optional dependency 'snowflake' is not installed. Some functionalities may not be available.")
14
+ _SNOWFLAKE_AVAILABLE = False
13
15
  from cloe_logging.utility.serializer import create_logserializer
14
16
 
15
17
 
@@ -26,6 +28,7 @@ class SnowflakeHandler(logging.Handler):
26
28
  target_table: str = "",
27
29
  column_split_char: str = "|",
28
30
  key_value_split_char: str = ":",
31
+ datefmt: str | None = None,
29
32
  **kwargs, # noqa: ARG002 required to work with the Factory
30
33
  ):
31
34
  """Initializes a new instance of the SnowflakeHandler class.
@@ -37,6 +40,7 @@ class SnowflakeHandler(logging.Handler):
37
40
  column_split_char (str, optional): The character used to split columns in the log message. Defaults to "|".
38
41
  key_value_split_char (str, optional): The character used to split keys and values in the log message.
39
42
  Defaults to ":".
43
+ datefmt (str, optional): The format of the date/time in log messages. If None, uses the default format.
40
44
  """
41
45
  self.column_split_char: str = column_split_char
42
46
  self.key_value_split_char: str = key_value_split_char
@@ -45,7 +49,7 @@ class SnowflakeHandler(logging.Handler):
45
49
  self.target_table: str = os.environ.get("CLOE_SNOWFLAKE_TABLE", target_table)
46
50
  logging.Handler.__init__(self)
47
51
  self.connection = self._get_snowflake_connection()
48
- formatter = logging.Formatter("timestamp:%(asctime)s | level: %(levelname)-8s | %(message)s")
52
+ formatter = logging.Formatter("timestamp:%(asctime)s | level: %(levelname)-8s | %(message)s", datefmt=datefmt)
49
53
  self.setFormatter(formatter)
50
54
  self.serializer = create_logserializer()
51
55
 
@@ -80,6 +84,10 @@ class SnowflakeHandler(logging.Handler):
80
84
  return hash((self.target_db, self.target_schema, self.target_table))
81
85
 
82
86
  def _get_snowflake_connection(self) -> SnowflakeInterface:
87
+ if not _SNOWFLAKE_AVAILABLE:
88
+ raise ImportError(
89
+ "Snowflake dependencies are not installed. Install them with: pip install cloe-logging[snowflake]"
90
+ )
83
91
  conn_params = ConnectionParameters.init_from_env_variables()
84
92
  return SnowflakeInterface(conn_params)
85
93
 
@@ -1,14 +1,17 @@
1
1
  import json
2
2
  import logging
3
- from typing import cast
3
+ from typing import TYPE_CHECKING, cast
4
4
 
5
5
  try:
6
6
  from databricks.sdk import WorkspaceClient # type: ignore[import-not-found]
7
7
  from databricks.sdk.service.sql import ExecuteStatementRequestOnWaitTimeout # type: ignore[import-not-found]
8
+
9
+ _DATABRICKS_AVAILABLE = True
8
10
  except ImportError:
9
- WorkspaceClient = None # type: ignore
10
- ExecuteStatementRequestOnWaitTimeout = None # type: ignore
11
- print("Optional dependency 'databricks' is not installed. Some functionalities may not be available.")
11
+ _DATABRICKS_AVAILABLE = False
12
+
13
+ if TYPE_CHECKING:
14
+ from databricks.sdk import WorkspaceClient # type: ignore[import-not-found]
12
15
 
13
16
  from ..formatters import DictFormatter
14
17
 
@@ -29,7 +32,8 @@ class UnityCatalogHandler(logging.Handler):
29
32
  warehouse_id: str | None = None,
30
33
  column_split_char: str = "|",
31
34
  key_value_split_char: str = ":",
32
- workspace_client: WorkspaceClient | None = None,
35
+ datefmt: str | None = None,
36
+ workspace_client: "WorkspaceClient | None" = None,
33
37
  formatter: DictFormatter | None = None,
34
38
  **kwargs, # required to work with the Factory
35
39
  ):
@@ -48,6 +52,7 @@ class UnityCatalogHandler(logging.Handler):
48
52
  warehouse_id: The ID of the Databricks warehouse.
49
53
  column_split_char: The character used to split columns in the log message. Defaults to "|".
50
54
  key_value_split_char: The character used to split keys and values in the log message. Defaults to ":".
55
+ datefmt: The format of the date/time in log messages. If None, uses the default format.
51
56
  workspace_client: An instance of WorkspaceClient for dependency injection.
52
57
  formatter: An instance of DictFormatter for dependency injection.
53
58
  """
@@ -64,10 +69,15 @@ class UnityCatalogHandler(logging.Handler):
64
69
  " schema, and table to create a DatabricksHandler."
65
70
  )
66
71
  self.table_identifier = f"{self.catalog}.{self.schema}.{self.table}"
72
+ if not _DATABRICKS_AVAILABLE:
73
+ raise ImportError("Databricks SDK is not installed. Install it with: pip install cloe-logging[databricks]")
67
74
  self.workspace_client = workspace_client or WorkspaceClient(host=self.workspace_url)
68
75
  super().__init__(**kwargs)
69
76
  self.setFormatter(
70
- formatter or DictFormatter(column_split_char=column_split_char, key_value_split_char=key_value_split_char)
77
+ formatter
78
+ or DictFormatter(
79
+ column_split_char=column_split_char, key_value_split_char=key_value_split_char, datefmt=datefmt
80
+ )
71
81
  )
72
82
  self.ensure_table_exists(columns)
73
83
 
@@ -15,6 +15,7 @@ class LoggerFactory:
15
15
  logger_name: str = __name__,
16
16
  logging_level: int = logging.INFO,
17
17
  log_format: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
18
+ datefmt: str | None = None,
18
19
  **kwargs,
19
20
  ) -> logging.Logger:
20
21
  """Creates a logger with the specified handler types.
@@ -24,6 +25,7 @@ class LoggerFactory:
24
25
  logger_name: The name of the logger.
25
26
  logging_level: The logging level for the logger.
26
27
  log_format: The format of the log messages.
28
+ datefmt: The format of the date/time in log messages. If None, uses the default format.
27
29
  kwargs: Additional arguments to pass to the handler.
28
30
 
29
31
  Note:
@@ -38,7 +40,7 @@ class LoggerFactory:
38
40
  handler_types = [handler_types]
39
41
 
40
42
  for handler_type in handler_types:
41
- handler = LoggerFactory.get_handler(handler_type, log_format, **kwargs)
43
+ handler = LoggerFactory.get_handler(handler_type, log_format, datefmt=datefmt, **kwargs)
42
44
  LoggerFactory.add_handler_if_not_exists(logger, handler)
43
45
  return logger
44
46
 
@@ -46,6 +48,7 @@ class LoggerFactory:
46
48
  def get_handler(
47
49
  handler_type: str,
48
50
  log_format: str = "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
51
+ datefmt: str | None = None,
49
52
  **kwargs,
50
53
  ) -> logging.Handler:
51
54
  handler_functions: dict[str, Callable] = {
@@ -55,18 +58,19 @@ class LoggerFactory:
55
58
  "snowflake": LoggerFactory.get_snowflake_handler,
56
59
  "log_analytics": LoggerFactory.get_log_analytics_handler,
57
60
  }
58
- handler = handler_functions[handler_type](**kwargs, log_format=log_format)
61
+ handler = handler_functions[handler_type](**kwargs, log_format=log_format, datefmt=datefmt)
59
62
  return cast(logging.Handler, handler)
60
63
 
61
64
  @staticmethod
62
- def get_console_handler(log_format: str, **kwargs) -> logging.Handler: # noqa: ARG004
65
+ def get_console_handler(log_format: str, datefmt: str | None = None, **kwargs) -> logging.Handler: # noqa: ARG004
63
66
  handler = logging.StreamHandler()
64
- handler.setFormatter(logging.Formatter(log_format))
67
+ handler.setFormatter(logging.Formatter(log_format, datefmt=datefmt))
65
68
  return handler
66
69
 
67
70
  @staticmethod
68
71
  def get_file_handler(
69
72
  log_format: str,
73
+ datefmt: str | None = None,
70
74
  filename: str | None = None,
71
75
  mode: str = "a",
72
76
  encoding: str | None = None,
@@ -76,7 +80,7 @@ class LoggerFactory:
76
80
  if filename is None:
77
81
  raise ValueError("filename is required for file logger")
78
82
  handler = logging.FileHandler(filename, mode, encoding, delay)
79
- handler.setFormatter(logging.Formatter(log_format))
83
+ handler.setFormatter(logging.Formatter(log_format, datefmt=datefmt))
80
84
  return handler
81
85
 
82
86
  @classmethod
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cloe-logging
3
- Version: 0.3.9
3
+ Version: 0.3.11
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
@@ -1,17 +1,17 @@
1
1
  cloe_logging/__init__.py,sha256=3rsW-XtJbAaENMtN9ah2qRZyQnZOtqTnkCE_OqXBLNw,74
2
- cloe_logging/logger_factory.py,sha256=3H_5_Ry-l2ap2-aGe-bkh9lmDcHr0a81qLN8X7mkXaA,5666
2
+ cloe_logging/logger_factory.py,sha256=XnC6hhr--_2Zwk--G7OHqcWfip_SF2p-RRAL7NQMvfk,5970
3
3
  cloe_logging/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  cloe_logging/decorators/__init__.py,sha256=ZFfADCScnpZ3ofxNgle1UybF322cdH9vuIGCx3S9wUU,71
5
5
  cloe_logging/decorators/devops_decorator.py,sha256=npuOLa2HLxPlhTN9HMa_EBqyVWQxv8HvlTtaICyfVRw,1961
6
6
  cloe_logging/formatters/__init__.py,sha256=1hhmT6qeIGuom63oHrg_2SHQZpLWG2GclMSTmF-fR_g,136
7
- cloe_logging/formatters/devops_formatter.py,sha256=EeTgN932jGisW1Q_z9RXdd0yvXuOgbN-CuFaSQ3usss,3315
7
+ cloe_logging/formatters/devops_formatter.py,sha256=Sgf8eUj4AqP9kfMR4N-VKMPnGAl9KeSgmp09xzX-6Po,3346
8
8
  cloe_logging/formatters/dict_formatter.py,sha256=QGUcCx3KrCAXFGkYD3SY4s13k0OIgSBn6fhijgJ4m0Y,1553
9
9
  cloe_logging/handlers/__init__.py,sha256=5RTIz8UooLgVc9h5GnXvI2yF-FkOKiJBfHbSKHKitRE,236
10
- cloe_logging/handlers/log_analytics_handler.py,sha256=x5gX98srlvBsEFmIWTISzO0v1Fx-O6CfsBDvyigA4YI,9048
11
- cloe_logging/handlers/snowflake_handler.py,sha256=TWctiCR10UacVrkDCIF6Z1GvuhfhC7iIpNefzdTgd0Q,5049
12
- cloe_logging/handlers/unity_catalog_handler.py,sha256=DabwGA-2_F1BGGUZnEA9YMSIPmeaUkhkKjo3Fm-rXps,6928
10
+ cloe_logging/handlers/log_analytics_handler.py,sha256=YMm9CgUluXC0dziNnAlIokP_lDdN7N1L1v61iIWCmWs,9370
11
+ cloe_logging/handlers/snowflake_handler.py,sha256=9AdgQbpx2x_KRbmuAB6rT4ZYJEdP0y_n_grL324cXSY,5375
12
+ cloe_logging/handlers/unity_catalog_handler.py,sha256=55bzN5WpZodvwXF6v9Tc7pvpGXoW0m2RAFHrba001F0,7252
13
13
  cloe_logging/utility/__init__.py,sha256=wp758l5P1M20bNUbbGojSkBUscFUgRd_TLLdnHgQ_l8,70
14
14
  cloe_logging/utility/serializer.py,sha256=a_XNHC3DTPongLXcEBp7UCvVdmdjT-qAQ9ZHubCV0oI,2656
15
- cloe_logging-0.3.9.dist-info/METADATA,sha256=QsOVBzsajELGWn-VhU9_uLYuVAEfAuYA7q5fcv7-GpQ,2487
16
- cloe_logging-0.3.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
17
- cloe_logging-0.3.9.dist-info/RECORD,,
15
+ cloe_logging-0.3.11.dist-info/METADATA,sha256=5cvMi8OEqTu5lH8_ZFPRhvMbqsuxn1Wiq_-GSGzPr-U,2488
16
+ cloe_logging-0.3.11.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
17
+ cloe_logging-0.3.11.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