orionis 0.77.0__py3-none-any.whl → 0.78.0__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.
orionis/framework.py CHANGED
@@ -5,7 +5,7 @@
5
5
  NAME = "orionis"
6
6
 
7
7
  # Current version of the framework
8
- VERSION = "0.77.0"
8
+ VERSION = "0.78.0"
9
9
 
10
10
  # Full name of the author or maintainer of the project
11
11
  AUTHOR = "Raul Mauricio Uñate Castro"
@@ -1,8 +1,9 @@
1
1
  from dataclasses import dataclass, field
2
- from typing import Any, Dict, Union
2
+ from datetime import time
3
+ from typing import Dict, Union
3
4
 
4
5
  @dataclass
5
- class Single:
6
+ class Stack:
6
7
  """
7
8
  Represents a single log file configuration.
8
9
 
@@ -17,7 +18,25 @@ class Single:
17
18
  """
18
19
  path: str
19
20
  level: str
20
- stream: bool
21
+
22
+
23
+ @dataclass
24
+ class Hourly:
25
+ """
26
+ Represents an hourly log file rotation configuration.
27
+
28
+ Attributes
29
+ ----------
30
+ path : str
31
+ The file path where hourly logs are stored.
32
+ level : str
33
+ The logging level (e.g., 'info', 'error', 'debug').
34
+ retention_hours : int
35
+ The number of hours to retain log files before deletion.
36
+ """
37
+ path: str
38
+ level: str
39
+ retention_hours: int
21
40
 
22
41
 
23
42
  @dataclass
@@ -31,15 +50,53 @@ class Daily:
31
50
  The file path where daily logs are stored.
32
51
  level : str
33
52
  The logging level (e.g., 'info', 'error', 'debug').
34
- days : int
53
+ retention_days : int
35
54
  The number of days to retain log files before deletion.
36
- stream : bool
37
- Whether to output logs to the console.
55
+ at_time : time
56
+ The time of day when the log rotation should occur.
57
+ """
58
+ path: str
59
+ level: str
60
+ retention_days: int
61
+ at: time
62
+
63
+
64
+ @dataclass
65
+ class Weekly:
66
+ """
67
+ Represents a weekly log file rotation configuration.
68
+
69
+ Attributes
70
+ ----------
71
+ path : str
72
+ The file path where weekly logs are stored.
73
+ level : str
74
+ The logging level (e.g., 'info', 'error', 'debug').
75
+ retention_weeks : int
76
+ The number of weeks to retain log files before deletion.
77
+ """
78
+ path: str
79
+ level: str
80
+ retention_weeks: int
81
+
82
+
83
+ @dataclass
84
+ class Monthly:
85
+ """
86
+ Represents a monthly log file rotation configuration.
87
+
88
+ Attributes
89
+ ----------
90
+ path : str
91
+ The file path where monthly logs are stored.
92
+ level : str
93
+ The logging level (e.g., 'info', 'error', 'debug').
94
+ retention_months : int
95
+ The number of months to retain log files before deletion.
38
96
  """
39
97
  path: str
40
98
  level: str
41
- days: int
42
- stream: bool
99
+ retention_months: int
43
100
 
44
101
 
45
102
  @dataclass
@@ -56,20 +113,16 @@ class Chunked:
56
113
  The file path where chunked logs are stored.
57
114
  level : str
58
115
  The logging level (e.g., 'info', 'error', 'debug').
59
- max_size : Union[int, str]
116
+ max_mb_size : Union[int, str]
60
117
  The maximum file size before creating a new chunk.
61
118
  Can be an integer (bytes) or a string (e.g., '10MB', '500KB').
62
119
  max_files : int
63
120
  The maximum number of log files to retain before older files are deleted.
64
- stream : bool
65
- Whether to output logs to the console.
66
121
  """
67
-
68
122
  path: str
69
123
  level: str
70
- max_size: Union[int, str] # Supports both numeric and formatted string sizes ('10MB')
71
- max_files: int # Ensures only a certain number of log files are kept
72
- stream: bool
124
+ mb_size: Union[int, str]
125
+ files: int
73
126
 
74
127
 
75
128
  @dataclass
@@ -86,9 +139,12 @@ class Channels:
86
139
  chunked : Chunked
87
140
  Configuration for chunked log file storage.
88
141
  """
89
- single: Single
90
- daily: Daily
91
- chunked: Chunked
142
+ stack = Stack
143
+ hourly = Hourly
144
+ daily = Daily
145
+ weekly = Weekly
146
+ monthly = Monthly
147
+ chunked = Chunked
92
148
 
93
149
 
94
150
  @dataclass
@@ -1,8 +1,11 @@
1
- import os
2
1
  import logging
2
+ import os
3
+ import re
4
+ from datetime import datetime
5
+ from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler
3
6
  from pathlib import Path
4
- from typing import Optional
5
7
  from orionis.contracts.services.log.i_log_service import ILogguerService
8
+ from orionis.luminate.services.config.config_service import ConfigService
6
9
 
7
10
  class LogguerService(ILogguerService):
8
11
  """
@@ -18,10 +21,10 @@ class LogguerService(ILogguerService):
18
21
 
19
22
  Methods
20
23
  -------
21
- __init__(path: Optional[str] = None, level: int = logging.INFO, filename: Optional[str] = 'orionis.log')
22
- Initializes the logger with the specified path, log level, and filename.
23
- _initialize_logger(path: Optional[str], level: int, filename: Optional[str] = 'orionis.log')
24
- Configures the logger with the specified settings.
24
+ __init__(config_service: ConfigService)
25
+ Initializes the logger with ConfigService
26
+ _initialize_logger(config_service: ConfigService)
27
+ Configures the logger with ConfigService settings.
25
28
  info(message: str) -> None
26
29
  Logs an informational message.
27
30
  error(message: str) -> None
@@ -34,24 +37,32 @@ class LogguerService(ILogguerService):
34
37
  Logs a debug message.
35
38
  """
36
39
 
37
- def __init__(self, path: Optional[str] = None, level: int = logging.INFO, filename: Optional[str] = 'orionis.log'):
40
+ def __init__(self, config_service : ConfigService):
38
41
  """
39
42
  Initializes the logger with the specified path, log level, and filename.
40
43
 
41
44
  Parameters
42
45
  ----------
43
- path : Optional[str]
44
- The directory path where the log file will be stored. If not provided,
45
- it defaults to a 'logs' directory inside the 'storage' folder of the
46
- current working directory.
47
- level : int
48
- The logging level (e.g., logging.INFO, logging.ERROR). Defaults to logging.INFO.
49
- filename : Optional[str]
50
- The name of the log file. Defaults to 'orionis.log'.
46
+ config_service : ConfigService
47
+ The configuration service instance.
48
+ """
49
+ self.config_service = config_service
50
+ self._initialize_logger()
51
+
52
+ def _path_resolver(self, filename: str):
51
53
  """
52
- self._initialize_logger(path, level, filename)
54
+ Resolves the log file path based on the specified filename.
55
+ """
56
+ base_path = Path(os.getcwd())
57
+ log_dir = base_path / "storage" / "logs"
58
+
59
+ # Create the log directory if it does not exist
60
+ if not log_dir.exists():
61
+ log_dir.mkdir(parents=True, exist_ok=True)
62
+
63
+ return log_dir / filename
53
64
 
54
- def _initialize_logger(self, path: Optional[str], level: int, filename: Optional[str] = 'orionis.log'):
65
+ def _initialize_logger(self):
55
66
  """
56
67
  Configures the logger with the specified settings.
57
68
 
@@ -61,12 +72,8 @@ class LogguerService(ILogguerService):
61
72
 
62
73
  Parameters
63
74
  ----------
64
- path : Optional[str]
65
- The directory path where the log file will be stored.
66
- level : int
67
- The logging level (e.g., logging.INFO, logging.ERROR).
68
- filename : Optional[str]
69
- The name of the log file.
75
+ config_service : ConfigService
76
+ The configuration service instance.
70
77
 
71
78
  Raises
72
79
  ------
@@ -74,27 +81,112 @@ class LogguerService(ILogguerService):
74
81
  If the logger cannot be initialized due to an error.
75
82
  """
76
83
  try:
77
- # Resolve the log directory and file path
78
- if path is None:
79
- base_path = Path(os.getcwd())
80
- log_dir = base_path / "storage" / "logs"
81
84
 
82
- # Create the log directory if it does not exist
83
- if not log_dir.exists():
84
- log_dir.mkdir(parents=True, exist_ok=True)
85
+ channel : str = self.config_service.get("logging.default")
86
+ config : dict = self.config_service.get(f"logging.channels.{channel}", {})
87
+ path : str = config.get("path", 'logs/orionis.log')
88
+ app_timezone : str = self.config_service.get("app.timezone", "UTC")
89
+
90
+ if channel == "stack":
91
+
92
+ handlers = [
93
+ logging.FileHandler(
94
+ filename=self._path_resolver(path),
95
+ encoding="utf-8"
96
+ )
97
+ ]
98
+
99
+ elif channel == "hourly":
100
+
101
+ handlers = [
102
+ TimedRotatingFileHandler(
103
+ filename=self._path_resolver(path),
104
+ when="h",
105
+ interval=1,
106
+ backupCount=config.get('retention_hours', 24),
107
+ encoding="utf-8",
108
+ utc= True if app_timezone == "UTC" else False
109
+ )
110
+ ]
111
+
112
+ elif channel == "daily":
113
+
114
+ backup_count : str = config.get('retention_days', 30)
115
+ hour_at : str = config.get('at', "00:00")
116
+ if backup_count < 1 or not backup_count.isdigit():
117
+ raise ValueError("The 'retention_days' value must be an integer greater than 0.")
118
+ if not bool(re.match(r"^(?:[01]?\d|2[0-3]):[0-5]?\d$", hour_at)):
119
+ raise ValueError("The 'at' value must be a valid time in the format HH:MM.")
120
+
121
+ handlers = [
122
+ TimedRotatingFileHandler(
123
+ filename=self._path_resolver(path),
124
+ when="d",
125
+ interval=1,
126
+ backupCount=backup_count,
127
+ encoding="utf-8",
128
+ atTime=datetime.strptime(hour_at, "%H:%M").time(),
129
+ utc= True if app_timezone == "UTC" else False
130
+ )
131
+ ]
132
+
133
+ elif channel == "weekly":
134
+
135
+ backup_count : str = config.get('retention_weeks', 4)
136
+ if backup_count < 1 or not backup_count.isdigit():
137
+ raise ValueError("The 'retention_weeks' value must be an integer greater than 0.")
138
+ handlers = [
139
+ TimedRotatingFileHandler(
140
+ filename=self._path_resolver(path),
141
+ when="w0",
142
+ interval=1,
143
+ backupCount=backup_count,
144
+ encoding="utf-8",
145
+ utc= True if app_timezone == "UTC" else False
146
+ )
147
+ ]
148
+
149
+ elif channel == "monthly":
150
+
151
+ backup_count : str = config.get('retention_months', 2)
152
+ if backup_count < 1 or not backup_count.isdigit():
153
+ raise ValueError("The 'retention_months' value must be an integer greater than 0.")
154
+ handlers = [
155
+ TimedRotatingFileHandler(
156
+ filename=self._path_resolver(path),
157
+ when="midnight",
158
+ interval=30,
159
+ backupCount=backup_count,
160
+ encoding="utf-8",
161
+ utc= True if app_timezone == "UTC" else False
162
+ )
163
+ ]
164
+
165
+ elif channel == "chunked":
166
+
167
+ max_bytes : str = config.get('mb_size', 5).replace("MB", "")
168
+ if max_bytes < 1 or not max_bytes.isdigit():
169
+ raise ValueError("The 'mb_size' value must be an integer greater than 0.")
170
+ backup_count : str = config.get('max_files', 5)
171
+ if backup_count < 1 or not backup_count.isdigit():
172
+ raise ValueError("The 'max_files' value must be an integer greater than 0.")
173
+ handlers = [
174
+ RotatingFileHandler(
175
+ filename=self._path_resolver(path),
176
+ maxBytes= max_bytes * 1024 * 1024,
177
+ backupCount=backup_count,
178
+ encoding="utf-8"
179
+ )
180
+ ]
85
181
 
86
- path = log_dir / filename
87
182
 
88
183
  # Configure the logger
89
184
  logging.basicConfig(
90
- level=level,
185
+ level=config.get("level", "INFO").upper(),
91
186
  format="%(asctime)s - %(message)s",
92
187
  datefmt="%Y-%m-%d %H:%M:%S",
93
188
  encoding="utf-8",
94
- handlers=[
95
- logging.FileHandler(path, encoding="utf-8")
96
- # logging.StreamHandler() # Uncomment to also log to the console
97
- ]
189
+ handlers=handlers
98
190
  )
99
191
 
100
192
  # Get the logger instance
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: orionis
3
- Version: 0.77.0
3
+ Version: 0.78.0
4
4
  Summary: Orionis Framework – Elegant, Fast, and Powerful.
5
5
  Home-page: https://github.com/orionis-framework/framework
6
6
  Author: Raul Mauricio Uñate Castro
@@ -1,6 +1,6 @@
1
1
  orionis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  orionis/cli_manager.py,sha256=0bM-hABXJSoPGuvEgnqeaj9qcLP8VjTQ3z9Mb0TSEUI,1381
3
- orionis/framework.py,sha256=IFueK59k0Oi4I_rwHSuiTjwOQfrBLbjm5_0VhY8Y-Q4,1386
3
+ orionis/framework.py,sha256=M6GR_dTDAIhgQsjWISzWq42J6CbanHXfek4R1OVnad0,1386
4
4
  orionis/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  orionis/contracts/bootstrap/i_command_bootstrapper.py,sha256=cfpYWSlNhOY1q_C9o0H7F381OoM0Oh0qaeqP-c85nzk,2457
6
6
  orionis/contracts/bootstrap/i_config_bootstrapper.py,sha256=d2TXT74H2fCBbzWgrt9-ZG11S_H_YPQOEcJoIOrsgb0,4462
@@ -71,7 +71,7 @@ orionis/luminate/config/cache.py,sha256=nBKmDFDb91sbBriEsVLjMhrNb__j7YsRzZGQRDdA
71
71
  orionis/luminate/config/cors.py,sha256=zWKUylPiaUzGXTJM3eLmwY0HcAD7iOLp9QiAoTyAL08,2275
72
72
  orionis/luminate/config/database.py,sha256=oj-FQWtbwIYrJAQktSGBl96EZu78fr6IBcQxHbWDVBM,5619
73
73
  orionis/luminate/config/filesystems.py,sha256=fAn4Wx6naIb8E4U2TXJhVnx0Ipxpxc_Ee2w_FWfwlHI,2444
74
- orionis/luminate/config/logging.py,sha256=H110K6LyTCNgxZPqiGGn0z8FZ2I6kW5ZKfsVhoWB4KM,2832
74
+ orionis/luminate/config/logging.py,sha256=mx3ifEVjKNZgaRlql1D7u-KxRiewKRAbz5VDcwAubaw,4047
75
75
  orionis/luminate/config/mail.py,sha256=3iYXG72bXiVns4sEPZ_A3-cGcFjGEGDXkuLKkk-hKtY,2102
76
76
  orionis/luminate/config/queue.py,sha256=DYjP5zD09ISsIX117wtOfjiG_iQrcrPoQVeeftmuO3c,1739
77
77
  orionis/luminate/config/session.py,sha256=7mOC_DfGIBDqAClSiewHoTA9Kht_zdHApvALcZc7cfY,1861
@@ -132,7 +132,7 @@ orionis/luminate/services/environment/environment_service.py,sha256=IgrfzLELNhnE
132
132
  orionis/luminate/services/files/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
133
133
  orionis/luminate/services/files/path_resolver_service.py,sha256=E-G_E2H5QAZyxeMssARp7l1OBSxQurxkUPoKdSOCKEE,2041
134
134
  orionis/luminate/services/log/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
135
- orionis/luminate/services/log/log_service.py,sha256=aiENimOQHqaEAsBJz2_698bt1IeJjddHnledLKfg25o,5262
135
+ orionis/luminate/services/log/log_service.py,sha256=tlKnBLtJPx-LK6nQt39xYA48jcNkaJt2_Xj-wgcpfXA,8842
136
136
  orionis/luminate/support/dot_dict.py,sha256=FVHfBuAGTTVMjNG01Fix645fRNKKUMmNx61pYkxPL5c,1253
137
137
  orionis/luminate/support/exception_to_dict.py,sha256=jpQ-c7ud1JLm8dTWbvMT1dI-rL3yTB2P8VxNscAX71k,2098
138
138
  orionis/luminate/support/reflection.py,sha256=VYpluTQJ0W_m6jYQ9_L02sYFrk2wlLYtLY2yp9rZMKA,11944
@@ -153,9 +153,9 @@ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
153
153
  tests/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
154
154
  tests/tools/class_example.py,sha256=dIPD997Y15n6WmKhWoOFSwEldRm9MdOHTZZ49eF1p3c,1056
155
155
  tests/tools/test_reflection.py,sha256=bhLQ7VGVod4B8sv-rW9AjnOumvaBVsoxieA3sdoM2yM,5244
156
- orionis-0.77.0.dist-info/LICENCE,sha256=-_4cF2EBKuYVS_SQpy1uapq0oJPUU1vl_RUWSy2jJTo,1111
157
- orionis-0.77.0.dist-info/METADATA,sha256=Olf98-_eRhclDi6IPTI95YgOvLWUlFleh4UZztctlcM,2978
158
- orionis-0.77.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
159
- orionis-0.77.0.dist-info/entry_points.txt,sha256=eef1_CVewfokKjrGBynXa06KabSJYo7LlDKKIKvs1cM,53
160
- orionis-0.77.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
161
- orionis-0.77.0.dist-info/RECORD,,
156
+ orionis-0.78.0.dist-info/LICENCE,sha256=-_4cF2EBKuYVS_SQpy1uapq0oJPUU1vl_RUWSy2jJTo,1111
157
+ orionis-0.78.0.dist-info/METADATA,sha256=WDNwmK36LqcGJUK9AeNPmk-tzZ1zf0pSz47qs283Qh4,2978
158
+ orionis-0.78.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
159
+ orionis-0.78.0.dist-info/entry_points.txt,sha256=eef1_CVewfokKjrGBynXa06KabSJYo7LlDKKIKvs1cM,53
160
+ orionis-0.78.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
161
+ orionis-0.78.0.dist-info/RECORD,,