Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.nerdvision.agent.AgentImpl Maven / Gradle / Ivy
package com.nerdvision.agent;
import com.nerdvision.agent.api.INVError;
import com.nerdvision.agent.api.INerdVision;
import com.nerdvision.agent.api.INerdVisionHook;
import com.nerdvision.agent.api.decorators.IDecorator;
import com.nerdvision.agent.api.logging.ILogger;
import com.nerdvision.agent.api.reflection.IReflection;
import com.nerdvision.agent.inst.InstrumentationBreakpointService;
import com.nerdvision.agent.inst.PluginTransformer;
import com.nerdvision.agent.snapshot.Callback;
import com.nerdvision.agent.snapshot.EventSnapshot;
import com.nerdvision.agent.snapshot.NVError;
import java.lang.instrument.Instrumentation;
import java.util.Date;
import java.util.Map;
import java.util.UUID;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.logging.ConsoleHandler;
import java.util.logging.Level;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import static com.nerdvision.agent.ClientReg.backoff;
public class AgentImpl
{
public static final String PRODUCT_NAME = "nerd.vision";
private static volatile boolean shutdown = false;
private static Logger logger;
static IBreakpointService breakpointService;
private static Thread thread;
static ClientReg clientReg;
private static HTTPClient httpClient;
private static Settings settings;
static ClientConfig clientConfig;
public static void startup( final JarFile jarFile, final Instrumentation inst, final Map args )
{
final Attributes manifest = getManifest( jarFile );
settings = Settings.build( args );
logger = configureLogging( settings );
announceClient( manifest, logger );
clientConfig = new ClientConfig();
final String uuid = UUID.randomUUID().toString();
httpClient = new HTTPClient( uuid, settings.getSettingAs( "api.key", String.class ), clientConfig );
clientReg = new ClientReg( settings, manifest, jarFile.getName(), uuid, httpClient );
final Boolean lambdaSetting = settings.getSettingAs( "lambda", Boolean.class );
final Boolean lambda = lambdaSetting == null ? Boolean.FALSE : lambdaSetting;
breakpointService = new InstrumentationBreakpointService( inst, settings );
// TODO: 16.07.21 Can we scan the jarFile for plugins ? see FR MixinTransformer2
PluginTransformer.init( inst, settings );
Callback.init( settings, breakpointService, httpClient, clientConfig, lambda );
final ThreadGroup threadGroup = new ThreadGroup( PRODUCT_NAME );
thread = createThread( threadGroup, lambda, clientReg, settings, breakpointService, logger );
thread.setDaemon( true );
thread.setName( PRODUCT_NAME );
thread.start();
@SuppressWarnings("Convert2Lambda")
final Thread hook = new Thread( threadGroup, new Runnable()
{
@Override
public void run()
{
shutdown = true;
thread.interrupt();
}
} );
hook.setName( "nerd.vision shutdown" );
Runtime.getRuntime().addShutdownHook( hook );
if( lambda )
{
try
{
thread.join();
}
catch( InterruptedException e )
{
e.printStackTrace();
}
}
}
static Thread createThread( final ThreadGroup threadGroup,
final Boolean lambda,
final ClientReg clientReg,
final Settings settings,
final IBreakpointService breakpointService,
final Logger logger )
{
if( !lambda )
{
final long backoffMax = settings.getSettingAs( "grpc.backoff.max", long.class );
final double maxMultiplier = settings.getSettingAs( "grpc.backoff.multiplier", double.class );
//noinspection Convert2Lambda
return new Thread( threadGroup, new Runnable()
{
@Override
public void run()
{
final ClientReg.Response session = clientReg.getSessionWithBreakpoints();
logger.debug( "Session id: {}", session.getSession() );
AgentImpl.clientConfig.setSessionId( session.getSession() );
AgentImpl.clientConfig.setTags( session.getTags() );
AgentImpl.clientConfig.update( session.getConfig() );
int cnt = 0;
while( !shutdown )
{
try( final GrpcService grpcService = new GrpcService( settings, AgentImpl.breakpointService, AgentImpl.clientConfig ); )
{
grpcService.connect( session.getSession() );
grpcService.await();
if( !grpcService.hasFailed() )
{
cnt = 0; // reset cnt as we have connected successfully
}
}
catch( Throwable t )
{
t.printStackTrace();
}
finally
{
if( !shutdown )
{
long delay = backoff( cnt++, backoffMax, maxMultiplier );
logger.debug( "Attempting to reconnect GRPC waiting {}", delay );
if( delay > 0 )
{
synchronized( this )
{
try
{
wait( delay * 1000 );
}
catch( InterruptedException e )
{
logger.debug( "Interrupted during wait." );
}
}
}
}
}
}
}
}, "nerd.vision - GRPC" );
}
else
{
//noinspection Convert2Lambda
return new Thread( threadGroup, new Runnable()
{
@Override
public void run()
{
try
{
final ClientReg.Response session = clientReg.getSessionWithBreakpoints();
AgentImpl.clientConfig.setSessionId( session.getSession() );
AgentImpl.clientConfig.setTags( session.getTags() );
AgentImpl.clientConfig.update( session.getConfig() );
breakpointService.processBreakpoints( session.getBreakpoints() );
}
catch( Throwable t )
{
t.printStackTrace();
}
}
}, "nerd.vision - Service Thread" );
}
}
public static Logger configureLogging( final Settings settings )
{
final java.util.logging.Logger logger = java.util.logging.Logger.getLogger( "com.nerdvision" );
logger.setUseParentHandlers( false );
final ConsoleHandler handler = new ConsoleHandler();
logger.addHandler( handler );
final Level settingAs = settings.getSettingAs( "logging.level", Level.class );
handler.setLevel( settingAs );
logger.setLevel( settingAs );
return LoggerFactory.getLogger( AgentImpl.class );
}
public static Object loadNerdVisionAPI()
{
if( clientReg == null )
{
return null;
}
return new INerdVisionHook()
{
@Override
public INerdVision nerdVision()
{
return new INerdVision()
{
@Override
public void updateBreakpoints()
{
try
{
final ClientReg.Response sessionWithBreakpoints = clientReg.getSessionWithBreakpoints();
breakpointService.processBreakpoints( sessionWithBreakpoints.getBreakpoints() );
}
catch( Exception e )
{
e.printStackTrace();
}
}
@Override
public String registerDecorator( final IDecorator decorator )
{
return clientConfig.registerDecorator( decorator );
}
@Override
public void deregisterDecorator( final String id )
{
clientConfig.deregisterDecorator( id );
}
@Override
public void close() throws Exception
{
shutdown = true;
thread.interrupt();
}
@Override
public void captureException( final Throwable t )
{
final INVError invError = NVError.fromThrowable( t, clientConfig.getTags() );
httpClient.postJsonAsync( String.format( "%s", settings.getErrorUrl() ),
JsonUtils.toJson( EventSnapshot.processErrorAsMap( invError ) ),
new HTTPClient.SinkBodyHandler() );
}
@Override
public IVersion version()
{
final Map productData = clientReg.getProductData();
//noinspection Convert2Lambda
return new IVersion()
{
@Override
public String version()
{
return String.valueOf( productData.get( "version" ) );
}
};
}
};
}
@Override
public ILogger logger()
{
return new ILogger()
{
@Override
public void info( final String message, final Object... args )
{
logger.info( message, args );
}
@Override
public void debug( final String message, final Object... args )
{
logger.debug( message, args );
}
@Override
public void error( final String message, final Object... args )
{
logger.error( message, args );
}
};
}
@Override
public IReflection reflection()
{
return Utils.getReflection();
}
};
}
private static Attributes getManifest( final JarFile jarFile )
{
try
{
return jarFile.getManifest().getMainAttributes();
}
catch( Exception e )
{
return new Attributes( 0 );
}
}
private static void announceClient( final Attributes manifest, final Logger logger )
{
announce( logger, "--------------------------------------------------------------------------------------" );
announce( logger,
"nerdvision (" + manifest.getValue( "Version" ) + ") - Copyright (C) Intergral GmbH. All Rights Reserved" );
announceManifestValue( logger, manifest, "Version" );
announceManifestValue( logger, manifest, "Git-Commit-Id" );
announceManifestValue( logger, manifest, "Git-Commit-Time" );
announceManifestValue( logger, manifest, "Git-Branch" );
announce( logger,
"OS : " + System.getProperty( "os.name" ) + " [" + System.getProperty( "os.version" ) + "] "
+ System.getProperty( "os.arch" ) );
announce( logger,
"Java : " + System.getProperty( "java.version" ) + " [" + System.getProperty( "java.vm.version" ) +
"] " + System.getProperty( "java.vm.vendor" ) );
announce( logger, "Start Time : " + new Date() );
announce( logger, "--------------------------------------------------------------------------------------" );
}
private static void announceManifestValue( final Logger logger, final Attributes manifest, final String key )
{
final String s = String.format( "%-16s: %s", key, manifest.getValue( key ) );
announce( logger, s );
}
private static void announce( final Logger logger, final String message )
{
logger.debug( "{}: {}", PRODUCT_NAME, message );
}
}