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.

Files changed (110) hide show
  1. veadk/__init__.py +31 -0
  2. veadk/a2a/__init__.py +13 -0
  3. veadk/a2a/agent_card.py +45 -0
  4. veadk/a2a/remote_ve_agent.py +19 -0
  5. veadk/a2a/ve_a2a_server.py +77 -0
  6. veadk/a2a/ve_agent_executor.py +78 -0
  7. veadk/a2a/ve_task_store.py +37 -0
  8. veadk/agent.py +253 -0
  9. veadk/cli/__init__.py +13 -0
  10. veadk/cli/main.py +278 -0
  11. veadk/cli/services/agentpilot/__init__.py +17 -0
  12. veadk/cli/services/agentpilot/agentpilot.py +77 -0
  13. veadk/cli/services/veapig/__init__.py +17 -0
  14. veadk/cli/services/veapig/apig.py +224 -0
  15. veadk/cli/services/veapig/apig_utils.py +332 -0
  16. veadk/cli/services/vefaas/__init__.py +17 -0
  17. veadk/cli/services/vefaas/template/deploy.py +44 -0
  18. veadk/cli/services/vefaas/template/src/app.py +30 -0
  19. veadk/cli/services/vefaas/template/src/config.py +58 -0
  20. veadk/cli/services/vefaas/vefaas.py +346 -0
  21. veadk/cli/services/vefaas/vefaas_utils.py +408 -0
  22. veadk/cli/services/vetls/__init__.py +17 -0
  23. veadk/cli/services/vetls/vetls.py +87 -0
  24. veadk/cli/studio/__init__.py +13 -0
  25. veadk/cli/studio/agent_processor.py +247 -0
  26. veadk/cli/studio/fast_api.py +232 -0
  27. veadk/cli/studio/model.py +116 -0
  28. veadk/cloud/__init__.py +13 -0
  29. veadk/cloud/cloud_agent_engine.py +144 -0
  30. veadk/cloud/cloud_app.py +123 -0
  31. veadk/cloud/template/app.py +30 -0
  32. veadk/cloud/template/config.py +55 -0
  33. veadk/config.py +131 -0
  34. veadk/consts.py +17 -0
  35. veadk/database/__init__.py +17 -0
  36. veadk/database/base_database.py +45 -0
  37. veadk/database/database_factory.py +80 -0
  38. veadk/database/kv/__init__.py +13 -0
  39. veadk/database/kv/redis_database.py +109 -0
  40. veadk/database/local_database.py +43 -0
  41. veadk/database/relational/__init__.py +13 -0
  42. veadk/database/relational/mysql_database.py +114 -0
  43. veadk/database/vector/__init__.py +13 -0
  44. veadk/database/vector/opensearch_vector_database.py +205 -0
  45. veadk/database/vector/type.py +50 -0
  46. veadk/database/viking/__init__.py +13 -0
  47. veadk/database/viking/viking_database.py +378 -0
  48. veadk/database/viking/viking_memory_db.py +521 -0
  49. veadk/evaluation/__init__.py +17 -0
  50. veadk/evaluation/adk_evaluator/__init__.py +13 -0
  51. veadk/evaluation/adk_evaluator/adk_evaluator.py +291 -0
  52. veadk/evaluation/base_evaluator.py +242 -0
  53. veadk/evaluation/deepeval_evaluator/__init__.py +17 -0
  54. veadk/evaluation/deepeval_evaluator/deepeval_evaluator.py +223 -0
  55. veadk/evaluation/eval_set_file_loader.py +28 -0
  56. veadk/evaluation/eval_set_recorder.py +91 -0
  57. veadk/evaluation/utils/prometheus.py +142 -0
  58. veadk/knowledgebase/__init__.py +17 -0
  59. veadk/knowledgebase/knowledgebase.py +83 -0
  60. veadk/knowledgebase/knowledgebase_database_adapter.py +259 -0
  61. veadk/memory/__init__.py +13 -0
  62. veadk/memory/long_term_memory.py +119 -0
  63. veadk/memory/memory_database_adapter.py +235 -0
  64. veadk/memory/short_term_memory.py +124 -0
  65. veadk/memory/short_term_memory_processor.py +90 -0
  66. veadk/prompts/__init__.py +13 -0
  67. veadk/prompts/agent_default_prompt.py +30 -0
  68. veadk/prompts/prompt_evaluator.py +20 -0
  69. veadk/prompts/prompt_memory_processor.py +55 -0
  70. veadk/prompts/prompt_optimization.py +158 -0
  71. veadk/runner.py +252 -0
  72. veadk/tools/__init__.py +13 -0
  73. veadk/tools/builtin_tools/__init__.py +13 -0
  74. veadk/tools/builtin_tools/lark.py +67 -0
  75. veadk/tools/builtin_tools/las.py +23 -0
  76. veadk/tools/builtin_tools/vesearch.py +49 -0
  77. veadk/tools/builtin_tools/web_scraper.py +76 -0
  78. veadk/tools/builtin_tools/web_search.py +192 -0
  79. veadk/tools/demo_tools.py +58 -0
  80. veadk/tools/load_knowledgebase_tool.py +144 -0
  81. veadk/tools/sandbox/__init__.py +13 -0
  82. veadk/tools/sandbox/browser_sandbox.py +27 -0
  83. veadk/tools/sandbox/code_sandbox.py +30 -0
  84. veadk/tools/sandbox/computer_sandbox.py +27 -0
  85. veadk/tracing/__init__.py +13 -0
  86. veadk/tracing/base_tracer.py +172 -0
  87. veadk/tracing/telemetry/__init__.py +13 -0
  88. veadk/tracing/telemetry/exporters/__init__.py +13 -0
  89. veadk/tracing/telemetry/exporters/apiserver_exporter.py +60 -0
  90. veadk/tracing/telemetry/exporters/apmplus_exporter.py +101 -0
  91. veadk/tracing/telemetry/exporters/base_exporter.py +28 -0
  92. veadk/tracing/telemetry/exporters/cozeloop_exporter.py +69 -0
  93. veadk/tracing/telemetry/exporters/inmemory_exporter.py +88 -0
  94. veadk/tracing/telemetry/exporters/tls_exporter.py +78 -0
  95. veadk/tracing/telemetry/metrics/__init__.py +13 -0
  96. veadk/tracing/telemetry/metrics/opentelemetry_metrics.py +73 -0
  97. veadk/tracing/telemetry/opentelemetry_tracer.py +167 -0
  98. veadk/types.py +23 -0
  99. veadk/utils/__init__.py +13 -0
  100. veadk/utils/logger.py +59 -0
  101. veadk/utils/misc.py +33 -0
  102. veadk/utils/patches.py +85 -0
  103. veadk/utils/volcengine_sign.py +199 -0
  104. veadk/version.py +15 -0
  105. veadk_python-0.1.0.dist-info/METADATA +124 -0
  106. veadk_python-0.1.0.dist-info/RECORD +110 -0
  107. veadk_python-0.1.0.dist-info/WHEEL +5 -0
  108. veadk_python-0.1.0.dist-info/entry_points.txt +2 -0
  109. veadk_python-0.1.0.dist-info/licenses/LICENSE +201 -0
  110. 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.