diff --git a/assembly/assembly-wsmaster-war/pom.xml b/assembly/assembly-wsmaster-war/pom.xml index 3b716b4696..e7c21cc6a4 100644 --- a/assembly/assembly-wsmaster-war/pom.xml +++ b/assembly/assembly-wsmaster-war/pom.xml @@ -229,6 +229,10 @@ org.eclipse.che.core che-core-ide-stacks + + org.eclipse.che.core + che-core-metrics-core + org.eclipse.che.core che-core-sql-schema diff --git a/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java b/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java index 97a43311a3..9a5f2e71b3 100644 --- a/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java +++ b/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterModule.java @@ -276,6 +276,9 @@ public class WsMasterModule extends AbstractModule { if (Boolean.valueOf(System.getenv("CHE_TRACING_ENABLED"))) { install(new org.eclipse.che.core.tracing.TracingModule()); } + if (Boolean.valueOf(System.getenv("CHE_METRICS_ENABLED"))) { + install(new org.eclipse.che.core.metrics.MetricsModule()); + } } private void configureSingleUserMode(Map persistenceProperties) { diff --git a/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterServletModule.java b/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterServletModule.java index bbf270e224..f7af2b87f6 100644 --- a/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterServletModule.java +++ b/assembly/assembly-wsmaster-war/src/main/java/org/eclipse/che/api/deploy/WsMasterServletModule.java @@ -61,6 +61,10 @@ public class WsMasterServletModule extends ServletModule { } else { configureSingleUserMode(); } + + if (Boolean.valueOf(System.getenv("CHE_METRICS_ENABLED"))) { + install(new org.eclipse.che.core.metrics.MetricsServletModule()); + } } private void configureSingleUserMode() { diff --git a/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/che/che.properties b/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/che/che.properties index 72d1261315..3a2b21aee5 100644 --- a/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/che/che.properties +++ b/assembly/assembly-wsmaster-war/src/main/webapp/WEB-INF/classes/che/che.properties @@ -549,3 +549,7 @@ che.server.secure_exposer.jwtproxy.memory_limit=128mb # Maximum size of the json processing pool # in case if pool size would be exceeded message execution will be rejected che.core.jsonrpc.processor_max_pool_size=100 + + +## Port the the http server endpoint that would be exposed with Prometheus metrics +che.metrics.port=8087 diff --git a/core/che-core-metrics-core/pom.xml b/core/che-core-metrics-core/pom.xml new file mode 100644 index 0000000000..b26d364288 --- /dev/null +++ b/core/che-core-metrics-core/pom.xml @@ -0,0 +1,104 @@ + + + + 4.0.0 + + che-core-parent + org.eclipse.che.core + 6.15.0-SNAPSHOT + + che-core-metrics-core + Che Core :: Metrics :: Core + + + com.google.guava + guava + + + com.google.inject + guice + + + com.google.inject.extensions + guice-multibindings + + + com.google.inject.extensions + guice-servlet + + + io.micrometer + micrometer-core + + + io.micrometer + micrometer-registry-prometheus + + + io.prometheus + simpleclient + + + io.prometheus + simpleclient_httpserver + + + javax.inject + javax.inject + + + org.slf4j + slf4j-api + + + javax.servlet + javax.servlet-api + provided + + + org.apache.tomcat + tomcat-catalina + provided + + + ch.qos.logback + logback-classic + test + + + org.testng + testng + test + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + analyze + + + org.apache.tomcat:tomcat-annotations-api + + + + + + + + diff --git a/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/FileStoresMeterBinder.java b/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/FileStoresMeterBinder.java new file mode 100644 index 0000000000..c5411b6e9b --- /dev/null +++ b/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/FileStoresMeterBinder.java @@ -0,0 +1,76 @@ +/* + * 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.core.metrics; + +import io.micrometer.core.instrument.Gauge; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.Tags; +import io.micrometer.core.instrument.binder.MeterBinder; +import java.io.IOException; +import java.nio.file.FileStore; +import java.nio.file.FileSystems; +import java.util.function.ToDoubleFunction; +import javax.inject.Singleton; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** Bind disk usage metrics for for every {@link java.nio.file.FileStore}. */ +@Singleton +public class FileStoresMeterBinder implements MeterBinder { + + private static final Logger LOG = LoggerFactory.getLogger(FileStoresMeterBinder.class); + + @Override + public void bindTo(MeterRegistry registry) { + for (FileStore fileStore : FileSystems.getDefault().getFileStores()) { + LOG.debug("Add gauge metric for {}", fileStore.name()); + Iterable tagsWithPath = Tags.concat(Tags.empty(), "path", fileStore.toString()); + + Gauge.builder("disk.free", fileStore, exceptionToNonWrapper(FileStore::getUnallocatedSpace)) + .tags(tagsWithPath) + .description("Unallocated space for file store") + .baseUnit("bytes") + .strongReference(true) + .register(registry); + Gauge.builder("disk.total", fileStore, exceptionToNonWrapper(FileStore::getTotalSpace)) + .tags(tagsWithPath) + .description("Total space for file store") + .baseUnit("bytes") + .strongReference(true) + .register(registry); + Gauge.builder("disk.usable", fileStore, exceptionToNonWrapper(FileStore::getUsableSpace)) + .tags(tagsWithPath) + .description("Usable space for file store") + .baseUnit("bytes") + .strongReference(true) + .register(registry); + } + } + + static ToDoubleFunction exceptionToNonWrapper( + ThrowingToDoubleFunction throwingConsumer) { + + return i -> { + try { + return throwingConsumer.applyAsDouble(i); + } catch (Exception ex) { + return Double.NaN; + } + }; + } + + @FunctionalInterface + interface ThrowingToDoubleFunction { + double applyAsDouble(T t) throws IOException; + } +} diff --git a/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/MetricsBinder.java b/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/MetricsBinder.java new file mode 100644 index 0000000000..ae67647027 --- /dev/null +++ b/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/MetricsBinder.java @@ -0,0 +1,33 @@ +/* + * 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.core.metrics; + +import io.micrometer.core.instrument.binder.MeterBinder; +import io.micrometer.prometheus.PrometheusMeterRegistry; +import java.util.Set; +import javax.inject.Inject; +import javax.inject.Singleton; + +/** + * Takes all {@link io.micrometer.core.instrument.binder.MeterBinder} from guice container, binded + * with {@link com.google.inject.multibindings.Multibinder}, and bind them to {@link + * io.micrometer.prometheus.PrometheusMeterRegistry} on PostConstruct. + */ +@Singleton +public class MetricsBinder { + + @Inject + public void bindToRegistry( + PrometheusMeterRegistry meterRegistry, Set meterBinderList) { + meterBinderList.forEach(e -> e.bindTo(meterRegistry)); + } +} diff --git a/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/MetricsModule.java b/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/MetricsModule.java new file mode 100644 index 0000000000..0241e4dc1a --- /dev/null +++ b/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/MetricsModule.java @@ -0,0 +1,52 @@ +/* + * 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.core.metrics; + +import com.google.common.annotations.Beta; +import com.google.inject.AbstractModule; +import com.google.inject.multibindings.Multibinder; +import io.micrometer.core.instrument.binder.MeterBinder; +import io.micrometer.core.instrument.binder.jvm.ClassLoaderMetrics; +import io.micrometer.core.instrument.binder.jvm.JvmGcMetrics; +import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics; +import io.micrometer.core.instrument.binder.jvm.JvmThreadMetrics; +import io.micrometer.core.instrument.binder.logging.LogbackMetrics; +import io.micrometer.core.instrument.binder.system.FileDescriptorMetrics; +import io.micrometer.core.instrument.binder.system.ProcessorMetrics; +import io.micrometer.core.instrument.binder.system.UptimeMetrics; +import io.micrometer.prometheus.PrometheusMeterRegistry; +import io.prometheus.client.CollectorRegistry; + +@Beta +public class MetricsModule extends AbstractModule { + @Override + protected void configure() { + bind(MetricsServer.class).asEagerSingleton(); + bind(MetricsBinder.class).asEagerSingleton(); + bind(CollectorRegistry.class).toInstance(CollectorRegistry.defaultRegistry); + bind(PrometheusMeterRegistry.class) + .toProvider(PrometheusMeterRegistryProvider.class) + .asEagerSingleton(); + + Multibinder meterMultibinder = + Multibinder.newSetBinder(binder(), MeterBinder.class); + meterMultibinder.addBinding().to(ClassLoaderMetrics.class); + meterMultibinder.addBinding().to(JvmMemoryMetrics.class); + meterMultibinder.addBinding().to(JvmGcMetrics.class); + meterMultibinder.addBinding().to(JvmThreadMetrics.class); + meterMultibinder.addBinding().to(LogbackMetrics.class); + meterMultibinder.addBinding().to(FileDescriptorMetrics.class); + meterMultibinder.addBinding().to(ProcessorMetrics.class); + meterMultibinder.addBinding().to(UptimeMetrics.class); + meterMultibinder.addBinding().to(FileStoresMeterBinder.class); + } +} diff --git a/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/MetricsServer.java b/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/MetricsServer.java new file mode 100644 index 0000000000..ca894bd00a --- /dev/null +++ b/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/MetricsServer.java @@ -0,0 +1,54 @@ +/* + * 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.core.metrics; + +import io.prometheus.client.CollectorRegistry; +import io.prometheus.client.exporter.HTTPServer; +import java.io.IOException; +import java.net.InetSocketAddress; +import javax.annotation.PreDestroy; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** Bind on 8087 port http endpoint with prometheus metrics. */ +@Singleton +public class MetricsServer { + + private static final Logger LOG = LoggerFactory.getLogger(MetricsServer.class); + + private HTTPServer server; + private final CollectorRegistry collectorRegistry; + private final Integer metricsPort; + + @Inject + public MetricsServer( + CollectorRegistry collectorRegistry, @Named("che.metrics.port") Integer metricsPort) { + this.collectorRegistry = collectorRegistry; + this.metricsPort = metricsPort; + } + + public void startServer() throws IOException { + this.server = new HTTPServer(new InetSocketAddress(metricsPort), collectorRegistry, true); + LOG.info("Metrics server started at port {} successfully ", metricsPort); + } + + @PreDestroy + public void stopServer() { + if (server != null) { + server.stop(); + LOG.info("Metrics server suspended at port {} successfully ", metricsPort); + } + } +} diff --git a/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/MetricsServletModule.java b/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/MetricsServletModule.java new file mode 100644 index 0000000000..7d919ef3b8 --- /dev/null +++ b/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/MetricsServletModule.java @@ -0,0 +1,63 @@ +/* + * 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.core.metrics; + +import com.google.inject.multibindings.Multibinder; +import com.google.inject.servlet.ServletModule; +import io.micrometer.core.instrument.binder.MeterBinder; +import java.lang.reflect.Field; +import javax.servlet.ServletContext; +import org.apache.catalina.Manager; +import org.apache.catalina.core.ApplicationContext; +import org.apache.catalina.core.ApplicationContextFacade; +import org.apache.catalina.core.StandardContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * ServletModule is made to bind {@link org.eclipse.che.core.metrics.TomcatMetricsProvider} in guice + * container. + */ +public class MetricsServletModule extends ServletModule { + private static final Logger LOG = LoggerFactory.getLogger(TomcatMetricsProvider.class); + + @Override + protected void configureServlets() { + Multibinder meterMultibinder = + Multibinder.newSetBinder(binder(), MeterBinder.class); + meterMultibinder.addBinding().toProvider(TomcatMetricsProvider.class); + + bind(Manager.class).toInstance(getManager(getServletContext())); + } + + private Manager getManager(ServletContext servletContext) { + + try { + + ApplicationContextFacade acf = (ApplicationContextFacade) servletContext; + Field applicationContextFacadeField = + ApplicationContextFacade.class.getDeclaredField("context"); + applicationContextFacadeField.setAccessible(true); + ApplicationContext appContext = (ApplicationContext) applicationContextFacadeField.get(acf); + + Field applicationContextField = ApplicationContext.class.getDeclaredField("context"); + applicationContextField.setAccessible(true); + StandardContext stdContext = (StandardContext) applicationContextField.get(appContext); + return stdContext.getManager(); + + } catch (Exception e) { + // maybe not in Tomcat? + LOG.error("Unable to get catalina manager. Cause: {}", e.getMessage(), e); + throw new RuntimeException(e.getMessage(), e); + } + } +} diff --git a/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/PrometheusMeterRegistryProvider.java b/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/PrometheusMeterRegistryProvider.java new file mode 100644 index 0000000000..2886f687db --- /dev/null +++ b/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/PrometheusMeterRegistryProvider.java @@ -0,0 +1,42 @@ +/* + * 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.core.metrics; + +import io.micrometer.core.instrument.Clock; +import io.micrometer.core.instrument.Metrics; +import io.micrometer.prometheus.PrometheusConfig; +import io.micrometer.prometheus.PrometheusMeterRegistry; +import io.prometheus.client.CollectorRegistry; +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; + +/** + * {@link javax.inject.Provider} of {@link io.micrometer.prometheus.PrometheusMeterRegistry} + * instances. Used constructor with PrometheusConfig#DEFAULT and Clock.SYSTEM parameters. + */ +@Singleton +public class PrometheusMeterRegistryProvider implements Provider { + private final PrometheusMeterRegistry prometheusMeterRegistry; + + @Inject + public PrometheusMeterRegistryProvider(CollectorRegistry registry) { + prometheusMeterRegistry = + new PrometheusMeterRegistry(PrometheusConfig.DEFAULT, registry, Clock.SYSTEM); + Metrics.addRegistry(prometheusMeterRegistry); + } + + @Override + public PrometheusMeterRegistry get() { + return prometheusMeterRegistry; + } +} diff --git a/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/TomcatMetricsProvider.java b/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/TomcatMetricsProvider.java new file mode 100644 index 0000000000..3192a50ad8 --- /dev/null +++ b/core/che-core-metrics-core/src/main/java/org/eclipse/che/core/metrics/TomcatMetricsProvider.java @@ -0,0 +1,40 @@ +/* + * 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.core.metrics; + +import io.micrometer.core.instrument.Tags; +import io.micrometer.core.instrument.binder.tomcat.TomcatMetrics; +import javax.inject.Inject; +import javax.inject.Provider; +import javax.inject.Singleton; +import org.apache.catalina.Manager; + +/** + * {@link javax.inject.Provider} of {@link + * io.micrometer.core.instrument.binder.tomcat.TomcatMetrics} instance. Used constructor with empty + * {@link io.micrometer.core.instrument.Tags} + */ +@Singleton +public class TomcatMetricsProvider implements Provider { + + private final Manager manager; + + @Inject + public TomcatMetricsProvider(Manager manager) { + this.manager = manager; + } + + @Override + public TomcatMetrics get() { + return new TomcatMetrics(manager, Tags.empty()); + } +} diff --git a/core/che-core-metrics-core/src/test/java/org/eclipse/che/core/metrics/FileStoresMeterTest.java b/core/che-core-metrics-core/src/test/java/org/eclipse/che/core/metrics/FileStoresMeterTest.java new file mode 100644 index 0000000000..5b076fd4ac --- /dev/null +++ b/core/che-core-metrics-core/src/test/java/org/eclipse/che/core/metrics/FileStoresMeterTest.java @@ -0,0 +1,54 @@ +/* + * 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.core.metrics; + +import static org.testng.Assert.*; + +import io.micrometer.core.instrument.Gauge; +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.simple.SimpleMeterRegistry; +import java.nio.file.FileStore; +import java.nio.file.FileSystems; +import java.util.Collection; +import java.util.Iterator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.annotations.Test; + +public class FileStoresMeterTest { + + private static final Logger LOG = LoggerFactory.getLogger(FileStoresMeterTest.class); + + @Test + public void shouldBindFileStores() { + MeterRegistry registry = new SimpleMeterRegistry(); + + new FileStoresMeterBinder().bindTo(registry); + Collection dd = registry.get("disk.free").gauges(); + + assertNotNull(dd); + assertEquals(dd.size(), getSize()); + assertTrue(registry.get("disk.free").gauge().value() >= 0); + assertTrue(registry.get("disk.total").gauge().value() >= 0); + assertTrue(registry.get("disk.usable").gauge().value() >= 0); + } + + private int getSize() { + int i = 0; + Iterator it = FileSystems.getDefault().getFileStores().iterator(); + while (it.hasNext()) { + LOG.debug("Found {} meter ", it.next().name()); + i++; + } + return i; + } +} diff --git a/core/che-core-metrics-core/src/test/resources/logback-test.xml b/core/che-core-metrics-core/src/test/resources/logback-test.xml new file mode 100644 index 0000000000..e6abf05f02 --- /dev/null +++ b/core/che-core-metrics-core/src/test/resources/logback-test.xml @@ -0,0 +1,27 @@ + + + + + + + %-41(%date[%.15thread]) %-45([%-5level] [%.30logger{30} %L]) - %msg%n + + + + + + + + diff --git a/core/pom.xml b/core/pom.xml index 9fc32499ee..8ca574d353 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -39,5 +39,6 @@ che-core-db-vendor-postgresql che-core-tracing-core che-core-tracing-web + che-core-metrics-core diff --git a/deploy/openshift/templates/che-server-template.yaml b/deploy/openshift/templates/che-server-template.yaml index 649257cd08..c5f46abfdc 100644 --- a/deploy/openshift/templates/che-server-template.yaml +++ b/deploy/openshift/templates/che-server-template.yaml @@ -38,6 +38,10 @@ objects: port: 8080 protocol: TCP targetPort: 8080 + - name: metrics + port: 8087 + protocol: TCP + targetPort: 8087 selector: app: che - apiVersion: v1 @@ -48,6 +52,8 @@ objects: to: kind: Service name: che-host + port: + targetPort: http - apiVersion: v1 kind: DeploymentConfig metadata: @@ -153,6 +159,8 @@ objects: value: "${CHE_WORKSPACE_PLUGIN__REGISTRY__URL}" - name: CHE_TRACING_ENABLED value: "${CHE_TRACING_ENABLED}" + - name: CHE_METRICS_ENABLED + value: "false" image: ${IMAGE_CHE}:${CHE_VERSION} imagePullPolicy: "${PULL_POLICY}" livenessProbe: @@ -176,6 +184,9 @@ objects: - containerPort: 8080 name: http protocol: TCP + - containerPort: 8087 + name: metrics + protocol: TCP - containerPort: 8000 name: http-debug - containerPort: 8888 diff --git a/pom.xml b/pom.xml index f2e19df5f4..03696f8a8f 100644 --- a/pom.xml +++ b/pom.xml @@ -742,6 +742,11 @@ ${che.version} gwt-lib + + org.eclipse.che.core + che-core-metrics-core + ${che.version} + org.eclipse.che.core che-core-orion-editor