\ No newline at end of file
diff --git a/user-dashboard/public/js/resources/dashboard/analytics/chaincode/chaincode.html b/user-dashboard/public/js/resources/dashboard/analytics/chaincode/chaincode.html
new file mode 100644
index 000000000..19d957382
--- /dev/null
+++ b/user-dashboard/public/js/resources/dashboard/analytics/chaincode/chaincode.html
@@ -0,0 +1,21 @@
+
+
${name}
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/user-dashboard/public/js/resources/dashboard/analytics/chaincode/operation.html b/user-dashboard/public/js/resources/dashboard/analytics/chaincode/operation.html
new file mode 100644
index 000000000..4dfeb11a9
--- /dev/null
+++ b/user-dashboard/public/js/resources/dashboard/analytics/chaincode/operation.html
@@ -0,0 +1,15 @@
+
+
+
${name}
+
+
+
${func}
+
+
+
${responseTime}
+
+
+
${operationTime}
+
+
\ No newline at end of file
diff --git a/user-dashboard/public/js/resources/dashboard/analytics/chaincode/overlay.html b/user-dashboard/public/js/resources/dashboard/analytics/chaincode/overlay.html
new file mode 100644
index 000000000..f45e116c0
--- /dev/null
+++ b/user-dashboard/public/js/resources/dashboard/analytics/chaincode/overlay.html
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/user-dashboard/public/js/resources/dashboard/analytics/chaincode/overview.html b/user-dashboard/public/js/resources/dashboard/analytics/chaincode/overview.html
new file mode 100644
index 000000000..4a8d03486
--- /dev/null
+++ b/user-dashboard/public/js/resources/dashboard/analytics/chaincode/overview.html
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Chaincode Name
+
Invoke Times
+
Response Time
+
Invoke History
+
+
+
+
\ No newline at end of file
diff --git a/user-dashboard/public/js/resources/dashboard/analytics/chaincode/piedialog.html b/user-dashboard/public/js/resources/dashboard/analytics/chaincode/piedialog.html
new file mode 100644
index 000000000..a3cb7693e
--- /dev/null
+++ b/user-dashboard/public/js/resources/dashboard/analytics/chaincode/piedialog.html
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/user-dashboard/public/js/resources/dashboard/analytics/fabric/block.html b/user-dashboard/public/js/resources/dashboard/analytics/fabric/block.html
new file mode 100644
index 000000000..fc55abbf1
--- /dev/null
+++ b/user-dashboard/public/js/resources/dashboard/analytics/fabric/block.html
@@ -0,0 +1,11 @@
+
+
+
${block}
+
+
+
${blockTime}
+
+
+
${createTime}
+
+
\ No newline at end of file
diff --git a/user-dashboard/public/js/resources/dashboard/analytics/fabric/fabric.html b/user-dashboard/public/js/resources/dashboard/analytics/fabric/fabric.html
new file mode 100644
index 000000000..7115be1df
--- /dev/null
+++ b/user-dashboard/public/js/resources/dashboard/analytics/fabric/fabric.html
@@ -0,0 +1,81 @@
+
+
+ <% if (health >= 90) { %>
+
+
+
+
+
+
+ <% } else if (health >= 80) { %>
+
+
+
+
+
+
+ <% } else { %>
+
+
+
+
+
+
+ <% } %>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Block
+
Block Time
+
Create Time
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/user-dashboard/public/js/resources/dashboard/analytics/infrastructure.html b/user-dashboard/public/js/resources/dashboard/analytics/infrastructure.html
new file mode 100644
index 000000000..29bacf287
--- /dev/null
+++ b/user-dashboard/public/js/resources/dashboard/analytics/infrastructure.html
@@ -0,0 +1,59 @@
+
+
+ <% if (health >= 90) { %>
+
+
+
+
+
+
+ <% } else if (health >= 80) { %>
+
+
+
+
+
+
+ <% } else { %>
+
+
+
+
+
+
+ <% } %>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/user-dashboard/public/js/resources/dashboard/analytics/overview.html b/user-dashboard/public/js/resources/dashboard/analytics/overview.html
new file mode 100644
index 000000000..a3449abc5
--- /dev/null
+++ b/user-dashboard/public/js/resources/dashboard/analytics/overview.html
@@ -0,0 +1,59 @@
+
+
+ <% if (health >= 90) { %>
+
+
+
+ <% } else if (health >= 80) { %>
+
+
+
+ <% } else { %>
+
+
+
+ <% } %>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/user-dashboard/routes/api.js b/user-dashboard/routes/api.js
index a2dc948e4..2acacd223 100644
--- a/user-dashboard/routes/api.js
+++ b/user-dashboard/routes/api.js
@@ -11,6 +11,7 @@ var Chain = require("../modules/chain");
var Chaincode = require("../modules/chaincode");
var mongoClient = require("../modules/mongoclient");
var Contract = require("../modules/contract");
+var Analytics = require("../modules/analytics");
var router = express.Router();
@@ -333,4 +334,44 @@ router.post("/:apikey/contract/:id/delete", function(req, res) {
res.json(err);
});
});
+router.get("/chain/:id/analytics", function(req, res) {
+ var analytics = new Analytics(req.params.id);
+ analytics.overview().then(function(result) {
+ res.json(result);
+ }).catch(function(err) {
+ res.json(err);
+ });
+});
+router.get("/chain/:id/analytics/chaincode/list", function(req, res) {
+ var analytics = new Analytics(req.params.id);
+ analytics.chaincodeList().then(function(result) {
+ res.json(result);
+ }).catch(function(err) {
+ res.json(err);
+ });
+});
+router.get("/chain/:chainId/analytics/chaincode/:chaincodeId/operations", function(req, res) {
+ var analytics = new Analytics(req.params.chainId);
+ analytics.chaincodeOperations(req.params.chaincodeId, req.query.timestamp).then(function(result) {
+ res.json(result);
+ }).catch(function(err) {
+ res.json(err);
+ });
+});
+router.get("/chain/:id/analytics/fabric", function(req, res) {
+ var analytics = new Analytics(req.params.id);
+ analytics.fabric(req.query.timestamp).then(function(result) {
+ res.json(result);
+ }).catch(function(err) {
+ res.json(err);
+ });
+});
+router.get("/chain/:id/analytics/infrastructure", function(req, res) {
+ var analytics = new Analytics(req.params.id);
+ analytics.infrastructure(req.query.size).then(function(result) {
+ res.json(result);
+ }).catch(function(err) {
+ res.json(err);
+ });
+});
module.exports = router;
\ No newline at end of file
diff --git a/user-dashboard/routes/dashboard/analytics.js b/user-dashboard/routes/dashboard/analytics.js
new file mode 100644
index 000000000..4f33804e2
--- /dev/null
+++ b/user-dashboard/routes/dashboard/analytics.js
@@ -0,0 +1,81 @@
+/**
+ * Created by lixuc on 2017/5/12.
+ */
+var express = require("express");
+var config = require("../../modules/configuration");
+var Chain = require("../../modules/chain");
+var Analytics = require("../../modules/analytics");
+
+var router = express.Router();
+
+router.get([
+ "/analytics",
+ "/analytics/chaincode",
+ "/analytics/fabric",
+ "/analytics/infrastructure"
+], function(req, res, next) {
+ var userInfo = JSON.parse(req.cookies[config.cookieName]);
+ var chain = new Chain(userInfo.apikey);
+ chain.list(-1).then(function(result) {
+ var chains = result.chains;
+ if (chains.length) {
+ chains.sort(function(c1, c2) {
+ if (c1.name < c2.name) return -1;
+ else if (c1.name > c2.name) return 1;
+ else return 0;
+ });
+ res.locals.chains = chains;
+ next();
+ } else {
+ res.render("dashboard/analytics/noChains");
+ }
+ }).catch(function(err) {
+ var e = new Error(err.message);
+ e.status = 500;
+ next(e);
+ });
+});
+router.get("/analytics", function(req, res, next) {
+ var chains = res.locals.chains;
+ var analytics = new Analytics(chains[0].id);
+ analytics.overview().then(function(result) {
+ res.render("dashboard/analytics/overview", result.statistic);
+ }).catch(function(err) {
+ var e = new Error(err.message);
+ e.status = 500;
+ next(e);
+ });
+});
+router.get("/analytics/chaincode", function(req, res, next) {
+ var chains = res.locals.chains;
+ var analytics = new Analytics(chains[0].id);
+ analytics.chaincodeList().then(function(result) {
+ var chaincodes = result.chaincodes;
+ var renderer = {
+ chaincodes: chaincodes
+ };
+ if (chaincodes.length) {
+ var invokeTimes = 0, responseTime = 0;
+ for (var i in chaincodes) {
+ invokeTimes += parseInt(chaincodes[i].invoke_times);
+ responseTime += parseFloat(chaincodes[i].avg_response_time);
+ }
+ Object.assign(renderer, {
+ invokeTimes: invokeTimes,
+ avgResponseTime: parseFloat((responseTime / chaincodes.length).toFixed(2))
+ });
+ }
+ res.render("dashboard/analytics/chaincode", renderer);
+ }).catch(function(err) {
+ var e = new Error(err.message);
+ e.status = 500;
+ next(e);
+ });
+});
+router.get("/analytics/fabric", function(req, res) {
+ res.render("dashboard/analytics/fabric");
+});
+router.get("/analytics/infrastructure", function(req, res) {
+ res.render("dashboard/analytics/infrastructure");
+});
+module.exports = router;
\ No newline at end of file
diff --git a/user-dashboard/views/dashboard/analytics/chaincode.pug b/user-dashboard/views/dashboard/analytics/chaincode.pug
new file mode 100644
index 000000000..d5180fbcc
--- /dev/null
+++ b/user-dashboard/views/dashboard/analytics/chaincode.pug
@@ -0,0 +1,77 @@
+extends ../../layout
+
+block css
+ link(rel="stylesheet", href="/css/addon/sticky.almost-flat.min.css")
+ link(rel="stylesheet", href="/css/dashboard/overlayer.css")
+ link(rel="stylesheet", href="/css/dashboard/navbar.css")
+ link(rel="stylesheet", href="/css/dashboard/analytics.css")
+block js
+ script(data-main="/js/entry/analytics/chaincode" src="/js/lib/require.js")
+block content
+ include ../includes/navbar.pug
+ +active("analytics")
+ section.ds-analytics.uk-container.uk-container-center.uk-padding-remove
+ .uk-grid
+ .uk-width-1-5
+ include includes/catalog.pug
+ +active("chaincode")
+ .uk-width-4-5
+ include includes/chainSelector.pug
+ #analyticsPanel.uk-margin-top
+ if chaincodes.length
+ .uk-grid.uk-margin-large-top
+ .uk-text-center
+ .uk-text-truncate.uk-margin-bottom.perfect-health-square
+ label.font-size-15 Chaincode
+ .uk-vertical-align.health-label-box
+ label.uk-vertical-align-middle.perfect-label Perfect
+ label.font-size-20 Health
+ .uk-vertical-align
+ .uk-vertical-align-middle.vertical-line(style="margin-bottom:37px;")
+ .uk-text-center
+ .uk-vertical-align.uk-margin-bottom(style="height:156px;")
+ label.uk-vertical-align-middle.font-size-50= chaincodes.length
+ label.font-size-20 Chaincodes
+ .uk-vertical-align
+ .uk-vertical-align-middle.vertical-line(style="margin-bottom:37px;")
+ .uk-text-center
+ .uk-vertical-align.uk-margin-bottom(style="height:156px;")
+ label.uk-vertical-align-middle.uk-margin-small-right.font-size-50= invokeTimes
+ label.uk-vertical-align-middle.font-size-20(style="margin-top:20px;")
+ = invokeTimes <= 1 ? "time" : "times"
+ label.font-size-20 Invoke
+ .uk-vertical-align
+ .uk-vertical-align-middle.vertical-line(style="margin-bottom:37px;")
+ .uk-text-center
+ .uk-vertical-align.uk-margin-bottom(style="height:156px;")
+ label.uk-vertical-align-middle.uk-margin-small-right.font-size-50= avgResponseTime
+ label.uk-vertical-align-middle.font-size-20(style="margin-top:20px;") s
+ label.font-size-20 Response Time
+ table.uk-table.uk-table-striped.uk-table-hover.uk-margin-large-top
+ thead
+ tr(style="border-top:1px solid #ddd;")
+ th Chaincode Name
+ th Invoke Times
+ th Response Time
+ th Invoke History
+ tbody
+ each chaincode in chaincodes
+ tr
+ td= chaincode.name
+ td
+ label.invokeTimes= chaincode.invoke_times
+ td
+ label.responseTime= parseFloat(chaincode.avg_response_time.toFixed(2)) + "s"
+ td
+ button.uk-button.uk-button-primary.uk-button-small.uk-margin-right(
+ type="button" data-type="functions" data-id=chaincode.id) Functions
+ |
+ i.uk-icon-pie-chart.uk-margin-small-left
+ |
+ button.uk-button.uk-button-primary.uk-button-small(
+ type="button" data-type="responseTime" data-id=chaincode.id) Response Time
+ |
+ i.uk-icon-bar-chart.uk-margin-small-left
+ else
+ label.uk-margin-large-top.empty No result.
+ div(style="height:80px;")
\ No newline at end of file
diff --git a/user-dashboard/views/dashboard/analytics/fabric.pug b/user-dashboard/views/dashboard/analytics/fabric.pug
new file mode 100644
index 000000000..2526681d9
--- /dev/null
+++ b/user-dashboard/views/dashboard/analytics/fabric.pug
@@ -0,0 +1,21 @@
+extends ../../layout
+
+block css
+ link(rel="stylesheet", href="/css/addon/sticky.almost-flat.min.css")
+ link(rel="stylesheet", href="/css/dashboard/overlayer.css")
+ link(rel="stylesheet", href="/css/dashboard/navbar.css")
+ link(rel="stylesheet", href="/css/dashboard/analytics.css")
+block js
+ script(data-main="/js/entry/analytics/fabric" src="/js/lib/require.js")
+block content
+ include ../includes/navbar.pug
+ +active("analytics")
+ section.ds-analytics.uk-container.uk-container-center.uk-padding-remove
+ .uk-grid
+ .uk-width-1-5
+ include includes/catalog.pug
+ +active("fabric")
+ .uk-width-4-5
+ include includes/chainSelector.pug
+ #analyticsPanel.uk-margin-top
+ div(style="height:80px;")
\ No newline at end of file
diff --git a/user-dashboard/views/dashboard/analytics/includes/catalog.pug b/user-dashboard/views/dashboard/analytics/includes/catalog.pug
new file mode 100644
index 000000000..b46bb6d31
--- /dev/null
+++ b/user-dashboard/views/dashboard/analytics/includes/catalog.pug
@@ -0,0 +1,31 @@
+mixin active(name)
+ - var overview_cls, chaincode_cls, fabric_cls, infrastructure_cls
+ case name
+ when "overview"
+ - overview_cls = "uk-active"
+ when "chaincode"
+ - chaincode_cls = "uk-active"
+ when "fabric"
+ - fabric_cls = "uk-active"
+ when "infrastructure"
+ - infrastructure_cls = "uk-active"
+ .uk-panel.uk-panel-box(data-uk-sticky="{top:20}")
+ h3.uk-panel-title Catalog
+ ul.uk-nav.uk-nav-side
+ li.uk-nav-divider
+ li(class=overview_cls)
+ a(href="/dashboard/analytics")
+ i.uk-icon-globe.uk-margin-small-right
+ | Overview
+ li(class=chaincode_cls)
+ a(href="/dashboard/analytics/chaincode")
+ i.uk-icon-file-code-o.uk-margin-small-right
+ | Chaincode
+ li(class=fabric_cls)
+ a(href="/dashboard/analytics/fabric")
+ i.uk-icon-cubes.uk-margin-small-right
+ | Fabric
+ li(class=infrastructure_cls)
+ a(href="/dashboard/analytics/infrastructure")
+ i.uk-icon-server.uk-margin-small-right
+ | Infrastructure
\ No newline at end of file
diff --git a/user-dashboard/views/dashboard/analytics/includes/chainSelector.pug b/user-dashboard/views/dashboard/analytics/includes/chainSelector.pug
new file mode 100644
index 000000000..21f9966d5
--- /dev/null
+++ b/user-dashboard/views/dashboard/analytics/includes/chainSelector.pug
@@ -0,0 +1,13 @@
+#chainSelector.uk-button-dropdown(data-uk-dropdown="{remaintime:100}")
+ button.uk-button.dropdown-button(data-uk-tooltip="{pos:'right'}" title="Select a chain")
+ i.uk-icon-chain
+ |
+ label(data-id=chains[0].id)= chains[0].name
+ i.uk-icon-caret-down.uk-margin-left
+ .uk-dropdown.uk-dropdown-small
+ ul.uk-nav.uk-nav-dropdown
+ each chain in chains
+ li(data-id=chain.id data-name=chain.name)
+ a
+ i.uk-icon-chain
+ | #{chain.name}
\ No newline at end of file
diff --git a/user-dashboard/views/dashboard/analytics/infrastructure.pug b/user-dashboard/views/dashboard/analytics/infrastructure.pug
new file mode 100644
index 000000000..3df0810b2
--- /dev/null
+++ b/user-dashboard/views/dashboard/analytics/infrastructure.pug
@@ -0,0 +1,21 @@
+extends ../../layout
+
+block css
+ link(rel="stylesheet", href="/css/addon/sticky.almost-flat.min.css")
+ link(rel="stylesheet", href="/css/dashboard/overlayer.css")
+ link(rel="stylesheet", href="/css/dashboard/navbar.css")
+ link(rel="stylesheet", href="/css/dashboard/analytics.css")
+block js
+ script(data-main="/js/entry/analytics/infrastructure" src="/js/lib/require.js")
+block content
+ include ../includes/navbar.pug
+ +active("analytics")
+ section.ds-analytics.uk-container.uk-container-center.uk-padding-remove
+ .uk-grid
+ .uk-width-1-5
+ include includes/catalog.pug
+ +active("infrastructure")
+ .uk-width-4-5
+ include includes/chainSelector.pug
+ #analyticsPanel.uk-margin-top
+ div(style="height:80px;")
\ No newline at end of file
diff --git a/user-dashboard/views/dashboard/analytics/noChains.pug b/user-dashboard/views/dashboard/analytics/noChains.pug
new file mode 100644
index 000000000..4444a4949
--- /dev/null
+++ b/user-dashboard/views/dashboard/analytics/noChains.pug
@@ -0,0 +1,14 @@
+extends ../../layout
+
+block css
+ link(rel="stylesheet", href="/css/dashboard/navbar.css")
+ link(rel="stylesheet", href="/css/dashboard/analytics.css")
+block js
+ script(data-main="/js/entry/analytics/nochains" src="/js/lib/require.js")
+block content
+ include ../includes/navbar.pug
+ +active("analytics")
+ section.ds-analytics.uk-container.uk-container-center
+ .uk-alert.uk-text-large.uk-container-center.uk-animation-slide-top(style="width:26%")
+ i.uk-icon-warning.uk-margin-small-right
+ | Please #[a.warning_link(href="/dashboard/chain") apply a new chain] first.
\ No newline at end of file
diff --git a/user-dashboard/views/dashboard/analytics/overview.pug b/user-dashboard/views/dashboard/analytics/overview.pug
new file mode 100644
index 000000000..37b6dae45
--- /dev/null
+++ b/user-dashboard/views/dashboard/analytics/overview.pug
@@ -0,0 +1,73 @@
+extends ../../layout
+
+block css
+ link(rel="stylesheet", href="/css/addon/sticky.almost-flat.min.css")
+ link(rel="stylesheet", href="/css/dashboard/overlayer.css")
+ link(rel="stylesheet", href="/css/dashboard/navbar.css")
+ link(rel="stylesheet", href="/css/dashboard/analytics.css")
+block js
+ script(data-main="/js/entry/analytics/overview" src="/js/lib/require.js")
+block content
+ include ../includes/navbar.pug
+ +active("analytics")
+ section.ds-analytics.uk-container.uk-container-center.uk-padding-remove
+ .uk-grid
+ .uk-width-1-5
+ include includes/catalog.pug
+ +active("overview")
+ .uk-width-4-5
+ include includes/chainSelector.pug
+ #analyticsPanel.uk-margin-top
+ .uk-grid.uk-margin-large-top
+ .uk-text-center
+ mixin div(val)
+ - var health_cls, health_label_cls, health_label
+ if (val >= 90)
+ - health_cls = "perfect-health-circle"
+ - health_label_cls = "perfect-label"
+ - health_label = "Perfect"
+ else if (val >= 80)
+ - health_cls = "good-health-circle"
+ - health_label_cls = "good-label"
+ - health_label = "Good"
+ else
+ - health_cls = "attention-health-circle"
+ - health_label_cls = "attention-label"
+ - health_label = "Attention"
+ .uk-vertical-align.uk-margin-bottom(class=[health_cls])
+ label.uk-vertical-align-middle(class=[health_label_cls])= health_label
+ +div(health)
+ label.font-size-20 Health
+ .uk-vertical-align
+ .uk-vertical-align-middle.vertical-line(style="margin-bottom:37px;")
+ .uk-text-center
+ .uk-vertical-align.uk-margin-bottom(style="height:171px;")
+ label.uk-vertical-align-middle
+ if (runTime.length == 4)
+ span.font-size-50= runTime[0]
+ |
+ span.uk-margin-right.font-size-20= runTime[1]
+ |
+ span.font-size-50= runTime[2]
+ |
+ span.font-size-20= runTime[3]
+ else
+ span.font-size-50= runTime[0]
+ |
+ span.font-size-20= runTime[1]
+ label.font-size-20 Run Time
+ .uk-vertical-align
+ .uk-vertical-align-middle.vertical-line(style="margin-bottom:37px;")
+ .uk-text-center
+ .uk-vertical-align.uk-margin-bottom(style="height:171px;")
+ label.uk-vertical-align-middle
+ span.font-size-50= chaincodes
+ label.font-size-20 Chaincodes
+ .uk-vertical-align
+ .uk-vertical-align-middle.vertical-line(style="margin-bottom:37px;")
+ .uk-text-center
+ .uk-vertical-align.uk-margin-bottom(style="height:171px;")
+ label.uk-vertical-align-middle
+ span.font-size-50= blocks
+ label.font-size-20 Blocks
+ div(style="height:80px;")
\ No newline at end of file