Skip to content

Commit ab82c3c

Browse files
committed
Merge branch 'master' of github.com:codex-team/hawk.api.nodejs into feat/timestamp-index-repetition
2 parents f017ee2 + 75b10df commit ab82c3c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1839
-173
lines changed

.env.sample

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# API server port
22
PORT=4000
33

4+
# Metrics server port
5+
METRICS_PORT=9090
6+
47
# Hawk API database URL
58
MONGO_HAWK_DB_URL=mongodb://mongodb:27017/hawk
69

@@ -17,6 +20,8 @@ JWT_SECRET_REFRESH_TOKEN=abacaba
1720
# JWT secret for user's access token
1821
JWT_SECRET_ACCESS_TOKEN=belarus
1922

23+
# max document could for one read request to the database
24+
MAX_DB_READ_BATCH_SIZE=100000
2025

2126
# JWT secret for signing tokens for processing billing requests
2227
JWT_SECRET_BILLING_CHECKSUM=checksum_secret

.github/workflows/build-and-push-docker-image.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Build and push docker image
33
on:
44
push:
55
branches:
6-
- '*'
6+
- '**'
77
tags:
88
- 'v*'
99

.github/workflows/integration-tests.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,10 @@ jobs:
1010
steps:
1111
- uses: actions/checkout@v2
1212

13+
- name: Use Node.js
14+
uses: actions/setup-node@v3
15+
with:
16+
node-version-file: '.nvmrc'
17+
1318
- name: Run tests
1419
run: yarn test:integration

.github/workflows/tests.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ jobs:
99
runs-on: ubuntu-22.04
1010
steps:
1111
- uses: actions/checkout@v2
12+
- name: Use Node.js
13+
uses: actions/setup-node@v3
14+
with:
15+
node-version-file: '.nvmrc'
1216
- name: Install modules
1317
run: yarn
1418
- name: Run tests

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ uploads
77
globalConfig.json
88
coverage
99
tls
10+
package-lock.json

LICENSE

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
Business Source License 1.1
2+
3+
Parameters
4+
5+
Licensor: CodeX (Hawk)
6+
Licensed Work: hawk.api.nodejs (https://github.com/codex-team/hawk.api.nodejs)
7+
The Licensed Work is © 2025 CodeX
8+
Additional Use Grant: Self-hosted use for own/internal needs and research/evaluation is permitted.
9+
Using this code to provide a competing error-tracking SaaS or commercial
10+
hosted service without the Licensor’s prior permission is prohibited.
11+
12+
Change Date: 2030-01-01
13+
14+
Change License: AGPL-3.0
15+
16+
-------------------------------------------------------------------------------
17+
18+
License text copyright © 2024 MariaDB plc, All Rights Reserved.
19+
“Business Source License” is a trademark of MariaDB plc.
20+
21+
Terms
22+
23+
The Licensor hereby grants you the right to copy, modify, create derivative
24+
works, redistribute, and make non-production use of the Licensed Work. The
25+
Licensor may make an Additional Use Grant, above, permitting limited
26+
production use.
27+
28+
Effective on the Change Date, or the fourth anniversary of the first publicly
29+
available distribution of a specific version of the Licensed Work under this
30+
License, whichever comes first, the Licensor hereby grants you rights under
31+
the terms of the Change License, and the rights granted in the paragraph
32+
above terminate.
33+
34+
If your use of the Licensed Work does not comply with the requirements
35+
currently in effect as described in this License, you must purchase a
36+
commercial license from the Licensor, its affiliated entities, or authorized
37+
resellers, or you must refrain from using the Licensed Work.
38+
39+
All copies of the original and modified Licensed Work, and derivative works
40+
of the Licensed Work, are subject to this License. This License applies
41+
separately for each version of the Licensed Work and the Change Date may vary
42+
for each version of the Licensed Work released by Licensor.
43+
44+
You must conspicuously display this License on each original or modified copy
45+
of the Licensed Work. If you receive the Licensed Work in original or
46+
modified form from a third party, the terms and conditions set forth in this
47+
License apply to your use of that work.
48+
49+
Any use of the Licensed Work in violation of this License will automatically
50+
terminate your rights under this License for the current and all other
51+
versions of the Licensed Work.
52+
53+
This License does not grant you any right in any trademark or logo of
54+
Licensor or its affiliates (provided that you may use a trademark or logo of
55+
Licensor as expressly required by this License). TO THE EXTENT PERMITTED BY
56+
APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON AN “AS IS” BASIS. LICENSOR
57+
HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS OR IMPLIED, INCLUDING
58+
(WITHOUT LIMITATION) WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
59+
PURPOSE, NON-INFRINGEMENT, AND TITLE. MariaDB hereby grants you permission to
60+
use this License’s text to license your works, and to refer to it using the
61+
trademark “Business Source License”, as long as you comply with the Covenants
62+
of Licensor below.
63+
64+
Covenants of Licensor
65+
66+
In consideration of the right to use this License’s text and the “Business
67+
Source License” name and trademark, Licensor covenants to MariaDB, and to all
68+
other recipients of the licensed work to be provided by Licensor:
69+
70+
1. To specify as the Change License the GPL Version 2.0 or any later version,
71+
or a license that is compatible with GPL Version 2.0 or a later version,
72+
where “compatible” means that software provided under the Change License can
73+
be included in a program with software provided under GPL Version 2.0 or a
74+
later version. Licensor may specify additional Change Licenses without
75+
limitation.
76+
77+
2. To either: (a) specify an additional grant of rights to use that does not
78+
impose any additional restriction on the right granted in this License, as
79+
the Additional Use Grant; or (b) insert the text “None”.
80+
81+
3. To specify a Change Date not later than the fourth anniversary of the first
82+
publicly available distribution of a specific version of the Licensed Work
83+
under this License.
84+
85+
4. Not to modify this License in any other way.
86+
87+
Notice
88+
89+
The Business Source License (this document, or the “License”) is not an Open
90+
Source license. However, the Licensed Work will eventually be made available
91+
under an Open Source License, as stated in this License.
92+
93+
For more information on the use of the Business Source License for MariaDB
94+
products, please visit the MariaDB Business Source License FAQ.
95+
For more information on the use of the Business Source License generally,
96+
please visit the Adopting and Developing Business Source License FAQ.

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Hawk API
22

3+
![License](https://img.shields.io/badge/license-BSL--1.1-orange)
4+
35
## Start API
46
For deployment (both in production and in development), you can use Docker.
57
See Docker instructions [here](DOCKER.md).
@@ -23,9 +25,15 @@ To execute the request, enter it in the input field on the left and click on the
2325
On the right side you will see the result of the query.
2426

2527
## GraphQL Voyager
26-
You can view API Schema visualization in `/voyager` page in your browser. To see current production schema go to [here](https://api.beta.hawk.so/voyager)
28+
You can view API Schema visualization in `/voyager` page in your browser.
29+
To see current production schema go to [here](https://api.beta.hawk.so/voyager)
2730

2831
## Migrations
2932

3033
Run `yarn migrations:up` command to apply migration revisions or
3134
`yarn migrations:down` to rollback the last revision.
35+
36+
## License
37+
38+
Source code is available under **Business Source License 1.1 (BSL 1.1)**.
39+
See [`LICENSE`](./LICENSE) for terms, including:

docker/Dockerfile.dev

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
1-
FROM node:14.17.0-alpine as builder
1+
FROM node:16-alpine as builder
22

33
WORKDIR /usr/src/app
4-
RUN apk add --no-cache git gcc g++ python make musl-dev
4+
RUN apk add --no-cache git gcc g++ python3 make musl-dev
55

66
COPY package.json yarn.lock ./
77

88
RUN yarn install
99

10-
FROM node:14.17.0-alpine
10+
FROM node:16-alpine
1111

1212
WORKDIR /usr/src/app
1313

docs/METRICS.md

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
# Prometheus Metrics
2+
3+
This application exposes Prometheus-compatible metrics on a separate port from the main API server.
4+
5+
## Configuration
6+
7+
The metrics server runs on a separate port configured via the `METRICS_PORT` environment variable:
8+
9+
```bash
10+
# Default: 9090
11+
METRICS_PORT=9090
12+
```
13+
14+
Add this to your `.env` file. See `.env.sample` for reference.
15+
16+
## Metrics Endpoint
17+
18+
The metrics are served at:
19+
20+
```
21+
http://localhost:9090/metrics
22+
```
23+
24+
(Replace `9090` with your configured `METRICS_PORT` if different)
25+
26+
## Available Metrics
27+
28+
### Default Node.js Metrics
29+
30+
The following default Node.js metrics are automatically collected:
31+
32+
- **nodejs_version_info** - Node.js version information
33+
- **process_cpu_user_seconds_total** - Total user CPU time spent in seconds
34+
- **process_cpu_system_seconds_total** - Total system CPU time spent in seconds
35+
- **nodejs_heap_size_total_bytes** - Total heap size in bytes
36+
- **nodejs_heap_size_used_bytes** - Used heap size in bytes
37+
- **nodejs_external_memory_bytes** - External memory in bytes
38+
- **nodejs_heap_space_size_total_bytes** - Total heap space size in bytes
39+
- **nodejs_heap_space_size_used_bytes** - Used heap space size in bytes
40+
- **nodejs_eventloop_lag_seconds** - Event loop lag in seconds
41+
- **nodejs_eventloop_lag_min_seconds** - Minimum event loop lag
42+
- **nodejs_eventloop_lag_max_seconds** - Maximum event loop lag
43+
- **nodejs_eventloop_lag_mean_seconds** - Mean event loop lag
44+
- **nodejs_eventloop_lag_stddev_seconds** - Standard deviation of event loop lag
45+
- **nodejs_eventloop_lag_p50_seconds** - 50th percentile event loop lag
46+
- **nodejs_eventloop_lag_p90_seconds** - 90th percentile event loop lag
47+
- **nodejs_eventloop_lag_p99_seconds** - 99th percentile event loop lag
48+
49+
### Custom HTTP Metrics
50+
51+
#### http_request_duration_seconds (Histogram)
52+
53+
Duration of HTTP requests in seconds, labeled by:
54+
- `method` - HTTP method (GET, POST, etc.)
55+
- `route` - Request route/path
56+
- `status_code` - HTTP status code
57+
58+
Buckets: 0.01, 0.05, 0.1, 0.5, 1, 5, 10 seconds
59+
60+
#### http_requests_total (Counter)
61+
62+
Total number of HTTP requests, labeled by:
63+
- `method` - HTTP method (GET, POST, etc.)
64+
- `route` - Request route/path
65+
- `status_code` - HTTP status code
66+
67+
### GraphQL Metrics
68+
69+
#### hawk_gql_operation_duration_seconds (Histogram)
70+
71+
Histogram of total GraphQL operation duration by operation name and type.
72+
73+
Labels:
74+
- `operation_name` - Name of the GraphQL operation
75+
- `operation_type` - Type of operation (query, mutation, subscription)
76+
77+
Buckets: 0.01, 0.05, 0.1, 0.5, 1, 5, 10 seconds
78+
79+
**Purpose**: Identify slow API operations (P95/P99 latency).
80+
81+
#### hawk_gql_operation_errors_total (Counter)
82+
83+
Counter of failed GraphQL operations grouped by operation name and error class.
84+
85+
Labels:
86+
- `operation_name` - Name of the GraphQL operation
87+
- `error_type` - Type/class of the error
88+
89+
**Purpose**: Detect increased error rates and failing operations.
90+
91+
#### hawk_gql_resolver_duration_seconds (Histogram)
92+
93+
Histogram of resolver execution time per type, field, and operation.
94+
95+
Labels:
96+
- `type_name` - GraphQL type name
97+
- `field_name` - Field name being resolved
98+
- `operation_name` - Name of the GraphQL operation
99+
100+
Buckets: 0.01, 0.05, 0.1, 0.5, 1, 5 seconds
101+
102+
**Purpose**: Find slow or CPU-intensive resolvers that degrade overall performance.
103+
104+
### MongoDB Metrics
105+
106+
#### hawk_mongo_command_duration_seconds (Histogram)
107+
108+
Histogram of MongoDB command duration by command, collection family, and database.
109+
110+
Labels:
111+
- `command` - MongoDB command name (find, insert, update, etc.)
112+
- `collection_family` - Collection family name (extracted from dynamic collection names to reduce cardinality)
113+
- `db` - Database name
114+
115+
Buckets: 0.01, 0.05, 0.1, 0.5, 1, 5, 10 seconds
116+
117+
**Purpose**: Detect slow queries and high-latency collections.
118+
119+
**Note on Collection Families**: To reduce metric cardinality, dynamic collection names are grouped into families. For example:
120+
- `events:projectId``events`
121+
- `dailyEvents:projectId``dailyEvents`
122+
- `repetitions:projectId``repetitions`
123+
- `membership:userId``membership`
124+
- `team:workspaceId``team`
125+
126+
This prevents metric explosion when dealing with thousands of projects, users, or workspaces, while still providing meaningful insights into collection performance patterns.
127+
128+
#### hawk_mongo_command_errors_total (Counter)
129+
130+
Counter of failed MongoDB commands grouped by command and error code.
131+
132+
Labels:
133+
- `command` - MongoDB command name
134+
- `error_code` - MongoDB error code
135+
136+
**Purpose**: Track transient or persistent database errors.
137+
138+
## Testing
139+
140+
### Manual Testing
141+
142+
You can test the metrics endpoint using curl:
143+
144+
```bash
145+
curl http://localhost:9090/metrics
146+
```
147+
148+
Or run the provided test script:
149+
150+
```bash
151+
./test-metrics.sh
152+
```
153+
154+
### Integration Tests
155+
156+
Integration tests for metrics are located in `test/integration/cases/metrics.test.ts`.
157+
158+
Run them with:
159+
160+
```bash
161+
npm run test:integration
162+
```
163+
164+
## Implementation Details
165+
166+
The metrics implementation uses the `prom-client` library and consists of:
167+
168+
1. **Metrics Module** (`src/metrics/index.ts`):
169+
- Initializes a Prometheus registry
170+
- Configures default Node.js metrics collection
171+
- Defines custom HTTP metrics (duration histogram and request counter)
172+
- Registers GraphQL and MongoDB metrics
173+
- Provides middleware for tracking HTTP requests
174+
- Creates a separate Express app for serving metrics
175+
176+
2. **GraphQL Metrics** (`src/metrics/graphql.ts`):
177+
- Implements Apollo Server plugin for tracking GraphQL operations
178+
- Tracks operation duration, errors, and resolver execution time
179+
- Automatically captures operation name, type, and field information
180+
181+
3. **MongoDB Metrics** (`src/metrics/mongodb.ts`):
182+
- Implements MongoDB command monitoring
183+
- Tracks command duration and errors
184+
- Uses MongoDB's command monitoring events
185+
- Extracts collection families from dynamic collection names to reduce cardinality
186+
187+
4. **Integration** (`src/index.ts`, `src/mongo.ts`):
188+
- Adds GraphQL metrics plugin to Apollo Server
189+
- Adds metrics middleware to the main Express app
190+
- Enables MongoDB command monitoring on database clients
191+
- Starts metrics server on a separate port
192+
- Keeps metrics server isolated from main API traffic
193+
194+
## Prometheus Configuration
195+
196+
To scrape these metrics with Prometheus, add the following to your `prometheus.yml`:
197+
198+
```yaml
199+
scrape_configs:
200+
- job_name: 'hawk-api'
201+
static_configs:
202+
- targets: ['localhost:9090']
203+
```
204+
205+
Adjust the target host and port according to your deployment.

0 commit comments

Comments
 (0)