You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ke...@apache.org on 2021/03/16 12:37:28 UTC

[skywalking] 01/01: Collect and report agent starting / shutdown events

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

kezhenxu94 pushed a commit to branch event/jvm
in repository https://gitbox.apache.org/repos/asf/skywalking.git

commit dc5c2dabd6381d2c06684b08bc20742b9ff8ab03
Author: kezhenxu94 <ke...@apache.org>
AuthorDate: Tue Mar 16 20:36:25 2021 +0800

    Collect and report agent starting / shutdown events
---
 ...tService.java => ServiceInstanceGenerator.java} |  31 ++--
 .../apm/agent/core/boot/BootService.java           |   9 +
 .../apm/agent/core/boot/ServiceManager.java        |   4 +-
 .../core/remote/EventReportServiceClient.java      | 190 +++++++++++++++++++++
 .../apm/agent/core/remote/GRPCChannelManager.java  |   5 +
 .../agent/core/remote/ServiceManagementClient.java |   8 +-
 ...ache.skywalking.apm.agent.core.boot.BootService |   3 +-
 .../skywalking/oap/server/core/event/Event.java    |   2 +-
 8 files changed, 233 insertions(+), 19 deletions(-)

diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/BootService.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/ServiceInstanceGenerator.java
similarity index 52%
copy from apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/BootService.java
copy to apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/ServiceInstanceGenerator.java
index eae8a5c..eff46e7 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/BootService.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/ServiceInstanceGenerator.java
@@ -16,18 +16,29 @@
  *
  */
 
-package org.apache.skywalking.apm.agent.core.boot;
+package org.apache.skywalking.apm.agent.core;
 
-/**
- * The <code>BootService</code> is an interface to all remote, which need to boot when plugin mechanism begins to work.
- * {@link #boot()} will be called when <code>BootService</code> start up.
- */
-public interface BootService {
-    void prepare() throws Throwable;
+import java.util.UUID;
+import lombok.Getter;
+import lombok.experimental.Accessors;
+import org.apache.skywalking.apm.agent.core.conf.Config;
+import org.apache.skywalking.apm.agent.core.os.OSUtil;
+
+import static org.apache.skywalking.apm.util.StringUtil.isEmpty;
+
+@Getter
+@Accessors(fluent = true)
+public enum ServiceInstanceGenerator {
+    SINGLETON;
 
-    void boot() throws Throwable;
+    private boolean isGenerated = false;
 
-    void onComplete() throws Throwable;
+    public synchronized void generateIfNotSpecified() {
+        if (!isEmpty(Config.Agent.INSTANCE_NAME)) {
+            return;
+        }
 
-    void shutdown() throws Throwable;
+        Config.Agent.INSTANCE_NAME = UUID.randomUUID().toString().replaceAll("-", "") + "@" + OSUtil.getIPV4();
+        isGenerated = true;
+    }
 }
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/BootService.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/BootService.java
index eae8a5c..4907866 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/BootService.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/BootService.java
@@ -18,6 +18,8 @@
 
 package org.apache.skywalking.apm.agent.core.boot;
 
+import org.apache.skywalking.apm.agent.core.remote.GRPCChannelManager;
+
 /**
  * The <code>BootService</code> is an interface to all remote, which need to boot when plugin mechanism begins to work.
  * {@link #boot()} will be called when <code>BootService</code> start up.
@@ -30,4 +32,11 @@ public interface BootService {
     void onComplete() throws Throwable;
 
     void shutdown() throws Throwable;
+
+    /**
+     * @return the shutdown order that {@link ServiceManager} should respect to when shutting down the services, e.g. services depending on {@link GRPCChannelManager} should be shut down after it.
+     */
+    default int shutdownOrder() {
+        return 0;
+    }
 }
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/ServiceManager.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/ServiceManager.java
index 46158cd..b2e9bdc 100644
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/ServiceManager.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/boot/ServiceManager.java
@@ -19,11 +19,13 @@
 package org.apache.skywalking.apm.agent.core.boot;
 
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.ServiceLoader;
+import java.util.stream.Collectors;
 import org.apache.skywalking.apm.agent.core.logging.api.ILog;
 import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
 import org.apache.skywalking.apm.agent.core.plugin.loader.AgentClassLoader;
@@ -46,7 +48,7 @@ public enum ServiceManager {
     }
 
     public void shutdown() {
-        for (BootService service : bootedServices.values()) {
+        for (BootService service : bootedServices.values().stream().sorted(Comparator.comparing(BootService::shutdownOrder)).collect(Collectors.toList())) {
             try {
                 service.shutdown();
             } catch (Throwable e) {
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/EventReportServiceClient.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/EventReportServiceClient.java
new file mode 100644
index 0000000..cad9ad3
--- /dev/null
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/EventReportServiceClient.java
@@ -0,0 +1,190 @@
+/*
+ * 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.apm.agent.core.remote;
+
+import io.grpc.stub.StreamObserver;
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.util.UUID;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+import org.apache.skywalking.apm.agent.core.ServiceInstanceGenerator;
+import org.apache.skywalking.apm.agent.core.boot.BootService;
+import org.apache.skywalking.apm.agent.core.boot.DefaultImplementor;
+import org.apache.skywalking.apm.agent.core.boot.ServiceManager;
+import org.apache.skywalking.apm.agent.core.commands.CommandService;
+import org.apache.skywalking.apm.agent.core.conf.Config;
+import org.apache.skywalking.apm.agent.core.logging.api.ILog;
+import org.apache.skywalking.apm.agent.core.logging.api.LogManager;
+import org.apache.skywalking.apm.network.common.v3.Commands;
+import org.apache.skywalking.apm.network.event.v3.Event;
+import org.apache.skywalking.apm.network.event.v3.EventServiceGrpc;
+import org.apache.skywalking.apm.network.event.v3.Source;
+import org.apache.skywalking.apm.network.event.v3.Type;
+
+import static org.apache.skywalking.apm.agent.core.remote.GRPCChannelStatus.CONNECTED;
+
+@DefaultImplementor
+public class EventReportServiceClient implements BootService, GRPCChannelListener {
+    private static final ILog LOGGER = LogManager.getLogger(EventReportServiceClient.class);
+
+    private final AtomicBoolean reported = new AtomicBoolean();
+
+    private Event.Builder startingEvent;
+
+    private EventServiceGrpc.EventServiceStub eventServiceStub;
+
+    private GRPCChannelStatus status;
+
+    @Override
+    public void prepare() throws Throwable {
+        ServiceManager.INSTANCE.findService(GRPCChannelManager.class).addChannelListener(this);
+        ServiceInstanceGenerator.SINGLETON.generateIfNotSpecified();
+
+        if (ServiceInstanceGenerator.SINGLETON.isGenerated()) {
+            LOGGER.debug("The service instance is generated, no starting event will be reported");
+            return;
+        }
+
+        final RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
+        startingEvent = Event.newBuilder()
+                             .setUuid(UUID.randomUUID().toString())
+                             .setName("Start")
+                             .setStartTime(runtimeMxBean.getStartTime())
+                             .setMessage("Start Java Application")
+                             .setType(Type.Normal)
+                             .setSource(
+                                 Source.newBuilder()
+                                       .setService(Config.Agent.SERVICE_NAME)
+                                       .setServiceInstance(Config.Agent.INSTANCE_NAME)
+                                       .build()
+                             )
+                             .putParameters(
+                                 "OPTS",
+                                 runtimeMxBean.getInputArguments()
+                                              .stream()
+                                              .sorted()
+                                              .collect(Collectors.joining(" "))
+                             );
+    }
+
+    @Override
+    public void boot() throws Throwable {
+
+    }
+
+    @Override
+    public void onComplete() throws Throwable {
+        reportStartingEvent();
+    }
+
+    @Override
+    public void shutdown() throws Throwable {
+        if (ServiceInstanceGenerator.SINGLETON.isGenerated()) {
+            // If the agent service instance name is randomly generated, ignore the shutdown signal.
+            return;
+        }
+
+        if (!CONNECTED.equals(status)) {
+            return;
+        }
+
+        final CountDownLatch latch = new CountDownLatch(1);
+        final Event.Builder shutdownEvent = Event.newBuilder()
+                                                 .setUuid(UUID.randomUUID().toString())
+                                                 .setName("Shutdown")
+                                                 .setStartTime(System.currentTimeMillis())
+                                                 .setEndTime(System.currentTimeMillis())
+                                                 .setMessage("Shutting down Java Application")
+                                                 .setType(Type.Normal)
+                                                 .setSource(
+                                                     Source.newBuilder()
+                                                           .setService(Config.Agent.SERVICE_NAME)
+                                                           .setServiceInstance(Config.Agent.INSTANCE_NAME)
+                                                           .build()
+                                                 );
+
+        final StreamObserver<Event> collector = eventServiceStub.collect(new StreamObserver<Commands>() {
+            @Override
+            public void onNext(final Commands commands) {
+                ServiceManager.INSTANCE.findService(CommandService.class).receiveCommand(commands);
+            }
+
+            @Override
+            public void onError(final Throwable t) {
+                LOGGER.error("Failed to report shutdown event.", t);
+                // Ignore status change at shutting down stage.
+                latch.countDown();
+            }
+
+            @Override
+            public void onCompleted() {
+                latch.countDown();
+            }
+        });
+
+        collector.onNext(shutdownEvent.build());
+        collector.onCompleted();
+        latch.await();
+    }
+
+    @Override
+    public void statusChanged(final GRPCChannelStatus status) {
+        this.status = status;
+
+        if (!CONNECTED.equals(status)) {
+            return;
+        }
+
+        eventServiceStub = EventServiceGrpc.newStub(ServiceManager.INSTANCE.findService(GRPCChannelManager.class).getChannel());
+
+        reportStartingEvent();
+    }
+
+    private void reportStartingEvent() {
+        if (ServiceInstanceGenerator.SINGLETON.isGenerated() || reported.compareAndSet(false, true)) {
+            return;
+        }
+
+        startingEvent.setEndTime(System.currentTimeMillis());
+
+        final StreamObserver<Event> collector = eventServiceStub.collect(new StreamObserver<Commands>() {
+            @Override
+            public void onNext(final Commands commands) {
+                ServiceManager.INSTANCE.findService(CommandService.class).receiveCommand(commands);
+            }
+
+            @Override
+            public void onError(final Throwable t) {
+                LOGGER.error("Failed to report starting event.", t);
+                ServiceManager.INSTANCE.findService(GRPCChannelManager.class).reportError(t);
+                reported.set(false);
+
+            }
+
+            @Override
+            public void onCompleted() {
+            }
+        });
+
+        collector.onNext(startingEvent.build());
+        collector.onCompleted();
+    }
+}
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/GRPCChannelManager.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/GRPCChannelManager.java
index 4822c75..5a2ffb0 100755
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/GRPCChannelManager.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/GRPCChannelManager.java
@@ -208,4 +208,9 @@ public class GRPCChannelManager implements BootService, Runnable {
         }
         return false;
     }
+
+    @Override
+    public int shutdownOrder() {
+        return Integer.MAX_VALUE;
+    }
 }
diff --git a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/ServiceManagementClient.java b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/ServiceManagementClient.java
index f271856..3d5437f 100755
--- a/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/ServiceManagementClient.java
+++ b/apm-sniffer/apm-agent-core/src/main/java/org/apache/skywalking/apm/agent/core/remote/ServiceManagementClient.java
@@ -21,11 +21,11 @@ package org.apache.skywalking.apm.agent.core.remote;
 import io.grpc.Channel;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.UUID;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.skywalking.apm.agent.core.ServiceInstanceGenerator;
 import org.apache.skywalking.apm.agent.core.boot.BootService;
 import org.apache.skywalking.apm.agent.core.boot.DefaultImplementor;
 import org.apache.skywalking.apm.agent.core.boot.DefaultNamedThreadFactory;
@@ -41,7 +41,6 @@ import org.apache.skywalking.apm.network.management.v3.InstancePingPkg;
 import org.apache.skywalking.apm.network.management.v3.InstanceProperties;
 import org.apache.skywalking.apm.network.management.v3.ManagementServiceGrpc;
 import org.apache.skywalking.apm.util.RunnableWithExceptionProtection;
-import org.apache.skywalking.apm.util.StringUtil;
 
 import static org.apache.skywalking.apm.agent.core.conf.Config.Collector.GRPC_UPSTREAM_TIMEOUT;
 
@@ -69,6 +68,7 @@ public class ServiceManagementClient implements BootService, Runnable, GRPCChann
     @Override
     public void prepare() {
         ServiceManager.INSTANCE.findService(GRPCChannelManager.class).addChannelListener(this);
+        ServiceInstanceGenerator.SINGLETON.generateIfNotSpecified();
 
         SERVICE_INSTANCE_PROPERTIES = new ArrayList<>();
 
@@ -78,10 +78,6 @@ public class ServiceManagementClient implements BootService, Runnable, GRPCChann
                                                               .setValue(Config.Agent.INSTANCE_PROPERTIES.get(key))
                                                               .build());
         }
-
-        Config.Agent.INSTANCE_NAME = StringUtil.isEmpty(Config.Agent.INSTANCE_NAME)
-            ? UUID.randomUUID().toString().replaceAll("-", "") + "@" + OSUtil.getIPV4()
-            : Config.Agent.INSTANCE_NAME;
     }
 
     @Override
diff --git a/apm-sniffer/apm-agent-core/src/main/resources/META-INF/services/org.apache.skywalking.apm.agent.core.boot.BootService b/apm-sniffer/apm-agent-core/src/main/resources/META-INF/services/org.apache.skywalking.apm.agent.core.boot.BootService
index bfa58a8..5b9d995 100644
--- a/apm-sniffer/apm-agent-core/src/main/resources/META-INF/services/org.apache.skywalking.apm.agent.core.boot.BootService
+++ b/apm-sniffer/apm-agent-core/src/main/resources/META-INF/services/org.apache.skywalking.apm.agent.core.boot.BootService
@@ -33,4 +33,5 @@ org.apache.skywalking.apm.agent.core.meter.MeterService
 org.apache.skywalking.apm.agent.core.meter.MeterSender
 org.apache.skywalking.apm.agent.core.context.status.StatusCheckService
 org.apache.skywalking.apm.agent.core.remote.LogReportServiceClient
-org.apache.skywalking.apm.agent.core.conf.dynamic.ConfigurationDiscoveryService
\ No newline at end of file
+org.apache.skywalking.apm.agent.core.conf.dynamic.ConfigurationDiscoveryService
+org.apache.skywalking.apm.agent.core.remote.EventReportServiceClient
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/event/Event.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/event/Event.java
index 8fb26d0..7065589 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/event/Event.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/event/Event.java
@@ -95,7 +95,7 @@ public class Event extends Metrics {
     @Column(columnName = MESSAGE)
     private String message;
 
-    @Column(columnName = PARAMETERS, storageOnly = true)
+    @Column(columnName = PARAMETERS, storageOnly = true, length = 1024)
     private String parameters;
 
     @Column(columnName = START_TIME)