Skip to content

Commit e0f225f

Browse files
authored
Merge pull request #4 from caiges/master
Use official fastly api client for fetching realtime metrics.
2 parents 866ddbc + 3b3ebc2 commit e0f225f

File tree

9 files changed

+735
-450
lines changed

9 files changed

+735
-450
lines changed

.env.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
ACCOUNT_ID=yourNewRelicAccountId
2+
FASTLY_KEY=yourFastlyKey
3+
INSERT_KEY=yourNewRelicInsertKey
4+
SERVICES=space separated list of services

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
node_modules/
1+
.env
2+
node_modules/

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
FROM alpine
44

5-
RUN apk add --update nodejs nodejs-npm
5+
RUN apk add --update nodejs npm
66

77
WORKDIR /usr/src/app
88

@@ -12,4 +12,4 @@ RUN npm install
1212

1313
COPY . .
1414

15-
CMD ["node", "app.js"]
15+
CMD ["node", "index.js"]

Makefile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
image_name=newrelic/fastly-to-insights
2+
3+
build:
4+
docker build -t $(image_name) .
5+
6+
run: build
7+
docker run --rm --env-file .env --name fastly-to-insights $(image_name)

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ This is the New Relic blessed way to get your Fastly metrics into Insights, pack
44

55
In order to use the Fastly to Insights Docker image, you will need an active New Relic account with Insights, an active Fastly account with Read access, a New Relic Insights Insert key and a Fastly API Key. The Docker image can be found [here](https://cloud.docker.com/swarm/newrelic/repository/docker/newrelic/fastly-to-insights/general).
66

7+
Once reporting starts, a `FastlySample` event will become available to query:
8+
9+
```nrql
10+
FROM FastlySample select *
11+
```
12+
713
## How to use this image
814

915
Before you get started, make sure that you have a [Fastly API Key](https://docs.fastly.com/guides/account-management-and-security/using-api-tokens) and a [New Relic Insert Key](https://docs.newrelic.com/docs/insights/insights-data-sources/custom-data/insert-custom-events-insights-api#register).
@@ -17,6 +23,8 @@ The Fastly to Insights image is configured by environment variables. These are m
1723

1824
`SERVICES` needs to be a string with the ids of the Fastly services you want to see data for in Insights, separated by a space. I know that's not ideal. A limitation of Fastly is that you have to query one service at a time, so I chose to create an array of service ids and loop through them to query Fastly. A limitation of Docker is that you can't pass an array via the command line, so I chose to split a string on "` `". If you have a better idea, I would love to hear it - please contribute!
1925

26+
Additionally, the polling interval (how often realtime metrics are requested from Fastly) can be configured by setting the `POLL_INTERVAL` which, by default, is 3 minutes.
27+
2028
### Example
2129

2230
```shell
@@ -32,6 +40,12 @@ $ docker run \
3240

3341
You are welcome to send pull requests to us - however, by doing so you agree that you are granting New Relic a non-exclusive, non-revokable, no-cost license to use the code, algorithms, patents, and ideas in that code in our products if we so choose. You also agree the code is provided as-is and you provide no warranties as to its fitness or correctness for any purpose.
3442

43+
## Developing
44+
45+
### Building and running the image locally
46+
47+
A Makefile is provided which you can use to build and run the fastly to insights integration locally -- `make run` will build and then run the image. You can provide configuration via a `.env` file (`.env.example` provided as an example).
48+
3549
## More Information
3650

3751
For more information on the Fastly Real-Time Analytics API, look [here](https://docs.fastly.com/api/analytics).

app.js

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

index.js

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Copyright 2018 New Relic, Inc. Licensed under the Apache License, version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, either express or implied.
2+
//Copyright 2018 New Relic Inc. All rights reserved.
3+
4+
import fetch from 'node-fetch';
5+
import { ApiClient, RealtimeApi, ServiceApi } from "fastly";
6+
7+
const ACCOUNT_ID = process.env.ACCOUNT_ID
8+
const INSERT_KEY = process.env.INSERT_KEY
9+
const FASTLY_KEY = process.env.FASTLY_KEY
10+
const INSIGHTS_HOST = process.env.INSIGHTS_HOST || "insights-collector.newrelic.com";
11+
const EVENT_TYPE = process.env.EVENT_TYPE || "FastlySample";
12+
const POLL_INTERVAL = process.env.POLL_INTERVAL || 180000 // 3 minutes.
13+
14+
// A limitation of Fastly is that you have to query one service at a time. I chose to create an array of my service ids, and loop through them.
15+
const LIST_OF_SERVICES = process.env.SERVICES.split(" ");
16+
17+
let timestamp = 0;
18+
19+
const realtimeApiClient = new ApiClient();
20+
realtimeApiClient.basePath = "https://rt.fastly.com";
21+
realtimeApiClient.authenticate(FASTLY_KEY);
22+
const realtimeApi = new RealtimeApi(realtimeApiClient);
23+
const apiClient = new ApiClient();
24+
apiClient.authenticate(FASTLY_KEY);
25+
const serviceApi = new ServiceApi(apiClient);
26+
27+
// Perform an initial poll of the services and then set an interval to poll every 3 minutes.
28+
pollServices();
29+
setInterval(pollServices, POLL_INTERVAL) // 3 minutes
30+
31+
function pollServices() {
32+
LIST_OF_SERVICES.map(async (service) => {
33+
pollFromFastly(service);
34+
});
35+
}
36+
37+
async function pollFromFastly(service) {
38+
console.log(`Polling ${service}`);
39+
40+
try {
41+
const serviceDetail = await serviceApi.getService({ service_id: service });
42+
const valuableData = await realtimeApi.getStatsLastSecond({
43+
service_id: service,
44+
timestamp_in_seconds: timestamp
45+
});
46+
47+
if (valuableData.Error) {
48+
console.log('error in stats', valuableData.Error)
49+
} else {
50+
timestamp = valuableData.Timestamp
51+
valuableData.Data.map((data) => {
52+
batchAndSend(data.aggregated, { id: service, name: serviceDetail.name });
53+
})
54+
}
55+
56+
} catch (error) {
57+
console.log('error fetching stats', error)
58+
}
59+
}
60+
61+
async function batchAndSend(aggregate, service) {
62+
let message = {
63+
"eventType": EVENT_TYPE,
64+
"service_id": service.id,
65+
"service_name": service.name,
66+
...aggregate,
67+
}
68+
await sendToInsights(message)
69+
}
70+
71+
async function sendToInsights(logMessages) {
72+
let insights_url = `https://${INSIGHTS_HOST}/v1/accounts/${ACCOUNT_ID}/events`;
73+
try {
74+
fetch(insights_url, {
75+
method: "POST",
76+
headers: {
77+
'Content-Type': 'application/json',
78+
"X-Insert-Key": INSERT_KEY
79+
},
80+
body: JSON.stringify(logMessages)
81+
});
82+
} catch (error) {
83+
console.log('error posting to insights', error);
84+
}
85+
}

0 commit comments

Comments
 (0)