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

hanahmily pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/skywalking.git


The following commit(s) were added to refs/heads/master by this push:
     new 924f25f  Self observability of OAP backend (#3140)
924f25f is described below

commit 924f25fec4e0bcccff95b1980a141923b7f9899a
Author: Gao Hongtao <hanahm...@gmail.com>
AuthorDate: Wed Jul 24 16:08:56 2019 +0800

    Self observability of OAP backend (#3140)
    
    * First commit
    
    * Fix e2e test and some nits
    
    * Documenting so11y and setting default values of it in dev env
---
 docker/oap/docker-entrypoint.sh                    |   9 +-
 docs/en/setup/backend/backend-telemetry.md         |  28 +-
 oap-server/server-receiver-plugin/pom.xml          |   1 +
 .../skywalking-so11y-receiver-plugin}/pom.xml      |  23 +-
 .../receiver/so11y/So11yReceiverConfig.java}       |  20 +-
 .../receiver/so11y/So11yReceiverModule.java}       |  18 +-
 .../so11y/So11yReceiverModuleProvider.java         | 381 +++++++++++++++++++++
 ...ywalking.oap.server.library.module.ModuleDefine |  19 +
 ...alking.oap.server.library.module.ModuleProvider |  19 +
 oap-server/server-starter/pom.xml                  |  10 +
 .../src/main/resources/application.yml             |  13 +-
 .../server-starter/src/main/resources/log4j2.xml   |   4 +-
 oap-server/server-telemetry/pom.xml                |   1 +
 .../oap/server/telemetry/TelemetryModule.java      |   3 +-
 .../oap/server/telemetry/api/MetricFamily.java     |  64 ++++
 .../MetricsCollector.java}                         |  25 +-
 .../MetricsCollectorNoop.java}                     |  25 +-
 .../telemetry/none/NoneTelemetryProvider.java      |   2 +
 .../server-telemetry/{ => telemetry-so11y}/pom.xml |  23 +-
 .../oap/server/telemetry/so11y/So11yConfig.java}   |  27 +-
 .../telemetry/so11y/So11yMetricsCollector.java     |  53 +++
 .../telemetry/so11y/So11yMetricsCreator.java       |  48 +++
 .../telemetry/so11y/So11yTelemetryProvider.java}   |  36 +-
 ...alking.oap.server.library.module.ModuleProvider |  20 ++
 24 files changed, 770 insertions(+), 102 deletions(-)

diff --git a/docker/oap/docker-entrypoint.sh b/docker/oap/docker-entrypoint.sh
index 5897b00..205cee4 100755
--- a/docker/oap/docker-entrypoint.sh
+++ b/docker/oap/docker-entrypoint.sh
@@ -256,6 +256,8 @@ receiver-jvm:
   default:
 receiver-clr:
   default:
+receiver-so11y:
+  default:
 service-mesh:
   default:
     bufferPath: \${SW_SERVICE_MESH_BUFFER_PATH:../mesh-buffer/}  # Path to 
trace buffer files, suggest to use absolute path
@@ -270,9 +272,10 @@ query:
 alarm:
   default:
 telemetry:
-  prometheus:
-    host: \${SW_TELEMETRY_PROMETHEUS_HOST:0.0.0.0}
-    port: \${SW_TELEMETRY_PROMETHEUS_PORT:1234}
+  so11y:
+    prometheusExporterEnabled: \${SW_TELEMETRY_SO11Y_PROMETHEUS_ENABLED:true}
+    prometheusExporterHost: \${SW_TELEMETRY_PROMETHEUS_HOST:0.0.0.0}
+    prometheusExporterPort: \${SW_TELEMETRY_PROMETHEUS_PORT:1234}
 EOT
     # generate configuration
     case ${SW_CONFIGURATION} in
diff --git a/docs/en/setup/backend/backend-telemetry.md 
b/docs/en/setup/backend/backend-telemetry.md
index 0034f13..2115478 100644
--- a/docs/en/setup/backend/backend-telemetry.md
+++ b/docs/en/setup/backend/backend-telemetry.md
@@ -27,4 +27,30 @@ telemetry:
 Provide two grafana dashboard settings.
 1. Use [SkyWalking trace-mode dashboard](telemetry/trace-mode-grafana.json) 
when SkyWalking is used with tracing agent.
 1. Use [SkyWalking mesh-mode dashboard](telemetry/mesh-mode-grafana.json) when 
SkyWalking is used with service mesh
-telemetry, including istio, envoy. 
\ No newline at end of file
+telemetry, including istio, envoy. 
+
+## Self Observability
+
+SkyWalking supports to collect telemetry data into OAP backend directly. Users 
could check them out through UI or
+GraphQL API then.
+
+Adding following configuration to enable `so11y`(self-observability) related 
modules.
+
+```yaml
+receiver-so11y:
+  default:
+telemetry:
+  so11y:
+```
+
+Another example represents how to combine `promethues` and `so11y`. Adding 
some items in `so11y` to make it happen.
+
+```yaml
+telemetry:
+  so11y:
+    prometheusExporterEnabled: true
+    prometheusExporterHost: 0.0.0.0
+    prometheusExporterPort: 1234
+```
+
+Then prometheus exporter is listening on `0.0.0.0:1234`.
diff --git a/oap-server/server-receiver-plugin/pom.xml 
b/oap-server/server-receiver-plugin/pom.xml
index 156e03b..f6ff8ff 100644
--- a/oap-server/server-receiver-plugin/pom.xml
+++ b/oap-server/server-receiver-plugin/pom.xml
@@ -39,6 +39,7 @@
         <module>skywalking-clr-receiver-plugin</module>
         <module>jaeger-receiver-plugin</module>
         <module>receiver-proto</module>
+        <module>skywalking-so11y-receiver-plugin</module>
     </modules>
 
     <dependencies>
diff --git a/oap-server/server-telemetry/pom.xml 
b/oap-server/server-receiver-plugin/skywalking-so11y-receiver-plugin/pom.xml
similarity index 63%
copy from oap-server/server-telemetry/pom.xml
copy to 
oap-server/server-receiver-plugin/skywalking-so11y-receiver-plugin/pom.xml
index 4f885aa..8f5e094 100644
--- a/oap-server/server-telemetry/pom.xml
+++ b/oap-server/server-receiver-plugin/skywalking-so11y-receiver-plugin/pom.xml
@@ -17,18 +17,25 @@
   ~
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
     <parent>
-        <artifactId>oap-server</artifactId>
+        <artifactId>server-receiver-plugin</artifactId>
         <groupId>org.apache.skywalking</groupId>
         <version>6.3.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
-    <artifactId>server-telemetry</artifactId>
-    <packaging>pom</packaging>
-    <modules>
-        <module>telemetry-prometheus</module>
-        <module>telemetry-api</module>
-    </modules>
+    <artifactId>skywalking-so11y-receiver-plugin</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>telemetry-api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+
 </project>
\ No newline at end of file
diff --git 
a/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
 
b/oap-server/server-receiver-plugin/skywalking-so11y-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/so11y/So11yReceiverConfig.java
similarity index 61%
copy from 
oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
copy to 
oap-server/server-receiver-plugin/skywalking-so11y-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/so11y/So11yReceiverConfig.java
index 78cdce4..c72c14d 100644
--- 
a/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
+++ 
b/oap-server/server-receiver-plugin/skywalking-so11y-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/so11y/So11yReceiverConfig.java
@@ -16,24 +16,12 @@
  *
  */
 
-package org.apache.skywalking.oap.server.telemetry;
+package org.apache.skywalking.oap.server.receiver.so11y;
 
-import org.apache.skywalking.oap.server.library.module.ModuleDefine;
-import org.apache.skywalking.oap.server.telemetry.api.MetricsCreator;
+import org.apache.skywalking.oap.server.library.module.ModuleConfig;
 
 /**
- * Telemetry module definition
- *
- * @author wusheng
+ * Self observability receiver config.
  */
-public class TelemetryModule extends ModuleDefine {
-    public static final String NAME = "telemetry";
-
-    public TelemetryModule() {
-        super(NAME);
-    }
-
-    @Override public Class[] services() {
-        return new Class[] {MetricsCreator.class};
-    }
+public class So11yReceiverConfig extends ModuleConfig {
 }
diff --git 
a/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
 
b/oap-server/server-receiver-plugin/skywalking-so11y-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/so11y/So11yReceiverModule.java
similarity index 69%
copy from 
oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
copy to 
oap-server/server-receiver-plugin/skywalking-so11y-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/so11y/So11yReceiverModule.java
index 78cdce4..454e9d4 100644
--- 
a/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
+++ 
b/oap-server/server-receiver-plugin/skywalking-so11y-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/so11y/So11yReceiverModule.java
@@ -16,24 +16,24 @@
  *
  */
 
-package org.apache.skywalking.oap.server.telemetry;
+package org.apache.skywalking.oap.server.receiver.so11y;
 
 import org.apache.skywalking.oap.server.library.module.ModuleDefine;
-import org.apache.skywalking.oap.server.telemetry.api.MetricsCreator;
 
 /**
- * Telemetry module definition
+ * Self observability receiver module.
  *
- * @author wusheng
+ * @author gaohongtao
  */
-public class TelemetryModule extends ModuleDefine {
-    public static final String NAME = "telemetry";
+public class So11yReceiverModule extends ModuleDefine {
+    public static final String NAME = "receiver-so11y";
 
-    public TelemetryModule() {
+    public So11yReceiverModule() {
         super(NAME);
     }
 
-    @Override public Class[] services() {
-        return new Class[] {MetricsCreator.class};
+    @Override
+    public Class[] services() {
+        return new Class[0];
     }
 }
diff --git 
a/oap-server/server-receiver-plugin/skywalking-so11y-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/so11y/So11yReceiverModuleProvider.java
 
b/oap-server/server-receiver-plugin/skywalking-so11y-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/so11y/So11yReceiverModuleProvider.java
new file mode 100644
index 0000000..346a962
--- /dev/null
+++ 
b/oap-server/server-receiver-plugin/skywalking-so11y-receiver-plugin/src/main/java/org/apache/skywalking/oap/server/receiver/so11y/So11yReceiverModuleProvider.java
@@ -0,0 +1,381 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.receiver.so11y;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.ToString;
+import org.apache.skywalking.oap.server.core.Const;
+import org.apache.skywalking.oap.server.core.CoreModule;
+import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
+import 
org.apache.skywalking.oap.server.core.register.service.IServiceInstanceInventoryRegister;
+import 
org.apache.skywalking.oap.server.core.register.service.IServiceInventoryRegister;
+import org.apache.skywalking.oap.server.core.source.*;
+import org.apache.skywalking.oap.server.library.module.*;
+import org.apache.skywalking.oap.server.telemetry.TelemetryModule;
+import org.apache.skywalking.oap.server.telemetry.api.MetricFamily;
+import org.apache.skywalking.oap.server.telemetry.api.MetricsCollector;
+import org.apache.skywalking.oap.server.telemetry.api.TelemetryRelatedContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.function.BiConsumer;
+
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.summingDouble;
+
+/**
+ * Self observability receiver provider.
+ *
+ * @author gaohongtao
+ */
+public class So11yReceiverModuleProvider extends ModuleProvider {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(So11yReceiverModuleProvider.class);
+
+    private static final String SERVICE_NAME = "SkyWalking";
+
+    private static final int RUN_RATE_SECONDS = 5;
+
+    private final long[] lastNewGc = new long[]{0L, 0L};
+
+    private final long[] lastOldGc = new long[]{0L, 0L};
+
+    private int serviceId;
+
+    private int serviceInstanceId;
+
+    private String serviceInstanceName;
+
+    private double lastCpuSeconds = -1;
+
+    private IServiceInventoryRegister serviceInventoryRegister;
+
+    private IServiceInstanceInventoryRegister serviceInstanceInventoryRegister;
+
+    private SourceReceiver sourceReceiver;
+
+
+    @Override
+    public String name() {
+        return "default";
+    }
+
+    @Override
+    public Class<? extends ModuleDefine> module() {
+        return So11yReceiverModule.class;
+    }
+
+    @Override
+    public ModuleConfig createConfigBeanIfAbsent() {
+        return new So11yReceiverConfig();
+    }
+
+    @Override
+    public void prepare() throws ServiceNotProvidedException, 
ModuleStartException {
+    }
+
+    @Override
+    public void start() throws ServiceNotProvidedException, 
ModuleStartException {
+        serviceInventoryRegister = 
getManager().find(CoreModule.NAME).provider().getService(IServiceInventoryRegister.class);
+        serviceInstanceInventoryRegister = 
getManager().find(CoreModule.NAME).provider().getService(IServiceInstanceInventoryRegister.class);
+        sourceReceiver = 
getManager().find(CoreModule.NAME).provider().getService(SourceReceiver.class);
+        MetricsCollector collector = 
getManager().find(TelemetryModule.NAME).provider().getService(MetricsCollector.class);
+        Executors.newSingleThreadScheduledExecutor(new ThreadFactoryBuilder()
+                
.setDaemon(true).setNameFormat("So11y-receiver-%s").build()).scheduleAtFixedRate(()
 -> {
+                    if (register()) {
+                        heartbeat();
+                    } else {
+                        return;
+                    }
+                    Iterable<MetricFamily> mfs = collector.collect();
+                    Map<String, MetricFamily> metricsIndex = new HashMap<>();
+                    for (MetricFamily each : mfs) {
+                        if (each.samples.size() < 1) {
+                            continue;
+                        }
+                        metricsIndex.put(each.name, each);
+                    }
+                    writeCpuUsage(metricsIndex);
+                    writeJvmMemory(metricsIndex);
+                    writeJvmMemoryPool(metricsIndex);
+                    writeGC(metricsIndex);
+                }, RUN_RATE_SECONDS, RUN_RATE_SECONDS, TimeUnit.SECONDS);
+    }
+
+
+
+    @Override
+    public void notifyAfterCompleted() throws ServiceNotProvidedException, 
ModuleStartException {
+
+    }
+
+    @Override
+    public String[] requiredModules() {
+        return new String[] {TelemetryModule.NAME, CoreModule.NAME};
+    }
+
+    private void writeGC(Map<String, MetricFamily> metricsIndex) {
+        if (!metricsIndex.containsKey("jvm_gc_collection_seconds")) {
+            return;
+        }
+        List<String> newGC = ImmutableList.of("PS Scavenge", "ParNew", "G1 
Young Generation", "Copy");
+        List<String> oldGC = ImmutableList.of("PS MarkSweep", 
"ConcurrentMarkSweep", "G1 Old Generation", "MarkSweepCompact");
+        metricsIndex.get("jvm_gc_collection_seconds").samples.stream()
+                .map(sample -> {
+                    int index = Iterables.indexOf(sample.labelNames, i -> 
Objects.equals(i, "gc"));
+                    if (index < 0) {
+                        return null;
+                    }
+                    String gcPhrase = sample.labelValues.get(index);
+                    GCMetricType type = sample.name.contains("sum") ? 
GCMetricType.SUM : GCMetricType.COUNT;
+                    double value = type == GCMetricType.SUM ? sample.value * 
1000 : sample.value;
+                    if (newGC.contains(gcPhrase)) {
+                        return new GCMetric(GCPhrase.NEW, type, value);
+                    } else if (oldGC.contains(gcPhrase)) {
+                        return new GCMetric(GCPhrase.OLD, type, value);
+                    }
+                    throw new RuntimeException(String.format("Unsupported gc 
phrase %s", gcPhrase));
+                })
+                .filter(Objects::nonNull)
+                .collect(groupingBy(GCMetric::getPhrase))
+                .forEach((gcPhrase, gcMetrics) -> {
+                    ServiceInstanceJVMGC gc = new ServiceInstanceJVMGC();
+                    gc.setId(serviceInstanceId);
+                    gc.setName(serviceInstanceName);
+                    gc.setServiceId(serviceId);
+                    gc.setServiceName(SERVICE_NAME);
+                    gc.setPhrase(gcPhrase);
+                    long[] lastGc = gcPhrase == GCPhrase.NEW ? lastNewGc : 
lastOldGc;
+                    gcMetrics.stream().filter(m -> 
m.type.equals(GCMetricType.COUNT)).findFirst().ifPresent(m -> {
+                        gc.setCount(m.getValue().longValue() - lastGc[0]);
+                        lastGc[0] = m.getValue().longValue();
+                    });
+                    gcMetrics.stream().filter(m -> 
m.type.equals(GCMetricType.SUM)).findFirst().ifPresent(m -> {
+                        gc.setTime(m.getValue().longValue() - lastGc[1]);
+                        lastGc[1] = m.getValue().longValue();
+                    });
+                    
gc.setTimeBucket(TimeBucket.getMinuteTimeBucket(System.currentTimeMillis()));
+                    if (logger.isDebugEnabled()) {
+                        logger.debug("Write {} {}counts {}ms to {}", 
gc.getPhrase(), gc.getCount(), gc.getTime(), gc.getName());
+                    }
+                    sourceReceiver.receive(gc);
+                });
+    }
+
+    private void writeJvmMemoryPool(Map<String, MetricFamily> metricsIndex) {
+        List<MetricSetter<ServiceInstanceJVMMemoryPool>> setterList = 
ImmutableList.of(
+                new MetricSetter<>("jvm_memory_pool_bytes_used", (m, v) -> 
m.setUsed(v.longValue())),
+                new MetricSetter<>("jvm_memory_pool_bytes_committed", (m, v) 
-> m.setCommitted(v.longValue())),
+                new MetricSetter<>("jvm_memory_pool_bytes_max", (m, v) -> 
m.setMax(v.longValue())),
+                new MetricSetter<>("jvm_memory_pool_bytes_init", (m, v) -> 
m.setInit(v.longValue())));
+        if (setterList.stream().anyMatch(i -> 
!metricsIndex.containsKey(i.name))) {
+            return;
+        }
+        Map<MemoryPoolType, ServiceInstanceJVMMemoryPool> poolMap = new 
HashMap<>();
+        setterList.forEach(setter -> 
metricsIndex.get(setter.name).samples.stream()
+                .map(sample -> {
+                    int index = Iterables.indexOf(sample.labelNames, i -> 
Objects.equals(i, "pool"));
+                    if (index < 0) {
+                        return null;
+                    }
+                    String poolType = sample.labelValues.get(index);
+                    if (poolType.contains("Code")) {
+                        return new PoolMetric(MemoryPoolType.CODE_CACHE_USAGE, 
sample.value);
+                    } else if (poolType.contains("Eden")) {
+                        return new PoolMetric(MemoryPoolType.NEWGEN_USAGE, 
sample.value);
+                    } else if (poolType.contains("Survivor")) {
+                        return new PoolMetric(MemoryPoolType.SURVIVOR_USAGE, 
sample.value);
+                    } else if (poolType.contains("Old")) {
+                        return new PoolMetric(MemoryPoolType.OLDGEN_USAGE, 
sample.value);
+                    } else if (poolType.contains("Metaspace")) {
+                        return new PoolMetric(MemoryPoolType.METASPACE_USAGE, 
sample.value);
+                    } else if (poolType.contains("Perm") || 
poolType.contains("Compressed Class Space")) {
+                        return new PoolMetric(MemoryPoolType.PERMGEN_USAGE, 
sample.value);
+                    }
+                    throw new RuntimeException(String.format("Unknown pool 
type %s", poolType));
+                })
+                .filter(Objects::nonNull)
+                .collect(groupingBy(PoolMetric::getType, 
summingDouble(PoolMetric::getValue)))
+                .forEach((memoryPoolType, value) -> {
+                    if (!poolMap.containsKey(memoryPoolType)) {
+                        ServiceInstanceJVMMemoryPool pool = new 
ServiceInstanceJVMMemoryPool();
+                        pool.setId(serviceInstanceId);
+                        pool.setName(serviceInstanceName);
+                        pool.setServiceId(serviceId);
+                        pool.setServiceName(SERVICE_NAME);
+                        pool.setPoolType(memoryPoolType);
+                        
pool.setTimeBucket(TimeBucket.getMinuteTimeBucket(System.currentTimeMillis()));
+                        poolMap.put(memoryPoolType, pool);
+                    }
+                    ServiceInstanceJVMMemoryPool pool = 
poolMap.get(memoryPoolType);
+                    setter.delegated.accept(pool, value);
+                }));
+        poolMap.values().forEach(p -> {
+            if (logger.isDebugEnabled()) {
+                logger.debug("Write {} {}-{}-{}-{} to {}", p.getPoolType(),
+                        humanReadableByteCount(p.getInit(), false),
+                        humanReadableByteCount(p.getUsed(), false),
+                        humanReadableByteCount(p.getCommitted(), false),
+                        humanReadableByteCount(p.getMax(), false), 
p.getName());
+            }
+            sourceReceiver.receive(p);
+        });
+    }
+
+    private void writeJvmMemory(final Map<String, MetricFamily> metricsIndex) {
+        List<MetricSetter<ServiceInstanceJVMMemory>> setterList = 
ImmutableList.of(
+                new MetricSetter<>("jvm_memory_bytes_used", (m, v) -> 
m.setUsed(v.longValue())),
+                new MetricSetter<>("jvm_memory_bytes_committed", (m, v) -> 
m.setCommitted(v.longValue())),
+                new MetricSetter<>("jvm_memory_bytes_max", (m, v) -> 
m.setMax(v.longValue())),
+                new MetricSetter<>("jvm_memory_bytes_init", (m, v) -> 
m.setInit(v.longValue())));
+        if (setterList.stream().anyMatch(i -> 
!metricsIndex.containsKey(i.name))) {
+            return;
+        }
+        ImmutableList.of(createJVMMemory(true), createJVMMemory(false))
+                .forEach(memory -> {
+                    String area = memory.isHeapStatus() ? "heap" : "nonheap";
+                    setterList.forEach(setter -> {
+                        metricsIndex.get(setter.name).samples.stream()
+                                .filter(input -> {
+                                    int index = 
Iterables.indexOf(input.labelNames, i -> Objects.equals(i, "area"));
+                                    if (index < 0) {
+                                        return false;
+                                    }
+                                    return 
Objects.equals(input.labelValues.get(index), area);
+                                })
+                                .findFirst()
+                                .ifPresent(sample -> 
setter.delegated.accept(memory, sample.value));
+                    });
+                    if (logger.isDebugEnabled()) {
+                        logger.debug("Write {} {}-{}-{}-{} to {}", area,
+                                humanReadableByteCount(memory.getInit(), 
false),
+                                humanReadableByteCount(memory.getUsed(), 
false),
+                                humanReadableByteCount(memory.getCommitted(), 
false),
+                                humanReadableByteCount(memory.getMax(), 
false), memory.getName());
+                    }
+                    sourceReceiver.receive(memory);
+                });
+    }
+
+    private ServiceInstanceJVMMemory createJVMMemory(boolean isHeap) {
+        ServiceInstanceJVMMemory memory = new ServiceInstanceJVMMemory();
+        memory.setId(serviceInstanceId);
+        memory.setName(serviceInstanceName);
+        memory.setServiceId(serviceId);
+        memory.setServiceName(SERVICE_NAME);
+        memory.setHeapStatus(isHeap);
+        
memory.setTimeBucket(TimeBucket.getMinuteTimeBucket(System.currentTimeMillis()));
+        return memory;
+    }
+
+    private void writeCpuUsage(Map<String, MetricFamily> metricsIndex) {
+        if (!metricsIndex.containsKey("process_cpu_seconds_total")) {
+            return;
+        }
+        double value = 
metricsIndex.get("process_cpu_seconds_total").samples.get(0).value;
+        if (lastCpuSeconds < 0) {
+            lastCpuSeconds = value;
+            return;
+        }
+        double percentage = (value - lastCpuSeconds) * 100 / (RUN_RATE_SECONDS 
* Runtime.getRuntime().availableProcessors());
+        lastCpuSeconds = value;
+        ServiceInstanceJVMCPU serviceInstanceJVMCPU = new 
ServiceInstanceJVMCPU();
+        serviceInstanceJVMCPU.setId(serviceInstanceId);
+        serviceInstanceJVMCPU.setName(serviceInstanceName);
+        serviceInstanceJVMCPU.setServiceId(serviceId);
+        serviceInstanceJVMCPU.setServiceName(SERVICE_NAME);
+        serviceInstanceJVMCPU.setUsePercent(percentage);
+        
serviceInstanceJVMCPU.setTimeBucket(TimeBucket.getMinuteTimeBucket(System.currentTimeMillis()));
+        logger.debug("Write so11y cpu usage {} to {}", percentage, 
serviceInstanceName);
+        sourceReceiver.receive(serviceInstanceJVMCPU);
+    }
+
+
+    private void heartbeat() {
+        long now = System.currentTimeMillis();
+        serviceInventoryRegister.heartbeat(serviceId, now);
+        serviceInstanceInventoryRegister.heartbeat(serviceInstanceId, now);
+    }
+
+    private boolean register() {
+        if (serviceId == Const.NONE) {
+            logger.debug("Register so11y service [{}].", SERVICE_NAME);
+            serviceId = serviceInventoryRegister.getOrCreate(SERVICE_NAME, 
null);
+        }
+        if (serviceId != Const.NONE && serviceInstanceId == Const.NONE) {
+            serviceInstanceName = TelemetryRelatedContext.INSTANCE.getId();
+            logger.debug("Register so11y service instance [{}].", 
serviceInstanceName);
+            serviceInstanceId = 
serviceInstanceInventoryRegister.getOrCreate(serviceId, serviceInstanceName, 
serviceInstanceName,
+                    System.currentTimeMillis(), null);
+        }
+        return serviceInstanceId != Const.NONE;
+    }
+
+    @RequiredArgsConstructor
+    private class MetricSetter<T> {
+
+        final String name;
+
+        final BiConsumer<T, Double> delegated;
+
+    }
+
+    private static String humanReadableByteCount(long bytes, boolean si) {
+        int unit = si ? 1000 : 1024;
+        if (bytes < unit) return bytes + " B";
+        int exp = (int) (Math.log(bytes) / Math.log(unit));
+        String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : 
"i");
+        return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre);
+    }
+
+    @RequiredArgsConstructor
+    @EqualsAndHashCode(of = "type")
+    @ToString
+    @Getter
+    private class PoolMetric {
+        private final MemoryPoolType type;
+        private final Double value;
+    }
+
+    @RequiredArgsConstructor
+    @EqualsAndHashCode(of = "phrase")
+    @ToString
+    @Getter
+    private class GCMetric {
+        private final GCPhrase phrase;
+        private final GCMetricType type;
+        private final Double value;
+    }
+
+    private enum GCMetricType {
+        SUM, COUNT
+    }
+
+}
diff --git 
a/oap-server/server-receiver-plugin/skywalking-so11y-receiver-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine
 
b/oap-server/server-receiver-plugin/skywalking-so11y-receiver-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine
new file mode 100644
index 0000000..e6616e5
--- /dev/null
+++ 
b/oap-server/server-receiver-plugin/skywalking-so11y-receiver-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleDefine
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+#
+
+org.apache.skywalking.oap.server.receiver.so11y.So11yReceiverModule
\ No newline at end of file
diff --git 
a/oap-server/server-receiver-plugin/skywalking-so11y-receiver-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
 
b/oap-server/server-receiver-plugin/skywalking-so11y-receiver-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
new file mode 100644
index 0000000..81ce655
--- /dev/null
+++ 
b/oap-server/server-receiver-plugin/skywalking-so11y-receiver-plugin/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+#
+
+org.apache.skywalking.oap.server.receiver.so11y.So11yReceiverModuleProvider
\ No newline at end of file
diff --git a/oap-server/server-starter/pom.xml 
b/oap-server/server-starter/pom.xml
index 761c377..cd9b471 100644
--- a/oap-server/server-starter/pom.xml
+++ b/oap-server/server-starter/pom.xml
@@ -117,6 +117,11 @@
             <artifactId>skywalking-clr-receiver-plugin</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>skywalking-so11y-receiver-plugin</artifactId>
+            <version>${project.version}</version>
+        </dependency>
         <!-- receiver module -->
 
         <!-- storage module -->
@@ -163,6 +168,11 @@
             <artifactId>telemetry-prometheus</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>telemetry-so11y</artifactId>
+            <version>${project.version}</version>
+        </dependency>
 
         <!-- exporter -->
         <dependency>
diff --git a/oap-server/server-starter/src/main/resources/application.yml 
b/oap-server/server-starter/src/main/resources/application.yml
index 30d2134..85a5b8b 100644
--- a/oap-server/server-starter/src/main/resources/application.yml
+++ b/oap-server/server-starter/src/main/resources/application.yml
@@ -106,6 +106,8 @@ receiver-jvm:
   default:
 receiver-clr:
   default:
+#receiver-so11y:
+#  default:
 service-mesh:
   default:
     bufferPath: ${SW_SERVICE_MESH_BUFFER_PATH:../mesh-buffer/}  # Path to 
trace buffer files, suggest to use absolute path
@@ -132,9 +134,14 @@ query:
 alarm:
   default:
 telemetry:
-  prometheus:
-    host: ${SW_TELEMETRY_PROMETHEUS_HOST:0.0.0.0}
-    port: ${SW_TELEMETRY_PROMETHEUS_PORT:1234}
+  none:
+#  prometheus:
+#    host: ${SW_TELEMETRY_PROMETHEUS_HOST:0.0.0.0}
+#    port: ${SW_TELEMETRY_PROMETHEUS_PORT:1234}
+#  so11y:
+#    prometheusExporterEnabled: ${SW_TELEMETRY_SO11Y_PROMETHEUS_ENABLED:true}
+#    prometheusExporterHost: ${SW_TELEMETRY_PROMETHEUS_HOST:0.0.0.0}
+#    prometheusExporterPort: ${SW_TELEMETRY_PROMETHEUS_PORT:1234}
 configuration:
   none:
 #  apollo:
diff --git a/oap-server/server-starter/src/main/resources/log4j2.xml 
b/oap-server/server-starter/src/main/resources/log4j2.xml
index e9a520b..cf83c5b 100644
--- a/oap-server/server-starter/src/main/resources/log4j2.xml
+++ b/oap-server/server-starter/src/main/resources/log4j2.xml
@@ -31,12 +31,12 @@
         <logger name="io.grpc.netty" level="INFO"/>
         <logger name="io.netty" level="INFO"/>
         <logger name="org.apache.http" level="INFO"/>
-        <logger 
name="org.apache.skywalking.oap.server.receiver.istio.telemetry" level="DEBUG"/>
         <logger 
name="org.apache.skywalking.oap.server.core.alarm.AlarmStandardPersistence" 
level="DEBUG"/>
         <logger name="org.apache.skywalking.oap.server.core" level="INFO"/>
         <logger name="org.apache.skywalking.oap.server.core.remote.client" 
level="DEBUG"/>
         <logger name="org.apache.skywalking.oap.server.library.buffer" 
level="INFO"/>
-        <Root level="DEBUG">
+        <logger name="org.apache.skywalking.oap.server.receiver.so11y" 
level="DEBUG" />
+        <Root level="ERROR">
             <AppenderRef ref="Console"/>
         </Root>
     </Loggers>
diff --git a/oap-server/server-telemetry/pom.xml 
b/oap-server/server-telemetry/pom.xml
index 4f885aa..3c17ace 100644
--- a/oap-server/server-telemetry/pom.xml
+++ b/oap-server/server-telemetry/pom.xml
@@ -30,5 +30,6 @@
     <modules>
         <module>telemetry-prometheus</module>
         <module>telemetry-api</module>
+        <module>telemetry-so11y</module>
     </modules>
 </project>
\ No newline at end of file
diff --git 
a/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
 
b/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
index 78cdce4..f9a9d13 100644
--- 
a/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
+++ 
b/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
@@ -19,6 +19,7 @@
 package org.apache.skywalking.oap.server.telemetry;
 
 import org.apache.skywalking.oap.server.library.module.ModuleDefine;
+import org.apache.skywalking.oap.server.telemetry.api.MetricsCollector;
 import org.apache.skywalking.oap.server.telemetry.api.MetricsCreator;
 
 /**
@@ -34,6 +35,6 @@ public class TelemetryModule extends ModuleDefine {
     }
 
     @Override public Class[] services() {
-        return new Class[] {MetricsCreator.class};
+        return new Class[] {MetricsCreator.class, MetricsCollector.class};
     }
 }
diff --git 
a/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/api/MetricFamily.java
 
b/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/api/MetricFamily.java
new file mode 100644
index 0000000..eabb2c6
--- /dev/null
+++ 
b/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/api/MetricFamily.java
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.telemetry.api;
+
+import lombok.AllArgsConstructor;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+import java.util.List;
+
+/**
+ * MetricFamily define a metric and all its samples.
+ *
+ * @author gaohongtao
+ */
+@AllArgsConstructor
+@EqualsAndHashCode
+@ToString
+public class MetricFamily {
+
+    public final String name;
+    public final Type type;
+    public final String help;
+    public final List<Sample> samples;
+
+    public enum Type {
+        COUNTER,
+        GAUGE,
+        SUMMARY,
+        HISTOGRAM,
+        UNTYPED,
+    }
+
+    /**
+     * A single Sample, with a unique name and set of labels.
+     */
+    @AllArgsConstructor
+    @EqualsAndHashCode
+    @ToString
+    public static class Sample {
+        public final String name;
+        public final List<String> labelNames;
+        public final List<String> labelValues;  // Must have same length as 
labelNames.
+        public final double value;
+        public final Long timestampMs;  // It's an epoch format with 
milliseconds value included (this field is subject to change).
+
+    }
+}
diff --git 
a/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
 
b/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/api/MetricsCollector.java
similarity index 62%
copy from 
oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
copy to 
oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/api/MetricsCollector.java
index 78cdce4..c0a988f 100644
--- 
a/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
+++ 
b/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/api/MetricsCollector.java
@@ -16,24 +16,21 @@
  *
  */
 
-package org.apache.skywalking.oap.server.telemetry;
+package org.apache.skywalking.oap.server.telemetry.api;
 
-import org.apache.skywalking.oap.server.library.module.ModuleDefine;
-import org.apache.skywalking.oap.server.telemetry.api.MetricsCreator;
+import org.apache.skywalking.oap.server.library.module.Service;
 
 /**
- * Telemetry module definition
+ * Collect all metrics from telemetry.
  *
- * @author wusheng
+ * @author gaohongtao
  */
-public class TelemetryModule extends ModuleDefine {
-    public static final String NAME = "telemetry";
+public interface MetricsCollector extends Service {
 
-    public TelemetryModule() {
-        super(NAME);
-    }
-
-    @Override public Class[] services() {
-        return new Class[] {MetricsCreator.class};
-    }
+    /**
+     * Get all of metrics.
+     *
+     * @return all metrics
+     */
+    Iterable<MetricFamily> collect();
 }
diff --git 
a/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
 
b/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/none/MetricsCollectorNoop.java
similarity index 62%
copy from 
oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
copy to 
oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/none/MetricsCollectorNoop.java
index 78cdce4..57eac8b 100644
--- 
a/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
+++ 
b/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/none/MetricsCollectorNoop.java
@@ -16,24 +16,21 @@
  *
  */
 
-package org.apache.skywalking.oap.server.telemetry;
+package org.apache.skywalking.oap.server.telemetry.none;
 
-import org.apache.skywalking.oap.server.library.module.ModuleDefine;
-import org.apache.skywalking.oap.server.telemetry.api.MetricsCreator;
+import org.apache.skywalking.oap.server.telemetry.api.MetricFamily;
+import org.apache.skywalking.oap.server.telemetry.api.MetricsCollector;
+
+import java.util.Collections;
 
 /**
- * Telemetry module definition
+ * No-op MetricFamily Collector.
  *
- * @author wusheng
+ * @author gaohongtao
  */
-public class TelemetryModule extends ModuleDefine {
-    public static final String NAME = "telemetry";
-
-    public TelemetryModule() {
-        super(NAME);
-    }
-
-    @Override public Class[] services() {
-        return new Class[] {MetricsCreator.class};
+public class MetricsCollectorNoop implements MetricsCollector {
+    @Override
+    public Iterable<MetricFamily> collect() {
+        return Collections.emptyList();
     }
 }
diff --git 
a/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/none/NoneTelemetryProvider.java
 
b/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/none/NoneTelemetryProvider.java
index 25db52b..96975e2 100644
--- 
a/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/none/NoneTelemetryProvider.java
+++ 
b/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/none/NoneTelemetryProvider.java
@@ -20,6 +20,7 @@ package org.apache.skywalking.oap.server.telemetry.none;
 
 import org.apache.skywalking.oap.server.library.module.*;
 import org.apache.skywalking.oap.server.telemetry.TelemetryModule;
+import org.apache.skywalking.oap.server.telemetry.api.MetricsCollector;
 import org.apache.skywalking.oap.server.telemetry.api.MetricsCreator;
 
 /**
@@ -43,6 +44,7 @@ public class NoneTelemetryProvider extends ModuleProvider {
 
     @Override public void prepare() throws ServiceNotProvidedException, 
ModuleStartException {
         this.registerServiceImplementation(MetricsCreator.class, new 
MetricsCreatorNoop());
+        this.registerServiceImplementation(MetricsCollector.class, new 
MetricsCollectorNoop());
     }
 
     @Override public void start() throws ServiceNotProvidedException, 
ModuleStartException {
diff --git a/oap-server/server-telemetry/pom.xml 
b/oap-server/server-telemetry/telemetry-so11y/pom.xml
similarity index 64%
copy from oap-server/server-telemetry/pom.xml
copy to oap-server/server-telemetry/telemetry-so11y/pom.xml
index 4f885aa..5932145 100644
--- a/oap-server/server-telemetry/pom.xml
+++ b/oap-server/server-telemetry/telemetry-so11y/pom.xml
@@ -17,18 +17,25 @@
   ~
   -->
 
-<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
     <parent>
-        <artifactId>oap-server</artifactId>
+        <artifactId>server-telemetry</artifactId>
         <groupId>org.apache.skywalking</groupId>
         <version>6.3.0-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 
-    <artifactId>server-telemetry</artifactId>
-    <packaging>pom</packaging>
-    <modules>
-        <module>telemetry-prometheus</module>
-        <module>telemetry-api</module>
-    </modules>
+    <artifactId>telemetry-so11y</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>telemetry-prometheus</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+
 </project>
\ No newline at end of file
diff --git 
a/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
 
b/oap-server/server-telemetry/telemetry-so11y/src/main/java/org/apache/skywalking/oap/server/telemetry/so11y/So11yConfig.java
similarity index 61%
copy from 
oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
copy to 
oap-server/server-telemetry/telemetry-so11y/src/main/java/org/apache/skywalking/oap/server/telemetry/so11y/So11yConfig.java
index 78cdce4..82271bd 100644
--- 
a/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/TelemetryModule.java
+++ 
b/oap-server/server-telemetry/telemetry-so11y/src/main/java/org/apache/skywalking/oap/server/telemetry/so11y/So11yConfig.java
@@ -16,24 +16,23 @@
  *
  */
 
-package org.apache.skywalking.oap.server.telemetry;
+package org.apache.skywalking.oap.server.telemetry.so11y;
 
-import org.apache.skywalking.oap.server.library.module.ModuleDefine;
-import org.apache.skywalking.oap.server.telemetry.api.MetricsCreator;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.skywalking.oap.server.library.module.ModuleConfig;
 
 /**
- * Telemetry module definition
- *
- * @author wusheng
+ * The module configuration of self observability.
  */
-public class TelemetryModule extends ModuleDefine {
-    public static final String NAME = "telemetry";
+@Setter
+@Getter
+public class So11yConfig extends ModuleConfig {
+
+    private boolean prometheusExporterEnabled = false;
+
+    private String prometheusExporterHost = "0.0.0.0";
 
-    public TelemetryModule() {
-        super(NAME);
-    }
+    private int prometheusExporterPort = 1234;
 
-    @Override public Class[] services() {
-        return new Class[] {MetricsCreator.class};
-    }
 }
diff --git 
a/oap-server/server-telemetry/telemetry-so11y/src/main/java/org/apache/skywalking/oap/server/telemetry/so11y/So11yMetricsCollector.java
 
b/oap-server/server-telemetry/telemetry-so11y/src/main/java/org/apache/skywalking/oap/server/telemetry/so11y/So11yMetricsCollector.java
new file mode 100644
index 0000000..de88bc9
--- /dev/null
+++ 
b/oap-server/server-telemetry/telemetry-so11y/src/main/java/org/apache/skywalking/oap/server/telemetry/so11y/So11yMetricsCollector.java
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.telemetry.so11y;
+
+import io.prometheus.client.Collector;
+import io.prometheus.client.CollectorRegistry;
+import org.apache.skywalking.oap.server.telemetry.api.MetricFamily;
+import org.apache.skywalking.oap.server.telemetry.api.MetricsCollector;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Implement MetricCollector to generate prometheus metrics.
+ *
+ * @author gaohongtao
+ */
+public class So11yMetricsCollector implements MetricsCollector {
+    @Override
+    public Iterable<MetricFamily> collect() {
+        Enumeration<Collector.MetricFamilySamples> mfs = 
CollectorRegistry.defaultRegistry.metricFamilySamples();
+        List<MetricFamily> result = new LinkedList<>();
+        while (mfs.hasMoreElements()) {
+            Collector.MetricFamilySamples metricFamilySamples = 
mfs.nextElement();
+            List<MetricFamily.Sample> samples = new 
ArrayList<>(metricFamilySamples.samples.size());
+            MetricFamily m = new MetricFamily(metricFamilySamples.name, 
MetricFamily.Type.valueOf(metricFamilySamples.type.name()),
+                    metricFamilySamples.help, samples);
+            result.add(m);
+            for (Collector.MetricFamilySamples.Sample sample: 
metricFamilySamples.samples) {
+                samples.add(new MetricFamily.Sample(sample.name, 
sample.labelNames, sample.labelValues, sample.value, sample.timestampMs));
+            }
+        }
+        return result;
+    }
+}
diff --git 
a/oap-server/server-telemetry/telemetry-so11y/src/main/java/org/apache/skywalking/oap/server/telemetry/so11y/So11yMetricsCreator.java
 
b/oap-server/server-telemetry/telemetry-so11y/src/main/java/org/apache/skywalking/oap/server/telemetry/so11y/So11yMetricsCreator.java
new file mode 100644
index 0000000..ddad834
--- /dev/null
+++ 
b/oap-server/server-telemetry/telemetry-so11y/src/main/java/org/apache/skywalking/oap/server/telemetry/so11y/So11yMetricsCreator.java
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.skywalking.oap.server.telemetry.so11y;
+
+import org.apache.skywalking.oap.server.telemetry.api.CounterMetrics;
+import org.apache.skywalking.oap.server.telemetry.api.GaugeMetrics;
+import org.apache.skywalking.oap.server.telemetry.api.HistogramMetrics;
+import org.apache.skywalking.oap.server.telemetry.api.MetricsTag;
+import 
org.apache.skywalking.oap.server.telemetry.prometheus.PrometheusMetricsCreator;
+
+/**
+ * Delegate prometheus metrics creator.
+ *
+ * @author gaohongtao
+ */
+public class So11yMetricsCreator extends PrometheusMetricsCreator {
+
+    @Override
+    public CounterMetrics createCounter(String name, String tips, 
MetricsTag.Keys tagKeys, MetricsTag.Values tagValues) {
+        return super.createCounter(name, tips, tagKeys, tagValues);
+    }
+
+    @Override
+    public GaugeMetrics createGauge(String name, String tips, MetricsTag.Keys 
tagKeys, MetricsTag.Values tagValues) {
+        return super.createGauge(name, tips, tagKeys, tagValues);
+    }
+
+    @Override
+    public HistogramMetrics createHistogramMetric(String name, String tips, 
MetricsTag.Keys tagKeys, MetricsTag.Values tagValues, double... buckets) {
+        return super.createHistogramMetric(name, tips, tagKeys, tagValues, 
buckets);
+    }
+}
diff --git 
a/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/none/NoneTelemetryProvider.java
 
b/oap-server/server-telemetry/telemetry-so11y/src/main/java/org/apache/skywalking/oap/server/telemetry/so11y/So11yTelemetryProvider.java
similarity index 62%
copy from 
oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/none/NoneTelemetryProvider.java
copy to 
oap-server/server-telemetry/telemetry-so11y/src/main/java/org/apache/skywalking/oap/server/telemetry/so11y/So11yTelemetryProvider.java
index 25db52b..27c8874 100644
--- 
a/oap-server/server-telemetry/telemetry-api/src/main/java/org/apache/skywalking/oap/server/telemetry/none/NoneTelemetryProvider.java
+++ 
b/oap-server/server-telemetry/telemetry-so11y/src/main/java/org/apache/skywalking/oap/server/telemetry/so11y/So11yTelemetryProvider.java
@@ -16,20 +16,31 @@
  *
  */
 
-package org.apache.skywalking.oap.server.telemetry.none;
+package org.apache.skywalking.oap.server.telemetry.so11y;
 
+import io.prometheus.client.exporter.HTTPServer;
+import io.prometheus.client.hotspot.DefaultExports;
 import org.apache.skywalking.oap.server.library.module.*;
 import org.apache.skywalking.oap.server.telemetry.TelemetryModule;
+import org.apache.skywalking.oap.server.telemetry.api.MetricsCollector;
 import org.apache.skywalking.oap.server.telemetry.api.MetricsCreator;
 
+import java.io.IOException;
+
 /**
- * A nutshell telemetry implementor.
+ * Self observability telemetry provider.
  *
- * @author wusheng
+ * @author gaohongtao
  */
-public class NoneTelemetryProvider extends ModuleProvider {
+public class So11yTelemetryProvider extends ModuleProvider {
+    private So11yConfig config;
+
+    public So11yTelemetryProvider() {
+        config = new So11yConfig();
+    }
+
     @Override public String name() {
-        return "none";
+        return "so11y";
     }
 
     @Override public Class<? extends ModuleDefine> module() {
@@ -37,12 +48,20 @@ public class NoneTelemetryProvider extends ModuleProvider {
     }
 
     @Override public ModuleConfig createConfigBeanIfAbsent() {
-        return new ModuleConfig() {
-        };
+        return config;
     }
 
     @Override public void prepare() throws ServiceNotProvidedException, 
ModuleStartException {
-        this.registerServiceImplementation(MetricsCreator.class, new 
MetricsCreatorNoop());
+        this.registerServiceImplementation(MetricsCreator.class, new 
So11yMetricsCreator());
+        this.registerServiceImplementation(MetricsCollector.class, new 
So11yMetricsCollector());
+        if (config.isPrometheusExporterEnabled()) {
+            try {
+                new HTTPServer(config.getPrometheusExporterHost(), 
config.getPrometheusExporterPort());
+            } catch (IOException e) {
+                throw new ModuleStartException(e.getMessage(), e);
+            }
+        }
+        DefaultExports.initialize();
     }
 
     @Override public void start() throws ServiceNotProvidedException, 
ModuleStartException {
@@ -50,7 +69,6 @@ public class NoneTelemetryProvider extends ModuleProvider {
     }
 
     @Override public void notifyAfterCompleted() throws 
ServiceNotProvidedException, ModuleStartException {
-
     }
 
     @Override public String[] requiredModules() {
diff --git 
a/oap-server/server-telemetry/telemetry-so11y/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
 
b/oap-server/server-telemetry/telemetry-so11y/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
new file mode 100644
index 0000000..fed0b08
--- /dev/null
+++ 
b/oap-server/server-telemetry/telemetry-so11y/src/main/resources/META-INF/services/org.apache.skywalking.oap.server.library.module.ModuleProvider
@@ -0,0 +1,20 @@
+#
+# 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.
+#
+#
+
+
+org.apache.skywalking.oap.server.telemetry.so11y.So11yTelemetryProvider

Reply via email to