|
| 1 | +import asyncio |
1 | 2 | import atexit |
2 | 3 | import contextlib |
| 4 | +import hashlib |
| 5 | +import http.client |
| 6 | +import json |
| 7 | +import platform |
3 | 8 | import socket |
4 | 9 | import sys |
| 10 | +import uuid |
| 11 | +from importlib import metadata |
| 12 | +from threading import Thread |
| 13 | +from typing import Any |
5 | 14 |
|
6 | 15 | import click |
7 | 16 | import requests |
|
10 | 19 | from requests.adapters import DEFAULT_POOLBLOCK, HTTPAdapter |
11 | 20 | from urllib3 import HTTPConnectionPool, HTTPSConnectionPool, PoolManager |
12 | 21 |
|
13 | | -from patchwork.common.utils import get_current_branch |
| 22 | +from patchwork.common.utils import get_current_branch, is_container |
14 | 23 | from patchwork.logger import logger |
15 | 24 |
|
16 | 25 |
|
@@ -64,6 +73,7 @@ def init_poolmanager(self, connections, maxsize, block=DEFAULT_POOLBLOCK, **pool |
64 | 73 | class PatchedClient(click.ParamType): |
65 | 74 | TOKEN_URL = "https://app.patched.codes/signin" |
66 | 75 | DEFAULT_PATCH_URL = "https://patchwork.patched.codes" |
| 76 | + ALLOWED_TELEMETRY_KEYS = {"model",} |
67 | 77 |
|
68 | 78 | def __init__(self, access_token: str, url: str = DEFAULT_PATCH_URL): |
69 | 79 | self.access_token = access_token |
@@ -119,6 +129,41 @@ def test_token(self) -> bool: |
119 | 129 |
|
120 | 130 | return body["msg"] == "ok" |
121 | 131 |
|
| 132 | + def __handle_telemetry_inputs(self, inputs: dict[str, Any]) -> dict: |
| 133 | + diff_keys = set(inputs.keys()).difference(self.ALLOWED_TELEMETRY_KEYS) |
| 134 | + |
| 135 | + inputs_copy = inputs.copy() |
| 136 | + for key in diff_keys: |
| 137 | + inputs_copy[key] = True |
| 138 | + |
| 139 | + return inputs_copy |
| 140 | + |
| 141 | + async def _public_telemetry(self, patchflow: str, inputs: dict[str, Any]): |
| 142 | + requests.post( |
| 143 | + url=self.url + "/v1/telemetry/", |
| 144 | + headers={"Authorization": f"Bearer {self.access_token}"}, |
| 145 | + json=dict( |
| 146 | + client_id=hashlib.sha256(str(uuid.getnode()).encode()).hexdigest(), |
| 147 | + patchflow=patchflow, |
| 148 | + inputs=self.__handle_telemetry_inputs(inputs), |
| 149 | + environment=dict( |
| 150 | + system=platform.system(), |
| 151 | + release=platform.release(), |
| 152 | + machine=platform.machine(), |
| 153 | + python_version=platform.python_version(), |
| 154 | + cli_version=metadata.version("patchwork-cli"), |
| 155 | + is_container=is_container(), |
| 156 | + ), |
| 157 | + ), |
| 158 | + ) |
| 159 | + |
| 160 | + def send_public_telemetry(self, patchflow: str, inputs: dict): |
| 161 | + try: |
| 162 | + _thread = Thread(target=asyncio.run, args=(self._public_telemetry(patchflow, inputs),)) |
| 163 | + _thread.start() |
| 164 | + except Exception as e: |
| 165 | + logger.debug(f"Failed to send public telemetry: {e}") |
| 166 | + |
122 | 167 | @contextlib.contextmanager |
123 | 168 | def patched_telemetry(self, patchflow: str, repo: Repo, inputs: dict): |
124 | 169 | if not self.access_token: |
|
0 commit comments