veadk-python 0.1.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.
Potentially problematic release.
This version of veadk-python might be problematic. Click here for more details.
- veadk/__init__.py +31 -0
- veadk/a2a/__init__.py +13 -0
- veadk/a2a/agent_card.py +45 -0
- veadk/a2a/remote_ve_agent.py +19 -0
- veadk/a2a/ve_a2a_server.py +77 -0
- veadk/a2a/ve_agent_executor.py +78 -0
- veadk/a2a/ve_task_store.py +37 -0
- veadk/agent.py +253 -0
- veadk/cli/__init__.py +13 -0
- veadk/cli/main.py +278 -0
- veadk/cli/services/agentpilot/__init__.py +17 -0
- veadk/cli/services/agentpilot/agentpilot.py +77 -0
- veadk/cli/services/veapig/__init__.py +17 -0
- veadk/cli/services/veapig/apig.py +224 -0
- veadk/cli/services/veapig/apig_utils.py +332 -0
- veadk/cli/services/vefaas/__init__.py +17 -0
- veadk/cli/services/vefaas/template/deploy.py +44 -0
- veadk/cli/services/vefaas/template/src/app.py +30 -0
- veadk/cli/services/vefaas/template/src/config.py +58 -0
- veadk/cli/services/vefaas/vefaas.py +346 -0
- veadk/cli/services/vefaas/vefaas_utils.py +408 -0
- veadk/cli/services/vetls/__init__.py +17 -0
- veadk/cli/services/vetls/vetls.py +87 -0
- veadk/cli/studio/__init__.py +13 -0
- veadk/cli/studio/agent_processor.py +247 -0
- veadk/cli/studio/fast_api.py +232 -0
- veadk/cli/studio/model.py +116 -0
- veadk/cloud/__init__.py +13 -0
- veadk/cloud/cloud_agent_engine.py +144 -0
- veadk/cloud/cloud_app.py +123 -0
- veadk/cloud/template/app.py +30 -0
- veadk/cloud/template/config.py +55 -0
- veadk/config.py +131 -0
- veadk/consts.py +17 -0
- veadk/database/__init__.py +17 -0
- veadk/database/base_database.py +45 -0
- veadk/database/database_factory.py +80 -0
- veadk/database/kv/__init__.py +13 -0
- veadk/database/kv/redis_database.py +109 -0
- veadk/database/local_database.py +43 -0
- veadk/database/relational/__init__.py +13 -0
- veadk/database/relational/mysql_database.py +114 -0
- veadk/database/vector/__init__.py +13 -0
- veadk/database/vector/opensearch_vector_database.py +205 -0
- veadk/database/vector/type.py +50 -0
- veadk/database/viking/__init__.py +13 -0
- veadk/database/viking/viking_database.py +378 -0
- veadk/database/viking/viking_memory_db.py +521 -0
- veadk/evaluation/__init__.py +17 -0
- veadk/evaluation/adk_evaluator/__init__.py +13 -0
- veadk/evaluation/adk_evaluator/adk_evaluator.py +291 -0
- veadk/evaluation/base_evaluator.py +242 -0
- veadk/evaluation/deepeval_evaluator/__init__.py +17 -0
- veadk/evaluation/deepeval_evaluator/deepeval_evaluator.py +223 -0
- veadk/evaluation/eval_set_file_loader.py +28 -0
- veadk/evaluation/eval_set_recorder.py +91 -0
- veadk/evaluation/utils/prometheus.py +142 -0
- veadk/knowledgebase/__init__.py +17 -0
- veadk/knowledgebase/knowledgebase.py +83 -0
- veadk/knowledgebase/knowledgebase_database_adapter.py +259 -0
- veadk/memory/__init__.py +13 -0
- veadk/memory/long_term_memory.py +119 -0
- veadk/memory/memory_database_adapter.py +235 -0
- veadk/memory/short_term_memory.py +124 -0
- veadk/memory/short_term_memory_processor.py +90 -0
- veadk/prompts/__init__.py +13 -0
- veadk/prompts/agent_default_prompt.py +30 -0
- veadk/prompts/prompt_evaluator.py +20 -0
- veadk/prompts/prompt_memory_processor.py +55 -0
- veadk/prompts/prompt_optimization.py +158 -0
- veadk/runner.py +252 -0
- veadk/tools/__init__.py +13 -0
- veadk/tools/builtin_tools/__init__.py +13 -0
- veadk/tools/builtin_tools/lark.py +67 -0
- veadk/tools/builtin_tools/las.py +23 -0
- veadk/tools/builtin_tools/vesearch.py +49 -0
- veadk/tools/builtin_tools/web_scraper.py +76 -0
- veadk/tools/builtin_tools/web_search.py +192 -0
- veadk/tools/demo_tools.py +58 -0
- veadk/tools/load_knowledgebase_tool.py +144 -0
- veadk/tools/sandbox/__init__.py +13 -0
- veadk/tools/sandbox/browser_sandbox.py +27 -0
- veadk/tools/sandbox/code_sandbox.py +30 -0
- veadk/tools/sandbox/computer_sandbox.py +27 -0
- veadk/tracing/__init__.py +13 -0
- veadk/tracing/base_tracer.py +172 -0
- veadk/tracing/telemetry/__init__.py +13 -0
- veadk/tracing/telemetry/exporters/__init__.py +13 -0
- veadk/tracing/telemetry/exporters/apiserver_exporter.py +60 -0
- veadk/tracing/telemetry/exporters/apmplus_exporter.py +101 -0
- veadk/tracing/telemetry/exporters/base_exporter.py +28 -0
- veadk/tracing/telemetry/exporters/cozeloop_exporter.py +69 -0
- veadk/tracing/telemetry/exporters/inmemory_exporter.py +88 -0
- veadk/tracing/telemetry/exporters/tls_exporter.py +78 -0
- veadk/tracing/telemetry/metrics/__init__.py +13 -0
- veadk/tracing/telemetry/metrics/opentelemetry_metrics.py +73 -0
- veadk/tracing/telemetry/opentelemetry_tracer.py +167 -0
- veadk/types.py +23 -0
- veadk/utils/__init__.py +13 -0
- veadk/utils/logger.py +59 -0
- veadk/utils/misc.py +33 -0
- veadk/utils/patches.py +85 -0
- veadk/utils/volcengine_sign.py +199 -0
- veadk/version.py +15 -0
- veadk_python-0.1.0.dist-info/METADATA +124 -0
- veadk_python-0.1.0.dist-info/RECORD +110 -0
- veadk_python-0.1.0.dist-info/WHEEL +5 -0
- veadk_python-0.1.0.dist-info/entry_points.txt +2 -0
- veadk_python-0.1.0.dist-info/licenses/LICENSE +201 -0
- veadk_python-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
# This file is partly adapted from https://github.com/volcengine/mcp-server/blob/main/server/mcp_server_vefaas_function/src/mcp_server_vefaas_function/vefaas_server.py
|
|
16
|
+
|
|
17
|
+
import base64
|
|
18
|
+
import datetime
|
|
19
|
+
import hashlib
|
|
20
|
+
import hmac
|
|
21
|
+
import json
|
|
22
|
+
import os
|
|
23
|
+
import shutil
|
|
24
|
+
import subprocess
|
|
25
|
+
import zipfile
|
|
26
|
+
from io import BytesIO
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
from typing import Tuple
|
|
29
|
+
from urllib.parse import quote
|
|
30
|
+
|
|
31
|
+
import requests
|
|
32
|
+
from volcenginesdkcore.rest import ApiException
|
|
33
|
+
|
|
34
|
+
Service = "apig"
|
|
35
|
+
Version = "2021-03-03"
|
|
36
|
+
Region = "cn-beijing"
|
|
37
|
+
Host = "iam.volcengineapi.com"
|
|
38
|
+
ContentType = "application/x-www-form-urlencoded"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def ensure_executable_permissions(folder_path: str):
|
|
42
|
+
for root, _, files in os.walk(folder_path):
|
|
43
|
+
for fname in files:
|
|
44
|
+
full_path = os.path.join(root, fname)
|
|
45
|
+
if fname.endswith(".sh") or fname in ("run.sh",):
|
|
46
|
+
os.chmod(full_path, 0o755)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def python_zip_implementation(folder_path: str) -> bytes:
|
|
50
|
+
"""Pure Python zip implementation with permissions support"""
|
|
51
|
+
buffer = BytesIO()
|
|
52
|
+
|
|
53
|
+
with zipfile.ZipFile(buffer, "w", compression=zipfile.ZIP_DEFLATED) as zipf:
|
|
54
|
+
for root, dirs, files in os.walk(folder_path):
|
|
55
|
+
for file in files:
|
|
56
|
+
file_path = os.path.join(root, file)
|
|
57
|
+
arcname = os.path.relpath(file_path, folder_path)
|
|
58
|
+
|
|
59
|
+
# Skip excluded paths and binary/cache files
|
|
60
|
+
if any(
|
|
61
|
+
excl in arcname for excl in [".git", ".venv", "__pycache__", ".pyc"]
|
|
62
|
+
):
|
|
63
|
+
continue
|
|
64
|
+
|
|
65
|
+
try:
|
|
66
|
+
st = os.stat(file_path)
|
|
67
|
+
dt = datetime.datetime.fromtimestamp(st.st_mtime)
|
|
68
|
+
date_time = (
|
|
69
|
+
dt.year,
|
|
70
|
+
dt.month,
|
|
71
|
+
dt.day,
|
|
72
|
+
dt.hour,
|
|
73
|
+
dt.minute,
|
|
74
|
+
dt.second,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
info = zipfile.ZipInfo(arcname)
|
|
78
|
+
info.external_attr = 0o755 << 16 # rwxr-xr-x
|
|
79
|
+
info.date_time = date_time
|
|
80
|
+
|
|
81
|
+
with open(file_path, "rb") as f:
|
|
82
|
+
zipf.writestr(info, f.read())
|
|
83
|
+
except Exception as e:
|
|
84
|
+
print(f"Warning: Skipping file {arcname} due to error: {str(e)}")
|
|
85
|
+
|
|
86
|
+
print(f"Your .zip project size: {buffer.tell() / 1024 / 1024:.2f} MB")
|
|
87
|
+
return buffer.getvalue()
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def zip_and_encode_folder(folder_path: str) -> Tuple[bytes, int, Exception]:
|
|
91
|
+
"""
|
|
92
|
+
Zips a folder with system zip command (if available) or falls back to Python implementation.
|
|
93
|
+
Returns (zip_data, size_in_bytes, error) tuple.
|
|
94
|
+
"""
|
|
95
|
+
# Check for system zip first
|
|
96
|
+
if not shutil.which("zip"):
|
|
97
|
+
print("System zip command not found, using Python implementation")
|
|
98
|
+
try:
|
|
99
|
+
data = python_zip_implementation(folder_path)
|
|
100
|
+
return data, len(data), None
|
|
101
|
+
except Exception as e:
|
|
102
|
+
return None, 0, e
|
|
103
|
+
|
|
104
|
+
# print(f"Zipping folder: {folder_path}")
|
|
105
|
+
try:
|
|
106
|
+
ensure_executable_permissions(folder_path)
|
|
107
|
+
# Create zip process with explicit arguments
|
|
108
|
+
proc = subprocess.Popen(
|
|
109
|
+
[
|
|
110
|
+
"zip",
|
|
111
|
+
"-r",
|
|
112
|
+
"-q",
|
|
113
|
+
"-",
|
|
114
|
+
".",
|
|
115
|
+
"-x",
|
|
116
|
+
"*.git*",
|
|
117
|
+
"-x",
|
|
118
|
+
"*.venv*",
|
|
119
|
+
"-x",
|
|
120
|
+
"*__pycache__*",
|
|
121
|
+
"-x",
|
|
122
|
+
"*.pyc",
|
|
123
|
+
],
|
|
124
|
+
cwd=folder_path,
|
|
125
|
+
stdout=subprocess.PIPE,
|
|
126
|
+
stderr=subprocess.PIPE,
|
|
127
|
+
bufsize=1024 * 8, # 8KB buffer
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# Collect output with proper error handling
|
|
131
|
+
try:
|
|
132
|
+
stdout, stderr = proc.communicate(timeout=30)
|
|
133
|
+
if proc.returncode != 0:
|
|
134
|
+
print(f"Zip error: {stderr.decode()}")
|
|
135
|
+
data = python_zip_implementation(folder_path)
|
|
136
|
+
return data, len(data), None
|
|
137
|
+
|
|
138
|
+
if stdout:
|
|
139
|
+
size = len(stdout)
|
|
140
|
+
# print(f"Zip finished, size: {size / 1024 / 1024:.2f} MB")
|
|
141
|
+
return stdout, size, None
|
|
142
|
+
else:
|
|
143
|
+
print("No data from zip command, falling back to Python implementation")
|
|
144
|
+
data = python_zip_implementation(folder_path)
|
|
145
|
+
return data, len(data), None
|
|
146
|
+
|
|
147
|
+
except subprocess.TimeoutExpired:
|
|
148
|
+
proc.kill()
|
|
149
|
+
proc.wait(timeout=5) # Give it 5 seconds to cleanup
|
|
150
|
+
print("Zip process timed out, falling back to Python implementation")
|
|
151
|
+
try:
|
|
152
|
+
data = python_zip_implementation(folder_path)
|
|
153
|
+
return data, len(data), None
|
|
154
|
+
except Exception as e:
|
|
155
|
+
return None, 0, e
|
|
156
|
+
|
|
157
|
+
except Exception as e:
|
|
158
|
+
print(f"System zip error: {str(e)}")
|
|
159
|
+
try:
|
|
160
|
+
data = python_zip_implementation(folder_path)
|
|
161
|
+
return data, len(data), None
|
|
162
|
+
except Exception as e2:
|
|
163
|
+
return None, 0, e2
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def get_project_path() -> str:
|
|
167
|
+
"""Pack the whole project into a zip file."""
|
|
168
|
+
proj_dir = Path(__file__).parent.parent.parent
|
|
169
|
+
return proj_dir
|
|
170
|
+
|
|
171
|
+
|
|
172
|
+
def encoding():
|
|
173
|
+
with open("/root/test_data/test_zip.zip", "rb") as zip_file:
|
|
174
|
+
zip_binary = zip_file.read()
|
|
175
|
+
zip_base64 = base64.b64encode(zip_binary).decode("utf-8")
|
|
176
|
+
return zip_base64
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def hmac_sha256(key: bytes, content: str):
|
|
180
|
+
return hmac.new(key, content.encode("utf-8"), hashlib.sha256).digest()
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def hash_sha256(content: str):
|
|
184
|
+
return hashlib.sha256(content.encode("utf-8")).hexdigest()
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def norm_query(params):
|
|
188
|
+
query = ""
|
|
189
|
+
for key in sorted(params.keys()):
|
|
190
|
+
if isinstance(params[key], list):
|
|
191
|
+
for k in params[key]:
|
|
192
|
+
query = (
|
|
193
|
+
query + quote(key, safe="-_.~") + "=" + quote(k, safe="-_.~") + "&"
|
|
194
|
+
)
|
|
195
|
+
else:
|
|
196
|
+
query = (
|
|
197
|
+
query
|
|
198
|
+
+ quote(key, safe="-_.~")
|
|
199
|
+
+ "="
|
|
200
|
+
+ quote(params[key], safe="-_.~")
|
|
201
|
+
+ "&"
|
|
202
|
+
)
|
|
203
|
+
query = query[:-1]
|
|
204
|
+
return query.replace("+", "%20")
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def request(method, date, query, header, ak, sk, token, action, body):
|
|
208
|
+
credential = {
|
|
209
|
+
"access_key_id": ak,
|
|
210
|
+
"secret_access_key": sk,
|
|
211
|
+
"service": Service,
|
|
212
|
+
"region": Region,
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if token is not None:
|
|
216
|
+
credential["session_token"] = token
|
|
217
|
+
|
|
218
|
+
if action in [
|
|
219
|
+
"CodeUploadCallback",
|
|
220
|
+
"CreateDependencyInstallTask",
|
|
221
|
+
"GetReleaseStatus",
|
|
222
|
+
"GetDependencyInstallTaskStatus",
|
|
223
|
+
]:
|
|
224
|
+
credential["service"] = "vefaas"
|
|
225
|
+
|
|
226
|
+
content_type = ContentType
|
|
227
|
+
version = Version
|
|
228
|
+
if method == "POST":
|
|
229
|
+
content_type = "application/json"
|
|
230
|
+
|
|
231
|
+
if action == "CreateRoute" or action == "ListRoutes":
|
|
232
|
+
version = "2022-11-12"
|
|
233
|
+
|
|
234
|
+
request_param = {
|
|
235
|
+
"body": body,
|
|
236
|
+
"host": Host,
|
|
237
|
+
"path": "/",
|
|
238
|
+
"method": method,
|
|
239
|
+
"content_type": content_type,
|
|
240
|
+
"date": date,
|
|
241
|
+
"query": {"Action": action, "Version": version, **query},
|
|
242
|
+
}
|
|
243
|
+
if body is None:
|
|
244
|
+
request_param["body"] = ""
|
|
245
|
+
|
|
246
|
+
x_date = request_param["date"].strftime("%Y%m%dT%H%M%SZ")
|
|
247
|
+
short_x_date = x_date[:8]
|
|
248
|
+
x_content_sha256 = hash_sha256(request_param["body"])
|
|
249
|
+
sign_result = {
|
|
250
|
+
"Host": request_param["host"],
|
|
251
|
+
"X-Content-Sha256": x_content_sha256,
|
|
252
|
+
"X-Date": x_date,
|
|
253
|
+
"Content-Type": request_param["content_type"],
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
signed_headers_str = ";".join(
|
|
257
|
+
["content-type", "host", "x-content-sha256", "x-date"]
|
|
258
|
+
)
|
|
259
|
+
# signed_headers_str = signed_headers_str + ";x-security-token"
|
|
260
|
+
canonical_request_str = "\n".join(
|
|
261
|
+
[
|
|
262
|
+
request_param["method"].upper(),
|
|
263
|
+
request_param["path"],
|
|
264
|
+
norm_query(request_param["query"]),
|
|
265
|
+
"\n".join(
|
|
266
|
+
[
|
|
267
|
+
"content-type:" + request_param["content_type"],
|
|
268
|
+
"host:" + request_param["host"],
|
|
269
|
+
"x-content-sha256:" + x_content_sha256,
|
|
270
|
+
"x-date:" + x_date,
|
|
271
|
+
]
|
|
272
|
+
),
|
|
273
|
+
"",
|
|
274
|
+
signed_headers_str,
|
|
275
|
+
x_content_sha256,
|
|
276
|
+
]
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
hashed_canonical_request = hash_sha256(canonical_request_str)
|
|
280
|
+
|
|
281
|
+
credential_scope = "/".join(
|
|
282
|
+
[short_x_date, credential["region"], credential["service"], "request"]
|
|
283
|
+
)
|
|
284
|
+
string_to_sign = "\n".join(
|
|
285
|
+
["HMAC-SHA256", x_date, credential_scope, hashed_canonical_request]
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
k_date = hmac_sha256(credential["secret_access_key"].encode("utf-8"), short_x_date)
|
|
289
|
+
k_region = hmac_sha256(k_date, credential["region"])
|
|
290
|
+
k_service = hmac_sha256(k_region, credential["service"])
|
|
291
|
+
k_signing = hmac_sha256(k_service, "request")
|
|
292
|
+
signature = hmac_sha256(k_signing, string_to_sign).hex()
|
|
293
|
+
|
|
294
|
+
sign_result["Authorization"] = (
|
|
295
|
+
"HMAC-SHA256 Credential={}, SignedHeaders={}, Signature={}".format(
|
|
296
|
+
credential["access_key_id"] + "/" + credential_scope,
|
|
297
|
+
signed_headers_str,
|
|
298
|
+
signature,
|
|
299
|
+
)
|
|
300
|
+
)
|
|
301
|
+
header = {**header, **sign_result}
|
|
302
|
+
header = {**header, **{"X-Security-Token": token}}
|
|
303
|
+
r = requests.request(
|
|
304
|
+
method=method,
|
|
305
|
+
url="https://{}{}".format(request_param["host"], request_param["path"]),
|
|
306
|
+
headers=header,
|
|
307
|
+
params=request_param["query"],
|
|
308
|
+
data=request_param["body"],
|
|
309
|
+
)
|
|
310
|
+
return r.json()
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def signed_request(ak: str, sk: str, target: str, body: dict):
|
|
314
|
+
now = datetime.datetime.utcnow()
|
|
315
|
+
|
|
316
|
+
try:
|
|
317
|
+
response_body = request(
|
|
318
|
+
"POST",
|
|
319
|
+
now,
|
|
320
|
+
{},
|
|
321
|
+
{},
|
|
322
|
+
ak,
|
|
323
|
+
sk,
|
|
324
|
+
"",
|
|
325
|
+
target,
|
|
326
|
+
json.dumps(body),
|
|
327
|
+
)
|
|
328
|
+
return response_body
|
|
329
|
+
except Exception as e:
|
|
330
|
+
error_message = f"Error creating upstream: {str(e)}"
|
|
331
|
+
raise ValueError(error_message)
|
|
332
|
+
except ApiException as e:
|
|
333
|
+
print("Exception when calling API: %s\n" % e)
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def create_api_gateway_trigger(
|
|
337
|
+
ak, sk, function_id: str, api_gateway_id: str, service_id: str, region: str = None
|
|
338
|
+
):
|
|
339
|
+
token = ""
|
|
340
|
+
|
|
341
|
+
now = datetime.datetime.utcnow()
|
|
342
|
+
|
|
343
|
+
body = {
|
|
344
|
+
"Name": f"{function_id}-trigger",
|
|
345
|
+
"GatewayId": api_gateway_id,
|
|
346
|
+
"SourceType": "VeFaas",
|
|
347
|
+
"UpstreamSpec": {"VeFaas": {"FunctionId": function_id}},
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
try:
|
|
351
|
+
response_body = request(
|
|
352
|
+
"POST", now, {}, {}, ak, sk, token, "CreateUpstream", json.dumps(body)
|
|
353
|
+
)
|
|
354
|
+
# Print the full response for debugging
|
|
355
|
+
# print(f"Response: {json.dumps(response_body)}")
|
|
356
|
+
# Check if response contains an error
|
|
357
|
+
if "Error" in response_body or (
|
|
358
|
+
"ResponseMetadata" in response_body
|
|
359
|
+
and "Error" in response_body["ResponseMetadata"]
|
|
360
|
+
):
|
|
361
|
+
error_info = response_body.get("Error") or response_body[
|
|
362
|
+
"ResponseMetadata"
|
|
363
|
+
].get("Error")
|
|
364
|
+
error_message = f"API Error: {error_info.get('Message', 'Unknown error')}"
|
|
365
|
+
raise ValueError(error_message)
|
|
366
|
+
|
|
367
|
+
# Check if Result exists in the response
|
|
368
|
+
if "Result" not in response_body:
|
|
369
|
+
raise ValueError(f"API call did not return a Result field: {response_body}")
|
|
370
|
+
|
|
371
|
+
upstream_id = response_body["Result"]["Id"]
|
|
372
|
+
except Exception as e:
|
|
373
|
+
error_message = f"Error creating upstream: {str(e)}"
|
|
374
|
+
raise ValueError(error_message)
|
|
375
|
+
|
|
376
|
+
body = {
|
|
377
|
+
"Name": "router1",
|
|
378
|
+
"UpstreamList": [{"Type": "VeFaas", "UpstreamId": upstream_id, "Weight": 100}],
|
|
379
|
+
"ServiceId": service_id,
|
|
380
|
+
"MatchRule": {
|
|
381
|
+
"Method": ["POST", "GET", "PUT", "DELETE", "HEAD", "OPTIONS"],
|
|
382
|
+
"Path": {"MatchType": "Prefix", "MatchContent": "/"},
|
|
383
|
+
},
|
|
384
|
+
"AdvancedSetting": {
|
|
385
|
+
"TimeoutSetting": {"Enable": False, "Timeout": 30},
|
|
386
|
+
"CorsPolicySetting": {"Enable": False},
|
|
387
|
+
},
|
|
388
|
+
}
|
|
389
|
+
try:
|
|
390
|
+
response_body = request(
|
|
391
|
+
"POST", now, {}, {}, ak, sk, token, "CreateRoute", json.dumps(body)
|
|
392
|
+
)
|
|
393
|
+
except Exception as e:
|
|
394
|
+
error_message = f"Error creating route: {str(e)}"
|
|
395
|
+
raise ValueError(error_message)
|
|
396
|
+
return response_body
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
def list_routes(ak, sk, upstream_id: str):
|
|
400
|
+
now = datetime.datetime.utcnow()
|
|
401
|
+
token = ""
|
|
402
|
+
|
|
403
|
+
body = {"UpstreamId": upstream_id}
|
|
404
|
+
|
|
405
|
+
response_body = request(
|
|
406
|
+
"POST", now, {}, {}, ak, sk, token, "ListRoutes", json.dumps(body)
|
|
407
|
+
)
|
|
408
|
+
return response_body
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from .vetls import VeTLS
|
|
16
|
+
|
|
17
|
+
__all__ = ["VeTLS"]
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from __future__ import absolute_import, division, print_function
|
|
16
|
+
|
|
17
|
+
import ast
|
|
18
|
+
import json
|
|
19
|
+
from collections import defaultdict
|
|
20
|
+
from datetime import datetime, timedelta
|
|
21
|
+
|
|
22
|
+
from volcengine.tls.tls_requests import SearchLogsRequest
|
|
23
|
+
from volcengine.tls.TLSService import TLSService
|
|
24
|
+
|
|
25
|
+
from veadk.utils.logger import get_logger
|
|
26
|
+
|
|
27
|
+
logger = get_logger(__name__)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class VeTLS:
|
|
31
|
+
def __init__(
|
|
32
|
+
self,
|
|
33
|
+
access_key: str,
|
|
34
|
+
secret_key: str,
|
|
35
|
+
dump_path: str,
|
|
36
|
+
endpoint: str = "https://tls-cn-beijing.volces.com",
|
|
37
|
+
region: str = "cn-beijing",
|
|
38
|
+
):
|
|
39
|
+
self.client = TLSService(endpoint, access_key, secret_key, region)
|
|
40
|
+
self.dump_path: str = dump_path
|
|
41
|
+
|
|
42
|
+
def query(self, topic_id: str, query: str):
|
|
43
|
+
logger.warning("Currently, we only search the logs in the last 24 hours.")
|
|
44
|
+
now = datetime.now()
|
|
45
|
+
one_day_ago = now - timedelta(days=1)
|
|
46
|
+
one_day_ago = int(one_day_ago.timestamp() * 1000)
|
|
47
|
+
now = int(now.timestamp() * 1000)
|
|
48
|
+
|
|
49
|
+
search_logs_request = SearchLogsRequest(
|
|
50
|
+
topic_id=topic_id,
|
|
51
|
+
query=query,
|
|
52
|
+
limit=100,
|
|
53
|
+
start_time=one_day_ago,
|
|
54
|
+
end_time=now,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
search_logs_response = self.client.search_logs_v2(search_logs_request)
|
|
58
|
+
log_str_list = search_logs_response.get_search_result().get_logs()
|
|
59
|
+
log_dict_list = []
|
|
60
|
+
for log in log_str_list:
|
|
61
|
+
# message: str -> dict
|
|
62
|
+
message = ast.literal_eval(log["message"])
|
|
63
|
+
trace_id = log.get("trace_id")
|
|
64
|
+
log_dict_list.append(
|
|
65
|
+
{
|
|
66
|
+
"trace_id": trace_id,
|
|
67
|
+
"message": message,
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
log_dict_list = log_dict_list[::-1]
|
|
71
|
+
|
|
72
|
+
# 创建一个默认为 list 的字典来聚合
|
|
73
|
+
grouped = defaultdict(list)
|
|
74
|
+
|
|
75
|
+
# 遍历原始数据,按 key 分组
|
|
76
|
+
for item in log_dict_list:
|
|
77
|
+
grouped[item["trace_id"]].append(item["message"])
|
|
78
|
+
result = [{"trace_id": k, "data": v} for k, v in grouped.items()]
|
|
79
|
+
|
|
80
|
+
self.dump_to_file(result)
|
|
81
|
+
|
|
82
|
+
def dump_to_file(self, logs: list[dict]):
|
|
83
|
+
with open(f"{self.dump_path}/logs.json", "w", encoding="utf-8") as f:
|
|
84
|
+
json.dump(logs, f, ensure_ascii=False, indent=4)
|
|
85
|
+
logger.info(f"VeTLS dumps log list to {self.dump_path}/logs.json")
|
|
86
|
+
logger.info(f"VeTLS dumps log list to {self.dump_path}/logs.json")
|
|
87
|
+
logger.info(f"VeTLS dumps log list to {self.dump_path}/logs.json")
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|