@torrent-tv/proxy 2.89.16 → 2.89.17
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.
- package/CHANGELOG.md +4 -0
- package/docs/logs.md +13 -0
- package/package.json +1 -1
- package/routes/api/client-logs/post.js +9 -2
- package/test/client-logs-route.test.js +34 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
## 2.89.17
|
|
2
|
+
|
|
3
|
+
- **Fix**: Every browser log line the proxy keeps names the page's send it came in, as `batch=<n>`, and the server prints the same number. A send that reached neither side, or a batch the proxy took over a connection that could no longer carry its answer back, is now visible by comparing the two (torrent-tv/meta#77).
|
|
4
|
+
|
|
1
5
|
## 2.89.16
|
|
2
6
|
|
|
3
7
|
- **Fix**: A proxy started without `--log-file` keeps the browser's log. The page sends its log to the proxy for most of a viewing, and the proxy wrote it only to per-session files beside its own log file; with no log file named, which is every run from npm or Docker other than the Home Assistant addon, the browser's half of every viewing was dropped. It now goes to the console, beside the proxy's lines, each prefixed `client <sessionId>`. `docs/logs.md` states where the log goes for each way of starting the proxy (torrent-tv/meta#96).
|
package/docs/logs.md
CHANGED
|
@@ -98,6 +98,19 @@ The split is by PHASE, and neither half is the whole session:
|
|
|
98
98
|
3. **At unload** it goes to the server again: `navigator.sendBeacon` is the only
|
|
99
99
|
thing a page that is going away can use, and a data channel is not;
|
|
100
100
|
4. **A batch that cannot reach the proxy** falls back to the server.
|
|
101
|
+
5. **A batch nobody took** goes back into the page's queue and leaves with the
|
|
102
|
+
next send. What the page lost — lines pushed out by its 500-line queue — and
|
|
103
|
+
every refused send, by route and cause, are written into the log itself as
|
|
104
|
+
one line, `[client-logger] since <time>: …`, which travels with the next
|
|
105
|
+
batch that is delivered.
|
|
106
|
+
|
|
107
|
+
Every line carries the number of the page's send it came in, as `batch=<n>`,
|
|
108
|
+
on both sides: `[Windows/Chrome batch=12]` here, `[client Windows/Chrome
|
|
109
|
+
<sessionId> batch=12]` on the droplet. A number on neither side is a send no
|
|
110
|
+
route took: its lines went out again under a later number, and the report line
|
|
111
|
+
says why. A number on both is a batch the proxy took but whose answer never
|
|
112
|
+
reached the page — a connection wedged in the proxy-to-page direction still
|
|
113
|
+
carries requests the other way — which the page then sent to the server too.
|
|
101
114
|
|
|
102
115
|
So a session that failed while connecting is on the droplet, a session that
|
|
103
116
|
failed while playing is on the addon host, and a complete reading of a long
|
package/package.json
CHANGED
|
@@ -53,7 +53,13 @@ function sanitizeLine(value) {
|
|
|
53
53
|
* `POST /api/client-logs`
|
|
54
54
|
*
|
|
55
55
|
* Body: `{ sessionId, startedAt, torrentName, infoHash, tag, signalSessionId,
|
|
56
|
-
* lines: [{ level, ts, msg }] }`.
|
|
56
|
+
* seq, lines: [{ level, ts, msg }] }`.
|
|
57
|
+
*
|
|
58
|
+
* `seq` numbers the page's sends and is printed as `batch=<seq>`. The server
|
|
59
|
+
* prints the same number, so a batch that reached neither side shows as a gap,
|
|
60
|
+
* and one taken here whose answer never reached the page — a wedged connection
|
|
61
|
+
* still carries the request — shows on both, because the page then sends it to
|
|
62
|
+
* the server too.
|
|
57
63
|
*
|
|
58
64
|
* @param {import("fastify").FastifyRequest} req
|
|
59
65
|
* @param {import("fastify").FastifyReply} reply
|
|
@@ -69,6 +75,7 @@ export async function handleApiClientLogsPost(req, reply, { clientLogs }) {
|
|
|
69
75
|
infoHash: safeString(body.infoHash, 40)
|
|
70
76
|
};
|
|
71
77
|
const tag = sanitizeLine(safeString(body.tag, MAX_TAG_LEN)) || "Unknown/Unknown";
|
|
78
|
+
const batch = Number.isSafeInteger(body.seq) && body.seq > 0 ? ` batch=${body.seq}` : "";
|
|
72
79
|
const rows = Array.isArray(body.lines) ? body.lines.slice(0, MAX_LINES) : [];
|
|
73
80
|
|
|
74
81
|
const lines = rows.map((row) => {
|
|
@@ -76,7 +83,7 @@ export async function handleApiClientLogsPost(req, reply, { clientLogs }) {
|
|
|
76
83
|
const level = safeString(entry.level, 8) || "log";
|
|
77
84
|
const at = sanitizeLine(safeString(entry.ts, 16));
|
|
78
85
|
const message = sanitizeLine(safeString(entry.msg, MAX_MSG_LEN));
|
|
79
|
-
return `[${tag}] ${at} ${level}: ${message}`;
|
|
86
|
+
return `[${tag}${batch}] ${at} ${level}: ${message}`;
|
|
80
87
|
});
|
|
81
88
|
|
|
82
89
|
if (lines.length > 0) {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import test from "node:test";
|
|
3
|
+
|
|
4
|
+
import { handleApiClientLogsPost } from "../routes/api/client-logs/post.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Post one body and return the lines the route wrote.
|
|
8
|
+
*
|
|
9
|
+
* @param {object} body
|
|
10
|
+
* @returns {Promise<string[]>}
|
|
11
|
+
*/
|
|
12
|
+
async function linesWrittenFor(body) {
|
|
13
|
+
/** @type {string[]} */
|
|
14
|
+
const written = [];
|
|
15
|
+
const reply = { code: () => reply, send: () => reply };
|
|
16
|
+
await handleApiClientLogsPost({ body }, reply, {
|
|
17
|
+
clientLogs: { write: (_session, lines) => written.push(...lines) }
|
|
18
|
+
});
|
|
19
|
+
return written;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const line = { level: "info", ts: "12:00:00.000", msg: "hello" };
|
|
23
|
+
|
|
24
|
+
test("each line names the page's send it came in, so the two receivers can be compared", async () => {
|
|
25
|
+
assert.deepEqual(await linesWrittenFor({ tag: "Windows/Chrome", seq: 12, lines: [line] }), [
|
|
26
|
+
"[Windows/Chrome batch=12] 12:00:00.000 info: hello"
|
|
27
|
+
]);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("a page that numbers nothing is written as before", async () => {
|
|
31
|
+
assert.deepEqual(await linesWrittenFor({ tag: "Windows/Chrome", seq: "12", lines: [line] }), [
|
|
32
|
+
"[Windows/Chrome] 12:00:00.000 info: hello"
|
|
33
|
+
]);
|
|
34
|
+
});
|