1 /*
  2  * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package jdk.jfr.internal;
 27 
 28 import java.util.Properties;
 29 
 30 import jdk.internal.access.SharedSecrets;
 31 import jdk.internal.event.JFRTracing;
 32 import jdk.internal.event.ThrowableTracer;
 33 import jdk.internal.platform.Container;
 34 import jdk.internal.platform.Metrics;
 35 import jdk.jfr.Event;
 36 import jdk.jfr.events.ActiveRecordingEvent;
 37 import jdk.jfr.events.ActiveSettingEvent;
 38 import jdk.jfr.events.ContainerCPUThrottlingEvent;
 39 import jdk.jfr.events.ContainerCPUUsageEvent;
 40 import jdk.jfr.events.ContainerConfigurationEvent;
 41 import jdk.jfr.events.ContainerIOUsageEvent;
 42 import jdk.jfr.events.ContainerMemoryUsageEvent;
 43 import jdk.jfr.events.DirectBufferStatisticsEvent;
 44 import jdk.jfr.events.InitialSecurityPropertyEvent;
 45 import jdk.jfr.events.MethodTimingEvent;
 46 import jdk.jfr.events.MethodTraceEvent;
 47 import jdk.jfr.internal.periodic.PeriodicEvents;
 48 import jdk.jfr.internal.settings.MethodSetting;
 49 import jdk.jfr.internal.tracing.PlatformTracer;
 50 import jdk.jfr.tracing.MethodTracer;
 51 
 52 public final class JDKEvents {
 53 
 54     private static final Class<?>[] eventClasses = {
 55         ActiveSettingEvent.class,
 56         ActiveRecordingEvent.class,
 57         // jdk.internal.event.* classes need their mirror
 58         // event class to be listed in the MirrorEvents class.
 59         jdk.internal.event.DeserializationEvent.class,
 60         jdk.internal.event.ErrorThrownEvent.class,
 61         jdk.internal.event.ExceptionStatisticsEvent.class,
 62         jdk.internal.event.ExceptionThrownEvent.class,
 63         jdk.internal.event.FileForceEvent.class,
 64         jdk.internal.event.FileReadEvent.class,
 65         jdk.internal.event.FileWriteEvent.class,
 66         jdk.internal.event.ProcessStartEvent.class,
 67         jdk.internal.event.SecurityPropertyModificationEvent.class,
 68         jdk.internal.event.SecurityProviderServiceEvent.class,
 69         jdk.internal.event.SerializationMisdeclarationEvent.class,
 70         jdk.internal.event.SocketReadEvent.class,
 71         jdk.internal.event.SocketWriteEvent.class,
 72         jdk.internal.event.ThreadSleepEvent.class,
 73         jdk.internal.event.TLSHandshakeEvent.class,
 74         jdk.internal.event.VirtualThreadParkEvent.class,
 75         jdk.internal.event.VirtualThreadStartEvent.class,
 76         jdk.internal.event.VirtualThreadEndEvent.class,
 77         jdk.internal.event.VirtualThreadSubmitFailedEvent.class,
 78         jdk.internal.event.X509CertificateEvent.class,
 79         jdk.internal.event.X509ValidationEvent.class,
 80         jdk.internal.event.FinalFieldMutationEvent.class,
 81         DirectBufferStatisticsEvent.class,
 82         InitialSecurityPropertyEvent.class,
 83         MethodTraceEvent.class,
 84         MethodTimingEvent.class,
 85     };
 86 
 87     private static final Runnable emitExceptionStatistics = JDKEvents::emitExceptionStatistics;
 88     private static final Runnable emitDirectBufferStatistics = JDKEvents::emitDirectBufferStatistics;
 89     private static final Runnable emitContainerConfiguration = JDKEvents::emitContainerConfiguration;
 90     private static final Runnable emitContainerCPUUsage = JDKEvents::emitContainerCPUUsage;
 91     private static final Runnable emitContainerCPUThrottling = JDKEvents::emitContainerCPUThrottling;
 92     private static final Runnable emitContainerMemoryUsage = JDKEvents::emitContainerMemoryUsage;
 93     private static final Runnable emitContainerIOUsage = JDKEvents::emitContainerIOUsage;
 94     private static final Runnable emitInitialSecurityProperties = JDKEvents::emitInitialSecurityProperties;
 95     private static final Runnable emitMethodTiming = JDKEvents::emitMethodTiming;
 96     private static Metrics containerMetrics = null;
 97     private static boolean initializationTriggered;
 98 
 99     @SuppressWarnings("unchecked")
100     public static synchronized void initialize() {
101         try {
102             if (initializationTriggered == false) {
103                 for (Class<?> eventClass : eventClasses) {
104                     MetadataRepository.getInstance().register((Class<? extends Event>) eventClass);
105                 }
106                 PeriodicEvents.addJavaEvent(jdk.internal.event.ExceptionStatisticsEvent.class, emitExceptionStatistics);
107                 PeriodicEvents.addJavaEvent(DirectBufferStatisticsEvent.class, emitDirectBufferStatistics);
108                 PeriodicEvents.addJavaEvent(InitialSecurityPropertyEvent.class, emitInitialSecurityProperties);
109                 PeriodicEvents.addJavaEvent(MethodTimingEvent.class, emitMethodTiming);
110 
111                 initializeContainerEvents();
112                 JFRTracing.enable();
113                 initializationTriggered = true;
114             }
115         } catch (Exception e) {
116             Logger.log(LogTag.JFR_SYSTEM, LogLevel.WARN, "Could not initialize JDK events. " + e.getMessage());
117         }
118     }
119 
120     private static void initializeContainerEvents() {
121         if (JVM.isContainerized() ) {
122             Logger.log(LogTag.JFR_SYSTEM, LogLevel.DEBUG, "JVM is containerized");
123             containerMetrics = Container.metrics();
124             if (containerMetrics != null) {
125                 Logger.log(LogTag.JFR_SYSTEM, LogLevel.DEBUG, "Container metrics are available");
126             }
127         }
128         // The registration of events and hooks are needed to provide metadata,
129         // even when not running in a container
130         registerEvent(ContainerConfigurationEvent.class);
131         registerEvent(ContainerCPUUsageEvent.class);
132         registerEvent(ContainerCPUThrottlingEvent.class);
133         registerEvent(ContainerMemoryUsageEvent.class);
134         registerEvent(ContainerIOUsageEvent.class);
135 
136         PeriodicEvents.addJavaEvent(ContainerConfigurationEvent.class, emitContainerConfiguration);
137         PeriodicEvents.addJavaEvent(ContainerCPUUsageEvent.class, emitContainerCPUUsage);
138         PeriodicEvents.addJavaEvent(ContainerCPUThrottlingEvent.class, emitContainerCPUThrottling);
139         PeriodicEvents.addJavaEvent(ContainerMemoryUsageEvent.class, emitContainerMemoryUsage);
140         PeriodicEvents.addJavaEvent(ContainerIOUsageEvent.class, emitContainerIOUsage);
141     }
142 
143     private static void registerEvent(Class<? extends jdk.internal.event.Event> eventClass) {
144         MetadataRepository.getInstance().register(eventClass);
145     }
146 
147     private static void emitExceptionStatistics() {
148         ThrowableTracer.emitStatistics();
149     }
150 
151     private static void emitContainerConfiguration() {
152         if (containerMetrics != null) {
153             ContainerConfigurationEvent t = new ContainerConfigurationEvent();
154             t.containerType = containerMetrics.getProvider();
155             t.cpuSlicePeriod = containerMetrics.getCpuPeriod();
156             t.cpuQuota = containerMetrics.getCpuQuota();
157             t.cpuShares = containerMetrics.getCpuShares();
158             t.effectiveCpuCount = containerMetrics.getEffectiveCpuCount();
159             t.memorySoftLimit = containerMetrics.getMemorySoftLimit();
160             t.memoryLimit = containerMetrics.getMemoryLimit();
161             t.swapMemoryLimit = containerMetrics.getMemoryAndSwapLimit();
162             t.hostTotalMemory = JVM.hostTotalMemory();
163             t.hostTotalSwapMemory = JVM.hostTotalSwapMemory();
164             t.commit();
165         }
166     }
167 
168     private static void emitContainerCPUUsage() {
169         if (containerMetrics != null) {
170             ContainerCPUUsageEvent event = new ContainerCPUUsageEvent();
171 
172             event.cpuTime = containerMetrics.getCpuUsage();
173             event.cpuSystemTime = containerMetrics.getCpuSystemUsage();
174             event.cpuUserTime = containerMetrics.getCpuUserUsage();
175             event.commit();
176         }
177     }
178     private static void emitContainerMemoryUsage() {
179         if (containerMetrics != null) {
180             ContainerMemoryUsageEvent event = new ContainerMemoryUsageEvent();
181 
182             event.memoryFailCount = containerMetrics.getMemoryFailCount();
183             event.memoryUsage = containerMetrics.getMemoryUsage();
184             event.swapMemoryUsage = containerMetrics.getMemoryAndSwapUsage();
185             event.commit();
186         }
187     }
188 
189     private static void emitContainerIOUsage() {
190         if (containerMetrics != null) {
191             ContainerIOUsageEvent event = new ContainerIOUsageEvent();
192 
193             event.serviceRequests = containerMetrics.getBlkIOServiceCount();
194             event.dataTransferred = containerMetrics.getBlkIOServiced();
195             event.commit();
196         }
197     }
198 
199     private static void emitContainerCPUThrottling() {
200         if (containerMetrics != null) {
201             ContainerCPUThrottlingEvent event = new ContainerCPUThrottlingEvent();
202 
203             event.cpuElapsedSlices = containerMetrics.getCpuNumPeriods();
204             event.cpuThrottledSlices = containerMetrics.getCpuNumThrottled();
205             event.cpuThrottledTime = containerMetrics.getCpuThrottledTime();
206             event.commit();
207         }
208     }
209 
210     public static void remove() {
211         PeriodicEvents.removeEvent(emitExceptionStatistics);
212         PeriodicEvents.removeEvent(emitDirectBufferStatistics);
213         PeriodicEvents.removeEvent(emitInitialSecurityProperties);
214         PeriodicEvents.removeEvent(emitMethodTiming);
215 
216         PeriodicEvents.removeEvent(emitContainerConfiguration);
217         PeriodicEvents.removeEvent(emitContainerCPUUsage);
218         PeriodicEvents.removeEvent(emitContainerCPUThrottling);
219         PeriodicEvents.removeEvent(emitContainerMemoryUsage);
220         PeriodicEvents.removeEvent(emitContainerIOUsage);
221     }
222 
223     private static void emitDirectBufferStatistics() {
224         DirectBufferStatisticsEvent e = new DirectBufferStatisticsEvent();
225         e.commit();
226     }
227 
228     private static void emitInitialSecurityProperties() {
229         Properties p = SharedSecrets.getJavaSecurityPropertiesAccess().getInitialProperties();
230         if (p != null) {
231             for (String key : p.stringPropertyNames()) {
232                 InitialSecurityPropertyEvent e = new InitialSecurityPropertyEvent();
233                 e.key = key;
234                 e.value = p.getProperty(key);
235                 e.commit();
236             }
237         }
238     }
239 
240     private static void emitMethodTiming() {
241         if (MethodSetting.isInitialized() && MethodTimingEvent.enabled()) {
242             PlatformTracer.emitTiming();
243         }
244     }
245 }