vnai 2.1.7__py3-none-any.whl → 2.1.8__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 +240 -178
- vnai/beam/__init__.py +4 -2
- vnai/beam/metrics.py +218 -167
- vnai/beam/pulse.py +108 -79
- vnai/beam/quota.py +486 -333
- vnai/flow/__init__.py +5 -2
- vnai/flow/queue.py +133 -100
- vnai/flow/relay.py +447 -356
- vnai/scope/__init__.py +7 -4
- vnai/scope/profile.py +765 -579
- vnai/scope/promo.py +375 -278
- vnai/scope/state.py +222 -155
- {vnai-2.1.7.dist-info → vnai-2.1.8.dist-info}/METADATA +20 -20
- vnai-2.1.8.dist-info/RECORD +16 -0
- vnai-2.1.7.dist-info/RECORD +0 -16
- {vnai-2.1.7.dist-info → vnai-2.1.8.dist-info}/WHEEL +0 -0
- {vnai-2.1.7.dist-info → vnai-2.1.8.dist-info}/top_level.txt +0 -0
vnai/scope/state.py
CHANGED
@@ -1,155 +1,222 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
import
|
4
|
-
import
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
"
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
"
|
29
|
-
"
|
30
|
-
"
|
31
|
-
}
|
32
|
-
|
33
|
-
self.
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
self.
|
40
|
-
|
41
|
-
|
42
|
-
self.
|
43
|
-
self.
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
if self.
|
65
|
-
try:
|
66
|
-
with open(self.
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
1
|
+
# vnai/scope/state.py
|
2
|
+
|
3
|
+
import time
|
4
|
+
import threading
|
5
|
+
import json
|
6
|
+
import os
|
7
|
+
from datetime import datetime
|
8
|
+
from pathlib import Path
|
9
|
+
|
10
|
+
class Tracker:
|
11
|
+
"""Tracks system state and performance metrics"""
|
12
|
+
|
13
|
+
_instance = None
|
14
|
+
_lock = threading.Lock()
|
15
|
+
|
16
|
+
def __new__(cls):
|
17
|
+
with cls._lock:
|
18
|
+
if cls._instance is None:
|
19
|
+
cls._instance = super(Tracker, cls).__new__(cls)
|
20
|
+
cls._instance._initialize()
|
21
|
+
return cls._instance
|
22
|
+
|
23
|
+
def _initialize(self):
|
24
|
+
"""Initialize tracker"""
|
25
|
+
self.metrics = {
|
26
|
+
"startup_time": datetime.now().isoformat(),
|
27
|
+
"function_calls": 0,
|
28
|
+
"api_requests": 0,
|
29
|
+
"errors": 0,
|
30
|
+
"warnings": 0
|
31
|
+
}
|
32
|
+
|
33
|
+
self.performance_metrics = {
|
34
|
+
"execution_times": [],
|
35
|
+
"last_error_time": None,
|
36
|
+
"peak_memory": 0
|
37
|
+
}
|
38
|
+
|
39
|
+
self.privacy_level = "standard"
|
40
|
+
|
41
|
+
# Setup data directory
|
42
|
+
self.home_dir = Path.home()
|
43
|
+
self.project_dir = self.home_dir / ".vnstock"
|
44
|
+
self.project_dir.mkdir(exist_ok=True)
|
45
|
+
self.data_dir = self.project_dir / 'data'
|
46
|
+
self.data_dir.mkdir(exist_ok=True)
|
47
|
+
self.metrics_path = self.data_dir / "usage_metrics.json"
|
48
|
+
self.privacy_config_path = self.project_dir / 'config' / "privacy.json"
|
49
|
+
|
50
|
+
# Create config directory if it doesn't exist
|
51
|
+
os.makedirs(os.path.dirname(self.privacy_config_path), exist_ok=True)
|
52
|
+
|
53
|
+
# Load existing metrics
|
54
|
+
self._load_metrics()
|
55
|
+
|
56
|
+
# Load privacy settings
|
57
|
+
self._load_privacy_settings()
|
58
|
+
|
59
|
+
# Start background metrics collector
|
60
|
+
self._start_background_collector()
|
61
|
+
|
62
|
+
def _load_metrics(self):
|
63
|
+
"""Load metrics from file"""
|
64
|
+
if self.metrics_path.exists():
|
65
|
+
try:
|
66
|
+
with open(self.metrics_path, 'r') as f:
|
67
|
+
stored_metrics = json.load(f)
|
68
|
+
|
69
|
+
# Update metrics with stored values
|
70
|
+
for key, value in stored_metrics.items():
|
71
|
+
if key in self.metrics:
|
72
|
+
self.metrics[key] = value
|
73
|
+
except:
|
74
|
+
pass
|
75
|
+
|
76
|
+
def _save_metrics(self):
|
77
|
+
"""Save metrics to file"""
|
78
|
+
try:
|
79
|
+
with open(self.metrics_path, 'w') as f:
|
80
|
+
json.dump(self.metrics, f)
|
81
|
+
except:
|
82
|
+
pass
|
83
|
+
|
84
|
+
def _load_privacy_settings(self):
|
85
|
+
"""Load privacy settings"""
|
86
|
+
if self.privacy_config_path.exists():
|
87
|
+
try:
|
88
|
+
with open(self.privacy_config_path, 'r') as f:
|
89
|
+
settings = json.load(f)
|
90
|
+
self.privacy_level = settings.get("level", "standard")
|
91
|
+
except:
|
92
|
+
pass
|
93
|
+
|
94
|
+
def setup_privacy(self, level=None):
|
95
|
+
"""Configure privacy level for data collection"""
|
96
|
+
privacy_levels = {
|
97
|
+
"minimal": "Essential system data only",
|
98
|
+
"standard": "Performance metrics and errors",
|
99
|
+
"enhanced": "Detailed operation analytics"
|
100
|
+
}
|
101
|
+
|
102
|
+
if level is None:
|
103
|
+
# Default level
|
104
|
+
level = "standard"
|
105
|
+
|
106
|
+
if level not in privacy_levels:
|
107
|
+
raise ValueError(f"Invalid privacy level: {level}. Choose from {', '.join(privacy_levels.keys())}")
|
108
|
+
|
109
|
+
# Store preference
|
110
|
+
self.privacy_level = level
|
111
|
+
|
112
|
+
# Store in configuration file
|
113
|
+
with open(self.privacy_config_path, "w") as f:
|
114
|
+
json.dump({"level": level}, f)
|
115
|
+
|
116
|
+
return level
|
117
|
+
|
118
|
+
def get_privacy_level(self):
|
119
|
+
"""Get current privacy level"""
|
120
|
+
return self.privacy_level
|
121
|
+
|
122
|
+
def _start_background_collector(self):
|
123
|
+
"""Start background metrics collection"""
|
124
|
+
def collect_metrics():
|
125
|
+
while True:
|
126
|
+
try:
|
127
|
+
import psutil
|
128
|
+
|
129
|
+
# Update peak memory
|
130
|
+
current_process = psutil.Process()
|
131
|
+
memory_info = current_process.memory_info()
|
132
|
+
memory_usage = memory_info.rss / (1024 * 1024) # MB
|
133
|
+
|
134
|
+
if memory_usage > self.performance_metrics["peak_memory"]:
|
135
|
+
self.performance_metrics["peak_memory"] = memory_usage
|
136
|
+
|
137
|
+
# Save metrics periodically
|
138
|
+
self._save_metrics()
|
139
|
+
|
140
|
+
except:
|
141
|
+
pass
|
142
|
+
|
143
|
+
time.sleep(300) # Run every 5 minutes
|
144
|
+
|
145
|
+
# Start thread
|
146
|
+
thread = threading.Thread(target=collect_metrics, daemon=True)
|
147
|
+
thread.start()
|
148
|
+
|
149
|
+
def record(self, event_type, data=None):
|
150
|
+
"""Record an event"""
|
151
|
+
# Check privacy level
|
152
|
+
if self.privacy_level == "minimal" and event_type != "errors":
|
153
|
+
# In minimal mode, only track errors
|
154
|
+
return True
|
155
|
+
|
156
|
+
# Update counts
|
157
|
+
if event_type in self.metrics:
|
158
|
+
self.metrics[event_type] += 1
|
159
|
+
else:
|
160
|
+
self.metrics[event_type] = 1
|
161
|
+
|
162
|
+
# Special handling for errors
|
163
|
+
if event_type == "errors":
|
164
|
+
self.performance_metrics["last_error_time"] = datetime.now().isoformat()
|
165
|
+
|
166
|
+
# Special handling for function calls with timing data
|
167
|
+
if event_type == "function_calls" and data and "execution_time" in data:
|
168
|
+
# Keep up to 100 latest execution times
|
169
|
+
self.performance_metrics["execution_times"].append(data["execution_time"])
|
170
|
+
if len(self.performance_metrics["execution_times"]) > 100:
|
171
|
+
self.performance_metrics["execution_times"] = self.performance_metrics["execution_times"][-100:]
|
172
|
+
|
173
|
+
# Save if metrics change significantly
|
174
|
+
if self.metrics["function_calls"] % 100 == 0 or event_type == "errors":
|
175
|
+
self._save_metrics()
|
176
|
+
|
177
|
+
return True
|
178
|
+
|
179
|
+
def get_metrics(self):
|
180
|
+
"""Get current metrics"""
|
181
|
+
# Calculate derived metrics
|
182
|
+
avg_execution_time = 0
|
183
|
+
if self.performance_metrics["execution_times"]:
|
184
|
+
avg_execution_time = sum(self.performance_metrics["execution_times"]) / len(self.performance_metrics["execution_times"])
|
185
|
+
|
186
|
+
# Add derived metrics to output
|
187
|
+
output = self.metrics.copy()
|
188
|
+
output.update({
|
189
|
+
"avg_execution_time": avg_execution_time,
|
190
|
+
"peak_memory_mb": self.performance_metrics["peak_memory"],
|
191
|
+
"uptime": (datetime.now() - datetime.fromisoformat(self.metrics["startup_time"])).total_seconds(),
|
192
|
+
"privacy_level": self.privacy_level
|
193
|
+
})
|
194
|
+
|
195
|
+
return output
|
196
|
+
|
197
|
+
def reset(self):
|
198
|
+
"""Reset metrics"""
|
199
|
+
self.metrics = {
|
200
|
+
"startup_time": datetime.now().isoformat(),
|
201
|
+
"function_calls": 0,
|
202
|
+
"api_requests": 0,
|
203
|
+
"errors": 0,
|
204
|
+
"warnings": 0
|
205
|
+
}
|
206
|
+
|
207
|
+
self.performance_metrics = {
|
208
|
+
"execution_times": [],
|
209
|
+
"last_error_time": None,
|
210
|
+
"peak_memory": 0
|
211
|
+
}
|
212
|
+
|
213
|
+
self._save_metrics()
|
214
|
+
return True
|
215
|
+
|
216
|
+
# Create singleton instance
|
217
|
+
tracker = Tracker()
|
218
|
+
|
219
|
+
|
220
|
+
def record(event_type, data=None):
|
221
|
+
"""Record an event"""
|
222
|
+
return tracker.record(event_type, data)
|
@@ -1,20 +1,20 @@
|
|
1
|
-
Metadata-Version: 2.4
|
2
|
-
Name: vnai
|
3
|
-
Version: 2.1.
|
4
|
-
Summary: Vnstock Analytics Interface
|
5
|
-
Author-email: Vnstock Analytics Team <support@vnstocks.com>
|
6
|
-
License: proprietary
|
7
|
-
Project-URL: Homepage, https://vnstocks.com
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
9
|
-
Classifier: Operating System :: OS Independent
|
10
|
-
Classifier: Development Status :: 4 - Beta
|
11
|
-
Classifier: Intended Audience :: Developers
|
12
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
13
|
-
Requires-Python: >=3.7
|
14
|
-
Description-Content-Type: text/markdown
|
15
|
-
Requires-Dist: requests>=2.25.0
|
16
|
-
Requires-Dist: psutil>=5.8.0
|
17
|
-
Provides-Extra: dev
|
18
|
-
Requires-Dist: pytest>=6.0.0; extra == "dev"
|
19
|
-
|
20
|
-
# VnAI
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: vnai
|
3
|
+
Version: 2.1.8
|
4
|
+
Summary: Vnstock Analytics Interface
|
5
|
+
Author-email: Vnstock Analytics Team <support@vnstocks.com>
|
6
|
+
License: proprietary
|
7
|
+
Project-URL: Homepage, https://vnstocks.com
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
9
|
+
Classifier: Operating System :: OS Independent
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
11
|
+
Classifier: Intended Audience :: Developers
|
12
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
13
|
+
Requires-Python: >=3.7
|
14
|
+
Description-Content-Type: text/markdown
|
15
|
+
Requires-Dist: requests>=2.25.0
|
16
|
+
Requires-Dist: psutil>=5.8.0
|
17
|
+
Provides-Extra: dev
|
18
|
+
Requires-Dist: pytest>=6.0.0; extra == "dev"
|
19
|
+
|
20
|
+
# VnAI
|
@@ -0,0 +1,16 @@
|
|
1
|
+
vnai/__init__.py,sha256=fZQKQSpvzFX9aum8kjJyZieGQnmEzWIbzLLgpaQvVQM,7996
|
2
|
+
vnai/beam/__init__.py,sha256=Ibfpu8ulgVw1E6ew5kaE1Z69V6mGxwYy6SRa0-DFivk,156
|
3
|
+
vnai/beam/metrics.py,sha256=TEBgrwrJbL7D3dlBVo9qdq9qEgqQKXef_otNMXqwm6E,8606
|
4
|
+
vnai/beam/pulse.py,sha256=SuzA_ZL_FGEHFNrLZOvXbSJSKn8pGsehNwmaADw9DyY,3427
|
5
|
+
vnai/beam/quota.py,sha256=dTbtOP82XSzLaNksPlW-2qnrnQgyvMI8KAH3GKPPQqE,21363
|
6
|
+
vnai/flow/__init__.py,sha256=xKOTxRtAkDekfJaQtx-zN1-5pxQdF_oAEcsK-DXGM2k,136
|
7
|
+
vnai/flow/queue.py,sha256=KcA20u-WiEPVV-knburw86t6ynuKXsv_Kwd-gJE5zT0,4138
|
8
|
+
vnai/flow/relay.py,sha256=Ar_GlGhUvTU1w8ByAMxKGjh6468MXTYY0haAGi4WKnE,16647
|
9
|
+
vnai/scope/__init__.py,sha256=overJZ_UiEfBRNcSieE1GPU_9X3oS4C5l6JeBaFFVxk,267
|
10
|
+
vnai/scope/profile.py,sha256=5DKB8_ImpAruJQ0V_jPs98PVZ1uyr0QyN3zjBbUfPSI,30706
|
11
|
+
vnai/scope/promo.py,sha256=EjdzmWuKozSauzcZo7C4K0OAMK7YOj49L1hwOhoezqE,16841
|
12
|
+
vnai/scope/state.py,sha256=7u-jH3TKXFo7Y5vUZUMhRM1_2YA9wXuHIat0rvhFgBc,7466
|
13
|
+
vnai-2.1.8.dist-info/METADATA,sha256=XpGL3ogyO6rZ9sLg8xi1axISrzZ2boCQ6cPW32Ly2qI,662
|
14
|
+
vnai-2.1.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
15
|
+
vnai-2.1.8.dist-info/top_level.txt,sha256=4zI0qZHePCwvgSqXl4420sBcd0VzZn4MEcRsAIFae3k,5
|
16
|
+
vnai-2.1.8.dist-info/RECORD,,
|
vnai-2.1.7.dist-info/RECORD
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
vnai/__init__.py,sha256=IPw89g9Ar7TnXHXq9YVU2Sa1EyCgP-udw7Qbfpi95UU,6226
|
2
|
-
vnai/beam/__init__.py,sha256=Of7ydx35u4gTOBCYXxDwTfDAZVyIpbds09dXX0hJh-w,133
|
3
|
-
vnai/beam/metrics.py,sha256=p0WzO1a5MvXm98KyyshLzB4FCk-5ERh7JN65IxVB0I0,6441
|
4
|
-
vnai/beam/pulse.py,sha256=WTdjJ8mr2fvtPEZcoyzVO9Nv8jt2QPCjOZjCh7CB4Ww,2563
|
5
|
-
vnai/beam/quota.py,sha256=6DQdA7qwft1VWsscjpxUGyA59PEGmUY2mnGomj2aDRE,14748
|
6
|
-
vnai/flow/__init__.py,sha256=d96OtNAJeYEYYW_3ZZXbGh8NWbVK3cd78lsub9m9--Q,82
|
7
|
-
vnai/flow/queue.py,sha256=LBuaiAdfaOfbOL_1oxapEKlNav7qGdUk8BQdfJTxMyA,3322
|
8
|
-
vnai/flow/relay.py,sha256=e7H_MSNm0AYwDeY0AeHCptl2vuD1NCRUvmsGWNmQK2c,13515
|
9
|
-
vnai/scope/__init__.py,sha256=VVFWdhAVGYJY-4CykgyhjsqoL17WlbRjVk3CZYAN7S4,200
|
10
|
-
vnai/scope/profile.py,sha256=R_xM5DyDEZ6ju9CwTAv_iXDHx4Dhqd7b1lCeAmlj-lc,22145
|
11
|
-
vnai/scope/promo.py,sha256=lnoZJL5smBc1SF49bkCMMCrgzv5NnrIIAMbSqyTGmYI,13003
|
12
|
-
vnai/scope/state.py,sha256=Y8eZNVtG31E7Jv-RtHdDLkRRKbfCK8czbbyKp65065k,5543
|
13
|
-
vnai-2.1.7.dist-info/METADATA,sha256=Gw9R_X7XNv055XKhXZeHKOhstdtfBT88greichRFK9w,682
|
14
|
-
vnai-2.1.7.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
15
|
-
vnai-2.1.7.dist-info/top_level.txt,sha256=4zI0qZHePCwvgSqXl4420sBcd0VzZn4MEcRsAIFae3k,5
|
16
|
-
vnai-2.1.7.dist-info/RECORD,,
|
File without changes
|
File without changes
|