You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicecomb.apache.org by ni...@apache.org on 2019/08/10 07:50:12 UTC

[servicecomb-pack] 07/36: SCB-1411 Implement dashboard transaction statistics

This is an automated email from the ASF dual-hosted git repository.

ningjiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/servicecomb-pack.git

commit fdda5ba927ef4c0de84044dbfca85db6811e2c89
Author: Lei Zhang <co...@gmail.com>
AuthorDate: Wed Aug 7 19:23:18 2019 +0800

    SCB-1411 Implement dashboard transaction statistics
---
 .../fsm/repository/NoneTransactionRepository.java  |  6 ++++
 .../fsm/repository/TransactionRepository.java      |  3 ++
 .../ElasticsearchTransactionRepository.java        | 25 ++++++++++++--
 .../pack/alpha/server/api/APIControllerV1.java     |  7 ++++
 .../pack/alpha/ui/TransactionController.java       | 24 ++++++++++++++
 .../alpha/ui/vo/TransactionStatisticsDTO.java}     | 38 +++++++++++++++++-----
 .../main/resources/static/js/alpha-dashboard.js    | 30 +++++++++++++++++
 .../resources/templates/fragments/main_layout.html |  1 -
 .../src/main/resources/templates/index.html        | 32 ++++++++++--------
 9 files changed, 140 insertions(+), 26 deletions(-)

diff --git a/alpha/alpha-fsm/src/main/java/org/apache/servicecomb/pack/alpha/fsm/repository/NoneTransactionRepository.java b/alpha/alpha-fsm/src/main/java/org/apache/servicecomb/pack/alpha/fsm/repository/NoneTransactionRepository.java
index 5ebc21c..a376f25 100644
--- a/alpha/alpha-fsm/src/main/java/org/apache/servicecomb/pack/alpha/fsm/repository/NoneTransactionRepository.java
+++ b/alpha/alpha-fsm/src/main/java/org/apache/servicecomb/pack/alpha/fsm/repository/NoneTransactionRepository.java
@@ -18,6 +18,7 @@
 package org.apache.servicecomb.pack.alpha.fsm.repository;
 
 import java.lang.invoke.MethodHandles;
+import java.util.Map;
 import org.apache.servicecomb.pack.alpha.core.fsm.repository.model.GlobalTransaction;
 import org.apache.servicecomb.pack.alpha.core.fsm.repository.model.PagingGlobalTransactions;
 import org.slf4j.Logger;
@@ -41,4 +42,9 @@ public class NoneTransactionRepository implements TransactionRepository {
   public PagingGlobalTransactions getGlobalTransactions(int page, int size) throws Exception {
     throw new UnsupportedOperationException("NoneTransactionRepository Unsupported!");
   }
+
+  @Override
+  public Map<String,Long> getTransactionStatistics() {
+    throw new UnsupportedOperationException("NoneTransactionRepository Unsupported!");
+  }
 }
diff --git a/alpha/alpha-fsm/src/main/java/org/apache/servicecomb/pack/alpha/fsm/repository/TransactionRepository.java b/alpha/alpha-fsm/src/main/java/org/apache/servicecomb/pack/alpha/fsm/repository/TransactionRepository.java
index fd303d4..0b3bbb1 100644
--- a/alpha/alpha-fsm/src/main/java/org/apache/servicecomb/pack/alpha/fsm/repository/TransactionRepository.java
+++ b/alpha/alpha-fsm/src/main/java/org/apache/servicecomb/pack/alpha/fsm/repository/TransactionRepository.java
@@ -17,6 +17,7 @@
 
 package org.apache.servicecomb.pack.alpha.fsm.repository;
 
+import java.util.Map;
 import org.apache.servicecomb.pack.alpha.core.fsm.repository.model.GlobalTransaction;
 import org.apache.servicecomb.pack.alpha.core.fsm.repository.model.PagingGlobalTransactions;
 
@@ -29,4 +30,6 @@ public interface TransactionRepository {
 
   PagingGlobalTransactions getGlobalTransactions(int page, int size)
       throws Exception;
+
+  Map<String,Long> getTransactionStatistics();
 }
diff --git a/alpha/alpha-fsm/src/main/java/org/apache/servicecomb/pack/alpha/fsm/repository/elasticsearch/ElasticsearchTransactionRepository.java b/alpha/alpha-fsm/src/main/java/org/apache/servicecomb/pack/alpha/fsm/repository/elasticsearch/ElasticsearchTransactionRepository.java
index 4ccc5c4..e0aa41a 100644
--- a/alpha/alpha-fsm/src/main/java/org/apache/servicecomb/pack/alpha/fsm/repository/elasticsearch/ElasticsearchTransactionRepository.java
+++ b/alpha/alpha-fsm/src/main/java/org/apache/servicecomb/pack/alpha/fsm/repository/elasticsearch/ElasticsearchTransactionRepository.java
@@ -24,13 +24,19 @@ import java.lang.invoke.MethodHandles;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-import org.apache.servicecomb.pack.alpha.fsm.metrics.MetricsService;
-import org.apache.servicecomb.pack.alpha.fsm.repository.TransactionRepository;
+import java.util.Map;
+import java.util.stream.Collectors;
 import org.apache.servicecomb.pack.alpha.core.fsm.repository.model.GlobalTransaction;
 import org.apache.servicecomb.pack.alpha.core.fsm.repository.model.PagingGlobalTransactions;
+import org.apache.servicecomb.pack.alpha.fsm.metrics.MetricsService;
+import org.apache.servicecomb.pack.alpha.fsm.repository.TransactionRepository;
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.index.query.QueryBuilders;
 import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.aggregations.AggregationBuilders;
+import org.elasticsearch.search.aggregations.bucket.MultiBucketsAggregation;
+import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
+import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.data.domain.PageRequest;
@@ -132,6 +138,21 @@ public class ElasticsearchTransactionRepository implements TransactionRepository
         .globalTransactions(globalTransactions).elapsed(System.currentTimeMillis() - start).build();
   }
 
+  public Map<String, Long> getTransactionStatistics() {
+    TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders
+        .terms("count_group_by_state").field("state.keyword");
+    SearchQuery searchQuery = new NativeSearchQueryBuilder()
+        .addAggregation(termsAggregationBuilder)
+        .build();
+    return this.template.query(searchQuery, response -> {
+      final StringTerms groupState = response.getAggregations().get("count_group_by_state");
+      return groupState.getBuckets()
+          .stream()
+          .collect(Collectors.toMap(MultiBucketsAggregation.Bucket::getKeyAsString,
+              MultiBucketsAggregation.Bucket::getDocCount));
+    });
+  }
+
   private final SearchResultMapper searchResultMapper = new SearchResultMapper() {
     @Override
     public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> aClass,
diff --git a/alpha/alpha-server/src/main/java/org/apache/servicecomb/pack/alpha/server/api/APIControllerV1.java b/alpha/alpha-server/src/main/java/org/apache/servicecomb/pack/alpha/server/api/APIControllerV1.java
index 88148db..4609821 100644
--- a/alpha/alpha-server/src/main/java/org/apache/servicecomb/pack/alpha/server/api/APIControllerV1.java
+++ b/alpha/alpha-server/src/main/java/org/apache/servicecomb/pack/alpha/server/api/APIControllerV1.java
@@ -17,6 +17,7 @@
 
 package org.apache.servicecomb.pack.alpha.server.api;
 
+import java.util.Map;
 import org.apache.servicecomb.pack.alpha.fsm.repository.TransactionRepository;
 import org.apache.servicecomb.pack.alpha.core.fsm.repository.model.GlobalTransaction;
 import org.apache.servicecomb.pack.alpha.core.fsm.repository.model.PagingGlobalTransactions;
@@ -60,4 +61,10 @@ public class APIControllerV1 {
         .getGlobalTransactions(page, size);
     return ResponseEntity.ok(pagingGlobalTransactions);
   }
+
+  @GetMapping(value = "/transaction/statistics")
+  ResponseEntity<Map<String,Long>> getTransactions() {
+    return ResponseEntity.ok(transactionRepository.getTransactionStatistics());
+  }
+
 }
diff --git a/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/TransactionController.java b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/TransactionController.java
index 10ab5a3..ff47ec7 100644
--- a/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/TransactionController.java
+++ b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/TransactionController.java
@@ -20,6 +20,7 @@ package org.apache.servicecomb.pack.alpha.ui;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 import javax.servlet.http.HttpServletRequest;
 import org.apache.servicecomb.pack.alpha.core.fsm.repository.model.GlobalTransaction;
 import org.apache.servicecomb.pack.alpha.core.fsm.repository.model.PagingGlobalTransactions;
@@ -28,6 +29,7 @@ import org.apache.servicecomb.pack.alpha.ui.vo.DataTablesResponseDTO;
 import org.apache.servicecomb.pack.alpha.ui.vo.EventDTO;
 import org.apache.servicecomb.pack.alpha.ui.vo.SubTransactionDTO;
 import org.apache.servicecomb.pack.alpha.ui.vo.TransactionRowDTO;
+import org.apache.servicecomb.pack.alpha.ui.vo.TransactionStatisticsDTO;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.web.context.WebServerInitializedEvent;
 import org.springframework.context.ApplicationListener;
@@ -172,6 +174,28 @@ public class TransactionController implements ApplicationListener<WebServerIniti
     return "transaction_details";
   }
 
+  @GetMapping("/ui/transaction/statistics")
+  @ResponseBody
+  public TransactionStatisticsDTO getGlobalTransactionStatistics() {
+    TransactionStatisticsDTO statisticsDTO = new TransactionStatisticsDTO();
+    UriComponents uriComponents = UriComponentsBuilder
+        .fromUriString("http://localhost:" + serverPort + "/alpha/api/v1/transaction/statistics")
+        .build();
+    ResponseEntity<Map> entity = restTemplate
+        .getForEntity(uriComponents.toUriString(), Map.class);
+    Map<String,Number> statistics = entity.getBody();
+    if(statistics.containsKey("COMMITTED")){
+      statisticsDTO.setSuccessful(statistics.get("COMMITTED").longValue());
+    }
+    if(statistics.containsKey("SUSPENDED")){
+      statisticsDTO.setFailed(statistics.get("SUSPENDED").longValue());
+    }
+    if(statistics.containsKey("COMPENSATED")){
+      statisticsDTO.setCompensated(statistics.get("COMPENSATED").longValue());
+    }
+    return statisticsDTO;
+  }
+
   private GlobalTransaction findGlobalTransactionByGlobalTxId(String globalTxId){
     UriComponents uriComponents = UriComponentsBuilder
         .fromUriString("http://localhost:" + serverPort + "/alpha/api/v1/transaction/"+globalTxId)
diff --git a/alpha/alpha-fsm/src/main/java/org/apache/servicecomb/pack/alpha/fsm/repository/TransactionRepository.java b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/vo/TransactionStatisticsDTO.java
similarity index 55%
copy from alpha/alpha-fsm/src/main/java/org/apache/servicecomb/pack/alpha/fsm/repository/TransactionRepository.java
copy to alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/vo/TransactionStatisticsDTO.java
index fd303d4..df3cb3a 100644
--- a/alpha/alpha-fsm/src/main/java/org/apache/servicecomb/pack/alpha/fsm/repository/TransactionRepository.java
+++ b/alpha/alpha-ui/src/main/java/org/apache/servicecomb/pack/alpha/ui/vo/TransactionStatisticsDTO.java
@@ -15,18 +15,38 @@
  * limitations under the License.
  */
 
-package org.apache.servicecomb.pack.alpha.fsm.repository;
+package org.apache.servicecomb.pack.alpha.ui.vo;
 
-import org.apache.servicecomb.pack.alpha.core.fsm.repository.model.GlobalTransaction;
-import org.apache.servicecomb.pack.alpha.core.fsm.repository.model.PagingGlobalTransactions;
+public class TransactionStatisticsDTO {
+  private long successful;
+  private long compensated;
+  private long failed;
 
-public interface TransactionRepository {
+  public long getTotal() {
+    return successful + compensated + failed;
+  }
 
-  void send(GlobalTransaction transaction) throws Exception;
+  public long getSuccessful() {
+    return successful;
+  }
 
-  GlobalTransaction getGlobalTransactionByGlobalTxId(String globalTxId)
-      throws Exception;
+  public void setSuccessful(long successful) {
+    this.successful = successful;
+  }
 
-  PagingGlobalTransactions getGlobalTransactions(int page, int size)
-      throws Exception;
+  public long getFailed() {
+    return failed;
+  }
+
+  public void setFailed(long failed) {
+    this.failed = failed;
+  }
+
+  public long getCompensated() {
+    return compensated;
+  }
+
+  public void setCompensated(long compensated) {
+    this.compensated = compensated;
+  }
 }
diff --git a/alpha/alpha-ui/src/main/resources/static/js/alpha-dashboard.js b/alpha/alpha-ui/src/main/resources/static/js/alpha-dashboard.js
new file mode 100644
index 0000000..e292e7a
--- /dev/null
+++ b/alpha/alpha-ui/src/main/resources/static/js/alpha-dashboard.js
@@ -0,0 +1,30 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You 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 OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+$(document).ready(function () {
+  $.ajax('/ui/transaction/statistics', {
+    success: function (data) {
+      $('#statistics-total').text(data.total)
+      $('#statistics-successful').text(data.successful)
+      $('#statistics-compensated').text(data.compensated)
+      $('#statistics-failed').text(data.failed)
+    },
+    error: function (state) {
+      // TODO show message
+    }
+  });
+});
\ No newline at end of file
diff --git a/alpha/alpha-ui/src/main/resources/templates/fragments/main_layout.html b/alpha/alpha-ui/src/main/resources/templates/fragments/main_layout.html
index 467074e..a632f70 100644
--- a/alpha/alpha-ui/src/main/resources/templates/fragments/main_layout.html
+++ b/alpha/alpha-ui/src/main/resources/templates/fragments/main_layout.html
@@ -64,7 +64,6 @@
 
   </div>
   <!-- End of Content Wrapper -->
-
 </div>
 <!-- End of Page Wrapper -->
 
diff --git a/alpha/alpha-ui/src/main/resources/templates/index.html b/alpha/alpha-ui/src/main/resources/templates/index.html
index f79afde..bc13638 100644
--- a/alpha/alpha-ui/src/main/resources/templates/index.html
+++ b/alpha/alpha-ui/src/main/resources/templates/index.html
@@ -16,7 +16,7 @@
   -->
 
 <!DOCTYPE html>
-<html xmlns:layout="http://www.w3.org/1999/xhtml" layout:decorate="~{fragments/main_layout}">
+<html xmlns:layout="http://www.w3.org/1999/xhtml" xmlns:th="http://www.w3.org/1999/xhtml" layout:decorate="~{fragments/main_layout}">
 <head>
   <title>Alpha Admin - Dashboard</title>
 </head>
@@ -27,31 +27,32 @@
 
     <!-- Content Row -->
     <div class="row">
-      <!-- Cluster Card -->
+
+      <!-- Total Transaction Card -->
       <div class="col-xl-3 col-md-6 mb-4">
         <div class="card border-left-primary shadow h-100 py-2">
           <div class="card-body">
             <div class="row no-gutters align-items-center">
               <div class="col mr-2">
-                <div class="text-xs font-weight-bold text-primary text-uppercase mb-1">Cluster</div>
-                <div class="h5 mb-0 font-weight-bold text-gray-800">2</div>
+                <div class="text-xs font-weight-bold text-primary text-uppercase mb-1">Total Transaction</div>
+                <div class="h5 mb-0 font-weight-bold text-gray-800" id="statistics-total">0</div>
               </div>
               <div class="col-auto">
-                <i class="fas fa-calendar fa-2x text-gray-300"></i>
+                <i class="fas fa-clipboard-list fa-2x text-gray-300"></i>
               </div>
             </div>
           </div>
         </div>
       </div>
 
-      <!-- Total Transaction Card -->
+      <!-- Successful Transaction Card -->
       <div class="col-xl-3 col-md-6 mb-4">
-        <div class="card border-left-primary shadow h-100 py-2">
+        <div class="card border-left-success shadow h-100 py-2">
           <div class="card-body">
             <div class="row no-gutters align-items-center">
               <div class="col mr-2">
-                <div class="text-xs font-weight-bold text-primary text-uppercase mb-1">Total Transaction</div>
-                <div class="h5 mb-0 font-weight-bold text-gray-800">215,00</div>
+                <div class="text-xs font-weight-bold text-success text-uppercase mb-1">Successful Transactions</div>
+                <div class="h5 mb-0 font-weight-bold text-gray-800" id="statistics-successful">0</div>
               </div>
               <div class="col-auto">
                 <i class="fas fa-clipboard-list fa-2x text-gray-300"></i>
@@ -61,14 +62,14 @@
         </div>
       </div>
 
-      <!-- Successful Transaction Card -->
+      <!-- Compensated Transaction Card -->
       <div class="col-xl-3 col-md-6 mb-4">
-        <div class="card border-left-success shadow h-100 py-2">
+        <div class="card border-left-warning shadow h-100 py-2">
           <div class="card-body">
             <div class="row no-gutters align-items-center">
               <div class="col mr-2">
-                <div class="text-xs font-weight-bold text-success text-uppercase mb-1">Successful Transactions</div>
-                <div class="h5 mb-0 font-weight-bold text-gray-800">215,00</div>
+                <div class="text-xs font-weight-bold text-warning text-uppercase mb-1">Compensated Transaction</div>
+                <div class="h5 mb-0 font-weight-bold text-gray-800" id="statistics-compensated">0</div>
               </div>
               <div class="col-auto">
                 <i class="fas fa-clipboard-list fa-2x text-gray-300"></i>
@@ -85,7 +86,7 @@
             <div class="row no-gutters align-items-center">
               <div class="col mr-2">
                 <div class="text-xs font-weight-bold text-danger text-uppercase mb-1">Failed Transactions</div>
-                <div class="h5 mb-0 font-weight-bold text-gray-800">0</div>
+                <div class="h5 mb-0 font-weight-bold text-gray-800" id="statistics-failed">0</div>
               </div>
               <div class="col-auto">
                 <i class="fas fa-clipboard-list fa-2x text-gray-300"></i>
@@ -129,5 +130,8 @@
       </div>
     </div>
   </div>
+  <div layout:fragment="scripts">
+    <script th:src="@{/js/alpha-dashboard.js}"></script>
+  </div>
 </body>
 </html>