vnai 2.0.2__py3-none-any.whl → 2.0.4__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.
vnai/__init__.py CHANGED
@@ -1,81 +1,274 @@
1
- _L='default'
2
- _K='standard'
3
- _J='accepted_agreement'
4
- _I='environment.json'
5
- _H='terms_agreement.txt'
6
- _G='timestamp'
7
- _F=False
8
- _E='id'
9
- _D='.vnstock'
10
- _C='machine_id'
11
- _B=None
12
- _A=True
13
- import os,pathlib,json,time,threading,functools
1
+ # vnai/__init__.py
2
+ # Main entry point for vnai package
3
+
4
+ import os
5
+ import pathlib
6
+ import json
7
+ import time
8
+ import threading
9
+ import functools
14
10
  from datetime import datetime
15
- from vnai.beam.quota import guardian,optimize
16
- from vnai.beam.metrics import collector,capture
11
+
12
+ # Import core functionality
13
+ from vnai.beam.quota import guardian, optimize
14
+ from vnai.beam.metrics import collector, capture
17
15
  from vnai.beam.pulse import monitor
18
- from vnai.flow.relay import conduit,configure
16
+ from vnai.flow.relay import conduit, configure
19
17
  from vnai.flow.queue import buffer
20
18
  from vnai.scope.profile import inspector
21
- from vnai.scope.state import tracker,record
19
+ from vnai.scope.state import tracker, record
22
20
  from vnai.scope.promo import present
23
- TC_VAR='ACCEPT_TC'
24
- TC_VAL='tôi đồng ý'
25
- TC_PATH=pathlib.Path.home()/_D/_E/_H
26
- TERMS_AND_CONDITIONS='\nKhi tiếp tục sử dụng Vnstock, bạn xác nhận rằng bạn đã đọc, hiểu và đồng ý với Chính sách quyền riêng tư và Điều khoản, điều kiện về giấy phép sử dụng Vnstock.\n\nChi tiết:\n- Giấy phép sử dụng phần mềm: https://vnstocks.com/docs/tai-lieu/giay-phep-su-dung\n- Chính sách quyền riêng tư: https://vnstocks.com/docs/tai-lieu/chinh-sach-quyen-rieng-tu\n'
21
+
22
+ # Constants for terms and conditions
23
+ TC_VAR = "ACCEPT_TC"
24
+ TC_VAL = "tôi đồng ý"
25
+ TC_PATH = pathlib.Path.home() / ".vnstock" / "id" / "terms_agreement.txt"
26
+
27
+ TERMS_AND_CONDITIONS = """
28
+ Khi tiếp tục sử dụng Vnstock, bạn xác nhận rằng bạn đã đọc, hiểu và đồng ý với Chính sách quyền riêng tư và Điều khoản, điều kiện về giấy phép sử dụng Vnstock.
29
+
30
+ Chi tiết:
31
+ - Giấy phép sử dụng phần mềm: https://vnstocks.com/docs/tai-lieu/giay-phep-su-dung
32
+ - Chính sách quyền riêng tư: https://vnstocks.com/docs/tai-lieu/chinh-sach-quyen-rieng-tu
33
+ """
34
+
27
35
  class Core:
28
- def __init__(A):A.initialized=_F;A.webhook_url=_B;A.init_time=datetime.now().isoformat();A.home_dir=pathlib.Path.home();A.project_dir=A.home_dir/_D;A.id_dir=A.project_dir/_E;A.terms_file_path=TC_PATH;A.system_info=_B;A.project_dir.mkdir(exist_ok=_A);A.id_dir.mkdir(exist_ok=_A);A.initialize()
29
- def initialize(A,webhook_url=_B):
30
- C=webhook_url
31
- if A.initialized:return _A
32
- if not A._check_terms():A._accept_terms()
33
- from vnai.scope.profile import inspector as B;B.setup_vnstock_environment();present()
34
- if C:A.webhook_url=C;configure(C)
35
- record('initialization',{_G:datetime.now().isoformat()});A.system_info=B.examine();conduit.queue({'type':'system_info','data':{'commercial':B.detect_commercial_usage(),'packages':B.scan_packages()}},priority='high');A.initialized=_A;return _A
36
- def _check_terms(A):return os.path.exists(A.terms_file_path)
37
- def _accept_terms(C):
38
- A=inspector.examine()
39
- if TC_VAR in os.environ and os.environ[TC_VAR]==TC_VAL:E=TC_VAL
40
- else:E=TC_VAL;os.environ[TC_VAR]=TC_VAL
41
- D=datetime.now();F=f"""Người dùng mã nhận dạng {A[_C]} đã chấp nhận điều khoản & điều kiện sử dụng Vnstock lúc {D}
42
- ---
43
-
44
- THÔNG TIN THIẾT BỊ: {json.dumps(A,indent=2)}
45
-
46
- Đính kèm bản sao nội dung bạn đã đọc, hiểu rõ và đồng ý dưới đây:
47
- {TERMS_AND_CONDITIONS}"""
48
- with open(C.terms_file_path,'w',encoding='utf-8')as B:B.write(F)
49
- G=C.id_dir/_I;H={_J:_A,_G:D.isoformat(),_C:A[_C]}
50
- with open(G,'w')as B:json.dump(H,B)
51
- return _A
52
- def status(A):return{'initialized':A.initialized,'health':monitor.report(),'metrics':tracker.get_metrics()}
53
- def configure_privacy(B,level=_K):from vnai.scope.state import tracker as A;return A.setup_privacy(level)
54
- core=Core()
55
- def tc_init(webhook_url=_B):return core.initialize(webhook_url)
56
- def setup(webhook_url=_B):return core.initialize(webhook_url)
57
- def optimize_execution(resource_type=_L):return optimize(resource_type)
58
- def agg_execution(resource_type=_L):return optimize(resource_type,ad_cooldown=1500,content_trigger_threshold=100000)
59
- def measure_performance(module_type='function'):return capture(module_type)
60
- def accept_license_terms(terms_text=_B):
61
- A=terms_text
62
- if A is _B:A=TERMS_AND_CONDITIONS
63
- D=inspector.examine();C=pathlib.Path.home()/_D/_E/_H;os.makedirs(os.path.dirname(C),exist_ok=_A)
64
- with open(C,'w',encoding='utf-8')as B:B.write(f"Terms accepted at {datetime.now().isoformat()}\n");B.write(f"System: {json.dumps(D)}\n\n");B.write(A)
65
- return _A
36
+ """Core functionality for system optimization"""
37
+
38
+ def __init__(self):
39
+ """Initialize core"""
40
+ self.initialized = False
41
+ self.webhook_url = None
42
+ self.init_time = datetime.now().isoformat()
43
+ self.home_dir = pathlib.Path.home()
44
+ self.project_dir = self.home_dir / ".vnstock"
45
+ self.id_dir = self.project_dir / 'id'
46
+ self.terms_file_path = TC_PATH
47
+ self.system_info = None
48
+
49
+ # Create necessary directories
50
+ self.project_dir.mkdir(exist_ok=True)
51
+ self.id_dir.mkdir(exist_ok=True)
52
+
53
+ # Auto-initialize
54
+ self.initialize()
55
+
56
+ def initialize(self, webhook_url=None):
57
+ """Initialize the system"""
58
+ if self.initialized:
59
+ return True
60
+
61
+ # Check terms acceptance
62
+ if not self._check_terms():
63
+ self._accept_terms()
64
+
65
+ # Set up vnstock environment
66
+ from vnai.scope.profile import inspector
67
+ inspector.setup_vnstock_environment()
68
+
69
+ # Display content during initialization
70
+ present()
71
+
72
+ # Configure webhook if provided
73
+ if webhook_url:
74
+ self.webhook_url = webhook_url
75
+ configure(webhook_url)
76
+
77
+ # Record initialization
78
+ record("initialization", {"timestamp": datetime.now().isoformat()})
79
+
80
+ # Get system information ONCE and store it in the class
81
+ self.system_info = inspector.examine()
82
+
83
+ # Queue system data with optimal structure
84
+ conduit.queue({
85
+ "type": "system_info",
86
+ "data": {
87
+ "commercial": inspector.detect_commercial_usage(),
88
+ "packages": inspector.scan_packages()
89
+ }
90
+ }, priority="high")
91
+
92
+ self.initialized = True
93
+ return True
94
+
95
+ def _check_terms(self):
96
+ """Check if terms have been accepted"""
97
+ return os.path.exists(self.terms_file_path)
98
+
99
+ def _accept_terms(self):
100
+ """Record terms acceptance"""
101
+ # Get system information
102
+ system_info = inspector.examine()
103
+
104
+ # Auto-accept terms
105
+ if TC_VAR in os.environ and os.environ[TC_VAR] == TC_VAL:
106
+ response = TC_VAL
107
+ else:
108
+ # For non-interactive environments, accept by default
109
+ response = TC_VAL
110
+ os.environ[TC_VAR] = TC_VAL
111
+
112
+ # Store the acceptance with hardware info
113
+ now = datetime.now()
114
+ signed_agreement = (
115
+ f"Người dùng có mã nhận dạng {system_info['machine_id']} đã chấp nhận "
116
+ f"điều khoản & điều kiện sử dụng Vnstock lúc {now}\n"
117
+ f"---\n\n"
118
+ f"THÔNG TIN THIẾT BỊ: {json.dumps(system_info, indent=2)}\n\n"
119
+ f"Đính kèm bản sao nội dung bạn đã đọc, hiểu rõ và đồng ý dưới đây:\n"
120
+ f"{TERMS_AND_CONDITIONS}"
121
+ )
122
+
123
+ # Store the acceptance
124
+ with open(self.terms_file_path, "w", encoding="utf-8") as f:
125
+ f.write(signed_agreement)
126
+
127
+ # Create the environment.json file that vnstock expects
128
+ env_file = self.id_dir / "environment.json"
129
+ env_data = {
130
+ "accepted_agreement": True,
131
+ "timestamp": now.isoformat(),
132
+ "machine_id": system_info['machine_id']
133
+ }
134
+
135
+ with open(env_file, "w") as f:
136
+ json.dump(env_data, f)
137
+
138
+ return True
139
+
140
+ def status(self):
141
+ """Get system status"""
142
+ return {
143
+ "initialized": self.initialized,
144
+ "health": monitor.report(),
145
+ "metrics": tracker.get_metrics()
146
+ # Environment information available via self.system_info
147
+ }
148
+
149
+ def configure_privacy(self, level="standard"):
150
+ """Configure privacy settings"""
151
+ from vnai.scope.state import tracker
152
+ return tracker.setup_privacy(level)
153
+
154
+
155
+ # Create singleton instance
156
+ core = Core()
157
+
158
+ # Backward support
159
+ def tc_init(webhook_url=None):
160
+ return core.initialize(webhook_url)
161
+
162
+ # Public API
163
+ def setup(webhook_url=None):
164
+ """Setup vnai with optional webhook URL"""
165
+ return core.initialize(webhook_url)
166
+
167
+ def optimize_execution(resource_type="default"):
168
+ """Decorator for optimizing function execution"""
169
+ return optimize(resource_type)
170
+
171
+ def agg_execution(resource_type="default"):
172
+ """Decorator for aggregating function execution"""
173
+ return optimize(resource_type, ad_cooldown=1500, content_trigger_threshold=100000)
174
+
175
+ def measure_performance(module_type="function"):
176
+ """Decorator for measuring function performance"""
177
+ return capture(module_type)
178
+
179
+ def accept_license_terms(terms_text=None):
180
+ """Accept license terms and conditions"""
181
+ if terms_text is None:
182
+ terms_text = TERMS_AND_CONDITIONS
183
+
184
+ # Get system information
185
+ system_info = inspector.examine()
186
+
187
+ # Record acceptance
188
+ terms_file = pathlib.Path.home() / ".vnstock" / "id" / "terms_agreement.txt"
189
+ os.makedirs(os.path.dirname(terms_file), exist_ok=True)
190
+
191
+ with open(terms_file, "w", encoding="utf-8") as f:
192
+ f.write(f"Terms accepted at {datetime.now().isoformat()}\n")
193
+ f.write(f"System: {json.dumps(system_info)}\n\n")
194
+ f.write(terms_text)
195
+
196
+ return True
197
+
66
198
  def accept_vnstock_terms():
67
- from vnai.scope.profile import inspector as C;D=C.examine();E=pathlib.Path.home();A=E/_D;A.mkdir(exist_ok=_A);B=A/_E;B.mkdir(exist_ok=_A);F=B/_I;G={_J:_A,_G:datetime.now().isoformat(),_C:D[_C]}
68
- try:
69
- with open(F,'w')as H:json.dump(G,H)
70
- print('Vnstock terms accepted successfully.');return _A
71
- except Exception as I:print(f"Error accepting terms: {I}");return _F
72
- def setup_for_colab():from vnai.scope.profile import inspector as A;A.detect_colab_with_delayed_auth(immediate=_A);A.setup_vnstock_environment();return'Environment set up for Google Colab'
73
- def display_content():return present()
74
- def configure_privacy(level=_K):from vnai.scope.state import tracker as A;return A.setup_privacy(level)
75
- def check_commercial_usage():from vnai.scope.profile import inspector as A;return A.detect_commercial_usage()
76
- def authenticate_for_persistence():from vnai.scope.profile import inspector as A;return A.get_or_create_user_id()
199
+ """Accept vnstock terms and create necessary files"""
200
+ # Get system information
201
+ from vnai.scope.profile import inspector
202
+ system_info = inspector.examine()
203
+
204
+ # Create necessary directories
205
+ home_dir = pathlib.Path.home()
206
+ project_dir = home_dir / ".vnstock"
207
+ project_dir.mkdir(exist_ok=True)
208
+ id_dir = project_dir / 'id'
209
+ id_dir.mkdir(exist_ok=True)
210
+
211
+ # Create environment.json file that vnstock looks for
212
+ env_file = id_dir / "environment.json"
213
+ env_data = {
214
+ "accepted_agreement": True,
215
+ "timestamp": datetime.now().isoformat(),
216
+ "machine_id": system_info['machine_id']
217
+ }
218
+
219
+ try:
220
+ with open(env_file, "w") as f:
221
+ json.dump(env_data, f)
222
+ print("Vnstock terms accepted successfully.")
223
+ return True
224
+ except Exception as e:
225
+ print(f"Error accepting terms: {e}")
226
+ return False
227
+
228
+ def setup_for_colab():
229
+ """Special setup for Google Colab environments"""
230
+ from vnai.scope.profile import inspector
231
+
232
+ # Immediate authentication for Colab
233
+ inspector.detect_colab_with_delayed_auth(immediate=True)
234
+
235
+ # Setup vnstock environment
236
+ inspector.setup_vnstock_environment()
237
+
238
+ return "Environment set up for Google Colab"
239
+
240
+ def display_content():
241
+ """Display promotional content appropriate for the current environment"""
242
+ return present()
243
+
244
+ def configure_privacy(level="standard"):
245
+ """Configure privacy level for analytics data"""
246
+ from vnai.scope.state import tracker
247
+ return tracker.setup_privacy(level)
248
+
249
+ def check_commercial_usage():
250
+ """Check if running in commercial environment"""
251
+ from vnai.scope.profile import inspector
252
+ return inspector.detect_commercial_usage()
253
+
254
+ def authenticate_for_persistence():
255
+ """Authenticate to Google Drive for persistent settings (Colab only)"""
256
+ from vnai.scope.profile import inspector
257
+ return inspector.get_or_create_user_id()
258
+
77
259
  def configure_webhook(webhook_id='80b8832b694a75c8ddc811ac7882a3de'):
78
- A=webhook_id
79
- if not A:return _F
80
- from vnai.flow.relay import configure as B;C=f"https://botbuilder.larksuite.com/api/trigger-webhook/{A}";return B(C)
260
+ """Configure webhook URL for analytics data transmission
261
+
262
+ This method should be called once during application initialization
263
+ to set up the analytics endpoint. For security reasons, the URL should
264
+ not be hardcoded in user-facing code.
265
+ """
266
+ if not webhook_id:
267
+ return False
268
+
269
+ from vnai.flow.relay import configure
270
+ webhook_url = f'https://botbuilder.larksuite.com/api/trigger-webhook/{webhook_id}'
271
+ return configure(webhook_url)
272
+
273
+ # Set the webhook
81
274
  configure_webhook()
vnai/beam/__init__.py CHANGED
@@ -1,3 +1,6 @@
1
- from vnai.beam.quota import guardian,optimize
2
- from vnai.beam.metrics import collector,capture
1
+ # vnai/beam/__init__.py
2
+ # System monitoring and resource management
3
+
4
+ from vnai.beam.quota import guardian, optimize
5
+ from vnai.beam.metrics import collector, capture
3
6
  from vnai.beam.pulse import monitor
vnai/beam/metrics.py CHANGED
@@ -1,59 +1,184 @@
1
- _K='success'
2
- _J='buffer_size'
3
- _I='request'
4
- _H='rate_limit'
5
- _G='execution_time'
6
- _F='timestamp'
7
- _E=False
8
- _D=True
9
- _C='error'
10
- _B=None
11
- _A='function'
12
- import sys,time,threading
1
+ # vnai/beam/metrics.py
2
+ # System performance metrics collection (formerly analytics)
3
+
4
+ import sys
5
+ import time
6
+ import threading
13
7
  from datetime import datetime
8
+
14
9
  class Collector:
15
- _instance=_B;_lock=threading.Lock()
16
- def __new__(A):
17
- with A._lock:
18
- if A._instance is _B:A._instance=super(Collector,A).__new__(A);A._instance._initialize()
19
- return A._instance
20
- def _initialize(A):A.metrics={_A:[],_H:[],_I:[],_C:[]};A.thresholds={_J:50,'error_threshold':.1,'performance_threshold':5.};A.function_count=0;A.colab_auth_triggered=_E
21
- def record(A,metric_type,data,priority=_B):
22
- D='system';C=metric_type;B=data
23
- if not isinstance(B,dict):B={'value':str(B)}
24
- if _F not in B:B[_F]=datetime.now().isoformat()
25
- if C!='system_info'and isinstance(B,dict):
26
- if D in B:del B[D]
27
- from vnai.scope.profile import inspector as E;B['machine_id']=E.fingerprint()
28
- if C in A.metrics:A.metrics[C].append(B)
29
- else:A.metrics[_A].append(B)
30
- if C==_A:
31
- A.function_count+=1
32
- if A.function_count>10 and not A.colab_auth_triggered and'google.colab'in sys.modules:A.colab_auth_triggered=_D;threading.Thread(target=A._trigger_colab_auth,daemon=_D).start()
33
- if sum(len(A)for A in A.metrics.values())>=A.thresholds[_J]:A._send_metrics()
34
- if priority=='high'or C==_C:A._send_metrics()
35
- def _trigger_colab_auth(B):
36
- try:from vnai.scope.profile import inspector as A;A.get_or_create_user_id()
37
- except:pass
38
- def _send_metrics(F):
39
- E='vnai';D='source';C='unknown';from vnai.flow.relay import track_function_call as H,track_rate_limit as I,track_api_request as J
40
- for(B,G)in F.metrics.items():
41
- if not G:continue
42
- for A in G:
43
- try:
44
- if B==_A:H(function_name=A.get(_A,C),source=A.get(D,E),execution_time=A.get(_G,0),success=A.get(_K,_D),error=A.get(_C),args=A.get('args'))
45
- elif B==_H:I(source=A.get(D,E),limit_type=A.get('limit_type',C),limit_value=A.get('limit_value',0),current_usage=A.get('current_usage',0),is_exceeded=A.get('is_exceeded',_E))
46
- elif B==_I:J(endpoint=A.get('endpoint',C),source=A.get(D,E),method=A.get('method','GET'),status_code=A.get('status_code',200),execution_time=A.get(_G,0),request_size=A.get('request_size',0),response_size=A.get('response_size',0))
47
- except Exception as K:continue
48
- F.metrics[B]=[]
49
- def get_metrics_summary(A):return{A:len(B)for(A,B)in A.metrics.items()}
50
- collector=Collector()
51
- def capture(module_type=_A):
52
- def A(func):
53
- def A(*A,**D):
54
- E=time.time();B=_E;C=_B
55
- try:F=func(*A,**D);B=_D;return F
56
- except Exception as G:C=str(G);raise
57
- finally:H=time.time()-E;collector.record(module_type,{_A:func.__name__,_G:H,_K:B,_C:C,_F:datetime.now().isoformat(),'args':str(A)[:100]if A else _B})
58
- return A
59
- return A
10
+ """Collects operation metrics for system optimization"""
11
+
12
+ _instance = None
13
+ _lock = threading.Lock()
14
+
15
+ def __new__(cls):
16
+ with cls._lock:
17
+ if cls._instance is None:
18
+ cls._instance = super(Collector, cls).__new__(cls)
19
+ cls._instance._initialize()
20
+ return cls._instance
21
+
22
+ def _initialize(self):
23
+ """Initialize collector"""
24
+ self.metrics = {
25
+ "function": [],
26
+ "rate_limit": [],
27
+ "request": [],
28
+ "error": []
29
+ }
30
+ self.thresholds = {
31
+ "buffer_size": 50,
32
+ "error_threshold": 0.1,
33
+ "performance_threshold": 5.0
34
+ }
35
+ self.function_count = 0
36
+ self.colab_auth_triggered = False
37
+
38
+ def record(self, metric_type, data, priority=None):
39
+ """Record operation metrics"""
40
+ # Ensure data is a dictionary
41
+ if not isinstance(data, dict):
42
+ data = {"value": str(data)}
43
+
44
+ # Add timestamp if not present
45
+ if "timestamp" not in data:
46
+ data["timestamp"] = datetime.now().isoformat()
47
+
48
+ # For system_info type, keep full data
49
+ # For other types, only include machine_id reference
50
+ if metric_type != "system_info" and isinstance(data, dict):
51
+ # Remove any system info and just reference machine_id
52
+ if "system" in data:
53
+ del data["system"]
54
+
55
+ # Get machine_id for reference
56
+ from vnai.scope.profile import inspector
57
+ data["machine_id"] = inspector.fingerprint()
58
+
59
+ # Add to appropriate metrics collection
60
+ if metric_type in self.metrics:
61
+ self.metrics[metric_type].append(data)
62
+ else:
63
+ self.metrics["function"].append(data)
64
+
65
+ # Keep track of function call count for Colab auth trigger
66
+ if metric_type == "function":
67
+ self.function_count += 1
68
+
69
+ # Check if we should trigger Colab authentication
70
+ if self.function_count > 10 and not self.colab_auth_triggered and 'google.colab' in sys.modules:
71
+ self.colab_auth_triggered = True
72
+ # Trigger in a separate thread to avoid blocking
73
+ threading.Thread(
74
+ target=self._trigger_colab_auth,
75
+ daemon=True
76
+ ).start()
77
+
78
+ # Check buffer size and send if threshold reached
79
+ if sum(len(metric_list) for metric_list in self.metrics.values()) >= self.thresholds["buffer_size"]:
80
+ self._send_metrics()
81
+
82
+ # Send immediately for high priority metrics
83
+ if priority == "high" or (metric_type == "error"):
84
+ self._send_metrics()
85
+
86
+ def _trigger_colab_auth(self):
87
+ """Trigger Google Colab authentication in a background thread"""
88
+ try:
89
+ from vnai.scope.profile import inspector
90
+ inspector.get_or_create_user_id()
91
+ except:
92
+ pass # Silently fail if there's an issue
93
+
94
+ def _send_metrics(self):
95
+ """Send collected metrics to data relay"""
96
+ # Import here to avoid circular imports
97
+ from vnai.flow.relay import track_function_call, track_rate_limit, track_api_request
98
+
99
+ # Process and send each type of metric using the appropriate tracking function
100
+ for metric_type, data_list in self.metrics.items():
101
+ if not data_list:
102
+ continue
103
+
104
+ # Process each metric by type
105
+ for data in data_list:
106
+ try:
107
+ if metric_type == "function":
108
+ # Use the track_function_call interface
109
+ track_function_call(
110
+ function_name=data.get("function", "unknown"),
111
+ source=data.get("source", "vnai"),
112
+ execution_time=data.get("execution_time", 0),
113
+ success=data.get("success", True),
114
+ error=data.get("error"),
115
+ args=data.get("args")
116
+ )
117
+ elif metric_type == "rate_limit":
118
+ # Use the track_rate_limit interface
119
+ track_rate_limit(
120
+ source=data.get("source", "vnai"),
121
+ limit_type=data.get("limit_type", "unknown"),
122
+ limit_value=data.get("limit_value", 0),
123
+ current_usage=data.get("current_usage", 0),
124
+ is_exceeded=data.get("is_exceeded", False)
125
+ )
126
+ elif metric_type == "request":
127
+ # Use the track_api_request interface
128
+ track_api_request(
129
+ endpoint=data.get("endpoint", "unknown"),
130
+ source=data.get("source", "vnai"),
131
+ method=data.get("method", "GET"),
132
+ status_code=data.get("status_code", 200),
133
+ execution_time=data.get("execution_time", 0),
134
+ request_size=data.get("request_size", 0),
135
+ response_size=data.get("response_size", 0)
136
+ )
137
+ except Exception as e:
138
+ # If tracking fails, just continue with the next item
139
+ continue
140
+
141
+ # Clear the processed metrics
142
+ self.metrics[metric_type] = []
143
+
144
+ def get_metrics_summary(self):
145
+ """Get summary of collected metrics"""
146
+ return {
147
+ metric_type: len(data_list)
148
+ for metric_type, data_list in self.metrics.items()
149
+ }
150
+
151
+ # Create singleton instance
152
+ collector = Collector()
153
+
154
+ def capture(module_type="function"):
155
+ """Decorator to capture metrics for any function"""
156
+ def decorator(func):
157
+ def wrapper(*args, **kwargs):
158
+ start_time = time.time()
159
+ success = False
160
+ error = None
161
+
162
+ try:
163
+ result = func(*args, **kwargs)
164
+ success = True
165
+ return result
166
+ except Exception as e:
167
+ error = str(e)
168
+ raise
169
+ finally:
170
+ execution_time = time.time() - start_time
171
+
172
+ collector.record(
173
+ module_type,
174
+ {
175
+ "function": func.__name__,
176
+ "execution_time": execution_time,
177
+ "success": success,
178
+ "error": error,
179
+ "timestamp": datetime.now().isoformat(),
180
+ "args": str(args)[:100] if args else None # Truncate for privacy
181
+ }
182
+ )
183
+ return wrapper
184
+ return decorator