|
19 | 19 |
|
20 | 20 | from typing import List
|
21 | 21 |
|
22 |
| -from .common import ClientError, LoginError, WorkspaceRole, ProjectRole |
| 22 | +from .common import ClientError, LoginError, WorkspaceRole, ProjectRole, LOG_FILE_SIZE_TO_SEND, MERGIN_DEFAULT_LOGS_URL |
23 | 23 | from .merginproject import MerginProject
|
24 | 24 | from .client_pull import (
|
25 | 25 | download_file_finalize,
|
@@ -1360,3 +1360,64 @@ def remove_project_collaborator(self, project_id: str, user_id: int):
|
1360 | 1360 | Remove a user from project collaborators
|
1361 | 1361 | """
|
1362 | 1362 | self.delete(f"v2/projects/{project_id}/collaborators/{user_id}")
|
| 1363 | + |
| 1364 | + def server_config(self) -> dict: |
| 1365 | + """Get server configuration as dictionary.""" |
| 1366 | + response = self.get("/config") |
| 1367 | + return json.load(response) |
| 1368 | + |
| 1369 | + def send_logs( |
| 1370 | + self, |
| 1371 | + logfile: str, |
| 1372 | + global_log_file: typing.Optional[str] = None, |
| 1373 | + application: typing.Optional[str] = None, |
| 1374 | + meta: typing.Optional[str] = None, |
| 1375 | + ): |
| 1376 | + """Send logs to configured server or the default Mergin server.""" |
| 1377 | + |
| 1378 | + if application is None: |
| 1379 | + application = "mergin-client-{}".format(__version__) |
| 1380 | + |
| 1381 | + params = {"app": application, "username": self.username()} |
| 1382 | + |
| 1383 | + config = self.server_config() |
| 1384 | + diagnostic_logs_url = config.get("diagnostic_logs_url", None) |
| 1385 | + |
| 1386 | + use_server_api = False |
| 1387 | + if is_version_acceptable(self.server_version(), "2025.4.1") and ( |
| 1388 | + diagnostic_logs_url is None or diagnostic_logs_url == "" |
| 1389 | + ): |
| 1390 | + url = "v2/diagnostic-logs" + "?" + urllib.parse.urlencode(params) |
| 1391 | + use_server_api = True |
| 1392 | + else: |
| 1393 | + if diagnostic_logs_url: |
| 1394 | + url = diagnostic_logs_url + "?" + urllib.parse.urlencode(params) |
| 1395 | + else: |
| 1396 | + # fallback to default logs URL |
| 1397 | + url = MERGIN_DEFAULT_LOGS_URL + "?" + urllib.parse.urlencode(params) |
| 1398 | + |
| 1399 | + if meta is None: |
| 1400 | + meta = "Python API Client\nSystem: {} \nMergin Maps URL: {} \nMergin Maps user: {} \n--------------------------------\n\n".format( |
| 1401 | + platform.system(), self.url, self.username() |
| 1402 | + ) |
| 1403 | + |
| 1404 | + global_logs = b"" |
| 1405 | + if global_log_file and os.path.exists(global_log_file): |
| 1406 | + with open(global_log_file, "rb") as f: |
| 1407 | + if os.path.getsize(global_log_file) > LOG_FILE_SIZE_TO_SEND: |
| 1408 | + f.seek(-LOG_FILE_SIZE_TO_SEND, os.SEEK_END) |
| 1409 | + global_logs = f.read() + b"\n--------------------------------\n\n" |
| 1410 | + |
| 1411 | + with open(logfile, "rb") as f: |
| 1412 | + if os.path.getsize(logfile) > 512 * 1024: |
| 1413 | + f.seek(-512 * 1024, os.SEEK_END) |
| 1414 | + logs = f.read() |
| 1415 | + |
| 1416 | + payload = meta.encode() + global_logs + logs |
| 1417 | + header = {"content-type": "text/plain"} |
| 1418 | + |
| 1419 | + if use_server_api: |
| 1420 | + return self.post(url, data=payload, headers=header) |
| 1421 | + else: |
| 1422 | + request = urllib.request.Request(url, data=payload, headers=header) |
| 1423 | + return self._do_request(request) |
0 commit comments