All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ajjpj.asysmon.impl.ASysMonImpl Maven / Gradle / Ivy

There is a newer version: 1.0-pre28
Show newest version
package com.ajjpj.asysmon.impl;

import com.ajjpj.abase.collection.immutable.AList;
import com.ajjpj.asysmon.ASysMonApi;
import com.ajjpj.asysmon.config.ASysMonAware;
import com.ajjpj.asysmon.config.ASysMonConfig;
import com.ajjpj.asysmon.config.log.ASysMonLogger;
import com.ajjpj.asysmon.config.presentation.APresentationMenuEntry;
import com.ajjpj.asysmon.config.presentation.APresentationPageDefinition;
import com.ajjpj.asysmon.data.ACorrelationId;
import com.ajjpj.asysmon.data.AHierarchicalDataRoot;
import com.ajjpj.asysmon.data.AScalarDataPoint;
import com.ajjpj.asysmon.datasink.ADataSink;
import com.ajjpj.asysmon.measure.*;
import com.ajjpj.asysmon.measure.environment.AEnvironmentData;
import com.ajjpj.asysmon.measure.environment.AEnvironmentMeasurer;
import com.ajjpj.asysmon.measure.scalar.AScalarMeasurer;
import com.ajjpj.asysmon.util.AShutdownable;

import java.util.*;


/**
 * This class is the point of contact for an application to ASysMon. There are basically two ways to use it:
 *
 * 
    *
  • Use the static get() method to access it as a singleton. That is simple and convenient, and it is * sufficient for many applications. If it is used that way, all configuration must be done through * the static methods of ADefaultSysMonConfig.
  • *
  • Create and manage your own instance (or instances) by calling the constructor, passing in your * configuration. This is for maximum flexibility, but you lose some convenience.
  • *
* * @author arno */ public class ASysMonImpl implements AShutdownable, ASysMonApi { private static final ASysMonLogger log = ASysMonLogger.get(ASysMonImpl.class); private final ASysMonConfig config; private volatile AList handlers = AList.nil(); private volatile AList scalarMeasurers = AList.nil(); private volatile AList environmentMeasurers = AList.nil(); private final ThreadLocal hierarchyPerThread = new ThreadLocal(); public ASysMonImpl(ASysMonConfig config) { this.config = config; for(AScalarMeasurer m: config.initialScalarMeasurers) { addScalarMeasurer(m); } for(ADataSink h: config.initialDataSinks) { addDataSink(h); } for(AEnvironmentMeasurer m: config.initialEnvironmentMeasurers) { addEnvironmentMeasurer(m); } for(APresentationMenuEntry menuEntry: config.presentationMenuEntries) { for(APresentationPageDefinition pageDef: menuEntry.pageDefinitions) { pageDef.init(this); } } } @Override public ASysMonConfig getConfig() { return config; } private void injectSysMon(Object o) { if(o instanceof ASysMonAware) { ((ASysMonAware) o).setASysMon(this); } } void addScalarMeasurer(AScalarMeasurer m) { injectSysMon(m); scalarMeasurers = scalarMeasurers.cons(new RobustScalarMeasurerWrapper(m, config.measurementTimeoutNanos, config.maxNumMeasurementTimeouts)); } void addEnvironmentMeasurer(AEnvironmentMeasurer m) { injectSysMon(m); environmentMeasurers = environmentMeasurers.cons(new RobustEnvironmentMeasurerWrapper(m, config.measurementTimeoutNanos, config.maxNumMeasurementTimeouts)); } void addDataSink(ADataSink handler) { injectSysMon(handler); handlers = handlers.cons(new RobustDataSinkWrapper(handler, config.dataSinkTimeoutNanos, config.maxNumDataSinkTimeouts)); } private ADataSink getCompositeDataSink() { return new ADataSink() { @Override public void onStartedHierarchicalMeasurement(String identifier) { for(RobustDataSinkWrapper handler: handlers) { handler.onStartedHierarchicalMeasurement(identifier); } } @Override public void onFinishedHierarchicalMeasurement(AHierarchicalDataRoot data) { hierarchyPerThread.remove(); for(RobustDataSinkWrapper handler: handlers) { handler.onFinishedHierarchicalMeasurement(data); } } @Override public void shutdown() { } }; } private AMeasurementHierarchy getMeasurementHierarchy(boolean create) { final AMeasurementHierarchy candidate = hierarchyPerThread.get(); if(candidate != null || ! create) { return candidate; } final AMeasurementHierarchy result = new AMeasurementHierarchyImpl(config, getCompositeDataSink()); hierarchyPerThread.set(result); return result; } @Override public void measure(String identifier, AMeasureCallbackVoid callback) throws E { final ASimpleMeasurement m = start(identifier); try { callback.call(m); } finally { m.finish(); } } @Override public R measure(String identifier, AMeasureCallback callback) throws E { final ASimpleMeasurement m = start(identifier); try { return callback.call(m); } finally { m.finish(); } } @Override public ASimpleMeasurement start(String identifier) { return start(identifier, true); } @Override public ASimpleMeasurement start(String identifier, boolean serial) { return getMeasurementHierarchy(true).start(identifier, serial); } @Override public boolean hasRunningMeasurement() { return getMeasurementHierarchy(false) != null; } @Override public void startFlow(ACorrelationId flowId) { final AMeasurementHierarchy h = getMeasurementHierarchy(false); if(h == null) { throw new IllegalStateException("flow handling only while a measurement is running"); } h.onStartFlow(flowId); } @Override public void joinFlow(ACorrelationId flowId) { final AMeasurementHierarchy h = getMeasurementHierarchy(false); if(h == null) { throw new IllegalStateException("flow handling only while a measurement is running"); } h.onJoinFlow(flowId); } /** * This is for the rare case that measurement data was collected by other means and should be 'injected' * into A-SysMon. If you do not understand this, this method is probably not for you. */ @Override public void injectSyntheticMeasurement(AHierarchicalDataRoot d) { getCompositeDataSink().onStartedHierarchicalMeasurement(d.getRootNode().getIdentifier()); getCompositeDataSink().onFinishedHierarchicalMeasurement(d); } @Override public ACollectingMeasurement startCollectingMeasurement(String identifier) { return startCollectingMeasurement(identifier, true); } @Override public ACollectingMeasurement startCollectingMeasurement(String identifier, boolean serial) { return getMeasurementHierarchy(true).startCollectingMeasurement(identifier, serial); } @Override public Map getScalarMeasurements() { return getScalarMeasurements(config.averagingDelayForScalarsMillis); } @Override public Map getScalarMeasurements(int averagingDelayForScalarsMillis) { final Map result = new TreeMap(); if(ASysMonConfig.isGloballyDisabled()) { return result; } final Map mementos = new TreeMap(); for(RobustScalarMeasurerWrapper measurer: scalarMeasurers) { measurer.prepareMeasurements(mementos); } try { Thread.sleep(averagingDelayForScalarsMillis); } catch (InterruptedException e) { // } final long now = System.currentTimeMillis(); for(RobustScalarMeasurerWrapper measurer: scalarMeasurers) { measurer.contributeMeasurements(result, now, mementos); } return result; } @Override public List getEnvironmentMeasurements() { final List result = new ArrayList(); if(ASysMonConfig.isGloballyDisabled()) { return result; } for(RobustEnvironmentMeasurerWrapper m: environmentMeasurers) { m.contributeMeasurements(new AEnvironmentMeasurer.EnvironmentCollector(result)); } return result; } @Override public void shutdown() { log.info("shutting down A-SysMon"); for(RobustDataSinkWrapper handler: handlers) { handler.shutdown(); } for (RobustScalarMeasurerWrapper m: scalarMeasurers) { m.shutdown(); } for(RobustEnvironmentMeasurerWrapper m: environmentMeasurers) { m.shutdown(); } log.info("finished shutting down A-SysMon"); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy