Skip to content

Commit 2431de5

Browse files
authored
feat: add x-github-request-id into logging message (#382)
1 parent 25434e2 commit 2431de5

File tree

2 files changed

+64
-14
lines changed

2 files changed

+64
-14
lines changed

src/index.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,20 @@ export function requestLog(octokit: Octokit) {
1515

1616
return (request as typeof octokit.request)(options)
1717
.then((response) => {
18+
const requestId = response.headers["x-github-request-id"];
1819
octokit.log.info(
19-
`${requestOptions.method} ${path} - ${response.status} in ${
20+
`${requestOptions.method} ${path} - ${response.status} with id ${requestId} in ${
2021
Date.now() - start
2122
}ms`,
2223
);
2324
return response;
2425
})
2526

2627
.catch((error) => {
27-
octokit.log.info(
28-
`${requestOptions.method} ${path} - ${error.status} in ${
28+
const requestId =
29+
error.response.headers["x-github-request-id"] || "UNKNOWN";
30+
octokit.log.error(
31+
`${requestOptions.method} ${path} - ${error.status} with id ${requestId} in ${
2932
Date.now() - start
3033
}ms`,
3134
);

test/request-log.test.ts

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,16 @@ import { jest } from "@jest/globals";
55
import { requestLog } from "../src/index.js";
66

77
describe("logging", () => {
8-
it("logs sucessful 'GET /'", async () => {
9-
const mock = fetchMock
10-
.sandbox()
11-
.getOnce("https://api.github.com/", { ok: true });
8+
it("logs successful 'GET /'", async () => {
9+
const mock = fetchMock.sandbox().getOnce("https://api.github.com/", {
10+
status: 200,
11+
body: {
12+
ok: true,
13+
},
14+
headers: {
15+
"x-github-request-id": "1234",
16+
},
17+
});
1218

1319
const mockLogInfo = jest.fn();
1420
const mockDebugInfo = jest.fn();
@@ -31,15 +37,22 @@ describe("logging", () => {
3137
method: "GET",
3238
url: "/",
3339
});
34-
expect(mockLogInfo.mock.calls[0][0]).toMatch(/GET \/ - 200 in \d+ms/);
40+
expect(mockLogInfo.mock.calls[0][0]).toMatch(
41+
/GET \/ - 200 with id 1234 in \d+ms/,
42+
);
3543
});
3644

3745
it("logs 404 for 'GET /unknown'", async () => {
38-
const mock = fetchMock
39-
.sandbox()
40-
.getOnce("https://api.github.com/unknown", 404);
46+
const mock = fetchMock.sandbox().getOnce("https://api.github.com/unknown", {
47+
status: 404,
48+
body: { message: "Not Found" },
49+
headers: {
50+
"x-github-request-id": "1234",
51+
},
52+
});
4153

4254
const mockLogInfo = jest.fn();
55+
const mockErrorInfo = jest.fn();
4356
const mockDebugInfo = jest.fn();
4457
const MyOctokit = Octokit.plugin(requestLog);
4558
const octokit = new MyOctokit({
@@ -50,15 +63,49 @@ describe("logging", () => {
5063
debug: mockDebugInfo,
5164
info: mockLogInfo,
5265
warn() {},
53-
error() {},
66+
error: mockErrorInfo,
67+
},
68+
});
69+
70+
try {
71+
await octokit.request("GET /unknown");
72+
} catch (error) {
73+
expect(mockErrorInfo.mock.calls[0][0]).toMatch(
74+
/GET \/unknown - 404 with id 1234 in \d+ms/,
75+
);
76+
return;
77+
}
78+
79+
throw new Error('"GET /unknown" should not resolve');
80+
});
81+
82+
it("logs malformed error response for 'GET /unknown'", async () => {
83+
const mock = fetchMock.sandbox().getOnce("https://api.github.com/unknown", {
84+
status: 500,
85+
body: "Internal Server Error",
86+
});
87+
88+
const mockLogInfo = jest.fn();
89+
const mockErrorInfo = jest.fn();
90+
const mockDebugInfo = jest.fn();
91+
const MyOctokit = Octokit.plugin(requestLog);
92+
const octokit = new MyOctokit({
93+
request: {
94+
fetch: mock,
95+
},
96+
log: {
97+
debug: mockDebugInfo,
98+
info: mockLogInfo,
99+
warn() {},
100+
error: mockErrorInfo,
54101
},
55102
});
56103

57104
try {
58105
await octokit.request("GET /unknown");
59106
} catch (error) {
60-
expect(mockLogInfo.mock.calls[0][0]).toMatch(
61-
/GET \/unknown - 404 in \d+ms/,
107+
expect(mockErrorInfo.mock.calls[0][0]).toMatch(
108+
/GET \/unknown - 500 with id UNKNOWN in \d+ms/,
62109
);
63110
return;
64111
}

0 commit comments

Comments
 (0)