We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Increase WebSocket message timestamp precision
#### Is your feature request related to a problem? Please describe.
Timestamps for WebSocket messages are rounded to whole seconds. For at least some protocols or analyses, a higher precision may be useful or even necessary for productive use; one example is measuring the performance impact of mitmproxy.

#### Describe the solution you'd like
Avoid converting the timestamp to an integer and use a float instead:

https://github.com/mitmproxy/mitmproxy/blob/7fdcbb09e6034ab1f76724965cfdf45f3d775129/mitmproxy/websocket.py#L28

Basic support for higher-precision timestamps seems to be as simple as changing the type of `WebSocketMessage.timestamp` from `int` to `float` and dropping the `int()` call around `time.time()`. I'm not sure if more is needed e.g. to ensure backward compatibility, but I was able to read a previous dump just fine with that modification (which makes sense since integers in the relevant range are strictly a subset of double-precision floats).

#### Describe alternatives you've considered
If keeping the `timestamp` an `int` is unavoidable, the Linux approach of storing the microseconds in a second integer (between 0 and 999999, inclusive) could be used. I don't think this is a good idea though.

#### Additional context
None

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mitmproxy/websocket.py`
Content:
```
1 import time
2 import queue
3 from typing import List, Optional
4 
5 from wsproto.frame_protocol import CloseReason
6 from wsproto.frame_protocol import Opcode
7 
8 from mitmproxy import flow
9 from mitmproxy.net import websockets
10 from mitmproxy.coretypes import serializable
11 from mitmproxy.utils import strutils, human
12 
13 
14 class WebSocketMessage(serializable.Serializable):
15     """
16     A WebSocket message sent from one endpoint to the other.
17     """
18 
19     def __init__(
20         self, type: int, from_client: bool, content: bytes, timestamp: Optional[int]=None, killed: bool=False
21     ) -> None:
22         self.type = Opcode(type)  # type: ignore
23         """indicates either TEXT or BINARY (from wsproto.frame_protocol.Opcode)."""
24         self.from_client = from_client
25         """True if this messages was sent by the client."""
26         self.content = content
27         """A byte-string representing the content of this message."""
28         self.timestamp: int = timestamp or int(time.time())
29         """Timestamp of when this message was received or created."""
30         self.killed = killed
31         """True if this messages was killed and should not be sent to the other endpoint."""
32 
33     @classmethod
34     def from_state(cls, state):
35         return cls(*state)
36 
37     def get_state(self):
38         return int(self.type), self.from_client, self.content, self.timestamp, self.killed
39 
40     def set_state(self, state):
41         self.type, self.from_client, self.content, self.timestamp, self.killed = state
42         self.type = Opcode(self.type)  # replace enum with bare int
43 
44     def __repr__(self):
45         if self.type == Opcode.TEXT:
46             return "text message: {}".format(repr(self.content))
47         else:
48             return "binary message: {}".format(strutils.bytes_to_escaped_str(self.content))
49 
50     def kill(self):
51         """
52         Kill this message.
53 
54         It will not be sent to the other endpoint. This has no effect in streaming mode.
55         """
56         self.killed = True
57 
58 
59 class WebSocketFlow(flow.Flow):
60     """
61     A WebSocketFlow is a simplified representation of a Websocket connection.
62     """
63 
64     def __init__(self, client_conn, server_conn, handshake_flow, live=None):
65         super().__init__("websocket", client_conn, server_conn, live)
66 
67         self.messages: List[WebSocketMessage] = []
68         """A list containing all WebSocketMessage's."""
69         self.close_sender = 'client'
70         """'client' if the client initiated connection closing."""
71         self.close_code = CloseReason.NORMAL_CLOSURE
72         """WebSocket close code."""
73         self.close_message = '(message missing)'
74         """WebSocket close message."""
75         self.close_reason = 'unknown status code'
76         """WebSocket close reason."""
77         self.stream = False
78         """True of this connection is streaming directly to the other endpoint."""
79         self.handshake_flow = handshake_flow
80         """The HTTP flow containing the initial WebSocket handshake."""
81         self.ended = False
82         """True when the WebSocket connection has been closed."""
83 
84         self._inject_messages_client = queue.Queue(maxsize=1)
85         self._inject_messages_server = queue.Queue(maxsize=1)
86 
87         if handshake_flow:
88             self.client_key = websockets.get_client_key(handshake_flow.request.headers)
89             self.client_protocol = websockets.get_protocol(handshake_flow.request.headers)
90             self.client_extensions = websockets.get_extensions(handshake_flow.request.headers)
91             self.server_accept = websockets.get_server_accept(handshake_flow.response.headers)
92             self.server_protocol = websockets.get_protocol(handshake_flow.response.headers)
93             self.server_extensions = websockets.get_extensions(handshake_flow.response.headers)
94         else:
95             self.client_key = ''
96             self.client_protocol = ''
97             self.client_extensions = ''
98             self.server_accept = ''
99             self.server_protocol = ''
100             self.server_extensions = ''
101 
102     _stateobject_attributes = flow.Flow._stateobject_attributes.copy()
103     # mypy doesn't support update with kwargs
104     _stateobject_attributes.update(dict(
105         messages=List[WebSocketMessage],
106         close_sender=str,
107         close_code=int,
108         close_message=str,
109         close_reason=str,
110         client_key=str,
111         client_protocol=str,
112         client_extensions=str,
113         server_accept=str,
114         server_protocol=str,
115         server_extensions=str,
116         # Do not include handshake_flow, to prevent recursive serialization!
117         # Since mitmproxy-console currently only displays HTTPFlows,
118         # dumping the handshake_flow will include the WebSocketFlow too.
119     ))
120 
121     def get_state(self):
122         d = super().get_state()
123         d['close_code'] = int(d['close_code'])  # replace enum with bare int
124         return d
125 
126     @classmethod
127     def from_state(cls, state):
128         f = cls(None, None, None)
129         f.set_state(state)
130         return f
131 
132     def __repr__(self):
133         return "<WebSocketFlow ({} messages)>".format(len(self.messages))
134 
135     def message_info(self, message: WebSocketMessage) -> str:
136         return "{client} {direction} WebSocket {type} message {direction} {server}{endpoint}".format(
137             type=message.type,
138             client=human.format_address(self.client_conn.address),
139             server=human.format_address(self.server_conn.address),
140             direction="->" if message.from_client else "<-",
141             endpoint=self.handshake_flow.request.path,
142         )
143 
144     def inject_message(self, endpoint, payload):
145         """
146         Inject and send a full WebSocket message to the remote endpoint.
147         This might corrupt your WebSocket connection! Be careful!
148 
149         The endpoint needs to be either flow.client_conn or flow.server_conn.
150 
151         If ``payload`` is of type ``bytes`` then the message is flagged as
152         being binary If it is of type ``str`` encoded as UTF-8 and sent as
153         text.
154 
155         :param payload: The message body to send.
156         :type payload: ``bytes`` or ``str``
157         """
158 
159         if endpoint == self.client_conn:
160             self._inject_messages_client.put(payload)
161         elif endpoint == self.server_conn:
162             self._inject_messages_server.put(payload)
163         else:
164             raise ValueError('Invalid endpoint')
165
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/mitmproxy/websocket.py b/mitmproxy/websocket.py
--- a/mitmproxy/websocket.py
+++ b/mitmproxy/websocket.py
@@ -17,7 +17,7 @@
     """
 
     def __init__(
-        self, type: int, from_client: bool, content: bytes, timestamp: Optional[int]=None, killed: bool=False
+        self, type: int, from_client: bool, content: bytes, timestamp: Optional[float]=None, killed: bool=False
     ) -> None:
         self.type = Opcode(type)  # type: ignore
         """indicates either TEXT or BINARY (from wsproto.frame_protocol.Opcode)."""
@@ -25,7 +25,7 @@
         """True if this messages was sent by the client."""
         self.content = content
         """A byte-string representing the content of this message."""
-        self.timestamp: int = timestamp or int(time.time())
+        self.timestamp: float = timestamp or time.time()
         """Timestamp of when this message was received or created."""
         self.killed = killed
         """True if this messages was killed and should not be sent to the other endpoint."""

{"golden_diff": "diff --git a/mitmproxy/websocket.py b/mitmproxy/websocket.py\n--- a/mitmproxy/websocket.py\n+++ b/mitmproxy/websocket.py\n@@ -17,7 +17,7 @@\n     \"\"\"\n \n     def __init__(\n-        self, type: int, from_client: bool, content: bytes, timestamp: Optional[int]=None, killed: bool=False\n+        self, type: int, from_client: bool, content: bytes, timestamp: Optional[float]=None, killed: bool=False\n     ) -> None:\n         self.type = Opcode(type)  # type: ignore\n         \"\"\"indicates either TEXT or BINARY (from wsproto.frame_protocol.Opcode).\"\"\"\n@@ -25,7 +25,7 @@\n         \"\"\"True if this messages was sent by the client.\"\"\"\n         self.content = content\n         \"\"\"A byte-string representing the content of this message.\"\"\"\n-        self.timestamp: int = timestamp or int(time.time())\n+        self.timestamp: float = timestamp or time.time()\n         \"\"\"Timestamp of when this message was received or created.\"\"\"\n         self.killed = killed\n         \"\"\"True if this messages was killed and should not be sent to the other endpoint.\"\"\"\n", "issue": "Increase WebSocket message timestamp precision\n#### Is your feature request related to a problem? Please describe.\r\nTimestamps for WebSocket messages are rounded to whole seconds. For at least some protocols or analyses, a higher precision may be useful or even necessary for productive use; one example is measuring the performance impact of mitmproxy.\r\n\r\n#### Describe the solution you'd like\r\nAvoid converting the timestamp to an integer and use a float instead:\r\n\r\nhttps://github.com/mitmproxy/mitmproxy/blob/7fdcbb09e6034ab1f76724965cfdf45f3d775129/mitmproxy/websocket.py#L28\r\n\r\nBasic support for higher-precision timestamps seems to be as simple as changing the type of `WebSocketMessage.timestamp` from `int` to `float` and dropping the `int()` call around `time.time()`. I'm not sure if more is needed e.g. to ensure backward compatibility, but I was able to read a previous dump just fine with that modification (which makes sense since integers in the relevant range are strictly a subset of double-precision floats).\r\n\r\n#### Describe alternatives you've considered\r\nIf keeping the `timestamp` an `int` is unavoidable, the Linux approach of storing the microseconds in a second integer (between 0 and 999999, inclusive) could be used. I don't think this is a good idea though.\r\n\r\n#### Additional context\r\nNone\n", "before_files": [{"content": "import time\nimport queue\nfrom typing import List, Optional\n\nfrom wsproto.frame_protocol import CloseReason\nfrom wsproto.frame_protocol import Opcode\n\nfrom mitmproxy import flow\nfrom mitmproxy.net import websockets\nfrom mitmproxy.coretypes import serializable\nfrom mitmproxy.utils import strutils, human\n\n\nclass WebSocketMessage(serializable.Serializable):\n    \"\"\"\n    A WebSocket message sent from one endpoint to the other.\n    \"\"\"\n\n    def __init__(\n        self, type: int, from_client: bool, content: bytes, timestamp: Optional[int]=None, killed: bool=False\n    ) -> None:\n        self.type = Opcode(type)  # type: ignore\n        \"\"\"indicates either TEXT or BINARY (from wsproto.frame_protocol.Opcode).\"\"\"\n        self.from_client = from_client\n        \"\"\"True if this messages was sent by the client.\"\"\"\n        self.content = content\n        \"\"\"A byte-string representing the content of this message.\"\"\"\n        self.timestamp: int = timestamp or int(time.time())\n        \"\"\"Timestamp of when this message was received or created.\"\"\"\n        self.killed = killed\n        \"\"\"True if this messages was killed and should not be sent to the other endpoint.\"\"\"\n\n    @classmethod\n    def from_state(cls, state):\n        return cls(*state)\n\n    def get_state(self):\n        return int(self.type), self.from_client, self.content, self.timestamp, self.killed\n\n    def set_state(self, state):\n        self.type, self.from_client, self.content, self.timestamp, self.killed = state\n        self.type = Opcode(self.type)  # replace enum with bare int\n\n    def __repr__(self):\n        if self.type == Opcode.TEXT:\n            return \"text message: {}\".format(repr(self.content))\n        else:\n            return \"binary message: {}\".format(strutils.bytes_to_escaped_str(self.content))\n\n    def kill(self):\n        \"\"\"\n        Kill this message.\n\n        It will not be sent to the other endpoint. This has no effect in streaming mode.\n        \"\"\"\n        self.killed = True\n\n\nclass WebSocketFlow(flow.Flow):\n    \"\"\"\n    A WebSocketFlow is a simplified representation of a Websocket connection.\n    \"\"\"\n\n    def __init__(self, client_conn, server_conn, handshake_flow, live=None):\n        super().__init__(\"websocket\", client_conn, server_conn, live)\n\n        self.messages: List[WebSocketMessage] = []\n        \"\"\"A list containing all WebSocketMessage's.\"\"\"\n        self.close_sender = 'client'\n        \"\"\"'client' if the client initiated connection closing.\"\"\"\n        self.close_code = CloseReason.NORMAL_CLOSURE\n        \"\"\"WebSocket close code.\"\"\"\n        self.close_message = '(message missing)'\n        \"\"\"WebSocket close message.\"\"\"\n        self.close_reason = 'unknown status code'\n        \"\"\"WebSocket close reason.\"\"\"\n        self.stream = False\n        \"\"\"True of this connection is streaming directly to the other endpoint.\"\"\"\n        self.handshake_flow = handshake_flow\n        \"\"\"The HTTP flow containing the initial WebSocket handshake.\"\"\"\n        self.ended = False\n        \"\"\"True when the WebSocket connection has been closed.\"\"\"\n\n        self._inject_messages_client = queue.Queue(maxsize=1)\n        self._inject_messages_server = queue.Queue(maxsize=1)\n\n        if handshake_flow:\n            self.client_key = websockets.get_client_key(handshake_flow.request.headers)\n            self.client_protocol = websockets.get_protocol(handshake_flow.request.headers)\n            self.client_extensions = websockets.get_extensions(handshake_flow.request.headers)\n            self.server_accept = websockets.get_server_accept(handshake_flow.response.headers)\n            self.server_protocol = websockets.get_protocol(handshake_flow.response.headers)\n            self.server_extensions = websockets.get_extensions(handshake_flow.response.headers)\n        else:\n            self.client_key = ''\n            self.client_protocol = ''\n            self.client_extensions = ''\n            self.server_accept = ''\n            self.server_protocol = ''\n            self.server_extensions = ''\n\n    _stateobject_attributes = flow.Flow._stateobject_attributes.copy()\n    # mypy doesn't support update with kwargs\n    _stateobject_attributes.update(dict(\n        messages=List[WebSocketMessage],\n        close_sender=str,\n        close_code=int,\n        close_message=str,\n        close_reason=str,\n        client_key=str,\n        client_protocol=str,\n        client_extensions=str,\n        server_accept=str,\n        server_protocol=str,\n        server_extensions=str,\n        # Do not include handshake_flow, to prevent recursive serialization!\n        # Since mitmproxy-console currently only displays HTTPFlows,\n        # dumping the handshake_flow will include the WebSocketFlow too.\n    ))\n\n    def get_state(self):\n        d = super().get_state()\n        d['close_code'] = int(d['close_code'])  # replace enum with bare int\n        return d\n\n    @classmethod\n    def from_state(cls, state):\n        f = cls(None, None, None)\n        f.set_state(state)\n        return f\n\n    def __repr__(self):\n        return \"<WebSocketFlow ({} messages)>\".format(len(self.messages))\n\n    def message_info(self, message: WebSocketMessage) -> str:\n        return \"{client} {direction} WebSocket {type} message {direction} {server}{endpoint}\".format(\n            type=message.type,\n            client=human.format_address(self.client_conn.address),\n            server=human.format_address(self.server_conn.address),\n            direction=\"->\" if message.from_client else \"<-\",\n            endpoint=self.handshake_flow.request.path,\n        )\n\n    def inject_message(self, endpoint, payload):\n        \"\"\"\n        Inject and send a full WebSocket message to the remote endpoint.\n        This might corrupt your WebSocket connection! Be careful!\n\n        The endpoint needs to be either flow.client_conn or flow.server_conn.\n\n        If ``payload`` is of type ``bytes`` then the message is flagged as\n        being binary If it is of type ``str`` encoded as UTF-8 and sent as\n        text.\n\n        :param payload: The message body to send.\n        :type payload: ``bytes`` or ``str``\n        \"\"\"\n\n        if endpoint == self.client_conn:\n            self._inject_messages_client.put(payload)\n        elif endpoint == self.server_conn:\n            self._inject_messages_server.put(payload)\n        else:\n            raise ValueError('Invalid endpoint')\n", "path": "mitmproxy/websocket.py"}], "after_files": [{"content": "import time\nimport queue\nfrom typing import List, Optional\n\nfrom wsproto.frame_protocol import CloseReason\nfrom wsproto.frame_protocol import Opcode\n\nfrom mitmproxy import flow\nfrom mitmproxy.net import websockets\nfrom mitmproxy.coretypes import serializable\nfrom mitmproxy.utils import strutils, human\n\n\nclass WebSocketMessage(serializable.Serializable):\n    \"\"\"\n    A WebSocket message sent from one endpoint to the other.\n    \"\"\"\n\n    def __init__(\n        self, type: int, from_client: bool, content: bytes, timestamp: Optional[float]=None, killed: bool=False\n    ) -> None:\n        self.type = Opcode(type)  # type: ignore\n        \"\"\"indicates either TEXT or BINARY (from wsproto.frame_protocol.Opcode).\"\"\"\n        self.from_client = from_client\n        \"\"\"True if this messages was sent by the client.\"\"\"\n        self.content = content\n        \"\"\"A byte-string representing the content of this message.\"\"\"\n        self.timestamp: float = timestamp or time.time()\n        \"\"\"Timestamp of when this message was received or created.\"\"\"\n        self.killed = killed\n        \"\"\"True if this messages was killed and should not be sent to the other endpoint.\"\"\"\n\n    @classmethod\n    def from_state(cls, state):\n        return cls(*state)\n\n    def get_state(self):\n        return int(self.type), self.from_client, self.content, self.timestamp, self.killed\n\n    def set_state(self, state):\n        self.type, self.from_client, self.content, self.timestamp, self.killed = state\n        self.type = Opcode(self.type)  # replace enum with bare int\n\n    def __repr__(self):\n        if self.type == Opcode.TEXT:\n            return \"text message: {}\".format(repr(self.content))\n        else:\n            return \"binary message: {}\".format(strutils.bytes_to_escaped_str(self.content))\n\n    def kill(self):\n        \"\"\"\n        Kill this message.\n\n        It will not be sent to the other endpoint. This has no effect in streaming mode.\n        \"\"\"\n        self.killed = True\n\n\nclass WebSocketFlow(flow.Flow):\n    \"\"\"\n    A WebSocketFlow is a simplified representation of a Websocket connection.\n    \"\"\"\n\n    def __init__(self, client_conn, server_conn, handshake_flow, live=None):\n        super().__init__(\"websocket\", client_conn, server_conn, live)\n\n        self.messages: List[WebSocketMessage] = []\n        \"\"\"A list containing all WebSocketMessage's.\"\"\"\n        self.close_sender = 'client'\n        \"\"\"'client' if the client initiated connection closing.\"\"\"\n        self.close_code = CloseReason.NORMAL_CLOSURE\n        \"\"\"WebSocket close code.\"\"\"\n        self.close_message = '(message missing)'\n        \"\"\"WebSocket close message.\"\"\"\n        self.close_reason = 'unknown status code'\n        \"\"\"WebSocket close reason.\"\"\"\n        self.stream = False\n        \"\"\"True of this connection is streaming directly to the other endpoint.\"\"\"\n        self.handshake_flow = handshake_flow\n        \"\"\"The HTTP flow containing the initial WebSocket handshake.\"\"\"\n        self.ended = False\n        \"\"\"True when the WebSocket connection has been closed.\"\"\"\n\n        self._inject_messages_client = queue.Queue(maxsize=1)\n        self._inject_messages_server = queue.Queue(maxsize=1)\n\n        if handshake_flow:\n            self.client_key = websockets.get_client_key(handshake_flow.request.headers)\n            self.client_protocol = websockets.get_protocol(handshake_flow.request.headers)\n            self.client_extensions = websockets.get_extensions(handshake_flow.request.headers)\n            self.server_accept = websockets.get_server_accept(handshake_flow.response.headers)\n            self.server_protocol = websockets.get_protocol(handshake_flow.response.headers)\n            self.server_extensions = websockets.get_extensions(handshake_flow.response.headers)\n        else:\n            self.client_key = ''\n            self.client_protocol = ''\n            self.client_extensions = ''\n            self.server_accept = ''\n            self.server_protocol = ''\n            self.server_extensions = ''\n\n    _stateobject_attributes = flow.Flow._stateobject_attributes.copy()\n    # mypy doesn't support update with kwargs\n    _stateobject_attributes.update(dict(\n        messages=List[WebSocketMessage],\n        close_sender=str,\n        close_code=int,\n        close_message=str,\n        close_reason=str,\n        client_key=str,\n        client_protocol=str,\n        client_extensions=str,\n        server_accept=str,\n        server_protocol=str,\n        server_extensions=str,\n        # Do not include handshake_flow, to prevent recursive serialization!\n        # Since mitmproxy-console currently only displays HTTPFlows,\n        # dumping the handshake_flow will include the WebSocketFlow too.\n    ))\n\n    def get_state(self):\n        d = super().get_state()\n        d['close_code'] = int(d['close_code'])  # replace enum with bare int\n        return d\n\n    @classmethod\n    def from_state(cls, state):\n        f = cls(None, None, None)\n        f.set_state(state)\n        return f\n\n    def __repr__(self):\n        return \"<WebSocketFlow ({} messages)>\".format(len(self.messages))\n\n    def message_info(self, message: WebSocketMessage) -> str:\n        return \"{client} {direction} WebSocket {type} message {direction} {server}{endpoint}\".format(\n            type=message.type,\n            client=human.format_address(self.client_conn.address),\n            server=human.format_address(self.server_conn.address),\n            direction=\"->\" if message.from_client else \"<-\",\n            endpoint=self.handshake_flow.request.path,\n        )\n\n    def inject_message(self, endpoint, payload):\n        \"\"\"\n        Inject and send a full WebSocket message to the remote endpoint.\n        This might corrupt your WebSocket connection! Be careful!\n\n        The endpoint needs to be either flow.client_conn or flow.server_conn.\n\n        If ``payload`` is of type ``bytes`` then the message is flagged as\n        being binary If it is of type ``str`` encoded as UTF-8 and sent as\n        text.\n\n        :param payload: The message body to send.\n        :type payload: ``bytes`` or ``str``\n        \"\"\"\n\n        if endpoint == self.client_conn:\n            self._inject_messages_client.put(payload)\n        elif endpoint == self.server_conn:\n            self._inject_messages_server.put(payload)\n        else:\n            raise ValueError('Invalid endpoint')\n", "path": "mitmproxy/websocket.py"}]}