Repository: incubator-eagle Updated Branches: refs/heads/master 725e73377 -> 12a0fb961
[MINOR] Refine policy detail and logging format Project: http://git-wip-us.apache.org/repos/asf/incubator-eagle/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-eagle/commit/12a0fb96 Tree: http://git-wip-us.apache.org/repos/asf/incubator-eagle/tree/12a0fb96 Diff: http://git-wip-us.apache.org/repos/asf/incubator-eagle/diff/12a0fb96 Branch: refs/heads/master Commit: 12a0fb96144f70a9bd73939d7e968a2160b9999a Parents: 725e733 Author: Hao Chen <h...@apache.org> Authored: Mon Dec 19 20:50:17 2016 +0800 Committer: Hao Chen <h...@apache.org> Committed: Mon Dec 19 20:50:17 2016 +0800 ---------------------------------------------------------------------- .../service/MetadataServiceClientImpl.java | 8 +- .../trigger/DynamicPolicyLoader.java | 11 +- .../app/environment/AbstractEnvironment.java | 7 +- .../environment/impl/StormExecutionRuntime.java | 8 +- .../impl/ApplicationHealthCheckServiceImpl.java | 20 +-- .../ApplicationStatusUpdateServiceImpl.java | 22 ++- .../webapp/app/dev/partials/alert/detail.html | 2 +- .../app/dev/partials/alert/policyDetail.html | 170 +++++++++---------- 8 files changed, 130 insertions(+), 118 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/12a0fb96/eagle-core/eagle-alert-parent/eagle-alert/alert-common/src/main/java/org/apache/eagle/alert/service/MetadataServiceClientImpl.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-alert-parent/eagle-alert/alert-common/src/main/java/org/apache/eagle/alert/service/MetadataServiceClientImpl.java b/eagle-core/eagle-alert-parent/eagle-alert/alert-common/src/main/java/org/apache/eagle/alert/service/MetadataServiceClientImpl.java index 8571e56..4565d96 100644 --- a/eagle-core/eagle-alert-parent/eagle-alert/alert-common/src/main/java/org/apache/eagle/alert/service/MetadataServiceClientImpl.java +++ b/eagle-core/eagle-alert-parent/eagle-alert/alert-common/src/main/java/org/apache/eagle/alert/service/MetadataServiceClientImpl.java @@ -150,7 +150,7 @@ public class MetadataServiceClientImpl implements IMetadataServiceClient { private <T> List<T> list(String path, GenericType<List<T>> type) { WebResource r = client.resource(basePath + path); - LOG.info("query URL {}", basePath + path); + LOG.info("Requesting {}", basePath + path); List<T> ret = r.accept(MediaType.APPLICATION_JSON_TYPE).type(MediaType.APPLICATION_JSON).get(type); return ret; } @@ -172,7 +172,7 @@ public class MetadataServiceClientImpl implements IMetadataServiceClient { } private <T> T listOne(String path, Class<T> tClz) { - LOG.info("query URL {}", basePath + path); + LOG.info("Requesting {}", basePath + path); WebResource r = client.resource(basePath + path); ClientResponse resp = r.accept(MediaType.APPLICATION_JSON_TYPE).type(MediaType.APPLICATION_JSON) @@ -181,10 +181,10 @@ public class MetadataServiceClientImpl implements IMetadataServiceClient { try { return resp.getEntity(tClz); } catch (Exception e) { - LOG.warn(" list one entity failed, ignored and continute, path {}, message {}!", path, e.getMessage()); + LOG.warn("List one entity failed, ignored and continue, path:{}", path, e); } } else { - LOG.warn("fail querying metadata service {} with http status {}", basePath + path, resp.getStatus()); + LOG.warn("Fail querying metadata service {}, http status: {}", basePath + path, resp.getStatus()); } return null; } http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/12a0fb96/eagle-core/eagle-alert-parent/eagle-alert/alert-coordinator/src/main/java/org/apache/eagle/alert/coordinator/trigger/DynamicPolicyLoader.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-alert-parent/eagle-alert/alert-coordinator/src/main/java/org/apache/eagle/alert/coordinator/trigger/DynamicPolicyLoader.java b/eagle-core/eagle-alert-parent/eagle-alert/alert-coordinator/src/main/java/org/apache/eagle/alert/coordinator/trigger/DynamicPolicyLoader.java index 07ae966..7d0ead5 100644 --- a/eagle-core/eagle-alert-parent/eagle-alert/alert-coordinator/src/main/java/org/apache/eagle/alert/coordinator/trigger/DynamicPolicyLoader.java +++ b/eagle-core/eagle-alert-parent/eagle-alert/alert-coordinator/src/main/java/org/apache/eagle/alert/coordinator/trigger/DynamicPolicyLoader.java @@ -55,7 +55,7 @@ public class DynamicPolicyLoader implements Runnable { // we should catch every exception to avoid zombile thread try { final Stopwatch watch = Stopwatch.createStarted(); - LOG.info("policies loader start."); + LOG.info("Starting to load policies"); List<PolicyDefinition> current = client.listPolicies(); Map<String, PolicyDefinition> currPolicies = new HashMap<>(); current.forEach(pe -> currPolicies.put(pe.getName(), pe)); @@ -80,9 +80,10 @@ public class DynamicPolicyLoader implements Runnable { } if (!policyChanged) { - LOG.info("policy is not changed since last run"); + LOG.info("No policy (totally {}) changed since last round", current.size()); return; } + synchronized (this) { for (PolicyChangeListener listener : listeners) { listener.onPolicyChange(current, addedPolicies, removedPolicies, reallyModifiedPolicies); @@ -90,11 +91,13 @@ public class DynamicPolicyLoader implements Runnable { } watch.stop(); - LOG.info("policies loader completed. used time milliseconds: {}", watch.elapsed(TimeUnit.MILLISECONDS)); + + LOG.info("Finished loading {} policies, added: {}, removed: {}, modified: {}, taken: {} ms", + current.size(), addedPolicies.size(), removedPolicies.size(), potentiallyModifiedPolicies.size(), watch.elapsed(TimeUnit.MILLISECONDS)); // reset cached policies cachedPolicies = currPolicies; } catch (Throwable t) { - LOG.error("error loading policy, but continue to run", t); + LOG.warn("Error loading policy, but continue to run", t); } } } http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/12a0fb96/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/environment/AbstractEnvironment.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/environment/AbstractEnvironment.java b/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/environment/AbstractEnvironment.java index 5032aa6..ec2ffe1 100644 --- a/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/environment/AbstractEnvironment.java +++ b/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/environment/AbstractEnvironment.java @@ -16,9 +16,10 @@ */ package org.apache.eagle.app.environment; -import org.apache.eagle.app.messaging.*; import com.typesafe.config.Config; import org.apache.commons.lang3.builder.HashCodeBuilder; +import org.apache.eagle.app.messaging.KafkaStreamProvider; +import org.apache.eagle.app.messaging.StreamProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,7 +45,9 @@ public abstract class AbstractEnvironment implements Environment { throw new IllegalStateException(sinkProviderClassName + "is not assignable from " + StreamProvider.class.getCanonicalName()); } StreamProvider instance = (StreamProvider) sinkProviderClass.newInstance(); - LOGGER.info("Loaded {}", instance); + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Loaded {}", instance); + } return instance; } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { LOGGER.error(e.getMessage(), e); http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/12a0fb96/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/environment/impl/StormExecutionRuntime.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/environment/impl/StormExecutionRuntime.java b/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/environment/impl/StormExecutionRuntime.java index a4e9fac..f61a291 100644 --- a/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/environment/impl/StormExecutionRuntime.java +++ b/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/environment/impl/StormExecutionRuntime.java @@ -168,7 +168,7 @@ public class StormExecutionRuntime implements ExecutionRuntime<StormEnvironment, @Override public ApplicationEntity.Status status(Application<StormEnvironment, StormTopology> executor, com.typesafe.config.Config config) { String appId = config.getString("appId"); - LOG.info("Fetching status of topology {} ...", appId); + LOG.info("Fetching {} status", appId); List<TopologySummary> topologySummaries ; ApplicationEntity.Status status = null; try { @@ -186,7 +186,9 @@ public class StormExecutionRuntime implements ExecutionRuntime<StormEnvironment, } else if (topologySummary.get_status().equalsIgnoreCase("INACTIVE")) { status = ApplicationEntity.Status.STOPPED; } else if (topologySummary.get_status().equalsIgnoreCase("KILLED")) { - status = ApplicationEntity.Status.REMOVED; + status = ApplicationEntity.Status.STOPPED; + } else { + LOG.error("Unknown storm topology ({}) status: {}", topologySummary.get_status(),topologySummary.get_status()); } } } @@ -198,7 +200,7 @@ public class StormExecutionRuntime implements ExecutionRuntime<StormEnvironment, LOG.error("Got error to fetch status of {}", appId, e); status = ApplicationEntity.Status.UNKNOWN; } - LOG.info("Status of {}: {}", appId, status); + LOG.info("{} status is {}", appId, status); return status; } http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/12a0fb96/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/service/impl/ApplicationHealthCheckServiceImpl.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/service/impl/ApplicationHealthCheckServiceImpl.java b/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/service/impl/ApplicationHealthCheckServiceImpl.java index d1d4360..1607b0f 100644 --- a/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/service/impl/ApplicationHealthCheckServiceImpl.java +++ b/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/service/impl/ApplicationHealthCheckServiceImpl.java @@ -94,7 +94,7 @@ public class ApplicationHealthCheckServiceImpl extends ApplicationHealthCheckSer this.config.getConfig(HEALTH_PUBLISHER_PATH).withFallback(this.config.getConfig(SERVICE_PATH))); } } catch (Exception e) { - LOG.warn("exception found when create ApplicationHealthCheckPublisher instance {}", e.getCause()); + LOG.warn("Exception found when create ApplicationHealthCheckPublisher instance {}", e.getCause()); } } } @@ -114,7 +114,7 @@ public class ApplicationHealthCheckServiceImpl extends ApplicationHealthCheckSer @Override public void register(ApplicationEntity appEntity) { if (environment == null) { - LOG.warn("environment is null, can not register"); + LOG.warn("Environment is null, can not register"); return; } ApplicationProvider<?> appProvider = applicationProviderService.getApplicationProviderByType(appEntity.getDescriptor().getType()); @@ -125,7 +125,7 @@ public class ApplicationHealthCheckServiceImpl extends ApplicationHealthCheckSer ); if (!applicationHealthCheck.isPresent()) { - LOG.warn("application {} does not implement HealthCheck", appEntity.getAppId()); + LOG.warn("Application {} does not implement HealthCheck", appEntity.getAppId()); return; } this.environment.healthChecks().register(appEntity.getAppId(), applicationHealthCheck.get()); @@ -133,7 +133,7 @@ public class ApplicationHealthCheckServiceImpl extends ApplicationHealthCheckSer synchronized (lock) { if (!appHealthChecks.containsKey(appEntity.getAppId())) { appHealthChecks.put(appEntity.getAppId(), applicationHealthCheck); - LOG.info("successfully register health check for {}", appEntity.getAppId()); + LOG.info("Successfully register health check for {}", appEntity.getAppId()); } } } @@ -141,19 +141,19 @@ public class ApplicationHealthCheckServiceImpl extends ApplicationHealthCheckSer @Override public void unregister(ApplicationEntity appEntity) { if (environment == null) { - LOG.warn("environment is null, can not unregister"); + LOG.warn("Environment is null, can not unregister"); return; } this.environment.healthChecks().unregister(appEntity.getAppId()); synchronized (lock) { appHealthChecks.remove(appEntity.getAppId()); } - LOG.info("successfully unregister health check for {}", appEntity.getAppId()); + LOG.info("Successfully unregister health check for {}", appEntity.getAppId()); } @Override protected void runOneIteration() throws Exception { - LOG.info("start application health check"); + LOG.info("Starting ApplicationHealthCheckService"); registerAll(); boolean isDaily = false; @@ -185,10 +185,10 @@ public class ApplicationHealthCheckServiceImpl extends ApplicationHealthCheckSer results.put(appId, result); } } - LOG.info("application {} is healthy", appId); + LOG.info("Application {} is healthy", appId); } else { results.put(appId, result); - LOG.warn("application {} is not healthy, {}", appId, result.getMessage(), result.getError()); + LOG.warn("Application {} is not healthy, {}", appId, result.getMessage(), result.getError()); } } @@ -203,7 +203,7 @@ public class ApplicationHealthCheckServiceImpl extends ApplicationHealthCheckSer hasSendDaily = true; } } catch (Exception e) { - LOG.warn("failed to send email for unhealthy applications", e); + LOG.warn("Failed to send email for unhealthy applications", e); } } http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/12a0fb96/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/service/impl/ApplicationStatusUpdateServiceImpl.java ---------------------------------------------------------------------- diff --git a/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/service/impl/ApplicationStatusUpdateServiceImpl.java b/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/service/impl/ApplicationStatusUpdateServiceImpl.java index b6b27b2..a1ceb83 100644 --- a/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/service/impl/ApplicationStatusUpdateServiceImpl.java +++ b/eagle-core/eagle-app/eagle-app-base/src/main/java/org/apache/eagle/app/service/impl/ApplicationStatusUpdateServiceImpl.java @@ -18,8 +18,6 @@ package org.apache.eagle.app.service.impl; import com.google.inject.Inject; import com.google.inject.Singleton; -import com.typesafe.config.Config; -import com.typesafe.config.ConfigFactory; import org.apache.eagle.app.service.ApplicationOperations; import org.apache.eagle.metadata.model.ApplicationEntity; import org.apache.eagle.metadata.service.ApplicationEntityService; @@ -31,14 +29,14 @@ import java.util.Collection; import java.util.concurrent.TimeUnit; @Singleton -public class ApplicationStatusUpdateServiceImpl extends ApplicationStatusUpdateService { +public class ApplicationStatusUpdateServiceImpl extends ApplicationStatusUpdateService { private static final Logger LOG = LoggerFactory.getLogger(ApplicationStatusUpdateServiceImpl.class); private final ApplicationEntityService applicationEntityService; private final ApplicationManagementServiceImpl applicationManagementService; // default value 30, 30 - private int initialDelay = 30; - private int period = 30; + private int initialDelay = 30; + private int period = 30; @Inject @@ -49,16 +47,21 @@ public class ApplicationStatusUpdateServiceImpl extends ApplicationStatusUpdate @Override protected void runOneIteration() throws Exception { - LOG.info("Checking app status"); + LOG.info("Updating application status"); try { Collection<ApplicationEntity> applicationEntities = applicationEntityService.findAll(); - for (ApplicationEntity applicationEntity: applicationEntities) { + if (applicationEntities.size() == 0) { + LOG.info("No application installed yet"); + return; + } + for (ApplicationEntity applicationEntity : applicationEntities) { if (applicationEntity.getDescriptor().isExecutable()) { updateApplicationEntityStatus(applicationEntity); } } + LOG.info("Updated {} application status", applicationEntities.size()); } catch (Exception e) { - LOG.error("failed to update app status", e); + LOG.error("Failed to update application status", e); } } @@ -68,7 +71,8 @@ public class ApplicationStatusUpdateServiceImpl extends ApplicationStatusUpdate } @Override - public void updateApplicationEntityStatus(Collection<ApplicationEntity> applicationEntities) {} + public void updateApplicationEntityStatus(Collection<ApplicationEntity> applicationEntities) { + } @Override public void updateApplicationEntityStatus(ApplicationEntity applicationEntity) { http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/12a0fb96/eagle-server/src/main/webapp/app/dev/partials/alert/detail.html ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/webapp/app/dev/partials/alert/detail.html b/eagle-server/src/main/webapp/app/dev/partials/alert/detail.html index 5f63ccf..2a0f54e 100644 --- a/eagle-server/src/main/webapp/app/dev/partials/alert/detail.html +++ b/eagle-server/src/main/webapp/app/dev/partials/alert/detail.html @@ -47,7 +47,7 @@ </tr> <tr> <th>Alert Policy</th> - <td colspan="3"><a ui-sref="policyDetail({name: item.policyId})">{{alert.tags.policyId}}</a></td> + <td colspan="3"><a ui-sref="policyDetail({name: alert.tags.policyId})">{{alert.tags.policyId}}</a></td> </tr> <tr> <th>Alert Event</th> http://git-wip-us.apache.org/repos/asf/incubator-eagle/blob/12a0fb96/eagle-server/src/main/webapp/app/dev/partials/alert/policyDetail.html ---------------------------------------------------------------------- diff --git a/eagle-server/src/main/webapp/app/dev/partials/alert/policyDetail.html b/eagle-server/src/main/webapp/app/dev/partials/alert/policyDetail.html index c0ff80a..559785c 100644 --- a/eagle-server/src/main/webapp/app/dev/partials/alert/policyDetail.html +++ b/eagle-server/src/main/webapp/app/dev/partials/alert/policyDetail.html @@ -55,13 +55,68 @@ <div class="nav-tabs-custom"> <ul class="nav nav-tabs"> <!--li><a href="#statistic" data-toggle="tab">Statistic</a></li--> - <li class="active"><a href="#setting" data-toggle="tab" ng-click="setTab('setting')">Setting</a></li> - <li><a href="#assignments" data-toggle="tab" ng-click="setTab('assignments')">Assignments</a></li> + <li class="active"><a href="#alerts" data-toggle="tab" ng-click="setTab('alerts')">Alert List</a></li> <li><a href="#definition" data-toggle="tab" ng-click="setTab('definition')">Alert Definition</a></li> - <li><a href="#alerts" data-toggle="tab" ng-click="setTab('alerts')">Alert List</a></li> + <li><a href="#setting" data-toggle="tab" ng-click="setTab('setting')">Policy Settings</a></li> + <li><a href="#assignments" data-toggle="tab" ng-click="setTab('assignments')">Execution Assignments</a></li> </ul> <div class="tab-content"> - <div class="tab-pane active" id="setting"> + <div class="tab-pane active" id="alerts"> + <div sort-table="alertList"> + <table class="table table-bordered"> + <thead> + <tr> + <th sortpath="timestamp" width="135"> + Alert Time + <span class="fa fa-refresh fa-spin no-animate" ng-show="!alertList._done || isSorting"></span> + </th> + <th>Alert Subject</th> + <th width="10"></th> + </tr> + </thead> + <tbody> + <tr> + <td>{{Time.format(item.timestamp)}}</td> + <td class="text-break"> + {{item.alertSubject}} + </td> + <td> + <a ui-sref="alertDetail({alertId: item.tags.alertId})">Detail</a> + </td> + </tr> + </tbody> + </table> + </div> + </div> + + <div class="tab-pane" id="definition"> + <table class="table"> + <tbody> + <tr> + <th width="15%">Category</th> + <td>{{policy.alertDefinition.category}}</td> + </tr> + <tr> + <th>Severity</th> + <td> + <span class="label label-{{Policy.getSeverityClass(policy.alertDefinition.severity)}}"> + {{policy.alertDefinition.severity}} + </span> + </td> + </tr> + <tr> + <th>Alert Subject</th> + <td><pre>{{policy.alertDefinition.subject}}</pre></td> + </tr> + <tr> + <th>Alert Body</th> + <td><pre>{{policy.alertDefinition.body}}</pre></td> + </tr> + </tbody> + </table> + </div> + + <div class="tab-pane" id="setting"> <table class="table"> <tbody> <tr> @@ -128,98 +183,43 @@ </ul> </td> </tr> - <tr> - <th class="text-no-break">Execution Plan</th> - <td><pre>{{executionPlan.policyExecutionPlan.executionPlanDesc}}</pre></td> - </tr> + <!--<tr>--> + <!--<th class="text-no-break">Execution Plan</th>--> + <!--<td><pre>{{executionPlan.policyExecutionPlan.executionPlanDesc}}</pre></td>--> + <!--</tr>--> </tbody> </table> </div> - <div class="tab-pane" id="statistic">statistic - </div> <div class="tab-pane" id="assignments"> <table class="table"> <tbody> - <tr> - <th>Version</th> - <td>{{assignment.version}}</td> - </tr> - <tr> - <th>Queue Id</th> - <td>{{assignment.queueId}}</td> - </tr> - <tr> - <th class="text-no-break" width="120">working Slots</th> - <td> - <div na-block="queue.workingSlots.length > 0"> - <ul class="no-margin"> - <li ng-repeat="slot in queue.workingSlots track by $index"> - <span class="text-primary">{{slot.topologyName}}</span> - - {{slot.boltId}} - </li> - </ul> - </div> - </td> - </tr> - </tbody> - </table> - </div> - - <div class="tab-pane" id="definition"> - <table class="table"> - <tbody> - <tr> - <th width="15%">Category</th> - <td>{{policy.alertDefinition.category}}</td> - </tr> - <tr> - <th>Severity</th> - <td> - <span class="label label-{{Policy.getSeverityClass(policy.alertDefinition.severity)}}"> - {{policy.alertDefinition.severity}} - </span> - </td> - </tr> - <tr> - <th>Alert Subject</th> - <td>{{policy.alertDefinition.subject}}</td> - </tr> - <tr> - <th>Alert Body</th> - <td><pre>{{policy.alertDefinition.body}}</pre></td> - </tr> + <tr> + <th>Assigned Version</th> + <td>{{assignment.version}}</td> + </tr> + <tr> + <th>Assigned Queue</th> + <td>{{assignment.queueId}}</td> + </tr> + <tr> + <th class="text-no-break" width="120">Assigned Slots</th> + <td> + <div na-block="queue.workingSlots.length > 0"> + <ul class="no-margin"> + <li ng-repeat="slot in queue.workingSlots track by $index"> + <span class="text-primary">{{slot.topologyName}}</span> + - {{slot.boltId}} + </li> + </ul> + </div> + </td> + </tr> </tbody> </table> </div> - <div class="tab-pane" id="alerts"> - <div sort-table="alertList"> - <table class="table table-bordered"> - <thead> - <tr> - <th sortpath="timestamp" width="135"> - Alert Time - <span class="fa fa-refresh fa-spin no-animate" ng-show="!alertList._done || isSorting"></span> - </th> - <th>Alert Subject</th> - <th width="10"></th> - </tr> - </thead> - <tbody> - <tr> - <td>{{Time.format(item.timestamp)}}</td> - <td class="text-break"> - {{item.alertSubject}} - </td> - <td> - <a ui-sref="alertDetail({alertId: item.tags.alertId})">Detail</a> - </td> - </tr> - </tbody> - </table> - </div> - </div> + <!--<div class="tab-pane" id="statistic">statistic</div>--> </div> </div>