This commit is contained in:
John Karahalis 2018-02-23 15:46:12 -05:00
Родитель 07827ac81d
Коммит 092580eea3
13 изменённых файлов: 5658 добавлений и 64 удалений

3
.babelrc Normal file
Просмотреть файл

@ -0,0 +1,3 @@
{
"presets": ["env"]
}

7
.gitignore поставляемый
Просмотреть файл

@ -1,3 +1,4 @@
# Python
env/
*.pyc
build
# Node
node_modules

Просмотреть файл

@ -1,4 +0,0 @@
update: insecure
search: False
requirements:
- requirements.txt

Просмотреть файл

@ -1 +0,0 @@
web: PYTHONPATH=$PYTHONPATH:lib gunicorn --reload --log-file - server:api

Просмотреть файл

@ -8,12 +8,14 @@ default. When that happens, we won't need this project any more.
### Install
1. Install the [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli)
2. Run `python3 -m venv env`
3. Run `source env/bin/activate`
4. Run `pip install -r requirements.txt`
`npm install`
### Run
1. Run `source env/bin/activate`
3. Run `heroku local`
#### Locally
`npm run local`
#### In production
`npm run start`

5529
package-lock.json сгенерированный Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

25
package.json Normal file
Просмотреть файл

@ -0,0 +1,25 @@
{
"name": "fhwr-unflattener",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node build/server",
"build": "babel src --source-maps --minified --out-dir build",
"postinstall": "npm run build",
"local": "npm-run-all --parallel local:*",
"local:build-and-watch": "babel src --watch --source-maps --out-dir build",
"local:start-and-watch": "nodemon build/server"
},
"dependencies": {
"babel-cli": "6.26.0",
"babel-preset-env": "1.6.1",
"decimal": "0.0.2",
"request": "2.83.0",
"restify": "6.3.4",
"restify-cors-middleware": "1.1.0"
},
"devDependencies": {
"nodemon": "1.15.1",
"npm-run-all": "4.1.2"
}
}

5
renovate.json Normal file
Просмотреть файл

@ -0,0 +1,5 @@
{
"extends": [
"config:base"
]
}

Просмотреть файл

@ -1,5 +0,0 @@
falcon==1.4.1
falcon-cors==1.1.7
gunicorn==19.7.1
python-mimeparse==1.6.0
six==1.11.0

Просмотреть файл

@ -1 +0,0 @@
python-3.6.2

Просмотреть файл

@ -1,44 +0,0 @@
import falcon
import json
from falcon_cors import CORS
from urllib.request import urlopen
class Unflattened:
def on_get(self, req, res):
source_url = 'https://analysis-output.telemetry.mozilla.org/game-hardware-survey/data/hwsurvey-weekly.json'
source_data = json.loads(urlopen(source_url).read())
pretransposed_data = []
for day in source_data:
metrics_dict = {}
day_dict = {'metrics': metrics_dict}
for k, v in day.items():
k_split = k.split('_', 1)
if len(k_split) == 1:
# it's metadata
day_dict[k] = v
else:
# it's a metric
metric_name = k_split[0]
if metric_name == "cpuCoresSpeed":
# these aren't used and are janky
continue
bucket_name = k_split[1]
metric_dict = metrics_dict.get(metric_name, None)
if metric_dict is None:
metric_dict = dict()
metrics_dict[metric_name] = metric_dict
metric_dict[bucket_name] = v
pretransposed_data.append(day_dict)
res.media = { "data": pretransposed_data }
cors = CORS(allow_all_origins=True,
allow_all_headers=True,
allow_methods_list=['GET'])
api = falcon.API(middleware=[cors.middleware])
# Routes
api.add_route('/', Unflattened())

29
src/server.js Normal file
Просмотреть файл

@ -0,0 +1,29 @@
import restify from 'restify';
import restifyCORSMiddleware from 'restify-cors-middleware';
import unflatten from './unflatten';
const server = restify.createServer();
const port = process.env.PORT || 8000;
function respond(req, res, next) {
unflatten('https://analysis-output.telemetry.mozilla.org/game-hardware-survey/data/hwsurvey-weekly.json', output => {
res.send(output);
});
next();
}
const cors = restifyCORSMiddleware({
origins: ['*'],
});
server.pre(cors.preflight);
server.pre(cors.actual);
server.get('/', respond);
server.listen(port, function() {
console.log('%s listening at %s', server.name, server.url);
});

55
src/unflatten.js Normal file
Просмотреть файл

@ -0,0 +1,55 @@
import request from 'request';
import decimal from 'decimal';
export default (sourceURL, callback) => {
request(sourceURL, (error, response, body) => {
if (error) {
return callback({
error: 'Cannot fetch ' + source,
});
}
const output = {
'data': [],
};
const sourceData = JSON.parse(body);
sourceData.forEach((day, index) => {
const metrics = {};
const entry = { metrics };
Object.keys(day).forEach(key => {
const value = sourceData[index][key];
const split = key.split(/_(.+)/);
// It's metadata
if (split.length === 1) {
entry[key] = value;
// It's a metric
} else {
const newMetricName = split[0];
// These aren't used
if (newMetricName === 'cpuCoresSpeed') {
return;
}
const bucketName = split[1];
if (metrics[newMetricName] === undefined) {
metrics[newMetricName] = {};
}
metrics[newMetricName][bucketName] = value;
}
});
output.data.push(entry);
});
callback(output);
});
}