Yes, as @Dino-at-Google wrote, there are a lot of great options! I like Google Charts (Charts | Google for Developers) for creating nice looking graphs on a web page.
You can create a simple line graph with a little Javascript and a call to the stats APIs:
Here is the code for a single page web application that draws that graph. You can save the code to an HTML file and run it in Chrome. It will request your Apigee user name and password so it can get an OAuth token for the call to stats API. Once it has a token it will ask for a org name and environment, for example “myorg” and “test”. You can supply a date range of a few days to see how it works. This is a quick example that is not robust or extensively tested.
// Sample code, offered as is without any support
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Analytics API Query Example</title>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script type="text/javascript">
// OAuth token for Apigee Edge Management APIs
var token = "";
// Load the Visualization API
google.load('visualization', '1.0', {'packages':['corechart']});
// wait until the document loads
$( document ).ready(function() {
// if the query button was clicked
$("#queryButton").click(getData);
// if the login button was clicked
$("#loginButton").click(getToken);
});
// Get an access token for Apigee Edge managment APIs
function getToken() {
// get values from input fields
var username = $('#username').val();
var password = $('#password').val();
var mfa = $('#mfa').val();
console.log("Getting token...");
// Call Apigee Edge managment authentication API
jQuery.ajax({
url: "https://login.apigee.com/oauth/token",
type: "POST",
headers: {
"Authorization": "Basic ZWRnZWNsaTplZGdlY2xpc2VjcmV0",
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
},
contentType: "application/x-www-form-urlencoded",
data: {
"username": username,
"password": password,
"mfa_token": mfa,
"grant_type": "password",
},
})
.done(function(data, textStatus, jqXHR) {
console.log("Login succeeded: " + jqXHR.status);
token = data.access_token;
$('#loginStatus').html("");
$('#auth').hide();
$('#application').show();
$('#password').val('');
$('#mfa').val('');
})
.fail(function(jqXHR, textStatus, errorThrown) {
console.log("HTTP Request Failed");
if(jqXHR.status == 401) {
$('#loginStatus').html("Invalid username/password");
}
else {
$('#loginStatus').html("Error (" + jqXHR.status + "): " + errorThrown);
}
})
.always(function() {
/* ... */
});
}
// Call Edge management API for analtyics and get data
function getData() {
// read values from HTML input fields
var org = $('#org').val();
var environment = $('#environment').val();
var user = $('#user').val();
var password = $('#password').val();
var startDate = $('#datepickerStart').val();
var endDate = $('#datepickerEnd').val();
// update status, ui
$('#chart_div').hide();
$('#statusMessage').html("Running query...");
$('#statusMessage').show();
console.log("Running query...");
// call management API and get analytics data
jQuery.ajax({
url: "https://api.enterprise.apigee.com/v1/o/" + org + "/environments/" + environment + "/stats/apps/",
type: "GET",
data: {
"select": "sum(message_count)",
"timeRange": startDate + " 06:00~" + endDate + " 07:00", // adjust for your timezone offset from GMT
"timeUnit": "hour",
},
headers: {
"Authorization": "Bearer " + token
},
})
.done(function(data, textStatus, jqXHR) {
$('#statusMessage').hide();
console.log("Query successful");
updateData(data);
})
.fail(function(jqXHR, textStatus, errorThrown) {
console.log("HTTP Request Failed");
$('#statusMessage').html(textStatus + ": " + errorThrown);
$('#responsecode').html("Status: " + jqXHR.status);
// if "unauthorized", show login UI
if(jqXHR.status == 401) {
onTokenExpiration();
}
});
}
// update HTML, draw graph
function updateData(myData) {
if(myData.environments[0].dimensions[0].metrics[0].values.length == 0) {
// no results? tell the user
$('#dateInfo').html("No data");
console.log("No data");
$('#chart_div').hide();
return;
}
// new variable, for convenience, to shorten the path
var counts = myData.environments[0].dimensions[0].metrics[0].values;
// sort data by timestamp
counts.sort(function(a, b) {return a.timestamp - b.timestamp} );
// create the data structure for the graph
var data = new google.visualization.DataTable();
data.addColumn('date', 'Time');
data.addColumn('number', 'Requests');
// Build data for graph
for(var i=0; i < counts.length; i++) {
temp = [];
temp.push(new Date(counts[i].timestamp)); // convert timestamp string to a Date
temp.push(Number(counts[i].value));
data.addRow(temp);
}
// Change format of tool-tip to show date and hours and minutes
var date_formatter = new google.visualization.DateFormat({ pattern: "MMM dd, yyyy HH:mm"});
date_formatter.format(data, 0);
// Set chart options
var options = {
chartArea: { top: 10, left: 70 },
width: 1200,
height: 600,
backgroundColor: '#1e1e1e',
vAxis: {
textStyle: { color: '#fff'},
titleTextStyle: { color: '#fff'}
},
hAxis: {
textStyle: { color: '#fff'},
titleTextStyle: { color: '#fff'},
baselineColor: { color: '#fff'}
},
legend: {
textStyle: { color: '#fff'},
titleTextStyle: { color: '#fff'},
},
animation: {
startup: true,
duration: 500,
easing: 'out'
},
series: {
0: {
color: '#88C1F2'
}
}
};
// Instantiate and draw chart, passing in chart options.
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
$('#chart_div').show();
chart.draw(data, options);
}
// set up UI for start and end date picker
$(function() {
$( "#datepickerStart" ).datepicker({ dateFormat: 'mm/dd/yy' });
$( "#datepickerEnd" ).datepicker({ dateFormat: 'mm/dd/yy' });
});
</script>
</head>
<body style="color: white; font-family: sans-serif; background-color: #1e1e1e">
<!-- login section -->
<div id="auth" style="border: 1px solid #858585">
<p>
<div style="font-family: sans-serif; font-size: 20px; font-weight: 400; color: white;"> Please log into Apigee Edge</div>
<table border="0" cellpadding="10">
<tr>
<td align="right">Username</td>
<td><input type="text" value="" id="username"></td>
<td></td>
</tr>
<tr>
<td align="right">Password</td>
<td><input type="password" value="" id="password"></td>
<td><input type="submit" value="Log in" id="loginButton"></td>
</tr>
<tr>
<td align="right">MFA token<br/><span style="font-size: x-small">(if required)</span></td>
<td><input type="password" value="" id="mfa"></td>
<td></td>
</tr>
</table>
</p>
<div id="loginStatus"></div>
</div>
<!-- application section -->
<div id="application" style="display: none;">
<p>Org: <input type="text" value="org name here" id="org">
Environment: <input type="text" value="prod" id="environment"></p>
<hr/>
<br/>
<p>Start date: <input type="text" id="datepickerStart" value="08/01/2018">
End date: <input type="text" id="datepickerEnd" value="08/15/2018">
<input type="submit" value="Run query" id="queryButton">
</p>
<div style="font-family: sans-serif; font-size: 40px; font-weight: 400; color: white;">Requests Per Hour</div>
<div id="statusMessage" style="font-family: sans-serif; font-size: 30px; font-weight: 300; color: white"></div><div>
<!-- div for the graph -->
<div id="chart_div"></div>
<hr>
<div id="responsecode"></div>
</div>
</body>
</html>