diff --git a/deploy/openshift/templates/monitoring/che-monitoring.yaml b/deploy/openshift/templates/monitoring/che-monitoring.yaml
index df7dae75e1..36def2ea01 100644
--- a/deploy/openshift/templates/monitoring/che-monitoring.yaml
+++ b/deploy/openshift/templates/monitoring/che-monitoring.yaml
@@ -74,7 +74,7 @@ objects:
deploymentconfig: grafana
spec:
containers:
- - image: grafana/grafana
+ - image: grafana/grafana:6.6.2
imagePullPolicy: Always
name: grafana
ports:
diff --git a/deploy/openshift/templates/monitoring/grafana-dashboards.yaml b/deploy/openshift/templates/monitoring/grafana-dashboards.yaml
index 4f215ffa46..95445c7bf5 100644
--- a/deploy/openshift/templates/monitoring/grafana-dashboards.yaml
+++ b/deploy/openshift/templates/monitoring/grafana-dashboards.yaml
@@ -3608,7 +3608,7 @@ data:
"version": 1
}
che-workspaces.json: |-
- {
+ {
"annotations": {
"list": [
{
@@ -3625,8 +3625,7 @@ data:
"editable": true,
"gnetId": null,
"graphTooltip": 1,
- "id": 2,
- "iteration": 1574014597638,
+ "iteration": 1587125836872,
"links": [],
"panels": [
{
@@ -3817,98 +3816,6 @@ data:
],
"valueName": "current"
},
- {
- "aliasColors": {},
- "bars": false,
- "dashLength": 10,
- "dashes": false,
- "datasource": "${datasource}",
- "fill": 1,
- "fillGradient": 0,
- "gridPos": {
- "h": 5,
- "w": 6,
- "x": 12,
- "y": 17
- },
- "hiddenSeries": false,
- "id": 110,
- "legend": {
- "avg": false,
- "current": false,
- "max": false,
- "min": false,
- "show": true,
- "total": false,
- "values": false
- },
- "lines": true,
- "linewidth": 1,
- "nullPointMode": "null",
- "options": {
- "dataLinks": []
- },
- "percentage": false,
- "pointradius": 2,
- "points": false,
- "renderer": "flot",
- "seriesOverrides": [],
- "spaceLength": 10,
- "stack": false,
- "steppedLine": false,
- "targets": [
- {
- "expr": "sum(che_workspace_starting_attempts_total)",
- "legendFormat": "Workspace start attempts",
- "refId": "A"
- },
- {
- "expr": "che_workspace_starting_attempts_total{debug='true'}",
- "legendFormat": "Workspace start attempts in start-debug mode",
- "refId": "B"
- }
- ],
- "thresholds": [],
- "timeFrom": null,
- "timeRegions": [],
- "timeShift": null,
- "title": "Workspace start attempts",
- "tooltip": {
- "shared": true,
- "sort": 0,
- "value_type": "individual"
- },
- "type": "graph",
- "xaxis": {
- "buckets": null,
- "mode": "time",
- "name": null,
- "show": true,
- "values": []
- },
- "yaxes": [
- {
- "format": "short",
- "label": null,
- "logBase": 1,
- "max": null,
- "min": 0,
- "show": true
- },
- {
- "format": "short",
- "label": null,
- "logBase": 1,
- "max": null,
- "min": 0,
- "show": true
- }
- ],
- "yaxis": {
- "align": false,
- "alignLevel": null
- }
- },
{
"collapsed": false,
"datasource": "$datasource",
@@ -3938,6 +3845,7 @@ data:
"x": 0,
"y": 7
},
+ "hiddenSeries": false,
"id": 36,
"interval": "",
"legend": {
@@ -4037,6 +3945,7 @@ data:
"x": 6,
"y": 7
},
+ "hiddenSeries": false,
"id": 48,
"interval": "",
"legend": {
@@ -4135,6 +4044,7 @@ data:
"x": 12,
"y": 7
},
+ "hiddenSeries": false,
"id": 6,
"legend": {
"avg": true,
@@ -4225,6 +4135,7 @@ data:
"x": 18,
"y": 7
},
+ "hiddenSeries": false,
"id": 59,
"legend": {
"avg": true,
@@ -4316,6 +4227,7 @@ data:
"x": 0,
"y": 12
},
+ "hiddenSeries": false,
"id": 44,
"legend": {
"avg": true,
@@ -4408,6 +4320,7 @@ data:
"x": 6,
"y": 12
},
+ "hiddenSeries": false,
"id": 49,
"legend": {
"avg": true,
@@ -4500,6 +4413,7 @@ data:
"x": 12,
"y": 12
},
+ "hiddenSeries": false,
"id": 8,
"legend": {
"avg": false,
@@ -4590,6 +4504,7 @@ data:
"x": 18,
"y": 12
},
+ "hiddenSeries": false,
"id": 10,
"legend": {
"avg": true,
@@ -4681,6 +4596,7 @@ data:
"x": 0,
"y": 17
},
+ "hiddenSeries": false,
"id": 62,
"legend": {
"avg": true,
@@ -4773,6 +4689,7 @@ data:
"x": 6,
"y": 17
},
+ "hiddenSeries": false,
"id": 77,
"legend": {
"avg": false,
@@ -4800,12 +4717,18 @@ data:
"steppedLine": false,
"targets": [
{
- "expr": "sum(che_workspace_status)",
+ "expr": "che_workspace_total",
"format": "time_series",
"instant": false,
+ "interval": "",
"intervalFactor": 1,
- "legendFormat": "Number of Workspaces",
+ "legendFormat": "total",
"refId": "A"
+ },
+ {
+ "expr": "sum(che_workspace_status)",
+ "legendFormat": "status sum",
+ "refId": "B"
}
],
"thresholds": [],
@@ -4851,6 +4774,98 @@ data:
"alignLevel": null
}
},
+ {
+ "aliasColors": {},
+ "bars": false,
+ "dashLength": 10,
+ "dashes": false,
+ "datasource": "${datasource}",
+ "fill": 1,
+ "fillGradient": 0,
+ "gridPos": {
+ "h": 5,
+ "w": 6,
+ "x": 12,
+ "y": 17
+ },
+ "hiddenSeries": false,
+ "id": 110,
+ "legend": {
+ "avg": false,
+ "current": false,
+ "max": false,
+ "min": false,
+ "show": true,
+ "total": false,
+ "values": false
+ },
+ "lines": true,
+ "linewidth": 1,
+ "nullPointMode": "null",
+ "options": {
+ "dataLinks": []
+ },
+ "percentage": false,
+ "pointradius": 2,
+ "points": false,
+ "renderer": "flot",
+ "seriesOverrides": [],
+ "spaceLength": 10,
+ "stack": false,
+ "steppedLine": false,
+ "targets": [
+ {
+ "expr": "sum(che_workspace_starting_attempts_total)",
+ "legendFormat": "Workspace start attempts",
+ "refId": "A"
+ },
+ {
+ "expr": "che_workspace_starting_attempts_total{debug='true'}",
+ "legendFormat": "Workspace start attempts in start-debug mode",
+ "refId": "B"
+ }
+ ],
+ "thresholds": [],
+ "timeFrom": null,
+ "timeRegions": [],
+ "timeShift": null,
+ "title": "Workspace start attempts",
+ "tooltip": {
+ "shared": true,
+ "sort": 0,
+ "value_type": "individual"
+ },
+ "type": "graph",
+ "xaxis": {
+ "buckets": null,
+ "mode": "time",
+ "name": null,
+ "show": true,
+ "values": []
+ },
+ "yaxes": [
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": 0,
+ "show": true
+ },
+ {
+ "format": "short",
+ "label": null,
+ "logBase": 1,
+ "max": null,
+ "min": 0,
+ "show": true
+ }
+ ],
+ "yaxis": {
+ "align": false,
+ "alignLevel": null
+ }
+ },
{
"collapsed": false,
"datasource": "$datasource",
@@ -4881,6 +4896,7 @@ data:
"x": 0,
"y": 23
},
+ "hiddenSeries": false,
"id": 78,
"legend": {
"avg": false,
@@ -4985,6 +5001,7 @@ data:
"x": 0,
"y": 29
},
+ "hiddenSeries": false,
"id": 16,
"legend": {
"avg": false,
@@ -5091,6 +5108,7 @@ data:
"x": 0,
"y": 37
},
+ "hiddenSeries": false,
"id": 105,
"interval": "",
"legend": {
@@ -5179,6 +5197,7 @@ data:
"x": 12,
"y": 37
},
+ "hiddenSeries": false,
"id": 108,
"interval": "",
"legend": {
@@ -9513,11 +9532,11 @@ data:
}
},
{
- "datasource": "${datasource}",
"aliasColors": {},
"bars": false,
"dashLength": 10,
"dashes": false,
+ "datasource": "${datasource}",
"fill": 1,
"fillGradient": 0,
"gridPos": {
@@ -9578,22 +9597,22 @@ data:
},
"yaxes": [
{
+ "decimals": 0,
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": 0,
- "show": true,
- "decimals": 0
+ "show": true
},
{
+ "decimals": 0,
"format": "short",
"label": null,
"logBase": 1,
"max": null,
"min": 0,
- "show": true,
- "decimals": 0
+ "show": true
}
],
"yaxis": {
@@ -9673,12 +9692,16 @@ data:
}
],
"refresh": "15m",
- "schemaVersion": 19,
+ "schemaVersion": 22,
"style": "dark",
"tags": [],
"templating": {
"list": [
{
+ "current": {
+ "text": "che",
+ "value": "che"
+ },
"hide": 0,
"includeAll": false,
"label": null,
@@ -9726,4 +9749,4 @@ data:
"title": "Che Server",
"uid": "sL0Klq_mz",
"version": 1
- }
+ }
\ No newline at end of file
diff --git a/multiuser/permission/che-multiuser-permission-workspace/src/main/java/org/eclipse/che/multiuser/permission/workspace/server/spi/jpa/MultiuserJpaWorkspaceDao.java b/multiuser/permission/che-multiuser-permission-workspace/src/main/java/org/eclipse/che/multiuser/permission/workspace/server/spi/jpa/MultiuserJpaWorkspaceDao.java
index 59280e0580..a97c370024 100644
--- a/multiuser/permission/che-multiuser-permission-workspace/src/main/java/org/eclipse/che/multiuser/permission/workspace/server/spi/jpa/MultiuserJpaWorkspaceDao.java
+++ b/multiuser/permission/che-multiuser-permission-workspace/src/main/java/org/eclipse/che/multiuser/permission/workspace/server/spi/jpa/MultiuserJpaWorkspaceDao.java
@@ -235,6 +235,19 @@ public class MultiuserJpaWorkspaceDao implements WorkspaceDao {
}
}
+ @Override
+ @Transactional
+ public long getWorkspacesTotalCount() throws ServerException {
+ try {
+ return managerProvider
+ .get()
+ .createNamedQuery("Workspace.getWorkspacesTotalCount", Long.class)
+ .getSingleResult();
+ } catch (RuntimeException x) {
+ throw new ServerException(x.getLocalizedMessage(), x);
+ }
+ }
+
@Transactional
protected void doCreate(WorkspaceImpl workspace) {
if (workspace.getConfig() != null) {
diff --git a/multiuser/permission/che-multiuser-permission-workspace/src/test/java/org/eclipse/che/multiuser/permission/workspace/server/jpa/MultiuserJpaWorkspaceDaoTest.java b/multiuser/permission/che-multiuser-permission-workspace/src/test/java/org/eclipse/che/multiuser/permission/workspace/server/jpa/MultiuserJpaWorkspaceDaoTest.java
index 66ef6893d5..3d993b036f 100644
--- a/multiuser/permission/che-multiuser-permission-workspace/src/test/java/org/eclipse/che/multiuser/permission/workspace/server/jpa/MultiuserJpaWorkspaceDaoTest.java
+++ b/multiuser/permission/che-multiuser-permission-workspace/src/test/java/org/eclipse/che/multiuser/permission/workspace/server/jpa/MultiuserJpaWorkspaceDaoTest.java
@@ -20,6 +20,7 @@ import java.util.Arrays;
import java.util.List;
import javax.persistence.EntityManager;
import org.eclipse.che.account.spi.AccountImpl;
+import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.user.server.model.impl.UserImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceConfigImpl;
import org.eclipse.che.api.workspace.server.model.impl.WorkspaceImpl;
@@ -126,6 +127,11 @@ public class MultiuserJpaWorkspaceDaoTest {
manager.getTransaction().commit();
}
+ @Test
+ public void shouldGetTotalWorkspaceCount() throws ServerException {
+ assertEquals(dao.getWorkspacesTotalCount(), 3);
+ }
+
@AfterClass
public void shutdown() throws Exception {
tckResourcesCleaner.clean();
diff --git a/wsmaster/che-core-api-metrics/pom.xml b/wsmaster/che-core-api-metrics/pom.xml
index ab259dc493..e8e02a8678 100644
--- a/wsmaster/che-core-api-metrics/pom.xml
+++ b/wsmaster/che-core-api-metrics/pom.xml
@@ -51,6 +51,10 @@
org.eclipse.che.core
che-core-api-user
+
+ org.eclipse.che.core
+ che-core-api-workspace
+
org.eclipse.che.core
che-core-api-workspace-activity
diff --git a/wsmaster/che-core-api-metrics/src/main/java/org/eclipse/che/api/metrics/WorkspaceMeterBinder.java b/wsmaster/che-core-api-metrics/src/main/java/org/eclipse/che/api/metrics/WorkspaceMeterBinder.java
new file mode 100644
index 0000000000..41da43ef33
--- /dev/null
+++ b/wsmaster/che-core-api-metrics/src/main/java/org/eclipse/che/api/metrics/WorkspaceMeterBinder.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012-2018 Red Hat, Inc.
+ * This program and the accompanying materials are made
+ * available under the terms of the Eclipse Public License 2.0
+ * which is available at https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Red Hat, Inc. - initial API and implementation
+ */
+package org.eclipse.che.api.metrics;
+
+import static org.eclipse.che.api.metrics.WorkspaceBinders.workspaceMetric;
+
+import io.micrometer.core.instrument.Gauge;
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.binder.MeterBinder;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.eclipse.che.api.core.ServerException;
+import org.eclipse.che.api.workspace.server.WorkspaceManager;
+
+/** Provides metrics of workspace. */
+@Singleton
+public class WorkspaceMeterBinder implements MeterBinder {
+ private final WorkspaceManager workspaceManager;
+
+ @Inject
+ public WorkspaceMeterBinder(WorkspaceManager workspaceManager) {
+ this.workspaceManager = workspaceManager;
+ }
+
+ @Override
+ public void bindTo(MeterRegistry registry) {
+ Gauge.builder(workspaceMetric("total"), this::count)
+ .description("Total number of workspaces")
+ .register(registry);
+ }
+
+ private double count() {
+ try {
+ return workspaceManager.getWorkspacesTotalCount();
+ } catch (ServerException e) {
+ return Double.NaN;
+ }
+ }
+}
diff --git a/wsmaster/che-core-api-metrics/src/main/java/org/eclipse/che/api/metrics/WsMasterMetricsModule.java b/wsmaster/che-core-api-metrics/src/main/java/org/eclipse/che/api/metrics/WsMasterMetricsModule.java
index ce4475f109..1e0e212f4f 100644
--- a/wsmaster/che-core-api-metrics/src/main/java/org/eclipse/che/api/metrics/WsMasterMetricsModule.java
+++ b/wsmaster/che-core-api-metrics/src/main/java/org/eclipse/che/api/metrics/WsMasterMetricsModule.java
@@ -35,5 +35,6 @@ public class WsMasterMetricsModule extends AbstractModule {
meterMultibinder.addBinding().to(WorkspaceStartAttemptsMeterBinder.class);
meterMultibinder.addBinding().to(UserMeterBinder.class);
meterMultibinder.addBinding().to(RuntimeLogMeterBinder.class);
+ meterMultibinder.addBinding().to(WorkspaceMeterBinder.class);
}
}
diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceManager.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceManager.java
index fd964c4c48..af0e5dff50 100644
--- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceManager.java
+++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/WorkspaceManager.java
@@ -585,6 +585,16 @@ public class WorkspaceManager {
}
}
+ /**
+ * Gets total count of all workspaces
+ *
+ * @return workspaces count
+ * @throws ServerException when any error occurs
+ */
+ public long getWorkspacesTotalCount() throws ServerException {
+ return workspaceDao.getWorkspacesTotalCount();
+ }
+
private WorkspaceImpl doCreateWorkspace(
WorkspaceConfig config, Account account, Map attributes, boolean isTemporary)
throws ConflictException, ServerException {
diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/jpa/JpaWorkspaceDao.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/jpa/JpaWorkspaceDao.java
index 0df54a1d7c..17b1df9734 100644
--- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/jpa/JpaWorkspaceDao.java
+++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/jpa/JpaWorkspaceDao.java
@@ -262,6 +262,19 @@ public class JpaWorkspaceDao implements WorkspaceDao {
return merged;
}
+ @Override
+ @Transactional
+ public long getWorkspacesTotalCount() throws ServerException {
+ try {
+ return managerProvider
+ .get()
+ .createNamedQuery("Workspace.getWorkspacesTotalCount", Long.class)
+ .getSingleResult();
+ } catch (RuntimeException x) {
+ throw new ServerException(x.getLocalizedMessage(), x);
+ }
+ }
+
@Singleton
public static class RemoveWorkspaceBeforeAccountRemovedEventSubscriber
extends CascadeEventSubscriber {
diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/WorkspaceImpl.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/WorkspaceImpl.java
index 00c7ed97b6..b315693c97 100644
--- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/WorkspaceImpl.java
+++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/model/impl/WorkspaceImpl.java
@@ -67,6 +67,9 @@ import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
@NamedQuery(
name = "Workspace.getByNamespaceCount",
query = "SELECT COUNT(w) " + "FROM Workspace w " + "WHERE w.account.name = :namespace "),
+ @NamedQuery(
+ name = "Workspace.getWorkspacesTotalCount",
+ query = "SELECT COUNT(w) FROM Workspace w"),
@NamedQuery(
name = "Workspace.getByTemporaryCount",
query = "SELECT COUNT(w) " + "FROM Workspace w " + "WHERE w.isTemporary = :temporary ")
diff --git a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/spi/WorkspaceDao.java b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/spi/WorkspaceDao.java
index 6c5f8b0306..7df8ebaef7 100644
--- a/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/spi/WorkspaceDao.java
+++ b/wsmaster/che-core-api-workspace/src/main/java/org/eclipse/che/api/workspace/server/spi/WorkspaceDao.java
@@ -134,4 +134,12 @@ public interface WorkspaceDao {
*/
Page getWorkspaces(boolean isTemporary, int maxItems, long skipCount)
throws ServerException;
+
+ /**
+ * Get the count of all workspaces from the persistent layer.
+ *
+ * @return workspace count
+ * @throws ServerException when any error occurs
+ */
+ long getWorkspacesTotalCount() throws ServerException;
}
diff --git a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/spi/tck/WorkspaceDaoTest.java b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/spi/tck/WorkspaceDaoTest.java
index d358001b10..8d915f2700 100644
--- a/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/spi/tck/WorkspaceDaoTest.java
+++ b/wsmaster/che-core-api-workspace/src/test/java/org/eclipse/che/api/workspace/server/spi/tck/WorkspaceDaoTest.java
@@ -127,6 +127,31 @@ public class WorkspaceDaoTest {
workspaceRepo.createAll(Stream.of(workspaces).map(WorkspaceImpl::new).collect(toList()));
}
+ @Test
+ public void shouldBeAbleToCountWorkspaces() throws ServerException {
+ assertEquals(workspaceDao.getWorkspacesTotalCount(), COUNT_OF_WORKSPACES);
+ }
+
+ @Test
+ public void shouldBeAbleToCountNewWorkspaces() throws ServerException, TckRepositoryException {
+ // given
+ // when
+ workspaceRepo.createAll(
+ ImmutableList.of(createWorkspaceFromDevfile("id222", accounts[0], "name-bbb")));
+ // then
+ assertEquals(workspaceDao.getWorkspacesTotalCount(), COUNT_OF_WORKSPACES + 1);
+ }
+
+ @Test
+ public void shouldBeAbleToSubtractRemovedWorkspaces()
+ throws ServerException, TckRepositoryException {
+ // given
+ // when
+ workspaceDao.remove(workspaces[1].getId());
+ // then
+ assertEquals(workspaceDao.getWorkspacesTotalCount(), COUNT_OF_WORKSPACES - 1);
+ }
+
@Test
public void shouldGetWorkspaceById() throws Exception {
final WorkspaceImpl workspace = workspaces[0];