Skip to content

Commit e436aba

Browse files
blktrdimitrov
authored and
Luke Hinds
committed
Add utilities to dump Copilot traffic. (#664)
This change adds a utility routine to dump raw data tapped from the wire to multiple files in a temporary directory under the path specified via `CODEGATE_DUMP_DIR`. No instrumentation is performed if `CODEGATE_DUMP_DIR` is `None`. The temporary directory is not deleted when the process exits. NOTE: the utility does not ensure the folder specified via `CODEGATE_DUMP_DIR` is writable, which might cause user-visible failures at startup. Co-authored-by: Radoslav Dimitrov <[email protected]>
1 parent 332a934 commit e436aba

File tree

1 file changed

+40
-0
lines changed

1 file changed

+40
-0
lines changed

src/codegate/providers/copilot/provider.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import asyncio
2+
import contextlib
3+
import datetime
4+
import os
25
import re
36
import ssl
7+
import tempfile
48
from dataclasses import dataclass
59
from typing import Dict, List, Optional, Tuple, Union
610
from urllib.parse import unquote, urljoin, urlparse
@@ -26,6 +30,41 @@
2630
setup_logging()
2731
logger = structlog.get_logger("codegate").bind(origin="copilot_proxy")
2832

33+
34+
TEMPDIR = None
35+
if os.getenv("CODEGATE_DUMP_DIR"):
36+
basedir = os.getenv("CODEGATE_DUMP_DIR")
37+
TEMPDIR = tempfile.TemporaryDirectory(prefix="codegate-", dir=basedir, delete=False)
38+
39+
40+
def _dump_data(suffix, func):
41+
if os.getenv("CODEGATE_DUMP_DIR"):
42+
buf = bytearray(b"")
43+
44+
def inner(self, data: bytes):
45+
nonlocal buf
46+
func(self, data)
47+
buf.extend(data)
48+
49+
if data == b"0\r\n\r\n":
50+
ts = datetime.datetime.now()
51+
fname = os.path.join(TEMPDIR.name, ts.strftime(f"{suffix}-%Y%m%dT%H%M%S%f.txt"))
52+
with open(fname, mode="wb") as fd:
53+
fd.write(buf)
54+
buf = bytearray()
55+
56+
return inner
57+
return func
58+
59+
60+
def _dump_request(func):
61+
return _dump_data("request", func)
62+
63+
64+
def _dump_response(func):
65+
return _dump_data("response", func)
66+
67+
2968
# Constants
3069
MAX_BUFFER_SIZE = 10 * 1024 * 1024 # 10MB
3170
CHUNK_SIZE = 64 * 1024 # 64KB
@@ -914,6 +953,7 @@ def _process_chunk(self, chunk: bytes):
914953

915954
self.stream_queue.put_nowait(record)
916955

956+
@_dump_response
917957
def _proxy_transport_write(self, data: bytes):
918958
# For debugging only
919959
# self.data_sent.append(data)

0 commit comments

Comments
 (0)