001/*
002 * ============================================================================
003 * Copyright © 2002-2026 by Thomas Thrien.
004 * All Rights Reserved.
005 * ============================================================================
006 * Licensed to the public under the agreements of the GNU Lesser General Public
007 * License, version 3.0 (the "License"). You may obtain a copy of the License at
008 *
009 *      http://www.gnu.org/licenses/lgpl.html
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014 * License for the specific language governing permissions and limitations
015 * under the License.
016 */
017
018package org.tquadrat.foundation.perflog.remote;
019
020import static org.apiguardian.api.API.Status.STABLE;
021import static org.tquadrat.foundation.mgmt.JMXUtils.composeServiceURL;
022
023import javax.management.AttributeNotFoundException;
024import javax.management.DynamicMBean;
025import javax.management.InstanceNotFoundException;
026import javax.management.IntrospectionException;
027import javax.management.MBeanException;
028import javax.management.MBeanInfo;
029import javax.management.NotificationListener;
030import javax.management.ObjectName;
031import javax.management.ReflectionException;
032import javax.management.remote.JMXServiceURL;
033import java.io.IOException;
034import java.net.MalformedURLException;
035
036import org.apiguardian.api.API;
037import org.tquadrat.foundation.annotation.ClassVersion;
038import org.tquadrat.foundation.perflog.remote.internal.PerfLogRemoteImpl;
039
040/**
041 *  <p>{@summary The declaration of a remote client for the Foundation
042 *  Performance Logging and Monitoring.}</p>
043 *
044 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
045 *  @version $Id: PerfLogRemote.java 1248 2026-05-17 11:08:34Z tquadrat $
046 *  @since 0.25.0
047 *
048 *  @UMLGraph.link
049 */
050@ClassVersion( sourceVersion = "$Id: PerfLogRemote.java 1248 2026-05-17 11:08:34Z tquadrat $" )
051@API( status = STABLE, since = "0.25.0" )
052public sealed interface PerfLogRemote extends AutoCloseable
053    permits PerfLogRemoteImpl
054{
055        /*-----------*\
056    ====** Constants **========================================================
057        \*-----------*/
058    /**
059     *  <p>{@summary The domain name part of the
060     *  {@link ObjectName}
061     *  identifying the Performance Logging MBean
062     *  in the MBean server: {@value}}.</p>
063     */
064    public static final String DOMAIN_NAME = "org.tquadrat.foundation.PerfLog";
065
066    /**
067     *  The name of the JSON boolean that holds the aborted flag:
068     *  {@value}.
069     */
070    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
071    public static final String JSONField_Aborted = "IsAborted";
072
073    /**
074     *  The name of the JSON Number that holds the number of aborted runs for
075     *  the performance section: {@value}.
076     */
077    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
078    public static final String JSONField_AbortedRuns = "Aborted";
079
080    /**
081     *  The name of the JSON String that holds the cause for the abort of a
082     *  performance section: {@value}.
083     */
084    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
085    public static final String JSONField_Cause = "Cause";
086
087    /**
088     *  The name of the JSON Number that holds the number of completed runs for
089     *  the performance section: {@value}.
090     */
091    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
092    public static final String JSONField_CompletedRuns = "Completed";
093
094    /**
095     *  The name of the JSON Object that holds the performance section context:
096     *  {@value}.
097     */
098    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
099    public static final String JSONField_Context = "Context";
100
101    /**
102     *  The name of the JSON Object that holds the elapsed time: {@value}.
103     */
104    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
105    public static final String JSONField_ElapsedTime = "ElapsedTime";
106
107    /**
108     *  The name of the JSON Object that holds an error message: {@value}.
109     */
110    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
111    public static final String JSONField_Error = "Error";
112
113    /**
114     *  The name of the JSON boolean that holds threshold exceeded flag:
115     *  {@value}.
116     */
117    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
118    public static final String JSONField_ExceededThreshold = "ExceededThreshold";
119
120    /**
121     *  The name of the JSON String that holds the time of the first start of
122     *  the performance section: {@value}.
123     */
124    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
125    public static final String JSONField_FirstStart = "FirstStart";
126
127    /**
128     *  The name of the JSON String that holds the time when the performance
129     *  section was last updated: {@value}.
130     */
131    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
132    public static final String JSONField_LastUpdated = "LastUpdated";
133
134    /**
135     *  The name of the JSON String that holds the text of an error message:
136     *  {@value}.
137     */
138    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
139    public static final String JSONField_Message = "Message";
140
141    /**
142     *  The name of the JSON Object that holds the data from the performance
143     *  section: {@value}.
144     */
145    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
146    public static final String JSONField_Section = "PerformanceSection";
147
148    /**
149     *  The name of the JSON String that holds the description of the
150     *  performance section: {@value}.
151     */
152    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
153    public static final String JSONField_SectionDescription = "Description";
154
155    /**
156     *  The name of the JSON Boolean that holds the flag indicating whether the
157     *  performance section is currently ignored: {@value}.
158     */
159    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
160    public static final String JSONField_SectionIgnored = "Ignored";
161
162    /**
163     *  The name of the JSON String that holds the name of the performance
164     *  section: {@value}.
165     */
166    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
167    public static final String JSONField_SectionName = "Name";
168
169    /**
170     *  The name of the JSON Object that holds the execution statistics of the
171     *  performance section: {@value}.
172     */
173    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
174    public static final String JSONField_SectionStatistics = "Statistics";
175
176    /**
177     *  The name of the JSON Object that holds the threshold time from the
178     *  performance section: {@value}.
179     */
180    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
181    public static final String JSONField_SectionThreshold = "Threshold";
182
183    /**
184     *  The name of the JSON boolean that holds the flag indicating whether a
185     *  report should be sent only when the threshold was exceeded: {@value}.
186     */
187    @SuppressWarnings( {"StaticMethodOnlyUsedInOneClass", "FieldNamingConvention"} )
188    public static final String JSONField_SectionThresholdOnlyReport = "ThresholdOnlyReport";
189
190    /**
191     *  The name of the JSON Object that holds the timeout time from the
192     *  performance section: {@value}.
193     */
194    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
195    public static final String JSONField_SectionTimeout = "Timeout";
196
197    /**
198     *  The name of the JSON String that holds the time when the performance
199     *  section was entered: {@value}.
200     */
201    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
202    public static final String JSONField_StartTime = "StartTime";
203
204    /**
205     *  The name of the JSON Object that holds a success message: {@value}.
206     */
207    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
208    public static final String JSONField_Success = "Success";
209
210    /**
211     *  The name of the JSON Number that holds the number of performance
212     *  section runs where the threshold was exceeded: {@value}.
213     */
214    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
215    public static final String JSONField_ThresholdExceededRuns = "ThresholdExceeded";
216
217    /**
218     *  The name of the JSON boolean that holds timed out flag: {@value}.
219     */
220    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
221    public static final String JSONField_TimedOut = "IsTimedOut";
222
223    /**
224     *  The name of the JSON Number that holds the number of performance
225     *  section runs that timed out: {@value}.
226     */
227    @SuppressWarnings( "StaticMethodOnlyUsedInOneClass" )
228    public static final String JSONField_TimedOutRuns = "TimedOut";
229
230    /**
231     *  The name of the JSON String that holds the unit for the dimension from
232     *  a dimensioned value: {@value}.
233     *
234     *  @see #JSONField_SectionThreshold
235     *  @see #JSONField_SectionTimeout
236     */
237    @SuppressWarnings( {"StaticMethodOnlyUsedInOneClass", "unused"} )
238    public static final String JSONField_Unit = "Unit";
239
240    /**
241     *  The name of the JSON Number that holds the value from a dimensioned
242     *  value: {@value}.
243     *
244     *  @see #JSONField_SectionThreshold
245     *  @see #JSONField_SectionTimeout
246     */
247    @SuppressWarnings( "unused" )
248    public static final String JSONField_Value = "Value";
249
250    /**
251     *  The type for the
252     *  {@link ObjectName}
253     *  identifying the Performance Logging MBean
254     *  in the MBean server: {@value}.
255     */
256    public static final String MBEAN_TYPE = "PerformanceLogging";
257
258    /**
259     *  The type for the
260     *  {@link javax.management.Notification}
261     *  instances emitted by Performance Logging MBean: {@value}.
262     */
263    public static final String NOTIFICATION_Type = "org.tquadrat.foundation.perflog.SectionExec";
264
265        /*---------*\
266    ====** Methods **==========================================================
267        \*---------*/
268    /**
269     *  {@inheritDoc}
270     */
271    @Override
272    public void close();
273
274    /**
275     *  <p>{@summary Connects to the Performance Logging MBean specified
276     *  through the given port number and the
277     *  {@link ObjectName}
278     *  returned by
279     *  {@link #getPerfLogMBeanObjectName()}.}</p>
280     *  <p>This method creates a local connection (both processes are running
281     *  on the same machine).</p>
282     *
283     *  @param  registryPort    The number of the registry port.
284     *  @param  listener    The notification listener.
285     *  @return The {@code PerfLogRemote} instance that manages the connection
286     *      to the performance logging MBean.
287     *  @throws IOException Unable to connect to the MBean server.
288     *  @throws InstanceNotFoundException   There is no performance logging
289     *      MBean registered on the MBean server.
290     */
291    @SuppressWarnings( "ClassReferencesSubclass" )
292    public static PerfLogRemote connect( final int registryPort, final NotificationListener listener ) throws InstanceNotFoundException, IOException
293    {
294        final var url = composeServiceURL( registryPort );
295        final var retValue = PerfLogRemoteImpl.connect( url, listener );
296
297        //---* Done *----------------------------------------------------------
298        return retValue;
299    }   //  connect()
300
301    /**
302     *  <p>{@summary Connects to the Performance Logging MBean specified
303     *  through the given host name, port numbers and the
304     *  {@link ObjectName}
305     *  returned by
306     *  {@link #getPerfLogMBeanObjectName()}.}</p>
307     *  <p>This method creates a remote connection (both processes are probably
308     *  running on different machines).</p>
309     *
310     *  @param  hostName    The host name.
311     *  @param  registryPort    The number of the registry port.
312     *  @param  dataPort    The number of the data port; can be the same as the
313     *      registry port.
314     *  @param  listener    The notification listener.
315     *  @return The {@code PerfLogRemote} instance that manages the connection
316     *      to the performance logging MBean.
317     *  @throws MalformedURLException   It is not possible to compose a valid
318     *      {@link JMXServiceURL}
319     *      with the given {@code hostName}.
320     *  @throws IOException Unable to connect to the MBean server.
321     *  @throws InstanceNotFoundException   There is no performance logging
322     *      MBean registered on the MBean server.
323     */
324    @SuppressWarnings( "ClassReferencesSubclass" )
325    public static PerfLogRemote connect( final String hostName, final int registryPort, final int dataPort, final NotificationListener listener ) throws IOException, InstanceNotFoundException
326    {
327        final var url = composeServiceURL( hostName, registryPort, dataPort );
328        final var retValue = PerfLogRemoteImpl.connect( url, listener );
329
330        //---* Done *----------------------------------------------------------
331        return retValue;
332    }   //  connect()
333
334    /**
335     *  Returns the
336     *  {@link MBeanInfo}
337     *  for the performance logging MBean.
338     *
339     *  @return The {@code MBeanInfo}.
340     *  @throws IllegalStateException   The instance was already closed.
341     *  @throws IntrospectionException  An exception occurred during
342     *      introspection.
343     *  @throws InstanceNotFoundException   The MBean specified was not found.
344     *  @throws ReflectionException An exception occurred when trying to invoke
345     *      the method
346     *      {@link DynamicMBean#getMBeanInfo() getMBeanInfo()} of a
347     *      {@linkplain DynamicMBean Dynamic MBean}.
348     *  @throws IOException A communication problem occurred when talking to
349     *      the MBean server.
350     */
351    public MBeanInfo getMBeanInfo() throws IllegalStateException, ReflectionException, InstanceNotFoundException, IntrospectionException, IOException;
352
353    /**
354     *  Returns the
355     *  {@link ObjectName}
356     *  for the Performance Logging MBean.
357     *
358     *  @return The object name for the MBean.
359     */
360    public static ObjectName getPerfLogMBeanObjectName() { return PerfLogRemoteImpl.getPerfLogMBeanObjectName(); }
361
362    /**
363     *  <p>{@summary Returns the status for the given performance section.}</p>
364     *
365     *  @param  name    The name of the performance section.
366     *  @return The status of the performance section, or a message indicating
367     *      what failed in case of error, as a JSON String.
368     *  @throws IllegalStateException   The instance was already closed.
369     *  @throws ReflectionException An exception occurred when trying to invoke
370     *      the method
371     *      {@link DynamicMBean#getAttribute(String) getAttribute()} of a
372     *      {@linkplain DynamicMBean Dynamic MBean}.
373     *  @throws MBeanException  Wraps an exception thrown by the MBean method.
374     *  @throws InstanceNotFoundException   The MBean specified was not found.
375     *  @throws IOException A communication problem occurred when talking to
376     *      the MBean server.
377     */
378    public String getPerformanceSection( final String name ) throws IllegalStateException, ReflectionException, InstanceNotFoundException, MBeanException, IOException;
379
380    /**
381     *  <p>{@summary Returns a list of the currently defined performance
382     *  sections.}</p>
383     *
384     *  @return The list of the performance section names.
385     *  @throws IllegalStateException   The instance was already closed.
386     *  @throws ReflectionException An exception occurred when trying to invoke
387     *      the method
388     *      {@link DynamicMBean#getAttribute(String) getAttribute()} of a
389     *      {@linkplain DynamicMBean Dynamic MBean}.
390     *  @throws MBeanException  Wraps an exception thrown by the MBean method.
391     *  @throws InstanceNotFoundException   The MBean specified was not found.
392     *  @throws AttributeNotFoundException  The attribute was missing.
393     *  @throws IOException A communication problem occurred when talking to
394     *      the MBean server.
395     */
396    @SuppressWarnings( "MethodWithTooExceptionsDeclared" )
397    public String [] getPerformanceSections() throws IllegalStateException, ReflectionException, AttributeNotFoundException, InstanceNotFoundException, MBeanException, IOException;
398}
399//  interface PerfLogRemote
400
401/*
402 *  End of File
403 */