001/*
002 * ============================================================================
003 * Copyright © 2002-2026 by Thomas Thrien.
004 * All Rights Reserved.
005 * ============================================================================
006 *
007 * Licensed to the public under the agreements of the GNU Lesser General Public
008 * License, version 3.0 (the "License"). You may obtain a copy of the License at
009 *
010 *      http://www.gnu.org/licenses/lgpl.html
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
014 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
015 * License for the specific language governing permissions and limitations
016 * under the License.
017 */
018
019package org.tquadrat.foundation.perflog;
020
021import static org.apiguardian.api.API.Status.STABLE;
022import static org.tquadrat.foundation.lang.Objects.requireNonNullArgument;
023import static org.tquadrat.foundation.perflog.PerformanceTracker.TrackerStatus.STATUS_STARTED;
024
025import org.apiguardian.api.API;
026import org.tquadrat.foundation.annotation.ClassVersion;
027import org.tquadrat.foundation.lang.StringConverter;
028import org.tquadrat.foundation.perflog.PerfLogUtils.PerformanceTrackerHolder;
029import org.tquadrat.foundation.perflog.internal.PerformanceTrackerImpl;
030
031/**
032 *  <p>{@summary This interface describes a performance tracker for the
033 *  Foundation Performance Logging and Monitoring.}</p>
034 *  <p>This is basically collecting the time that is spent within a performance
035 *  section.</p>
036 *  <p>Obviously, an instance of the implementation of this interface is not
037 *  thread-safe, but it can be reused multiple times.</p>
038 *
039 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
040 *  @version $Id: PerformanceTracker.java 1258 2026-06-04 18:33:06Z tquadrat $
041 *  @since 0.25.0
042 *
043 *  @UMLGraph.link
044 */
045@ClassVersion( sourceVersion = "$Id: PerformanceTracker.java 1258 2026-06-04 18:33:06Z tquadrat $" )
046@API( status = STABLE, since = "0.25.0" )
047public sealed interface PerformanceTracker
048    permits PerformanceTrackerHolder, PerformanceTrackerImpl
049{
050        /*---------------*\
051    ====** Inner Classes **====================================================
052        \*---------------*/
053    /**
054     *  <p>{@summary The status of a
055     *  {@link PerformanceTracker}.}</p>
056     *
057     *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
058     *  @version $Id: PerformanceTracker.java 1258 2026-06-04 18:33:06Z tquadrat $
059     *  @since 0.25.0
060     *
061     *  @UMLGraph.link
062     */
063    @ClassVersion( sourceVersion = "$Id: PerformanceTracker.java 1258 2026-06-04 18:33:06Z tquadrat $" )
064    @API( status = STABLE, since = "0.25.0" )
065    public static enum TrackerStatus
066    {
067            /*------------------*\
068        ====** Enum Declaration **=============================================
069            \*------------------*/
070        /**
071         *  The tracker was not started yet.
072         */
073        STATUS_READY,
074
075        /**
076         *  The tracker was started, but not yet stopped or aborted.
077         */
078        STATUS_STARTED,
079
080        /**
081         *  The tracker was stopped after it was started.
082         */
083        STATUS_STOPPED,
084
085        /**
086         *  The tracker was aborted after it was started.
087         */
088        STATUS_ABORTED
089    }
090    //  enum TrackerStatus
091
092        /*---------*\
093    ====** Methods **==========================================================
094        \*---------*/
095    /**
096     *  <p>{@summary Stops the performance timer.}</p>
097     *  <p>If the tracker has been aborted or stopped already, nothing happens.
098     *  Same if it was never started.</p>
099     */
100    public void abort();
101
102    /**
103     *  <p>{@summary Stops the performance timer and takes a message describing
104     *  the reason for the abort.}</p>
105     *  <p>If the tracker has been aborted or stopped already, nothing happens.
106     *  Same if it was never started.</p>
107     *
108     *  @param  message The message describing the reason for the abort.
109     */
110    public void abort( final String message );
111
112    /**
113     *  <p>{@summary Stops the performance timer and takes a message describing
114     *  the reason for the abort, plus the exception that caused it.}</p>
115     *  <p>If the tracker has been aborted or stopped already, nothing happens.
116     *  Same if it was never started.</p>
117     *
118     *  @param  message The message describing the reason for the abort.
119     *  @param  cause   The exception that caused the abort.
120     */
121    public void abort( final String message, final Throwable cause );
122
123    /**
124     *  <p>{@summary Adds context information to this tracker.} This is also
125     *  transferred to the
126     *  {@link PerfLogMBean}
127     *  when the tracker is
128     *  {@linkplain #stop() stopped} or
129     *  {@linkplain #abort() aborted}.</p>
130     *  <p>The given name must conform a valid JSON name and may not start with
131     *  an underscore (&quot;_&quot;/#x005f).</p>
132     *  <p>The given name is unique; if a value is added with an already known
133     *  name, it will overwrite the existing value.</p>
134     *  <p>A call to
135     *  {@link #start()}
136     *  will not reset the context.</p>
137     *  <p>An example on how to use the context may look like this:</p>
138     *  {@include ${javadoc}/sample3c.txt:SOURCE}
139     *
140     *  @param  name    The name of the context value.
141     *  @param  value   The context value; {@null} removes the entry with
142     *      the given name.
143     *  @return This instance.
144     */
145    public PerformanceTracker addContext( final String name, final String value );
146
147    /**
148     *  <p>{@summary Adds context information to this tracker.} This is also
149     *  transferred to the
150     *  {@link PerfLogMBean}
151     *  when the tracker is
152     *  {@linkplain #stop() stopped}.</p>
153     *  <p>The given name is unique; if a value is added with an already known
154     *  name, it will overwrite the existing value.</p>
155     *  <p>A call to
156     *  {@link #start()}
157     *  will not reset the context.</p>
158     *
159     *  @param  <T> The type of the context value.
160     *  @param  name    The name of the context value.
161     *  @param  value   The context value; {@null} removes the entry with
162     *      the given name.
163     *  @param  stringConverter The instance of
164     *      {@link StringConverter}
165     *      that is used to translate the value into a String.
166     *  @return This instance.
167     *
168     *  @see #addContext(String,String)
169     */
170    public default <T> PerformanceTracker addContext( final String name, final T value, final StringConverter<T> stringConverter )
171    {
172        final var retValue = addContext( requireNonNullArgument( name, "name" ), requireNonNullArgument( stringConverter, "stringConverter" ).toString( value ) );
173
174        //---* Done *----------------------------------------------------------
175        return retValue;
176    }   //  addContext
177
178    /**
179     *  Returns the status of this tracker instance.
180     *
181     *  @return The tracker status.
182     */
183    public TrackerStatus getStatus();
184
185    /**
186     *  Checks whether the tracker is active.
187     *
188     *  @return {@true} if the tracker was started, but not yet aborted or
189     *      stopped, {@false} otherwise.
190     */
191    public default boolean isActive() { return getStatus() == STATUS_STARTED; }
192
193    /**
194     *  <p>{@summary Resets the instance.}</p>
195     *  <p>If the tracker was already started, but never stopped or aborted, an
196     *  {@link IllegalStateException}
197     *  is thrown.</p>
198     *
199     *  @param  resetContext    {@true} if also the context should be
200     *      reset, {@false} to keep the current context.
201     *  @throws IllegalStateException   The tracker was already started but not
202     *      stopped or aborted.
203     *  @return This instance.
204     */
205    public PerformanceTracker reset( final boolean resetContext ) throws IllegalStateException;
206
207    /**
208     *  <p>{@summary Resets the instance and starts the performance timer.}</p>
209     *  <p>If the tracker was already started, but never stopped or aborted, an
210     *  {@link IllegalStateException}
211     *  is thrown.</p>
212     *
213     *  @throws IllegalStateException   The tracker was already started but not
214     *      stopped or aborted.
215     */
216    public void start() throws IllegalStateException;
217
218    /**
219     *  <p>{@summary Stops the performance timer and transfers the elapsed time
220     *  to the
221     *  {@link PerfLogMBean}
222     *  for further processing.}</p>
223     *  <p>If the tracker has been aborted already, nothing happens. Same if it
224     *  was never started.</p>
225     *
226     *  @throws IllegalStateException   The tracker was already stopped
227     *      previously.
228     */
229    public void stop() throws IllegalStateException;
230}
231//  interface PerformanceTracker
232
233/*
234 *  End of File
235 */