Skip to content

Commit 12e8adc

Browse files
authored
Merge pull request #30 from piyook/feat/add-logging
Feat(): add api request logging functionality
2 parents 6368ba8 + 7dbfce8 commit 12e8adc

File tree

14 files changed

+295
-5
lines changed

14 files changed

+295
-5
lines changed

.dockerignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
**/.classpath
22
**/.dockerignore
3-
**/.env
43
**/.git
54
**/.gitignore
65
**/.project

.env

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
PROJECT_NAME=mock-api-framework
22
SERVER_PORT=8000
3-
USE_API_URL_PREFIX=api
3+
USE_API_URL_PREFIX=api
4+
LOG_REQUESTS=ON
5+
DELETE_LOGS_ON_SERVER_RESTART=ON

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
node_modules
22
*.log
33
screenshots/
4-
videos/
4+
videos/

README.md

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ The framework is written in TypeScript and can :
2323
- Serve persisted mock data to the database
2424
- Perform CRUD operations on the local database via a REST endpoint
2525
- Mock API error codes/messages for testing frontend error handling logic
26+
- Log and store API requests in JSON format and display information on the localhost:8000/logs route
2627

2728
## Set-up
2829

@@ -64,7 +65,7 @@ A list of all endpoints can be viewed on http://localhost:8000/.
6465

6566
The project has been set-up with demo endpoints that can be removed or modified as needed.
6667

67-
![alt text](image.png)
68+
![main server page](image.png)
6869

6970
### Useful Commands
7071

@@ -297,6 +298,48 @@ this will return a 500 error code and the JSON response below:
297298
298299
```
299300

301+
## Logging
302+
303+
API request information and sent data can be logged and stored as JSON in the /src/logs/ folder.
304+
305+
Logs can be viewed at **localhost:8000/logs**.
306+
307+
![logging](logs.png)
308+
309+
### Set-up
310+
311+
To enable logging set the environment variables below in the .env
312+
313+
```js
314+
LOG_REQUESTS = ON;
315+
DELETE_LOGS_ON_SERVER_RESTART = ON;
316+
```
317+
318+
You can choose to refresh the logfile every time the server restarts or persist the data by setting the DELETE_LOGS_ON_SERVER_RESTART variable.
319+
320+
To set up logging for a route, add the following to the api.ts file in the relevant handler, adjusting the request type (GET/POST/PUT/DELETE) and passing data to be logged as required:
321+
322+
```js
323+
import logger from '../../utilities/logger';
324+
325+
function handler(pathName: string) {
326+
return [
327+
http.get(`/${pathName}`, ({ request }) => {
328+
329+
...
330+
logger({
331+
data: { <- extracted request body or query params data here -> },
332+
pathName,
333+
type: 'GET',
334+
});
335+
...
336+
}),
337+
]
338+
}
339+
```
340+
341+
**See the src/api/bikes api.ts file for an example of logging set up.**
342+
300343
## Customisation
301344

302345
### Changing api url prefix

cypress/e2e/log-page-spec.cy.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
describe('logging works expected information', () => {
2+
it('log page works', () => {
3+
cy.visit('/logs');
4+
cy.get('h2').contains('API Requests Made');
5+
6+
cy.get('h3').contains(
7+
'File can be viewed in /src/logs folder in container or local machine',
8+
);
9+
cy.get('h5').contains(
10+
"LOG_REQUESTS env var must be set to 'ON' to log requests",
11+
);
12+
});
13+
14+
it('logging GET request works', () => {
15+
cy.request('/api/bikes?type=ducati');
16+
cy.visit('/logs');
17+
cy.get('.json-container').should('exist');
18+
cy.get('.json-container').contains('api/bikes');
19+
cy.get('.json-container').contains('ducati');
20+
cy.get('.json-container').contains('GET');
21+
});
22+
23+
it('logging POST request works', () => {
24+
cy.request('POST', '/api/bikes', {
25+
name: 'kawasaki ninja',
26+
type: 'kawasaki',
27+
year: 2023,
28+
color: 'red',
29+
price: 20000,
30+
});
31+
cy.visit('/logs');
32+
cy.get('.json-container').should('exist');
33+
cy.get('.json-container').contains('api/bikes');
34+
cy.get('.json-container').contains('kawasaki ninja');
35+
cy.get('.json-container').contains('kawasaki');
36+
cy.get('.json-container').contains('2023');
37+
cy.get('.json-container').contains('red');
38+
cy.get('.json-container').contains('20000');
39+
cy.get('.json-container').contains('POST');
40+
});
41+
});

logs.png

56.1 KB
Loading

package-lock.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"highlight.js": "^11.11.1",
3030
"markdown-it": "^14.1.0",
3131
"msw": "^2.7.4",
32+
"pretty-print-json": "^3.0.4",
3233
"tsx": "^4.19.3",
3334
"typescript": "^5.8.3",
3435
"zod": "^3.24.2"

src/api/bikes/api.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { http, HttpResponse } from 'msw';
2+
import logger from '../../utilities/logger';
23

34
// Add any http handler here (get, push , delete etc., and middleware as needed)
45

@@ -9,13 +10,29 @@ function handler(pathName: string) {
910
const type = url.searchParams.get('type');
1011
console.log(`starting ${pathName}`);
1112
console.log('Item Type is', type);
13+
14+
// Log the request passing the request data, pathName and request type to the logger function
15+
logger({
16+
data: { type },
17+
pathName,
18+
type: 'GET',
19+
});
20+
1221
return HttpResponse.json({
1322
response: `this is a GET test response from ${pathName} for bike type: ${type ?? 'none'}`,
1423
});
1524
}),
1625
http.post(`/${pathName}`, async ({ request }) => {
1726
// Get Body Data using json(), text() or formData() depending on what is sent
1827
const bodyData = await request.json();
28+
29+
// Log the request passing the request data, pathName and extra information to the logger function
30+
logger({
31+
data: bodyData,
32+
type: 'POST',
33+
pathName,
34+
});
35+
1936
return HttpResponse.json({
2037
response: `this is a POST test response from ${pathName} with bodyData ${JSON.stringify(bodyData)}`,
2138
});

src/logs/.gitkeep

Whitespace-only changes.

0 commit comments

Comments
 (0)