ipulse-shared-core-ftredge 6.1.2__tar.gz → 6.3.1__tar.gz

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.

Potentially problematic release.


This version of ipulse-shared-core-ftredge might be problematic. Click here for more details.

Files changed (33) hide show
  1. {ipulse_shared_core_ftredge-6.1.2/src/ipulse_shared_core_ftredge.egg-info → ipulse_shared_core_ftredge-6.3.1}/PKG-INFO +2 -2
  2. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/setup.py +2 -2
  3. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge/dependencies/authorization_api.py +1 -1
  4. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge/models/user_profile.py +4 -3
  5. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge/models/user_status.py +9 -5
  6. ipulse_shared_core_ftredge-6.3.1/src/ipulse_shared_core_ftredge/services/__init__.py +6 -0
  7. ipulse_shared_core_ftredge-6.1.2/src/ipulse_shared_core_ftredge/services/exceptions.py → ipulse_shared_core_ftredge-6.3.1/src/ipulse_shared_core_ftredge/services/base_exceptions.py +3 -1
  8. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge/services/base_firestore_service.py +3 -2
  9. ipulse_shared_core_ftredge-6.3.1/src/ipulse_shared_core_ftredge/services/fastapiservicemon.py +138 -0
  10. ipulse_shared_core_ftredge-6.3.1/src/ipulse_shared_core_ftredge/services/servicemon.py +240 -0
  11. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1/src/ipulse_shared_core_ftredge.egg-info}/PKG-INFO +2 -2
  12. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge.egg-info/SOURCES.txt +3 -1
  13. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge.egg-info/requires.txt +1 -1
  14. ipulse_shared_core_ftredge-6.1.2/src/ipulse_shared_core_ftredge/services/__init__.py +0 -4
  15. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/LICENCE +0 -0
  16. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/README.md +0 -0
  17. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/pyproject.toml +0 -0
  18. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/setup.cfg +0 -0
  19. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge/__init__.py +0 -0
  20. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge/dependencies/__init__.py +0 -0
  21. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge/dependencies/auth_router.py +0 -0
  22. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge/dependencies/database.py +0 -0
  23. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge/dependencies/token_validation.py +0 -0
  24. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge/models/__init__.py +0 -0
  25. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge/models/base_api_response.py +0 -0
  26. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge/models/base_data_model.py +0 -0
  27. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge/models/organization_profile.py +0 -0
  28. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge/models/resource_catalog_item.py +0 -0
  29. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge/models/subscription.py +0 -0
  30. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge/models/user_auth.py +0 -0
  31. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge/models/user_profile_update.py +0 -0
  32. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge.egg-info/dependency_links.txt +0 -0
  33. {ipulse_shared_core_ftredge-6.1.2 → ipulse_shared_core_ftredge-6.3.1}/src/ipulse_shared_core_ftredge.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ipulse_shared_core_ftredge
3
- Version: 6.1.2
3
+ Version: 6.3.1
4
4
  Summary: Shared Core models and Logger util for the Pulse platform project. Using AI for financial advisory and investment management.
5
5
  Home-page: https://github.com/TheFutureEdge/ipulse_shared_core
6
6
  Author: Russlan Ramdowar
@@ -8,7 +8,7 @@ License-File: LICENCE
8
8
  Requires-Dist: pydantic[email]~=2.5
9
9
  Requires-Dist: python-dateutil~=2.8
10
10
  Requires-Dist: pytest~=7.1
11
- Requires-Dist: ipulse_shared_base_ftredge>=5.1.1
11
+ Requires-Dist: ipulse_shared_base_ftredge>=5.2.1
12
12
  Dynamic: author
13
13
  Dynamic: home-page
14
14
  Dynamic: requires-dist
@@ -3,7 +3,7 @@ from setuptools import setup, find_packages
3
3
 
4
4
  setup(
5
5
  name='ipulse_shared_core_ftredge',
6
- version='6.1.2',
6
+ version='6.3.1',
7
7
  package_dir={'': 'src'}, # Specify the source directory
8
8
  packages=find_packages(where='src'), # Look for packages in 'src'
9
9
  install_requires=[
@@ -11,7 +11,7 @@ setup(
11
11
  'pydantic[email]~=2.5',
12
12
  'python-dateutil~=2.8',
13
13
  'pytest~=7.1',
14
- 'ipulse_shared_base_ftredge>=5.1.1',
14
+ 'ipulse_shared_base_ftredge>=5.2.1',
15
15
  ],
16
16
  author='Russlan Ramdowar',
17
17
  description='Shared Core models and Logger util for the Pulse platform project. Using AI for financial advisory and investment management.',
@@ -5,7 +5,7 @@ from datetime import datetime, timedelta, timezone
5
5
  import httpx
6
6
  from fastapi import HTTPException, Request
7
7
  from google.cloud import firestore
8
- from ipulse_shared_core_ftredge.services.exceptions import ServiceError, AuthorizationError, ResourceNotFoundError
8
+ from ipulse_shared_core_ftredge.services import ServiceError, AuthorizationError, ResourceNotFoundError
9
9
 
10
10
  # Constants
11
11
  USERS_STATUS_COLLECTION_NAME = "user-statuses"
@@ -1,7 +1,7 @@
1
- from datetime import datetime, date
2
- import dateutil.parser
1
+ """ User Profile model representing user information. """
2
+ from datetime import date
3
3
  from typing import Set, Optional, ClassVar
4
- from pydantic import BaseModel, EmailStr, Field, ConfigDict, field_validator
4
+ from pydantic import EmailStr, Field, ConfigDict, field_validator
5
5
  from ipulse_shared_base_ftredge import Layer, Module, list_as_lower_strings, Subject
6
6
  from .base_data_model import BaseDataModel
7
7
 
@@ -83,6 +83,7 @@ class UserProfile(BaseDataModel):
83
83
  @field_validator('id', mode='before')
84
84
  @classmethod
85
85
  def validate_or_generate_id(cls, v: Optional[str], info) -> str:
86
+ """Validate or generate user ID based on user_uid."""
86
87
  # If id is already provided (Firebase Auth case), return it
87
88
  if v:
88
89
  return v
@@ -1,14 +1,15 @@
1
+ """ User Status model for tracking user subscription and access rights. """
1
2
  from datetime import datetime
2
3
  from typing import Set, Optional, Dict, List, ClassVar
3
- from pydantic import BaseModel, Field, ConfigDict, field_validator
4
- from .subscription import Subscription
4
+ from pydantic import Field, ConfigDict, field_validator
5
5
  from ipulse_shared_base_ftredge import Layer, Module, list_as_lower_strings, Subject
6
- import dateutil.parser
6
+ from .subscription import Subscription
7
7
  from .base_data_model import BaseDataModel
8
+
8
9
  # ORIGINAL AUTHOR ="Russlan Ramdowar;russlan@ftredge.com"
9
10
  # CLASS_ORGIN_DATE=datetime(2024, 2, 12, 20, 5)
10
11
 
11
- ############################################ !!!!! ALWAYS UPDATE SCHEMA VERSION , IF SCHEMA IS BEING MODIFIED !!! ############################################
12
+ ############################ !!!!! ALWAYS UPDATE SCHEMA VERSION , IF SCHEMA IS BEING MODIFIED !!! #################################
12
13
  class UserStatus(BaseDataModel):
13
14
  """
14
15
  User Status model for tracking user subscription and access rights.
@@ -35,7 +36,7 @@ class UserStatus(BaseDataModel):
35
36
  frozen=True,
36
37
  description="Version of this Class == version of DB Schema"
37
38
  )
38
-
39
+
39
40
  id : str = Field(
40
41
  ...,
41
42
  description="User ID, format: {OBJ_REF}_{user_uid}"
@@ -90,6 +91,9 @@ class UserStatus(BaseDataModel):
90
91
  @field_validator('id', mode='before')
91
92
  @classmethod
92
93
  def validate_or_generate_id(cls, v: Optional[str], info) -> str:
94
+ """
95
+ Validate or generate the id field based on user_uid.
96
+ """
93
97
  # If id is already provided (Firebase Auth case), return it
94
98
  if v:
95
99
  return v
@@ -0,0 +1,6 @@
1
+ from .base_firestore_service import BaseFirestoreService
2
+
3
+ from .base_exceptions import (BaseServiceException, ResourceNotFoundError, AuthorizationError,
4
+ ValidationError ,ServiceError)
5
+ from .servicemon import Servicemon
6
+ from .fastapiservicemon import FastAPIServiceMon
@@ -1,9 +1,11 @@
1
- from fastapi import HTTPException
1
+ """Base classes for service exceptions with enhanced logging"""
2
2
  from typing import Optional, Any, Dict
3
3
  import traceback
4
4
  import logging
5
+ from fastapi import HTTPException
5
6
 
6
7
  class BaseServiceException(HTTPException):
8
+ """Base class for service exceptions with enhanced logging"""
7
9
  def __init__(
8
10
  self,
9
11
  status_code: int,
@@ -1,9 +1,10 @@
1
- from typing import Dict, Any, Optional, List, TypeVar, Generic
1
+ """ Base class for Firestore services with common CRUD operations """
2
+ from typing import Dict, Any, List, TypeVar, Generic
2
3
  import logging
3
4
  from datetime import datetime, timezone
4
5
  from pydantic import BaseModel
5
6
  from google.cloud import firestore
6
- from .exceptions import ResourceNotFoundError, ValidationError, ServiceError
7
+ from .base_exceptions import ResourceNotFoundError, ValidationError, ServiceError
7
8
 
8
9
  T = TypeVar('T', bound=BaseModel)
9
10
 
@@ -0,0 +1,138 @@
1
+ """ FastAPI ServiceMon"""
2
+ import logging
3
+ import time
4
+ from fastapi import Request
5
+ from ipulse_shared_base_ftredge import DataResource, Action, ProgressStatus, LogLevel
6
+ from starlette.middleware.base import BaseHTTPMiddleware
7
+ from . import Servicemon
8
+
9
+
10
+ class FastAPIServiceMon(Servicemon):
11
+ """
12
+ Extension of Servicemon designed specifically for FastAPI applications.
13
+ Adds integration with FastAPI request/response lifecycle.
14
+ """
15
+
16
+ @staticmethod
17
+ def get_fastapi_middleware():
18
+ """
19
+ Creates a FastAPI middleware class that uses ServiceMon for request logging.
20
+
21
+ Returns:
22
+ A middleware class that can be registered with FastAPI
23
+ """
24
+
25
+
26
+ class ServiceMonMiddleware(BaseHTTPMiddleware):
27
+ """
28
+ Middleware class for integrating ServiceMon into FastAPI request/response lifecycle.
29
+ """
30
+ async def dispatch(self, request: Request, call_next):
31
+ # Create ServiceMon instance
32
+ logger_name = f"{request.app.state.env_prefix}__dp_core_api_live__apilogger"
33
+ logger = logging.getLogger(logger_name)
34
+
35
+ path = request.url.path
36
+ method = request.method
37
+
38
+ # Skip monitoring for certain paths
39
+ skip_paths = ["/health", "/metrics", "/docs", "/redoc", "/openapi.json"]
40
+ if any(path.startswith(skip_p) for skip_p in skip_paths):
41
+ return await call_next(request)
42
+
43
+ # Initialize ServiceMon
44
+ svcmon = Servicemon(
45
+ logger=logger,
46
+ base_context=f"API: {path}\nMethod: {method}",
47
+ service_name=f"API_{method}_{path.replace('/', '_')}"
48
+ )
49
+
50
+ # Start monitoring
51
+ client_ip = request.client.host if request.client else "unknown"
52
+ user_agent = request.headers.get("user-agent", "unknown")
53
+ svcmon.start(f"API Request {method} {path}")
54
+
55
+
56
+ # Add request info
57
+ svcmon.log(
58
+ level=LogLevel.INFO,
59
+ description=f"Request received for {method} {path}. Client IP: {client_ip}. User Agent: {user_agent}",
60
+ resource=DataResource.API_INTERNAL,
61
+ action=Action.EXECUTE,
62
+ progress_status=ProgressStatus.STARTED,
63
+ )
64
+
65
+ # Process the request and catch any errors
66
+ try:
67
+ # Store ServiceMon in request state for handlers to access
68
+ request.state.svcmon = svcmon
69
+
70
+ # Process request
71
+ start_time = time.time()
72
+ response = await call_next(request)
73
+ process_time = int((time.time() - start_time) * 1000)
74
+
75
+ # Log response
76
+ status_code = response.status_code
77
+ progress_status = (
78
+ ProgressStatus.DONE
79
+ if 200 <= status_code < 300
80
+ else ProgressStatus.FINISHED_WITH_ISSUES
81
+ )
82
+
83
+ log_level = (
84
+ LogLevel.ERROR if status_code >= 500
85
+ else LogLevel.WARNING if status_code >= 400
86
+ else LogLevel.INFO
87
+ )
88
+
89
+ svcmon.log(
90
+ level=log_level,
91
+ description=f"Response sent: {status_code} in {process_time}ms for {method} {path}",
92
+ resource=DataResource.API_INTERNAL,
93
+ action=Action.EXECUTE,
94
+ progress_status=progress_status
95
+
96
+ )
97
+
98
+ # Finalize monitoring
99
+ svcmon.end(status=progress_status)
100
+ return response
101
+
102
+ except Exception as exc:
103
+ svcmon.error(
104
+ f"Error processing request: {str(exc)}",
105
+ resource=DataResource.API_INTERNAL,
106
+ action=Action.EXECUTE,
107
+ progress_status=ProgressStatus.FAILED,
108
+ e=exc
109
+ )
110
+ svcmon.end(status=ProgressStatus.FAILED)
111
+ raise
112
+
113
+ return ServiceMonMiddleware
114
+
115
+ # @staticmethod
116
+ # def setup_fastapi(app):
117
+ # """
118
+ # Configure a FastAPI application with ServiceMon integration.
119
+
120
+ # Args:
121
+ # app: The FastAPI application instance
122
+ # """
123
+ # from fastapi import FastAPI
124
+
125
+ # if not isinstance(app, FastAPI):
126
+ # raise TypeError("Expected FastAPI application instance")
127
+
128
+ # # Register middleware
129
+ # app.add_middleware(FastAPIServiceMon.get_fastapi_middleware())
130
+
131
+ # # Add dependency for route handlers
132
+ # from fastapi import Depends, Request
133
+
134
+ # async def get_servicemon(request: Request):
135
+ # """Dependency for accessing the current ServiceMon instance."""
136
+ # return getattr(request.state, "svcmon", None)
137
+
138
+ # app.dependency_overrides[FastAPIServiceMon] = get_servicemon
@@ -0,0 +1,240 @@
1
+ """
2
+ ServiceMon - Lightweight monitoring for service functions and API endpoints
3
+ """
4
+ import uuid
5
+ import time
6
+ from datetime import datetime, timezone
7
+ from typing import Dict, Any, Optional
8
+ from contextlib import contextmanager
9
+ from ipulse_shared_base_ftredge import (LogLevel, AbstractResource,
10
+ ProgressStatus, Action, Resource,
11
+ Alert, StructLog)
12
+
13
+ class Servicemon:
14
+ """
15
+ ServiceMon is a lightweight version of Pipelinemon designed specifically for monitoring
16
+ service functions like Cloud Functions and API endpoints.
17
+
18
+ It provides:
19
+ 1. Structured logging with context tracking
20
+ 2. Performance metrics capture
21
+ 3. Service health monitoring
22
+ 4. Integration with FastAPI request/response cycle
23
+ """
24
+
25
+ def __init__(self, logger,
26
+ base_context: str,
27
+ service_name: str):
28
+ """
29
+ Initialize ServiceMon with basic configuration.
30
+
31
+ Args:
32
+ logger: The logger instance to use for logging
33
+ base_context: Base context information for all logs
34
+ service_name: Name of the service being monitored
35
+ """
36
+ # Set up execution tracking details
37
+ self._start_time = None
38
+ self._service_name = service_name
39
+
40
+ timestamp = datetime.now(timezone.utc).strftime('%Y%m%d_%H%M%S')
41
+ uuid_suffix = str(uuid.uuid4())[:8] # Take first 8 chars of UUID
42
+ self._id = f"{timestamp}_{uuid_suffix}"
43
+
44
+ # Set up context handling
45
+ self._base_context = base_context
46
+ self._context_stack = []
47
+
48
+ # Configure logging
49
+ self._logger = logger
50
+
51
+ # Metrics tracking
52
+ self._metrics = {
53
+ "status": ProgressStatus.NOT_STARTED.name,
54
+ "errors": 0,
55
+ "warnings": 0,
56
+ "start_time": None,
57
+ "end_time": None,
58
+ "duration_ms": None,
59
+ }
60
+
61
+ @property
62
+ def id(self) -> str:
63
+ """Get the unique ID for this service execution."""
64
+ return self._id
65
+
66
+ @property
67
+ def base_context(self) -> str:
68
+ """Get the base context for this service execution."""
69
+ return self._base_context
70
+
71
+ @property
72
+ def service_name(self) -> str:
73
+ """Get the service name being monitored."""
74
+ return self._service_name
75
+
76
+ @property
77
+ def metrics(self) -> Dict[str, Any]:
78
+ """Get the current service metrics."""
79
+ return self._metrics.copy()
80
+
81
+ @property
82
+ def current_context(self) -> str:
83
+ """Get the current context stack as a string."""
84
+ return " >> ".join(self._context_stack) if self._context_stack else "root"
85
+
86
+ @contextmanager
87
+ def context(self, context_name: str):
88
+ """
89
+ Context manager for tracking execution context.
90
+
91
+ Args:
92
+ context_name: The name of the current execution context
93
+ """
94
+ self.push_context(context_name)
95
+ try:
96
+ yield
97
+ finally:
98
+ self.pop_context()
99
+
100
+ def push_context(self, context: str):
101
+ """Add a context level to the stack."""
102
+ self._context_stack.append(context)
103
+
104
+ def pop_context(self):
105
+ """Remove the most recent context from the stack."""
106
+ if self._context_stack:
107
+ return self._context_stack.pop()
108
+
109
+ def start(self, description: Optional[str] = None) -> None:
110
+ """
111
+ Start monitoring a service execution.
112
+
113
+ Args:
114
+ description: Optional description of what's being executed
115
+ """
116
+ self._start_time = time.time()
117
+ self._metrics["start_time"] = datetime.now(timezone.utc).isoformat()
118
+ self._metrics["status"] = ProgressStatus.IN_PROGRESS.name
119
+
120
+ # Log the start event
121
+ msg = description if description else f"Starting {self.service_name}"
122
+ self.log(level=LogLevel.INFO, description=msg, resource=AbstractResource.SERVICEMON, action=Action.EXECUTE,
123
+ progress_status=ProgressStatus.IN_PROGRESS)
124
+
125
+ def end(self, status: ProgressStatus = ProgressStatus.DONE) -> Dict[str, Any]:
126
+ """
127
+ End monitoring and record final metrics.
128
+
129
+ Args:
130
+ status: The final status of the service execution
131
+
132
+ Returns:
133
+ Dict containing metrics summary
134
+ """
135
+ # Calculate duration
136
+ end_time = time.time()
137
+ if self._start_time:
138
+ duration_ms = int((end_time - self._start_time) * 1000)
139
+ self._metrics["duration_ms"] = duration_ms
140
+
141
+ # Update metrics
142
+ self._metrics["end_time"] = datetime.now(timezone.utc).isoformat()
143
+ self._metrics["status"] = status.name
144
+
145
+ # Determine log level based on metrics
146
+ if self._metrics["errors"] > 0:
147
+ level = LogLevel.ERROR
148
+ if status == ProgressStatus.DONE:
149
+ status = ProgressStatus.FINISHED_WITH_ISSUES
150
+ elif self._metrics["warnings"] > 0:
151
+ level = LogLevel.WARNING
152
+ if status == ProgressStatus.DONE:
153
+ status = ProgressStatus.DONE_WITH_WARNINGS
154
+ else:
155
+ level = LogLevel.INFO
156
+
157
+ # Prepare summary message
158
+ summary_msg = (
159
+ f"Service {self.service_name} completed with status {status.name}. "
160
+ f"Duration: {self._metrics['duration_ms']}ms. "
161
+ f"Errors: {self._metrics['errors']}, Warnings: {self._metrics['warnings']}"
162
+ )
163
+
164
+ # Log the completion
165
+ self.log(
166
+ level=level,
167
+ description=summary_msg,
168
+ resource=AbstractResource.SERVICEMON,
169
+ action=Action.EXECUTE,
170
+ progress_status=status,
171
+ )
172
+
173
+ return self._metrics
174
+
175
+ def log(self,
176
+ level: LogLevel,
177
+ description: str,
178
+ resource: Optional[Resource] = None,
179
+ source: Optional[str] = None,
180
+ destination: Optional[str] = None,
181
+ action: Optional[Action] = None,
182
+ progress_status: Optional[ProgressStatus] = None,
183
+ alert: Optional[Alert] = None,
184
+ e: Optional[Exception] = None,
185
+ systems_impacted: Optional[str] = None,
186
+ notes: Optional[str] = None,
187
+ **kwargs) -> None:
188
+ """
189
+ Log a message with structured context.
190
+
191
+ Args:
192
+ level: Log level
193
+ description: Log message
194
+ resource: Resource being accessed
195
+ action: Action being performed
196
+ progress_status: Current progress status
197
+ alert: Alert type if applicable
198
+ e: Exception if logging an error
199
+ **kwargs: Additional fields to include in the log
200
+ """
201
+ # Update metrics
202
+ if level in (LogLevel.ERROR, LogLevel.CRITICAL):
203
+ self._metrics["errors"] += 1
204
+ elif level == LogLevel.WARNING:
205
+ self._metrics["warnings"] += 1
206
+
207
+
208
+ formatted_notes = f"{notes} ;elapsed_ms: {int((time.time() - self._start_time) * 1000)} " + str(kwargs)
209
+ # Create structured log
210
+ log = StructLog(
211
+ level=level,
212
+ resource=resource,
213
+ action=action,
214
+ progress_status=progress_status,
215
+ alert=alert,
216
+ e=e,
217
+ source=source,
218
+ destination=destination,
219
+ description=description,
220
+ collector_id=self.id,
221
+ base_context=self.base_context,
222
+ context=self.current_context,
223
+ systems_impacted=systems_impacted,
224
+ note=formatted_notes,
225
+ **kwargs
226
+ )
227
+
228
+ # Add service-specific fields
229
+ log_dict = log.to_dict()
230
+
231
+ # Write to logger
232
+ if level.value >= LogLevel.ERROR.value:
233
+ self._logger.error(log_dict)
234
+ elif level.value >= LogLevel.WARNING.value:
235
+ self._logger.warning(log_dict)
236
+ elif level.value >= LogLevel.INFO.value:
237
+ self._logger.info(log_dict)
238
+ else:
239
+ self._logger.debug(log_dict)
240
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: ipulse_shared_core_ftredge
3
- Version: 6.1.2
3
+ Version: 6.3.1
4
4
  Summary: Shared Core models and Logger util for the Pulse platform project. Using AI for financial advisory and investment management.
5
5
  Home-page: https://github.com/TheFutureEdge/ipulse_shared_core
6
6
  Author: Russlan Ramdowar
@@ -8,7 +8,7 @@ License-File: LICENCE
8
8
  Requires-Dist: pydantic[email]~=2.5
9
9
  Requires-Dist: python-dateutil~=2.8
10
10
  Requires-Dist: pytest~=7.1
11
- Requires-Dist: ipulse_shared_base_ftredge>=5.1.1
11
+ Requires-Dist: ipulse_shared_base_ftredge>=5.2.1
12
12
  Dynamic: author
13
13
  Dynamic: home-page
14
14
  Dynamic: requires-dist
@@ -24,5 +24,7 @@ src/ipulse_shared_core_ftredge/models/user_profile.py
24
24
  src/ipulse_shared_core_ftredge/models/user_profile_update.py
25
25
  src/ipulse_shared_core_ftredge/models/user_status.py
26
26
  src/ipulse_shared_core_ftredge/services/__init__.py
27
+ src/ipulse_shared_core_ftredge/services/base_exceptions.py
27
28
  src/ipulse_shared_core_ftredge/services/base_firestore_service.py
28
- src/ipulse_shared_core_ftredge/services/exceptions.py
29
+ src/ipulse_shared_core_ftredge/services/fastapiservicemon.py
30
+ src/ipulse_shared_core_ftredge/services/servicemon.py
@@ -1,4 +1,4 @@
1
1
  pydantic[email]~=2.5
2
2
  python-dateutil~=2.8
3
3
  pytest~=7.1
4
- ipulse_shared_base_ftredge>=5.1.1
4
+ ipulse_shared_base_ftredge>=5.2.1
@@ -1,4 +0,0 @@
1
- from .base_firestore_service import BaseFirestoreService
2
-
3
- from .exceptions import (BaseServiceException, ResourceNotFoundError, AuthorizationError,
4
- ValidationError )