Skip to content

Commit

Permalink
Added timeline base functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
ArneTR committed Jul 24, 2023
1 parent 7dbce50 commit 7a94ca3
Show file tree
Hide file tree
Showing 6 changed files with 533 additions and 2 deletions.
46 changes: 46 additions & 0 deletions api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,52 @@ async def compare_in_repo(ids: str):

return ORJSONResponse({'success': True, 'data': phase_stats_object})

# This route is primarily used to load phase stats it into a pandas data frame
@app.get('/v1/timeline')
async def get_timeline_stats(uri: str, branch: str | None = None, filename: str | None = None):
if uri is None or uri.strip() == '':
return ORJSONResponse({'success': False, 'err': 'URI is empty'}, status_code=400)

if branch is None or branch.strip() == '':
branch = None
branch_condition = 'projects.branch IS NULL'
else:
branch_condition = 'projects.branch = %s'

if filename is None or filename.strip() == '':
filename = 'usage_scenario.yml'

query = f"""
SELECT
phase_stats.metric, phase_stats.detail_name, phase_stats.phase,
phase_stats.value, projects.commit_hash, projects.commit_timestamp
FROM projects
LEFT JOIN phase_stats ON
projects.id = phase_stats.project_id AND
phase LIKE '%%[RUNTIME]'
WHERE
projects.uri = %s AND
{branch_condition} AND
projects.filename = %s AND
projects.end_measurement IS NOT NULL
AND projects.last_run IS NOT NULL
ORDER BY
phase_stats.metric ASC, phase_stats.detail_name ASC,
phase_stats.phase ASC, projects.commit_timestamp ASC;
"""

if branch:
params = params = (uri, branch, filename)
else:
params = params = (uri, filename)

data = DB().fetch_all(query, params=params)

if data is None or data == []:
return Response(status_code=204) # No-Content

return ORJSONResponse({'success': True, 'data': data})

# This route is primarily used to load phase stats it into a pandas data frame
@app.get('/v1/phase_stats/single/{project_id}')
async def get_phase_stats_single(project_id: str):
Expand Down
1 change: 1 addition & 0 deletions docker/structure.sql
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ CREATE TABLE projects (
uri text,
branch text,
commit_hash text,
commit_timestamp timestamp,
email text,
categories int[],
usage_scenario json,
Expand Down
114 changes: 114 additions & 0 deletions frontend/js/timeline.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
const getURLParams = () => {
const query_string = window.location.search;
const url_params = (new URLSearchParams(query_string))
return url_params;
}

$(document).ready( (e) => {
(async () => {

let url_params = getURLParams();

if(url_params.get('uri') == null
|| url_params.get('uri') == ''
|| url_params.get('uri') == 'null') {
showNotification('No uri', 'uri parameter in URL is empty or not present. Did you follow a correct URL?');
throw "Error";
}

let api_url = `/v1/timeline?uri=${url_params.get('uri')}`;

if(url_params.get('branch') !== null && url_params.get('branch') !== 'null') {
api_url = `${api_url}&branch=${url_params.get('branch')}`
}

if(url_params.get('filename') !== null && url_params.get('filename') !== 'null') {
api_url = `${api_url}&filename=${url_params.get('filename')}`
}

try {
var phase_stats_data = (await makeAPICall(api_url)).data
} catch (err) {
showNotification('Could not get compare in-repo data from API', err);
}

if (phase_stats_data == undefined) return;

let legends = {};
let series = {};

phase_stats_data.forEach( (data) => {
let [metric_name, detail_name, phase, value, commit_hash, commit_timestamp] = data


if (series[`${metric_name} - ${detail_name}`] == undefined) {
series[`${metric_name} - ${detail_name}`] = {labels: [], values: [], notes: []}
}

series[`${metric_name} - ${detail_name}`].labels.push(commit_timestamp)
series[`${metric_name} - ${detail_name}`].values.push(value)
series[`${metric_name} - ${detail_name}`].notes.push({
commit_timestamp: commit_timestamp,
commit_hash: commit_hash,
phase: phase

})






})

const chart_instances = [];

for(my_series in series) {
const element = createChartContainer("#chart-container", `${my_series} [UNIT]`);

const chart_instance = echarts.init(element);

let data_series = [{
name: my_series,
type: 'bar',
smooth: true,
symbol: 'none',
areaStyle: {},
data: series[my_series].values,
markLine: {
precision: 4, // generally annoying that precision is by default 2. Wrong AVG if values are smaller than 0.001 and no autoscaling!
data: [ {type: "average",label: {formatter: "AVG:\n{c}"}}]
}
}]


let options = getLineBarChartOptions(series[my_series].labels, data_series, null, 'category');
options.tooltip = {
trigger: 'item',
formatter: function (params, ticket, callback) {
console.log(params);
return `<strong>${series[params.seriesName].notes[params.dataIndex]}</strong><br>
timestamp: ${series[params.seriesName].notes[params.dataIndex].commit_timestamp}<br>
commit_hash: ${series[params.seriesName].notes[params.dataIndex].commit_hash}<br>
`;
}
};

chart_instance.setOption(options);
chart_instances.push(chart_instance);

}



window.onresize = function() { // set callback when ever the user changes the viewport
chart_instances.forEach(chart_instance => {
chart_instance.resize();
})
}

document.querySelector('#api-loader').remove();

})();
});

Loading

0 comments on commit 7a94ca3

Please sign in to comment.