Skip to content

Commit 3d1f119

Browse files
authored
Merge pull request #1 from filecoin-station/cache-response-inside-cloudflare-worker
Add cloudflare worker to collect API key usage inside Influx DB
2 parents 9859e77 + 8f5ef87 commit 3d1f119

File tree

14 files changed

+286
-1190
lines changed

14 files changed

+286
-1190
lines changed

.dev.vars.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
INFLUX_TOKEN="example"

.env.example

Lines changed: 0 additions & 3 deletions
This file was deleted.

.github/workflows/ci.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: CI
2+
on:
3+
push:
4+
branches: [main]
5+
pull_request:
6+
branches: [main]
7+
8+
jobs:
9+
test:
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: actions/checkout@v4
13+
- run: cp wrangler.toml.example wrangler.toml
14+
- uses: actions/setup-node@v4
15+
with:
16+
node-version: 20
17+
- run: npm ci
18+
- run: npm test
19+
20+
deploy:
21+
if: github.ref == 'refs/heads/main'
22+
needs: [test]
23+
runs-on: ubuntu-latest
24+
steps:
25+
- uses: actions/checkout@v4
26+
- name: Deploy
27+
uses: cloudflare/wrangler-action@v3
28+
with:
29+
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
30+
preCommands: |
31+
cp wranger.toml.example wrangler.toml
32+
envsubst < wrangler.toml.example > wrangler.toml
33+
postCommands: |
34+
rm -f wrangler.toml
35+
environment: production
36+
secrets: |
37+
INFLUX_TOKEN
38+
env:
39+
INFLUX_METRIC_NAME: ${{ env.INFLUX_METRIC }}
40+
INFLUX_URL: ${{ env.INFLUX_URL }}
41+
INFLUX_TOKEN: ${{ secrets.INFLUX_TOKEN }}
42+
INFLUX_DATABASE: ${{ env.INFLUX_DATABASE }}

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
/dist
33
**/*.rs.bk
44
Cargo.lock
5-
bin/
65
pkg/
76
wasm-pack.log
87
worker/
98
node_modules/
109
.cargo-ok
1110
.env
11+
.dev.vars
1212
.wrangler
1313
data/
1414
config/
15-
wrangler.toml
15+
wrangler.toml

README.md

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,37 @@
11
# Cloudflare metrics worker
22

3-
Send your page views from [Cloudflare worker](https://developers.cloudflare.com/workers/) to InfluxDB.
3+
[Couldflare worker](https://developers.cloudflare.com/workers/) used to proxy requests to your application and send metrics to InfluxDB.
44

5-
![Dashboard views](static/dashboard.png)
5+
## Development
66

7-
## Requirements
8-
9-
1. Your site need to be setup behind Cloudflare CDN.
10-
2. You need to setup InfluxDB with external access (make sure you have set [authentication](https://docs.influxdata.com/influxdb/v1.7/administration/authentication_and_authorization/#set-up-authentication))
11-
1. Make sure InfluxDB is hosted under [supported port](https://blog.cloudflare.com/cloudflare-now-supporting-more-ports/) for Workers. Best option is 80 or 443.
12-
13-
## How to use
14-
15-
1. Install wrangler package
7+
1. Install dependencies
168

179
```
18-
npm i @cloudflare/wrangler -g
10+
npm install
1911
```
2012

2113
2. Copy example files
2214

2315
```
24-
cp .env.example .env
16+
cp .dev.vars.example .dev.vars
2517
cp wrangler.toml.example wrangler.toml
2618
```
2719

28-
3. Deploy your worker to a site with wrangler
20+
3. Edit secrets inside `.dev.vars` and environment variables inside `wrangler.toml` files
21+
22+
3. Run your worker
2923

3024
```
31-
wrangler publish --env production
25+
npm run dev
3226
```
3327

34-
4. (Optional) If you're using Grafana with InfluxDB, then you can import [example Dashboard](static/dashboard.json) from first screen.
28+
## Deployment to production
29+
30+
In order to deploy your worker via Github Actions, you need to have a [Cloudflare API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) and running instance of InfluxDB.
31+
32+
Add generated API token to Github secrets as `CLOUDFLARE_API_TOKEN` and authentication token under `INFLUX_TOKEN`.
33+
34+
Other required environment variables include the following:
35+
- `INFLUX_URL` - InfluxDB URL
36+
- `INFLUX_DATABASE` - InfluxDB database (bucket) name
37+
- `INFLUX_METRIC_NAME` - InfluxDB metric name

bin/worker.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { reportRequestMetrics as reportRequestMetricsToInflux } from '../lib/influx.js'
2+
3+
export default {
4+
async fetch(request, env, ctx, { reportRequestMetrics = reportRequestMetricsToInflux } = {}) {
5+
const response = await fetch(request)
6+
ctx.waitUntil(reportRequestMetrics(request, env))
7+
return response
8+
},
9+
}

index.js

Lines changed: 0 additions & 66 deletions
This file was deleted.

lib/influx.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Reports request metrics to InfluxDB
3+
* @param {Request} request - incoming request
4+
* @param {object} env - environment variables
5+
*/
6+
export const reportRequestMetrics = async (request, env) => {
7+
await writeMetrics(createMetricsFromRequest(request, env), env)
8+
}
9+
10+
/*
11+
* Returns request metrics in InfluxDB line protocol format
12+
* https://docs.influxdata.com/influxdb/cloud/reference/syntax/line-protocol/
13+
* @param {Request} request - incoming request
14+
* @param {object} env - environment variables
15+
*/
16+
export const createMetricsFromRequest = (request, env) => {
17+
const url = new URL(request.url);
18+
const timestamp = Date.now();
19+
const apiKey = request.headers.get('api-key') ||
20+
url.searchParams.get('api-key') || (
21+
request.headers.get('Authorization')?.startsWith('Bearer ')
22+
? request.headers.get('Authorization').substring(7)
23+
: 'unknown'
24+
);
25+
26+
return `${env.INFLUX_METRIC_NAME} api_key="${apiKey}" ${timestamp}`
27+
}
28+
29+
/*
30+
* Sends request metrics to InfluxDB
31+
* https://docs.influxdata.com/enterprise_influxdb/v1/guides/write_data/
32+
* @param {string} lineProtocolData - InfluxDB line protocol formatted data
33+
* @param {object} env - environment variables
34+
*/
35+
export const writeMetrics = async (lineProtocolData, env) => {
36+
// Define API endpoint and headers
37+
const url = `${env.INFLUX_URL}/api/v2/write?&bucket=${env.INFLUX_DATABASE}&precision=ms`;
38+
39+
return fetch(url, {
40+
method: 'POST',
41+
headers: {
42+
'Authorization': `Token ${env.INFLUX_TOKEN}`,
43+
'Content-Type': 'application/octet-stream'
44+
},
45+
body: lineProtocolData,
46+
})
47+
}

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@
66
"main": "index.js",
77
"scripts": {
88
"deploy": "wrangler deploy",
9-
"dev": "wrangler dev",
9+
"deploy:prod": "wrangler deploy --env production",
10+
"dev": "wrangler dev --env dev",
1011
"start": "wrangler dev",
11-
"test": "vitest"
12+
"test": "vitest run",
13+
"test:watch": "vitest"
1214
},
1315
"author": "vanadium23 <[email protected]>",
1416
"license": "MIT",

0 commit comments

Comments
 (0)