├── .gitmodules ├── src ├── test │ ├── resources │ │ ├── com │ │ │ └── iopipe │ │ │ │ ├── boolean.json │ │ │ │ ├── empty.json │ │ │ │ ├── integer.json │ │ │ │ ├── string.json │ │ │ │ ├── arrayinteger.json │ │ │ │ ├── arraystring.json │ │ │ │ ├── simplepojo.json │ │ │ │ ├── eventinfo_scheduled.json │ │ │ │ ├── arraysimplepojo.json │ │ │ │ ├── eventinfo_cloudfront.json │ │ │ │ ├── eventinfo_kinesis.json │ │ │ │ ├── eventinfo_sqs.json │ │ │ │ ├── eventinfo_sns.json │ │ │ │ ├── eventinfo_firehose.json │ │ │ │ ├── eventinfo_s3.json │ │ │ │ └── eventinfo_apigateway.json │ │ ├── tinylog.properties │ │ ├── iopipe.properties │ │ ├── META-INF │ │ │ └── services │ │ │ │ └── com.iopipe.plugin.IOpipePlugin │ │ └── log4j2-test.xml │ └── java │ │ └── com │ │ └── iopipe │ │ ├── elsewhere │ │ ├── SomeType.java │ │ ├── package-info.java │ │ ├── ParameterC.java │ │ ├── ParameterD.java │ │ ├── ParameterB.java │ │ ├── Classes.java │ │ ├── ParameterA.java │ │ ├── SimplePOJO.java │ │ ├── PublicClass.java │ │ └── PackagePrivateClass.java │ │ ├── Event.java │ │ ├── GenericEntryPointAWSRequestHandlerTest.java │ │ ├── WrappedResult.java │ │ ├── MockDynamicTest.java │ │ ├── RemoteEngine.java │ │ ├── Value.java │ │ ├── MockConnectionFactory.java │ │ ├── BooleanValue.java │ │ ├── TestExecution.java │ │ ├── RemoteDynamicTest.java │ │ ├── PutEvent.java │ │ ├── __Utils__.java │ │ ├── MockException.java │ │ ├── IntegerValue.java │ │ ├── MockEngine.java │ │ ├── __DoEmptyMethod__.java │ │ ├── __DoThrowException__.java │ │ ├── __DoRecursive__.java │ │ ├── TestPlugin.java │ │ ├── WrappedRequest.java │ │ ├── __DoInvalidToken__.java │ │ ├── __DoLongValueCustomMetric__.java │ │ ├── __DoLabel__.java │ │ ├── __DoConfigFileTest__.java │ │ ├── __DoLongNameCustomMetric__.java │ │ ├── __DoColdStartAutoLabel__.java │ │ ├── __DoDiskReportCheck__.java │ │ ├── __DoGenericHandler__.java │ │ ├── __DoCustomMetric__.java │ │ ├── __DoGenericObjectTranslate__.java │ │ ├── MockConnection.java │ │ ├── SignerEvent.java │ │ ├── __DoGenericEntryPoint__.java │ │ ├── __DoGenericStreamHandler__.java │ │ ├── __DoPluginTest__.java │ │ └── __DoTimeOut__.java └── main │ ├── resources │ └── com │ │ └── iopipe │ │ └── currentversion │ └── java │ └── com │ └── iopipe │ ├── generic │ ├── package-info.java │ ├── __IdentityConvert__.java │ ├── InvalidEntryPointException.java │ ├── __FunctionConvert__.java │ ├── __JacksonConvert__.java │ ├── __StringToConvert__.java │ └── GenericAWSRequestStreamHandler.java │ ├── plugin │ ├── logger │ │ ├── package-info.java │ │ └── LoggerPlugin.java │ ├── trace │ │ ├── package-info.java │ │ ├── TraceExecution.java │ │ ├── TracePlugin.java │ │ └── TraceMeasurement.java │ ├── package-info.java │ ├── eventinfo │ │ ├── package-info.java │ │ ├── FirehoseDecoder.java │ │ ├── ScheduledDecoder.java │ │ ├── KinesisDecoder.java │ │ ├── APIGatewayDecoder.java │ │ ├── EventInfoDecoder.java │ │ ├── SQSDecoder.java │ │ ├── SNSDecoder.java │ │ ├── EventInfoExecution.java │ │ ├── EventInfoPlugin.java │ │ ├── ValueAcceptor.java │ │ ├── CloudFrontDecoder.java │ │ └── S3Decoder.java │ ├── profiler │ │ ├── package-info.java │ │ ├── __SnapshotConstants__.java │ │ ├── TrackedThreadNodeTraversal.java │ │ ├── TimeKeeper.java │ │ ├── MemoryUsageStatistics.java │ │ ├── UptimeStatistics.java │ │ ├── CompilerStatistics.java │ │ ├── MemoryStatistics.java │ │ ├── ClassLoaderStatistics.java │ │ ├── Tracker.java │ │ ├── ProfilerPlugin.java │ │ ├── GarbageCollectorStatistics.java │ │ ├── BufferPoolStatistics.java │ │ └── __Poller__.java │ ├── IOpipePluginPreExecutable.java │ ├── IOpipePluginPostExecutable.java │ ├── NoSuchPluginException.java │ ├── IOpipePluginExecution.java │ └── IOpipePlugin.java │ ├── http │ ├── package-info.java │ ├── RequestType.java │ ├── NullConnectionFactory.java │ ├── NullConnection.java │ ├── RemoteException.java │ ├── RemoteConnectionFactory.java │ ├── ServiceConnectionFactory.java │ ├── RemoteConnection.java │ ├── RemoteRequest.java │ ├── ServiceConnection.java │ └── RemoteResult.java │ ├── package-info.java │ ├── IOpipeTimeOutException.java │ ├── __SignerRemote__.java │ ├── __Shared__.java │ ├── IOpipeWrappedException.java │ ├── IOpipeFatalError.java │ ├── SimpleRequestHandlerWrapper.java │ ├── SimpleRequestStreamHandlerWrapper.java │ └── __RequestSender__.java ├── settings.xml ├── .circleci ├── latestlayerversion.sh ├── layers.sh └── config.yml ├── .gitignore ├── .version-rules.xml └── CODE_OF_CONDUCT.md /.gitmodules: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/test/resources/com/iopipe/boolean.json: -------------------------------------------------------------------------------- 1 | true 2 | -------------------------------------------------------------------------------- /src/test/resources/com/iopipe/empty.json: -------------------------------------------------------------------------------- 1 | { 2 | } 3 | 4 | -------------------------------------------------------------------------------- /src/test/resources/com/iopipe/integer.json: -------------------------------------------------------------------------------- 1 | 1234567890 2 | -------------------------------------------------------------------------------- /src/main/resources/com/iopipe/currentversion: -------------------------------------------------------------------------------- 1 | ${project.version} 2 | -------------------------------------------------------------------------------- /src/test/resources/com/iopipe/string.json: -------------------------------------------------------------------------------- 1 | "Squirrels are cute!" 2 | -------------------------------------------------------------------------------- /src/test/resources/tinylog.properties: -------------------------------------------------------------------------------- 1 | tinylog.level = debug 2 | 3 | -------------------------------------------------------------------------------- /src/test/resources/iopipe.properties: -------------------------------------------------------------------------------- 1 | com.iopipe.cutestanimal = squirrel 2 | 3 | -------------------------------------------------------------------------------- /src/test/resources/META-INF/services/com.iopipe.plugin.IOpipePlugin: -------------------------------------------------------------------------------- 1 | com.iopipe.TestPlugin 2 | -------------------------------------------------------------------------------- /src/test/resources/com/iopipe/arrayinteger.json: -------------------------------------------------------------------------------- 1 | [ 2 | 1, 3 | 2, 4 | 3, 5 | 4 6 | ] 7 | 8 | -------------------------------------------------------------------------------- /src/test/resources/com/iopipe/arraystring.json: -------------------------------------------------------------------------------- 1 | [ 2 | "hello", 3 | "squirrels", 4 | "are", 5 | "cute" 6 | ] 7 | 8 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/elsewhere/SomeType.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.elsewhere; 2 | 3 | public class SomeType 4 | { 5 | } 6 | 7 | -------------------------------------------------------------------------------- /src/test/resources/com/iopipe/simplepojo.json: -------------------------------------------------------------------------------- 1 | { 2 | "favorite-animal":"squirrel", 3 | "favoriteFood":"acorn", 4 | "favorite-Number":29, 5 | "day-of-week":"Monday" 6 | } 7 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/generic/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package contains generic entry points. 3 | * 4 | * @since 2018/08/13 5 | */ 6 | 7 | package com.iopipe.generic; 8 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/logger/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package contains the logger plugin. 3 | * 4 | * @since 2018/09/20 5 | */ 6 | 7 | package com.iopipe.plugin.logger; 8 | 9 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/Event.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | /** 4 | * This represents an event. 5 | * 6 | * @since 2018/07/16 7 | */ 8 | public interface Event 9 | { 10 | } 11 | 12 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/trace/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This contains the trace plugin implementation. 3 | * 4 | * @since 2018/01/20 5 | */ 6 | 7 | package com.iopipe.plugin.trace; 8 | 9 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/elsewhere/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package contains entry points for methods which are outside of the 3 | * IOpipe package. 4 | * 5 | * @since 2018/08/13 6 | */ 7 | 8 | package com.iopipe.elsewhere; 9 | 10 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/http/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package contains the IOpipe specific classes and interfaces for 3 | * communicating with the remote IOpipe service. 4 | * 5 | * @since 2017/12/17 6 | */ 7 | 8 | package com.iopipe.http; 9 | 10 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package contains the support for plugins which may be used to add 3 | * functionality so that the client may utilize more monitoring tools. 4 | * 5 | * @since 2018/01/20 6 | */ 7 | 8 | package com.iopipe.plugin; 9 | 10 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/eventinfo/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package contains the event info plugin which is used as a means to 3 | * help determine where an invocation has come from. 4 | * 5 | * @since 2018/04/13 6 | */ 7 | 8 | package com.iopipe.plugin.eventinfo; 9 | 10 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/http/RequestType.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.http; 2 | 3 | /** 4 | * This is used to specify the type of request to make to the remote server. 5 | * 6 | * @since 2018/02/24 7 | */ 8 | public enum RequestType 9 | { 10 | /** HTTP POST. */ 11 | POST, 12 | 13 | /** HTTP PUT. */ 14 | PUT, 15 | 16 | /** End. */ 17 | ; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/profiler/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package contains the profiler plugin which is used to profile code 3 | * executions made by user code. 4 | * 5 | * The profiler outputs to the format which is used by VisualVM and as such 6 | * can be viewed by it. 7 | * 8 | * @since 2018/02/07 9 | */ 10 | 11 | package com.iopipe.plugin.profiler; 12 | 13 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/elsewhere/ParameterC.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.elsewhere; 2 | 3 | import com.iopipe.IOpipeExecution; 4 | 5 | public class ParameterC 6 | extends ParameterB 7 | { 8 | @Override 9 | public void normalCall(SimplePOJO __a) 10 | { 11 | IOpipeExecution.currentExecution().customMetric("parmc", 12 | (__a == null ? "null" : __a.getClass().getName())); 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/elsewhere/ParameterD.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.elsewhere; 2 | 3 | import com.iopipe.IOpipeExecution; 4 | 5 | public class ParameterD 6 | extends ParameterA 7 | { 8 | @Override 9 | public void normalCall(SimplePOJO __a) 10 | { 11 | IOpipeExecution.currentExecution().customMetric("parmd", 12 | (__a == null ? "null" : __a.getClass().getName())); 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/elsewhere/ParameterB.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.elsewhere; 2 | 3 | import com.iopipe.IOpipeExecution; 4 | 5 | public class ParameterB 6 | extends ParameterA 7 | { 8 | @Override 9 | public void normalCall(C __a) 10 | { 11 | IOpipeExecution.currentExecution().customMetric("parmb", 12 | (__a == null ? "null" : __a.getClass().getName())); 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/test/resources/com/iopipe/eventinfo_scheduled.json: -------------------------------------------------------------------------------- 1 | { 2 | "account": "123456789012", 3 | "region": "us-east-1", 4 | "detail": {}, 5 | "detailType": "Scheduled Event", 6 | "source": "aws.events", 7 | "time": "1970-01-01T00:00:00Z", 8 | "id": "cdc73f9d-aea9-11e3-9d5a-835b769c0d9c", 9 | "resources": [ 10 | "arn:aws:events:us-east-1:123456789012:rule/my-schedule" 11 | ] 12 | } 13 | 14 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/elsewhere/Classes.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.elsewhere; 2 | 3 | /** 4 | * Contains references to the test classes. 5 | * 6 | * @since 2018/08/14 7 | */ 8 | public final class Classes 9 | { 10 | /** The package private class. */ 11 | public static final Class PACKAGE_PRIVATE = 12 | PackagePrivateClass.class; 13 | 14 | /** The public class. */ 15 | public static final Class PUBLIC = 16 | PublicClass.class; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package contians the classes and interfaces which are used to interact 3 | * with the IOpipe service. 4 | * 5 | * The {@link com.amazonaws.services.lambda.runtime.Context} object can be 6 | * obtained by invoking the {@link com.iopipe.IOpipeExecution#context()} 7 | * method in the instance of an {@link com.iopipe.IOpipeExecution}. 8 | * 9 | * @since 2017/12/12 10 | */ 11 | 12 | package com.iopipe; 13 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/IOpipeTimeOutException.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | /** 4 | * This is used when a request being executed has timed out. 5 | * 6 | * @since 2017/12/16 7 | */ 8 | public class IOpipeTimeOutException 9 | extends RuntimeException 10 | { 11 | /** 12 | * Initializes the exception with the given message. 13 | * 14 | * @param __m The message to use. 15 | * @since 2017/12/16 16 | */ 17 | public IOpipeTimeOutException(String __m) 18 | { 19 | super(__m); 20 | } 21 | } 22 | 23 | -------------------------------------------------------------------------------- /src/test/resources/log4j2-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/GenericEntryPointAWSRequestHandlerTest.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import org.junit.jupiter.api.Test; 4 | 5 | import static org.junit.jupiter.api.Assertions.*; 6 | 7 | /** 8 | * This tests the generic AWS request handler. 9 | * 10 | * @since 2018/08/13 11 | */ 12 | public class GenericEntryPointAWSRequestHandlerTest 13 | { 14 | /** 15 | * Tests the generic entry point. 16 | * 17 | * @since 2018/08/13 18 | */ 19 | @Test 20 | public void test() 21 | { 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | bintray 7 | ${env.BINTRAY_USER} 8 | ${env.BINTRAY_API_KEY} 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/test/resources/com/iopipe/arraysimplepojo.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "favorite-animal":"squirrel", 4 | "favoriteFood":"acorn", 5 | "favorite-Number":29, 6 | "day-of-week":"Monday" 7 | }, 8 | { 9 | "favorite-animal":"squirrels", 10 | "favoriteFood":"acorns", 11 | "favorite-Number":30, 12 | "day-of-week":"Tuesday" 13 | }, 14 | { 15 | "favorite-animal":"squirrelss", 16 | "favoriteFood":"acornss", 17 | "favorite-Number":31, 18 | "day-of-week":"Wednesday" 19 | }, 20 | { 21 | "favorite-animal":"squirrelsss", 22 | "favoriteFood":"acornsss", 23 | "favorite-Number":32, 24 | "day-of-week":"Thursday" 25 | } 26 | ] 27 | -------------------------------------------------------------------------------- /.circleci/latestlayerversion.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | REGIONS=( 4 | ap-northeast-1 5 | ap-northeast-2 6 | ap-south-1 7 | ap-southeast-1 8 | ap-southeast-2 9 | ca-central-1 10 | eu-central-1 11 | eu-west-1 12 | eu-west-2 13 | eu-west-3 14 | #sa-east-1 15 | us-east-1 16 | us-east-2 17 | us-west-1 18 | us-west-2 19 | ) 20 | 21 | echo "" 22 | echo "java8:" 23 | echo "" 24 | 25 | for region in "${REGIONS[@]}"; do 26 | latest_arn=$(aws --region $region lambda list-layer-versions --layer-name IOpipeJava8 --output text --query "LayerVersions[0].LayerVersionArn") 27 | echo "* ${region}: \`${latest_arn}\`" 28 | done 29 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/http/NullConnectionFactory.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.http; 2 | 3 | import javax.json.JsonValue; 4 | 5 | /** 6 | * This is a factory which creates null connections. 7 | * 8 | * @since 2017/12/17 9 | */ 10 | public final class NullConnectionFactory 11 | implements RemoteConnectionFactory 12 | { 13 | /** 14 | * {@inheritDoc} 15 | * @since 2017/12/19 16 | */ 17 | @Override 18 | public final RemoteConnection connect(String __url, String __auth) 19 | throws NullPointerException, RemoteException 20 | { 21 | if (__url == null) 22 | throw new NullPointerException(); 23 | 24 | return new NullConnection(); 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/WrappedResult.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.http.RemoteResult; 4 | 5 | /** 6 | * This contains the result information. 7 | * 8 | * @since 2018/02/24 9 | */ 10 | public final class WrappedResult 11 | { 12 | /** The URL. */ 13 | public final String url; 14 | 15 | /** The result of the call. */ 16 | public final RemoteResult result; 17 | 18 | /** 19 | * Initializes the wrapped result. 20 | * 21 | * @param __u The URL. 22 | * @param __r The result of the result. 23 | * @since 2018/02/24 24 | */ 25 | public WrappedResult(String __u, RemoteResult __r) 26 | { 27 | this.url = __u; 28 | this.result = __r; 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/IOpipePluginPreExecutable.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin; 2 | 3 | /** 4 | * This interface is used for plugins which must be initialized and setup 5 | * before the logged method begins execution. 6 | * 7 | * @since 2018/01/20 8 | */ 9 | public interface IOpipePluginPreExecutable 10 | extends IOpipePlugin 11 | { 12 | /** 13 | * Performs a pre-execution of the given plugin using the specified state. 14 | * 15 | * @param __e The plugin execution state. 16 | * @throws NullPointerException On null arguments. 17 | * @since 2018/01/20 18 | */ 19 | public abstract void preExecute(IOpipePluginExecution __e) 20 | throws NullPointerException; 21 | } 22 | 23 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/http/NullConnection.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.http; 2 | 3 | /** 4 | * This is a connection which has no effect and always returns the 503 5 | * Service Unavailable code. 6 | * 7 | * @since 2017/12/15 8 | */ 9 | public final class NullConnection 10 | implements RemoteConnection 11 | { 12 | /** 13 | * {@inheritDoc} 14 | * @since 2017/12/15 15 | */ 16 | @Override 17 | public final RemoteResult send(RequestType __t, RemoteRequest __r) 18 | throws NullPointerException, RemoteException 19 | { 20 | if (__t == null || __r == null) 21 | throw new NullPointerException(); 22 | 23 | // Report service not available 24 | return new RemoteResult(503, RemoteBody.MIMETYPE_JSON, new byte[0]); 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/IOpipePluginPostExecutable.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin; 2 | 3 | /** 4 | * This interface is used for plugins which require that when the method 5 | * being traced has finished executing, that it should perform some final 6 | * operations as needed. 7 | * 8 | * @since 2018/01/20 9 | */ 10 | public interface IOpipePluginPostExecutable 11 | extends IOpipePlugin 12 | { 13 | /** 14 | * Performs a post-execution of the given plugin using the specified state. 15 | * 16 | * @param __e The plugin execution state. 17 | * @throws NullPointerException On null arguments. 18 | * @since 2018/01/20 19 | */ 20 | public abstract void postExecute(IOpipePluginExecution __e) 21 | throws NullPointerException; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/profiler/__SnapshotConstants__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.profiler; 2 | 3 | /** 4 | * Constants for the snapshot format. 5 | * 6 | * @since 2018/02/15 7 | */ 8 | interface __SnapshotConstants__ 9 | { 10 | /** Compression level for snapshot data. */ 11 | public static final int COMPRESSION_LEVEL = 12 | 3; 13 | 14 | /** The magic number. */ 15 | public static final String MAGIC_NUMBER = 16 | "nBpRoFiLeR"; 17 | 18 | /** The major version number. */ 19 | public static final int MAJOR_VERSION = 20 | 1; 21 | 22 | /** The minor version number. */ 23 | public static final int MINOR_VERSION = 24 | 2; 25 | 26 | /** The CPU snapshot type. */ 27 | public static final int TYPE_CPU = 28 | 1; 29 | } 30 | 31 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/MockDynamicTest.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import org.junit.jupiter.api.BeforeEach; 4 | import org.junit.jupiter.api.DynamicTest; 5 | import org.junit.jupiter.api.TestFactory; 6 | import org.junit.platform.runner.JUnitPlatform; 7 | import org.junit.runner.RunWith; 8 | 9 | /** 10 | * This creates tests which use the local mock environment. 11 | * 12 | * @since 2018/01/23 13 | */ 14 | //@RunWith(JUnitPlatform.class) 15 | public class MockDynamicTest 16 | { 17 | /** 18 | * Initializes all of the tests. 19 | * 20 | * @return All of the test. 21 | * @since 2018/01/23 22 | */ 23 | @TestFactory 24 | public Iterable doThings() 25 | { 26 | return Engine.generateTests(MockEngine::new); 27 | } 28 | } 29 | 30 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/elsewhere/ParameterA.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.elsewhere; 2 | 3 | import com.iopipe.IOpipeExecution; 4 | 5 | public class ParameterA 6 | { 7 | public void normalCall(A __a) 8 | { 9 | IOpipeExecution.currentExecution().customMetric("parma", 10 | (__a == null ? "null" : __a.getClass().getName())); 11 | } 12 | 13 | public B handleRequest(A __a) 14 | { 15 | IOpipeExecution.currentExecution().label("parameter-" + 16 | this.getClass().getName() + "-" + 17 | (__a == null ? "null" : __a.getClass().getName())); 18 | IOpipeExecution.currentExecution().customMetric("class", 19 | (__a == null ? "null" : __a.getClass().getName())); 20 | 21 | this.normalCall(__a); 22 | 23 | return null; 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/generic/__IdentityConvert__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.generic; 2 | 3 | import java.lang.reflect.Type; 4 | 5 | /** 6 | * This is the identity conversion which converts to objects without performing 7 | * any kind of translation. 8 | * 9 | * @since 2018/08/23 10 | */ 11 | final class __IdentityConvert__ 12 | extends ObjectTranslator 13 | { 14 | /** 15 | * Initializes the translator. 16 | * 17 | * @param __f The from type. 18 | * @param __t The to type. 19 | * @since 2018/08/23 20 | */ 21 | __IdentityConvert__(Type __f, Type __t) 22 | { 23 | super(__f, __t); 24 | } 25 | 26 | /** 27 | * {@inheritDoc} 28 | * @since 2018/08/23 29 | */ 30 | @Override 31 | public final Object translate(Object __f) 32 | { 33 | return __f; 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/__SignerRemote__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | /** 4 | * This contains information on the remote. 5 | * 6 | * @since 2018/07/27 7 | */ 8 | final class __SignerRemote__ 9 | { 10 | /** Is this remote valid? */ 11 | public final boolean valid; 12 | 13 | /** The URL to upload to. */ 14 | public final String url; 15 | 16 | /** The JWT access token. */ 17 | public final String jwtaccesstoken; 18 | 19 | /** 20 | * Initializes the remote information. 21 | * 22 | * @param __valid Is this valid? 23 | * @param __url The URL to upload to. 24 | * @param __at The access token. 25 | * @since 2018/07/22 26 | */ 27 | __SignerRemote__(boolean __valid, String __url, String __at) 28 | { 29 | this.valid = __valid; 30 | this.url = __url; 31 | this.jwtaccesstoken = __at; 32 | } 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/test/resources/com/iopipe/eventinfo_cloudfront.json: -------------------------------------------------------------------------------- 1 | { 2 | "Records": [ 3 | { 4 | "cf": { 5 | "config": { 6 | "distributionId": "EDFDVBD6EXAMPLE" 7 | }, 8 | "request": { 9 | "clientIp": "2001:0db8:85a3:0:0:8a2e:0370:7334", 10 | "method": "GET", 11 | "uri": "/picture.jpg", 12 | "headers": { 13 | "host": [ 14 | { 15 | "key": "Host", 16 | "value": "d111111abcdef8.cloudfront.net" 17 | } 18 | ], 19 | "user-agent": [ 20 | { 21 | "key": "User-Agent", 22 | "value": "curl/7.51.0" 23 | } 24 | ] 25 | } 26 | } 27 | } 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /src/test/resources/com/iopipe/eventinfo_kinesis.json: -------------------------------------------------------------------------------- 1 | { 2 | "Records": [ 3 | { 4 | "eventID": "shardId-000000000000:49545115243490985018280067714973144582180062593244200961", 5 | "eventVersion": "1.0", 6 | "kinesis": { 7 | "partitionKey": "partitionKey-3", 8 | "data": "SGVsbG8sIHRoaXMgaXMgYSB0ZXN0IDEyMy4=", 9 | "kinesisSchemaVersion": "1.0", 10 | "sequenceNumber": "49545115243490985018280067714973144582180062593244200961" 11 | }, 12 | "invokeIdentityArn": "invoked-by-arn", 13 | "eventName": "aws:kinesis:record", 14 | "eventSourceARN": "event-source-arn", 15 | "eventSource": "aws:kinesis", 16 | "awsRegion": "us-east-1" 17 | } 18 | ] 19 | } 20 | 21 | -------------------------------------------------------------------------------- /src/test/resources/com/iopipe/eventinfo_sqs.json: -------------------------------------------------------------------------------- 1 | { 2 | "Records": [ 3 | { 4 | "body": "Hello from SQS!", 5 | "receiptHandle": "MessageReceiptHandle", 6 | "md5OfBody": "7b270e59b47ff90a553787216d55d91d", 7 | "eventSourceARN": "arn:aws:sqs:us-east-1:123456789012:MyQueue", 8 | "eventSource": "aws:sqs", 9 | "awsRegion": "us-east-1", 10 | "messageId": "19dd0b57-b21e-4ac1-bd88-01bbb068cb78", 11 | "attributes": { 12 | "ApproximateFirstReceiveTimestamp": "1523232000001", 13 | "SenderId": "123456789012", 14 | "ApproximateReceiveCount": "1", 15 | "SentTimestamp": "1523232000000" 16 | }, 17 | "messageAttributes": {} 18 | } 19 | ] 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/http/RemoteException.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.http; 2 | 3 | /** 4 | * This is thrown when there is an error connecting to, sending to, or 5 | * receiving from a remote connection. 6 | * 7 | * @since 2017/12/17 8 | */ 9 | public class RemoteException 10 | extends RuntimeException 11 | { 12 | /** 13 | * Initializes the exception with the given message. 14 | * 15 | * @param __m The message to use. 16 | * @since 2017/12/17 17 | */ 18 | public RemoteException(String __m) 19 | { 20 | super(__m); 21 | } 22 | 23 | /** 24 | * Initializes the exception with the given message and cause. 25 | * 26 | * @param __m The message to use. 27 | * @param __c The cause of the exception. 28 | * @since 2017/12/17 29 | */ 30 | public RemoteException(String __m, Throwable __c) 31 | { 32 | super(__m, __c); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/NoSuchPluginException.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin; 2 | 3 | /** 4 | * This is thrown when a plugin was requested, but it does not exist or is 5 | * disabled. 6 | * 7 | * @since 2018/01/20 8 | */ 9 | public class NoSuchPluginException 10 | extends Exception 11 | { 12 | /** 13 | * Initializes the exception with the given message. 14 | * 15 | * @param __m The message to use. 16 | * @since 2018/01/20 17 | */ 18 | public NoSuchPluginException(String __m) 19 | { 20 | super(__m); 21 | } 22 | 23 | /** 24 | * Initializes the exception with the given message and cause. 25 | * 26 | * @param __m The message to use. 27 | * @param __c The cause of the exception. 28 | * @since 2018/01/20 29 | */ 30 | public NoSuchPluginException(String __m, Throwable __c) 31 | { 32 | super(__m, __c); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | pom.xml.tag 3 | pom.xml.releaseBackup 4 | pom.xml.versionsBackup 5 | pom.xml.next 6 | release.properties 7 | dependency-reduced-pom.xml 8 | buildNumber.properties 9 | .mvn/timing.properties 10 | 11 | # Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) 12 | !/.mvn/wrapper/maven-wrapper.jar 13 | # Compiled class file 14 | *.class 15 | 16 | # Log file 17 | *.log 18 | 19 | # BlueJ files 20 | *.ctxt 21 | 22 | # IntelliJ 23 | .idea 24 | 25 | # Mobile Tools for Java (J2ME) 26 | .mtj.tmp/ 27 | 28 | # Package Files # 29 | *.jar 30 | *.war 31 | *.ear 32 | *.zip 33 | *.tar.gz 34 | *.rar 35 | 36 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 37 | hs_err_pid* 38 | 39 | # Local testing script, it should never be added 40 | .test.sh 41 | .profile.sh 42 | 43 | # Serverless 44 | .serverless 45 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/RemoteEngine.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import java.util.function.Consumer; 4 | import java.util.function.Function; 5 | 6 | /** 7 | * This runs all of the tests but interacts directly 8 | * 9 | * @since 2018/01/23 10 | */ 11 | public class RemoteEngine 12 | extends Engine 13 | { 14 | /** 15 | * Initializes the engine. 16 | * 17 | * @since 2018/01/23 18 | */ 19 | public RemoteEngine() 20 | { 21 | super("remote"); 22 | } 23 | 24 | /** 25 | * {@inheritDoc} 26 | * @since 2018/01/23 27 | */ 28 | @Override 29 | protected IOpipeConfigurationBuilder generateConfig(Single __s) 30 | { 31 | if (__s == null) 32 | throw new NullPointerException(); 33 | 34 | // Use the system configuration, it will be modified accordingly 35 | return new IOpipeConfigurationBuilder(IOpipeConfiguration.byDefault()); 36 | } 37 | } 38 | 39 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/Value.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | /** 4 | * This represents the base of a value which is used to store something that 5 | * is set. 6 | * 7 | * @since 2018/01/24 8 | */ 9 | public abstract class Value 10 | { 11 | /** The name of the value. */ 12 | protected final String name; 13 | 14 | /** 15 | * Initializes the storage. 16 | * 17 | * @param __n The variable name. 18 | * @throws NullPointerException On null arguments. 19 | * @since 2018/01/24 20 | */ 21 | public Value(String __n) 22 | throws NullPointerException 23 | { 24 | if (__n == null) 25 | throw new NullPointerException(); 26 | 27 | this.name = __n; 28 | } 29 | 30 | /** 31 | * Returns the variable name. 32 | * 33 | * @return The variable name. 34 | * @since 2018/01/24 35 | */ 36 | public final String name() 37 | { 38 | return this.name; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/MockConnectionFactory.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.http.RemoteConnection; 4 | import com.iopipe.http.RemoteConnectionFactory; 5 | import com.iopipe.http.RemoteException; 6 | import com.iopipe.http.RemoteRequest; 7 | 8 | /** 9 | * This is the connection factory which is only meant to be used for testing. 10 | * It only verifies that the token is okay. 11 | * 12 | * @since 2017/12/13 13 | */ 14 | public final class MockConnectionFactory 15 | implements RemoteConnectionFactory 16 | { 17 | /** 18 | * {@inheritDoc} 19 | * @since 2017/12/19 20 | */ 21 | @Override 22 | public final RemoteConnection connect(String __url, String __auth) 23 | throws NullPointerException, RemoteException 24 | { 25 | if (__url == null) 26 | throw new NullPointerException(); 27 | 28 | return new MockConnection(__url, __auth); 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/IOpipePluginExecution.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin; 2 | 3 | import javax.json.JsonObject; 4 | 5 | /** 6 | * For plugins which provide access to information based on execution, this 7 | * interface is used as a base for those plugins to provide functionality that 8 | * is only needed per instance of a plugin. 9 | * 10 | * @since 2018/01/20 11 | */ 12 | public interface IOpipePluginExecution 13 | { 14 | /** 15 | * Plugins may add additional details to be reported, this allows the 16 | * plugin to specify fields which will be added to the plugin information. 17 | * 18 | * @return An object containing the key and value pairs to be added to 19 | * the plugin report, if the return value is {@code null} then nothing is 20 | * used. 21 | * @since 2018/03/15 22 | */ 23 | public default JsonObject extraReport() 24 | { 25 | return null; 26 | } 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/profiler/TrackedThreadNodeTraversal.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.profiler; 2 | 3 | /** 4 | * The thread stat and the node information all have the ability to obtain 5 | * nodes according to their subnodes. 6 | * 7 | * @since 2018/02/19 8 | */ 9 | public interface TrackedThreadNodeTraversal 10 | { 11 | /** 12 | * Obtains the specified sub-node. 13 | * 14 | * @param __m The method for tracking. 15 | * @return The node for the given method. 16 | * @throws NullPointerException On null arguments. 17 | * @since 2018/02/19 18 | */ 19 | public abstract TrackedThread.Node subNode(MethodTracker.TrackedMethod __m) 20 | throws NullPointerException; 21 | 22 | /** 23 | * Returns an array of all the available sub-nodes. 24 | * 25 | * @return An array containing all of the nodes. 26 | * @since 2018/02/19 27 | */ 28 | public abstract TrackedThread.Node[] subNodes(); 29 | } 30 | 31 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/http/RemoteConnectionFactory.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.http; 2 | 3 | /** 4 | * This interface is used to create connections to the IOpipe server for the 5 | * purpose of sending and receiving requests. 6 | * 7 | * @since 2017/12/13 8 | */ 9 | public interface RemoteConnectionFactory 10 | { 11 | /** 12 | * Initializes the connection to the IOpipe service. 13 | * 14 | * @param __url The URL to connect to for requests. 15 | * @param __auth The token to use for authorization, this is included 16 | * in the headers, this is optional and may be {@code null}. 17 | * @return A HTTP connection to the IOpipe service. 18 | * @throws NullPointerException If no URL was specified. 19 | * @throws RemoteException If the connection could not be made. 20 | * @since 2017/12/13 21 | */ 22 | public abstract RemoteConnection connect(String __url, String __auth) 23 | throws NullPointerException, RemoteException; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/BooleanValue.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import java.util.concurrent.atomic.AtomicBoolean; 4 | 5 | /** 6 | * Represents a boolean value. 7 | * 8 | * @since 2018/01/24 9 | */ 10 | public final class BooleanValue 11 | extends Value 12 | { 13 | /** The internal value. */ 14 | protected final AtomicBoolean value = 15 | new AtomicBoolean(); 16 | 17 | /** 18 | * Initializes the storage. 19 | * 20 | * @param __n The variable name. 21 | * @since 2018/01/24 22 | */ 23 | public BooleanValue(String __n) 24 | { 25 | super(__n); 26 | } 27 | 28 | /** 29 | * Obtains the value. 30 | * 31 | * @return The value. 32 | * @since 2018/01/24 33 | */ 34 | public boolean get() 35 | { 36 | return this.value.get(); 37 | } 38 | 39 | /** 40 | * Sets the value. 41 | * 42 | * @param __v The new value. 43 | * @since 2018/01/24 44 | */ 45 | public void set(boolean __v) 46 | { 47 | this.value.set(__v); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /.version-rules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | (?i).*Alpha(?:-?\d+)? 6 | (?i).*a(?:-?\d+)? 7 | (?i).*Beta(?:-?\d+)? 8 | (?i).*-B(?:-?\d+)? 9 | (?i).*RC(?:-?\d+)? 10 | (?i).*CR(?:-?\d+)? 11 | (?i).*M(?:-?\d+)? 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/http/ServiceConnectionFactory.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.http; 2 | 3 | import okhttp3.HttpUrl; 4 | import okhttp3.OkHttpClient; 5 | 6 | /** 7 | * This is a factory which can create connections to the remote IOpipe service 8 | * to send reports. 9 | * 10 | * @since 2017/12/17 11 | */ 12 | public final class ServiceConnectionFactory 13 | implements RemoteConnectionFactory 14 | { 15 | /** The OkHttp client manager. */ 16 | protected final OkHttpClient client = 17 | new OkHttpClient.Builder().build(); 18 | 19 | /** 20 | * {@inheritDoc} 21 | * @since 2018/02/24 22 | */ 23 | @Override 24 | public RemoteConnection connect(String __url, String __auth) 25 | throws NullPointerException, RemoteException 26 | { 27 | if (__url == null) 28 | throw new NullPointerException(); 29 | 30 | HttpUrl url = HttpUrl.parse(__url); 31 | if (url == null) 32 | throw new RemoteException("Invalid URL: " + __url); 33 | return new ServiceConnection(this.client, url, __auth); 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/TestExecution.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.IOpipeExecution; 4 | import com.iopipe.plugin.IOpipePluginExecution; 5 | 6 | /** 7 | * This is an execution for the plugin. 8 | * 9 | * @since 2018/01/20 10 | */ 11 | public class TestExecution 12 | implements IOpipePluginExecution 13 | { 14 | /** The execution to refer to. */ 15 | protected final IOpipeExecution execution; 16 | 17 | /** 18 | * Initializes the test execution. 19 | * 20 | * @param __e The execution to modify. 21 | * @throws NullPointerException On null arguments. 22 | * @since 2018/01/20 23 | */ 24 | public TestExecution(IOpipeExecution __e) 25 | throws NullPointerException 26 | { 27 | if (__e == null) 28 | throw new NullPointerException(); 29 | 30 | this.execution = __e; 31 | } 32 | 33 | /** 34 | * Returns the execution. 35 | * 36 | * @return The execution. 37 | * @since 2018/01/20 38 | */ 39 | public final IOpipeExecution execution() 40 | { 41 | return this.execution; 42 | } 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/RemoteDynamicTest.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import java.util.Collections; 4 | import java.util.Objects; 5 | import org.junit.jupiter.api.BeforeEach; 6 | import org.junit.jupiter.api.DynamicTest; 7 | import org.junit.jupiter.api.TestFactory; 8 | import org.junit.platform.runner.JUnitPlatform; 9 | import org.junit.runner.RunWith; 10 | 11 | /** 12 | * This initializes tests which uses and interacts with the real service. 13 | * 14 | * @since 2018/01/23 15 | */ 16 | //@RunWith(JUnitPlatform.class) 17 | public class RemoteDynamicTest 18 | { 19 | /** 20 | * Initializes all of the tests. 21 | * 22 | * @return All of the test. 23 | * @since 2018/01/23 24 | */ 25 | @TestFactory 26 | public Iterable doThings() 27 | { 28 | // Instead of skipping tests, just do nothing if they are not enabled 29 | if (!Boolean.valueOf(Objects.toString( 30 | System.getenv("IOPIPE_ENABLE_REMOTE_TESTS"), "false"))) 31 | return Collections.emptySet(); 32 | 33 | return Engine.generateTests(RemoteEngine::new); 34 | } 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/http/RemoteConnection.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.http; 2 | 3 | /** 4 | * This interface is used to represent a single connection to the IOpipe 5 | * service. The server is sent {@link RemoteRequest}s and the result of 6 | * those requests are returned within a {@link RemoteResult}. 7 | * 8 | * It is unspecified if this reuses a single connection to a server which is 9 | * streamlined with other requests or if it opens a new connection each time 10 | * a request is sent. 11 | * 12 | * @since 2017/12/13 13 | */ 14 | public interface RemoteConnection 15 | { 16 | /** 17 | * Sends the given request to the remote server. 18 | * 19 | * @param __t The type of request to make. 20 | * @param __r The request to send to the remote server. 21 | * @return The result of the request. 22 | * @throws NullPointerException On null arguments. 23 | * @throws RemoteException If the request could not be sent. 24 | * @since 2017/12/13 25 | */ 26 | public abstract RemoteResult send(RequestType __t, RemoteRequest __r) 27 | throws NullPointerException, RemoteException; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/__Shared__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * Internal shared variables and such 7 | * 8 | * @since 2018/08/01 9 | */ 10 | final class __Shared__ 11 | { 12 | /** The thread group to use main service threads under. */ 13 | static final ThreadGroup _SERVICE_THREAD_GROUP; 14 | 15 | /** The process ID, used to identify this process. */ 16 | static final UUID _PROCESS_ID = 17 | UUID.randomUUID(); 18 | 19 | /** 20 | * Initializes some shared variables. 21 | * 22 | * @since 2018/08/01 23 | */ 24 | static 25 | { 26 | // Setup a thread group where IOpipe's service threads are placed 27 | // under 28 | ThreadGroup stg = null; 29 | try 30 | { 31 | stg = new ThreadGroup("IOpipe-ServiceThreads"); 32 | } 33 | catch (SecurityException e) 34 | { 35 | // Just use our thread group 36 | stg = Thread.currentThread().getThreadGroup(); 37 | } 38 | 39 | _SERVICE_THREAD_GROUP = stg; 40 | } 41 | 42 | /** 43 | * Not used. 44 | * 45 | * @since 2018/08/01 46 | */ 47 | private __Shared__() 48 | { 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/PutEvent.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | /** 4 | * Represents any data that was PUT to the server. 5 | * 6 | * @since 2108/07/16 7 | */ 8 | public final class PutEvent 9 | implements Event 10 | { 11 | /** Event data. */ 12 | private final byte[] _data; 13 | 14 | /** 15 | * Initializes the put event. 16 | * 17 | * @param __d The data which was put to the remote end. 18 | * @throws NullPointerException On null arguments. 19 | * @since 2018/07/16 20 | */ 21 | public PutEvent(byte[] __d) 22 | throws NullPointerException 23 | { 24 | if (__d == null) 25 | throw new NullPointerException(); 26 | 27 | this._data = __d.clone(); 28 | } 29 | 30 | /** 31 | * Returns the data that was put. 32 | * 33 | * @return The data which was put. 34 | * @since 2018/09/26 35 | */ 36 | public final byte[] data() 37 | { 38 | return this._data.clone(); 39 | } 40 | 41 | /** 42 | * The length of the put data. 43 | * 44 | * @return The length of the data. 45 | * @since 2018/07/16 46 | */ 47 | public final int length() 48 | { 49 | return this._data.length; 50 | } 51 | } 52 | 53 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/__Utils__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.http.RemoteRequest; 4 | import com.iopipe.http.RemoteResult; 5 | import java.util.Map; 6 | import java.util.TreeMap; 7 | import javax.json.JsonArray; 8 | import javax.json.JsonObject; 9 | import javax.json.JsonString; 10 | import javax.json.JsonStructure; 11 | import javax.json.JsonValue; 12 | 13 | /** 14 | * Basic class to work with requests and results. 15 | * 16 | * @since 2018/01/23 17 | */ 18 | final class __Utils__ 19 | { 20 | /** 21 | * Not used. 22 | * 23 | * @since 2018/01/23 24 | */ 25 | private __Utils__() 26 | { 27 | } 28 | 29 | /** 30 | * Checks if the result status code is okay. 31 | * 32 | * @param __r The request to check. 33 | * @return If the status code is okay. 34 | * @throws NullPointerException On null arguments. 35 | * @since 2018/01/23 36 | */ 37 | public static boolean isResultOkay(RemoteResult __r) 38 | throws NullPointerException 39 | { 40 | if (__r == null) 41 | throw new NullPointerException(); 42 | 43 | int code = __r.code(); 44 | return code >= 200 && code < 300; 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/MockException.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | /** 4 | * This is a mock exception which is not really an error but is used for 5 | * debugging purposes. 6 | * 7 | * @since 2017/12/15 8 | */ 9 | public final class MockException 10 | extends RuntimeException 11 | { 12 | /** 13 | * Initializes with no message or cause. 14 | * 15 | * @since 2017/12/15 16 | */ 17 | public MockException() 18 | { 19 | } 20 | 21 | /** 22 | * Initializes with a message and no cause. 23 | * 24 | * @param __m The reason to use. 25 | * @since 2017/12/15 26 | */ 27 | public MockException(String __m) 28 | { 29 | super(__m); 30 | } 31 | 32 | /** 33 | * Initializes with a cause and no message. 34 | * 35 | * @param __c The cause of the exception. 36 | * @since 2017/12/15 37 | */ 38 | public MockException(Throwable __c) 39 | { 40 | super(__c); 41 | } 42 | 43 | /** 44 | * Initializes with a message and cause. 45 | * 46 | * @param __m The reason to use. 47 | * @param __c The cause of the exception. 48 | * @since 2017/12/15 49 | */ 50 | public MockException(String __m, Throwable __c) 51 | { 52 | super(__m, __c); 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/IOpipeWrappedException.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | /** 4 | * This class represents an exception which was wrapped by IOpipe. 5 | * 6 | * @since 2018/08/16 7 | */ 8 | public class IOpipeWrappedException 9 | extends RuntimeException 10 | { 11 | /** 12 | * Initialize the exception with no message or cause. 13 | * 14 | * @since 2018/08/16 15 | */ 16 | public IOpipeWrappedException() 17 | { 18 | } 19 | 20 | /** 21 | * Initialize the exception with a message and no cause. 22 | * 23 | * @param __m The message. 24 | * @since 2018/08/16 25 | */ 26 | public IOpipeWrappedException(String __m) 27 | { 28 | super(__m); 29 | } 30 | 31 | /** 32 | * Initialize the exception with a message and cause. 33 | * 34 | * @param __m The message. 35 | * @param __c The cause. 36 | * @since 2018/08/16 37 | */ 38 | public IOpipeWrappedException(String __m, Throwable __c) 39 | { 40 | super(__m, __c); 41 | } 42 | 43 | /** 44 | * Initialize the exception with no message and with a cause. 45 | * 46 | * @param __c The cause. 47 | * @since 2018/08/16 48 | */ 49 | public IOpipeWrappedException(Throwable __c) 50 | { 51 | super(__c); 52 | } 53 | } 54 | 55 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/IOpipeFatalError.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | /** 4 | * This error is thrown when IOpipe has been misconfigured and it is unable 5 | * to allow the lambda to continue execution. 6 | * 7 | * @since 2018/08/14 8 | */ 9 | public class IOpipeFatalError 10 | extends Error 11 | { 12 | /** 13 | * Initialize the exception with no message or cause. 14 | * 15 | * @since 2018/08/14 16 | */ 17 | public IOpipeFatalError() 18 | { 19 | } 20 | 21 | /** 22 | * Initialize the exception with a message and no cause. 23 | * 24 | * @param __m The message. 25 | * @since 2018/08/14 26 | */ 27 | public IOpipeFatalError(String __m) 28 | { 29 | super(__m); 30 | } 31 | 32 | /** 33 | * Initialize the exception with a message and cause. 34 | * 35 | * @param __m The message. 36 | * @param __c The cause. 37 | * @since 2018/08/14 38 | */ 39 | public IOpipeFatalError(String __m, Throwable __c) 40 | { 41 | super(__m, __c); 42 | } 43 | 44 | /** 45 | * Initialize the exception with no message and with a cause. 46 | * 47 | * @param __c The cause. 48 | * @since 2018/08/14 49 | */ 50 | public IOpipeFatalError(Throwable __c) 51 | { 52 | super(__c); 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/elsewhere/SimplePOJO.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.elsewhere; 2 | 3 | /** 4 | * A simple POJO for testing. 5 | * 6 | * @since 2018/08/20 7 | */ 8 | public class SimplePOJO 9 | extends SomeType 10 | { 11 | private String favoriteanimal; 12 | 13 | private String favoritefood; 14 | 15 | private int favoritenumber; 16 | 17 | public String dayofweek; 18 | 19 | public String getFavoriteAnimal() 20 | { 21 | return this.favoriteanimal; 22 | } 23 | 24 | public String getFavoriteFood() 25 | { 26 | return this.favoritefood; 27 | } 28 | 29 | public int getFavoriteNumber() 30 | { 31 | return this.favoritenumber; 32 | } 33 | 34 | public void setFavoriteAnimal(String __v) 35 | { 36 | this.favoriteanimal = __v; 37 | } 38 | 39 | public void setFavoriteFood(String __v) 40 | { 41 | this.favoritefood = __v; 42 | } 43 | 44 | public void setFavoriteNumber(int __v) 45 | { 46 | this.favoritenumber = __v; 47 | } 48 | 49 | public String toString() 50 | { 51 | return "{favoriteanimal=" + this.favoriteanimal + 52 | ", favoritefood=" + this.favoritefood + 53 | ", favoritenumber=" + this.favoritenumber + 54 | ", dayofweek=" + this.dayofweek + 55 | "}"; 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/generic/InvalidEntryPointException.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.generic; 2 | 3 | /** 4 | * This is thrown when the entry point is not valid. 5 | * 6 | * @since 2018/08/14 7 | */ 8 | public class InvalidEntryPointException 9 | extends RuntimeException 10 | { 11 | /** 12 | * Initialize the exception with no message or cause. 13 | * 14 | * @since 2018/08/14 15 | */ 16 | public InvalidEntryPointException() 17 | { 18 | } 19 | 20 | /** 21 | * Initialize the exception with a message and no cause. 22 | * 23 | * @param __m The message. 24 | * @since 2018/08/14 25 | */ 26 | public InvalidEntryPointException(String __m) 27 | { 28 | super(__m); 29 | } 30 | 31 | /** 32 | * Initialize the exception with a message and cause. 33 | * 34 | * @param __m The message. 35 | * @param __c The cause. 36 | * @since 2018/08/14 37 | */ 38 | public InvalidEntryPointException(String __m, Throwable __c) 39 | { 40 | super(__m, __c); 41 | } 42 | 43 | /** 44 | * Initialize the exception with no message and with a cause. 45 | * 46 | * @param __c The cause. 47 | * @since 2018/08/14 48 | */ 49 | public InvalidEntryPointException(Throwable __c) 50 | { 51 | super(__c); 52 | } 53 | } 54 | 55 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/profiler/TimeKeeper.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.profiler; 2 | 3 | import java.util.concurrent.atomic.AtomicLong; 4 | 5 | /** 6 | * This keeps track of the various times. 7 | * 8 | * @since 2018/02/20 9 | */ 10 | public final class TimeKeeper 11 | { 12 | /** Absolute time. */ 13 | private final AtomicLong _abs = 14 | new AtomicLong(); 15 | 16 | /** Time spent at the top of the stack. */ 17 | private final AtomicLong _self = 18 | new AtomicLong(); 19 | 20 | /** 21 | * Returns the absolute time. 22 | * 23 | * @return The absolute time. 24 | * @since 2018/02/20 25 | */ 26 | public final long absolute() 27 | { 28 | return this._abs.get(); 29 | } 30 | 31 | /** 32 | * Adds time to the timer. 33 | * 34 | * @param __self Include self time? 35 | * @param __v The time to add. 36 | * @since 2018/02/20 37 | */ 38 | public final void addTime(boolean __self, long __v) 39 | { 40 | this._abs.getAndAdd(__v); 41 | if (__self) 42 | this._self.getAndAdd(__v); 43 | } 44 | 45 | /** 46 | * Returns the self time. 47 | * 48 | * @return The self time. 49 | * @since 2018/02/20 50 | */ 51 | public final long self() 52 | { 53 | return this._self.get(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/eventinfo/FirehoseDecoder.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.eventinfo; 2 | 3 | import com.amazonaws.services.lambda.runtime.events.KinesisFirehoseEvent; 4 | 5 | /** 6 | * This class implements the decoder for Kinesis Firehose events. 7 | * 8 | * @since 2018/04/23 9 | */ 10 | public final class FirehoseDecoder 11 | implements EventInfoDecoder 12 | { 13 | /** 14 | * {@inheritDoc} 15 | * @since 2018/05/02 16 | */ 17 | @Override 18 | public void accept(ValueAcceptor __a, Object __v) 19 | throws NullPointerException 20 | { 21 | if (__a == null || __v == null) 22 | throw new NullPointerException(); 23 | 24 | KinesisFirehoseEvent v = (KinesisFirehoseEvent)__v; 25 | 26 | __a.accept("deliveryStreamArn", 27 | v.getDeliveryStreamArn()); 28 | __a.accept("region", 29 | v.getRegion()); 30 | } 31 | 32 | /** 33 | * {@inheritDoc} 34 | * @since 2018/04/23 35 | */ 36 | @Override 37 | public final String[] decodes() 38 | { 39 | return new String[] 40 | { 41 | "com.amazonaws.services.lambda.runtime.events.KinesisFirehoseEvent", 42 | }; 43 | } 44 | 45 | /** 46 | * {@inheritDoc} 47 | * @since 2018/04/23 48 | */ 49 | @Override 50 | public final String eventType() 51 | { 52 | return "firehose"; 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /src/test/resources/com/iopipe/eventinfo_sns.json: -------------------------------------------------------------------------------- 1 | { 2 | "Records": [ 3 | { 4 | "EventVersion": "1.0", 5 | "EventSource": "aws:sns", 6 | "EventSubscriptionArn": "arn:aws:sns:us-west-2:123456789000:ses_messages:26a58451-3392-4ab6-a829-d65c2968421a", 7 | "Sns": { 8 | "MessageId": "483eae4c-4fb0-57e5-a5f9-ff9b08612bef", 9 | "Signature": "Uy3tn/qAQg/sXARGk2DRddd31ZtyDE+B1IzRla/KA75BaerApJqN+H59q69z8H+pRx0AyUwOD1K0huBYdDRbAMVOUsMgZgdcNjj0gSfFg8uZvTuKaqTaWj4E0hmzoemHENWeuswuq3l6xoPcAJ9fHd2yFhX+792AV++i/8P4EKv/9I4j8Ejs3OxMRN49gkWefKbv4/avyHOdSaFTnXV0rGLmPb103dtjeY4K05PTKvUlPerN+MdRTvHrjApvqDvP0NEVyYBU4zFZQ6GnFcFnHtTk44c3NH/dVi6Gf9VrX8V1id5VSZICYiIG1iaUZ0b676IhRh8znzjMDWaczOBwkA==", 10 | "Type": "Notification", 11 | "TopicArn": "arn:aws:sns:us-west-2:123456789000:ses_messages", 12 | "SignatureVersion": "1", 13 | "Timestamp": "2017-07-05T20:01:21.366Z", 14 | "SigningCertUrl": "https://sns.us-west-2.amazonaws.com/SimpleNotificationService-b95095beb82e8f6a046b3aafc7f4149a.pem", 15 | "UnsubscribeUrl": "https://sns.us-west-2.amazonaws.com/?Action=Unsubscribe&eifjccgihujihfhrchunfnglreichbrcljrnlvtbeked", 16 | "Subject": "This is a test subject" 17 | } 18 | } 19 | ] 20 | } 21 | 22 | -------------------------------------------------------------------------------- /src/test/resources/com/iopipe/eventinfo_firehose.json: -------------------------------------------------------------------------------- 1 | { 2 | "invocationId": "invoked123", 3 | "deliveryStreamArn": "aws:lambda:events", 4 | "region": "us-west-2", 5 | "records": [ 6 | { 7 | "data": "SGVsbG8gV29ybGQ=", 8 | "recordId": "record1", 9 | "approximateArrivalTimestamp": 1510772160000, 10 | "kinesisRecordMetadata": { 11 | "shardId": "shardId-000000000000", 12 | "partitionKey": "4d1ad2b9-24f8-4b9d-a088-76e9947c317a", 13 | "approximateArrivalTimestamp": "2012-04-23T18:25:43.511Z", 14 | "sequenceNumber": "49546986683135544286507457936321625675700192471156785154", 15 | "subsequenceNumber": "" 16 | } 17 | }, 18 | { 19 | "data": "SGVsbG8gV29ybGQ=", 20 | "recordId": "record2", 21 | "approximateArrivalTimestamp": 151077216000, 22 | "kinesisRecordMetadata": { 23 | "shardId": "shardId-000000000001", 24 | "partitionKey": "4d1ad2b9-24f8-4b9d-a088-76e9947c318a", 25 | "approximateArrivalTimestamp": "2012-04-23T19:25:43.511Z", 26 | "sequenceNumber": "49546986683135544286507457936321625675700192471156785155", 27 | "subsequenceNumber": "" 28 | } 29 | } 30 | ] 31 | } 32 | 33 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/generic/__FunctionConvert__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.generic; 2 | 3 | import java.lang.reflect.Type; 4 | import java.util.function.Function; 5 | 6 | /** 7 | * This is a conversion which uses a simple functional mapping from one type 8 | * to another. 9 | * 10 | * This is much simpler than {@link __StringToConvert__} because this class 11 | * only operates on known methods that exist. 12 | * 13 | * @since 2018/08/27 14 | */ 15 | final class __FunctionConvert__ 16 | extends ObjectTranslator 17 | { 18 | /** The function used for conversion. */ 19 | protected final Function function; 20 | 21 | /** 22 | * Initializes the translator. 23 | * 24 | * @param __f The from type. 25 | * @param __t The to type. 26 | * @param __func The conversion function. 27 | * @throws NullPointerException On no handle was specified. 28 | * @since 2018/08/27 29 | */ 30 | __FunctionConvert__(Type __f, Type __t, Function __func) 31 | throws NullPointerException 32 | { 33 | super(__f, __t); 34 | 35 | if (__func == null) 36 | throw new NullPointerException(); 37 | 38 | this.function = __func; 39 | } 40 | 41 | /** 42 | * {@inheritDoc} 43 | * @since 2018/08/27 44 | */ 45 | @Override 46 | public final Object translate(Object __f) 47 | { 48 | // Map null to null 49 | if (__f == null) 50 | return null; 51 | 52 | // Apply the translation 53 | return this.function.apply(__f); 54 | } 55 | } 56 | 57 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/SimpleRequestHandlerWrapper.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.amazonaws.services.lambda.runtime.Context; 4 | import com.amazonaws.services.lambda.runtime.RequestHandler; 5 | 6 | /** 7 | * This class is used as a base to create simple instances of wrapped lambdas 8 | * which will provide measurements to the IOpipe service. 9 | * 10 | * This class may be used as a base to wrap requests. 11 | * 12 | * @param The input object type. 13 | * @param The output object type. 14 | * @since 2017/12/13 15 | */ 16 | public abstract class SimpleRequestHandlerWrapper 17 | implements RequestHandler 18 | { 19 | /** 20 | * This method is implemented by sub-classes and is used as the actual 21 | * entry point for lambdas. 22 | * 23 | * @param __exec The instance for the current lambda execution. The 24 | * {@link com.amazonaws.services.lambda.runtime.Context} object can be 25 | * obtained by invoking the {@link IOpipeExecution#context()} method on 26 | * the {@code __exec} parameter. 27 | * @param __input The input value. 28 | * @return The return value. 29 | * @since 2017/12/18 30 | */ 31 | protected abstract O wrappedHandleRequest(IOpipeExecution __exec, 32 | I __input); 33 | 34 | /** 35 | * {@inheritDoc} 36 | * @since 2017/12/13 37 | */ 38 | @Override 39 | public final O handleRequest(I __input, Context __context) 40 | { 41 | return IOpipeService.instance().run(__context, 42 | (__exec) -> this.wrappedHandleRequest(__exec, __input), __input); 43 | } 44 | } 45 | 46 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/trace/TraceExecution.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.trace; 2 | 3 | import com.iopipe.IOpipeExecution; 4 | import com.iopipe.plugin.IOpipePluginExecution; 5 | 6 | /** 7 | * This is the trace plugin which is used to track specific marks and measure 8 | * performance. 9 | * 10 | * @since 2018/01/20 11 | */ 12 | public class TraceExecution 13 | implements IOpipePluginExecution 14 | { 15 | /** 16 | * Initializes the trace execution instance. 17 | * 18 | * @since 2018/01/20 19 | */ 20 | TraceExecution() 21 | { 22 | } 23 | 24 | /** 25 | * Creates a new instance of a class which is used to measure how long 26 | * a block of code has executed for. The returned object is 27 | * {@link AutoCloseable} and it is highly recommended to use 28 | * try-with-resources when utilizing it although it is not required. 29 | * When the method 30 | * {@link AutoCloseable#close()} is called the measurement will be 31 | * recorded. 32 | * 33 | * @param __name The name of the measurement. 34 | * @return The measurement which was added to the report. 35 | * @throws NullPointerException On null arguments. 36 | * @deprecated This method is not recommended to be used, use 37 | * {@link TraceUtils#measure(String)} instead. 38 | * @since 2018/01/23 39 | */ 40 | @Deprecated 41 | public TraceMeasurement measure(String __name) 42 | throws NullPointerException 43 | { 44 | if (__name == null) 45 | throw new NullPointerException(); 46 | 47 | return TraceUtils.measure(__name); 48 | } 49 | } 50 | 51 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/eventinfo/ScheduledDecoder.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.eventinfo; 2 | 3 | import com.amazonaws.services.lambda.runtime.events.ScheduledEvent; 4 | import java.util.List; 5 | import java.util.Objects; 6 | 7 | /** 8 | * This class implements the decoder for Scheduled events. 9 | * 10 | * @since 2018/04/23 11 | */ 12 | public final class ScheduledDecoder 13 | implements EventInfoDecoder 14 | { 15 | /** 16 | * {@inheritDoc} 17 | * @since 2018/05/02 18 | */ 19 | @Override 20 | public void accept(ValueAcceptor __a, Object __v) 21 | throws NullPointerException 22 | { 23 | if (__a == null || __v == null) 24 | throw new NullPointerException(); 25 | 26 | ScheduledEvent v = (ScheduledEvent)__v; 27 | 28 | __a.accept("account", 29 | v.getAccount()); 30 | __a.accept("id", 31 | v.getId()); 32 | __a.accept("region", 33 | v.getRegion()); 34 | 35 | List resources = v.getResources(); 36 | if (resources != null && resources.size() >= 1) 37 | { 38 | __a.accept("resources[0]", 39 | resources.get(0)); 40 | } 41 | 42 | __a.accept("time", 43 | Objects.toString(v.getTime(), null)); 44 | } 45 | 46 | /** 47 | * {@inheritDoc} 48 | * @since 2018/04/23 49 | */ 50 | @Override 51 | public final String[] decodes() 52 | { 53 | return new String[] 54 | { 55 | "com.amazonaws.services.lambda.runtime.events.ScheduledEvent", 56 | }; 57 | } 58 | 59 | /** 60 | * {@inheritDoc} 61 | * @since 2018/04/23 62 | */ 63 | @Override 64 | public final String eventType() 65 | { 66 | return "scheduled"; 67 | } 68 | } 69 | 70 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/IntegerValue.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import java.util.concurrent.atomic.AtomicInteger; 4 | 5 | /** 6 | * Represents an integer value. 7 | * 8 | * @since 2018/01/26 9 | */ 10 | public final class IntegerValue 11 | extends Value 12 | { 13 | /** The internal value. */ 14 | protected final AtomicInteger value = 15 | new AtomicInteger(); 16 | 17 | /** 18 | * Initializes the storage. 19 | * 20 | * @param __n The variable name. 21 | * @since 2018/01/26 22 | */ 23 | public IntegerValue(String __n) 24 | { 25 | super(__n); 26 | } 27 | 28 | /** 29 | * Obtains the value. 30 | * 31 | * @return The value. 32 | * @since 2018/01/26 33 | */ 34 | public int get() 35 | { 36 | return this.value.get(); 37 | } 38 | 39 | /** 40 | * Adds to the value atomically then returns it. 41 | * 42 | * @return The new value. 43 | * @since 2018/08/15 44 | */ 45 | public int addAndGet(int __v) 46 | { 47 | return this.value.addAndGet(__v); 48 | } 49 | 50 | /** 51 | * Increments the value. 52 | * 53 | * @since 2018/01/26 54 | */ 55 | public void increment() 56 | { 57 | this.value.incrementAndGet(); 58 | } 59 | 60 | /** 61 | * Increments the value then returns it. 62 | * 63 | * @return The value after incrementing. 64 | * @since 2018/01/26 65 | */ 66 | public int incrementAndGet() 67 | { 68 | return this.value.incrementAndGet(); 69 | } 70 | 71 | /** 72 | * Sets the value. 73 | * 74 | * @param __v The new value. 75 | * @since 2018/01/26 76 | */ 77 | public void set(int __v) 78 | { 79 | this.value.set(__v); 80 | } 81 | } 82 | 83 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/trace/TracePlugin.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.trace; 2 | 3 | import com.iopipe.IOpipeConstants; 4 | import com.iopipe.IOpipeExecution; 5 | import com.iopipe.plugin.IOpipePlugin; 6 | import com.iopipe.plugin.IOpipePluginExecution; 7 | 8 | /** 9 | * This is the trace plugin which is used to track specific marks and measure 10 | * performance. 11 | * 12 | * @since 2018/01/20 13 | */ 14 | public class TracePlugin 15 | implements IOpipePlugin 16 | { 17 | /** 18 | * {@inheritDoc} 19 | * @since 2018/01/20 20 | */ 21 | @Override 22 | public boolean enabledByDefault() 23 | { 24 | return true; 25 | } 26 | 27 | /** 28 | * {@inheritDoc} 29 | * @since 2018/01/20 30 | */ 31 | @Override 32 | public IOpipePluginExecution execute(IOpipeExecution __e) 33 | { 34 | if (__e == null) 35 | throw new NullPointerException(); 36 | 37 | return new TraceExecution(); 38 | } 39 | 40 | /** 41 | * {@inheritDoc} 42 | * @since 2018/01/20 43 | */ 44 | @Override 45 | public Class executionClass() 46 | { 47 | return TraceExecution.class; 48 | } 49 | 50 | /** 51 | * {@inheritDoc} 52 | * @since 2018/01/20 53 | */ 54 | @Override 55 | public String homepage() 56 | { 57 | return "https://github.com/iopipe/iopipe-java"; 58 | } 59 | 60 | /** 61 | * {@inheritDoc} 62 | * @since 2018/01/20 63 | */ 64 | @Override 65 | public String name() 66 | { 67 | return "trace"; 68 | } 69 | 70 | /** 71 | * {@inheritDoc} 72 | * @since 2018/01/20 73 | */ 74 | @Override 75 | public String version() 76 | { 77 | return "1.8.0"; 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/eventinfo/KinesisDecoder.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.eventinfo; 2 | 3 | import com.amazonaws.services.lambda.runtime.events.KinesisEvent; 4 | import java.util.List; 5 | 6 | /** 7 | * This class implements the decoder for Kinesis events. 8 | * 9 | * @since 2018/04/23 10 | */ 11 | public final class KinesisDecoder 12 | implements EventInfoDecoder 13 | { 14 | /** 15 | * {@inheritDoc} 16 | * @since 2018/05/02 17 | */ 18 | @Override 19 | public void accept(ValueAcceptor __a, Object __v) 20 | throws NullPointerException 21 | { 22 | if (__a == null || __v == null) 23 | throw new NullPointerException(); 24 | 25 | KinesisEvent v = (KinesisEvent)__v; 26 | 27 | List records = v.getRecords(); 28 | if (records == null) 29 | return; 30 | 31 | int n = records.size(); 32 | __a.accept("Records.length", n); 33 | 34 | // Report the first one 35 | if (n >= 1) 36 | { 37 | KinesisEvent.KinesisEventRecord record = records.get(0); 38 | 39 | __a.accept("Records[0].awsRegion", 40 | record.getAwsRegion()); 41 | __a.accept("Records[0].eventSourceARN", 42 | record.getEventSourceARN()); 43 | } 44 | } 45 | 46 | /** 47 | * {@inheritDoc} 48 | * @since 2018/04/23 49 | */ 50 | @Override 51 | public final String[] decodes() 52 | { 53 | return new String[] 54 | { 55 | "com.amazonaws.services.lambda.runtime.events.KinesisEvent", 56 | }; 57 | } 58 | 59 | /** 60 | * {@inheritDoc} 61 | * @since 2018/04/23 62 | */ 63 | @Override 64 | public final String eventType() 65 | { 66 | return "kinesis"; 67 | } 68 | } 69 | 70 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/MockEngine.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.http.RemoteRequest; 4 | import java.util.function.Consumer; 5 | import java.util.function.Function; 6 | import javax.json.JsonObject; 7 | 8 | /** 9 | * This runs all of the tests using the mock service rather than the real 10 | * service. 11 | * 12 | * @since 2018/01/23 13 | */ 14 | public class MockEngine 15 | extends Engine 16 | { 17 | /** Mocked event URL. */ 18 | public static final String EVENT_URL = 19 | "https://localhost/event"; 20 | 21 | /** Mocked profiler URL. */ 22 | public static final String PROFILER_URL = 23 | "https://localhost/profiler"; 24 | 25 | /** URL Result for the profiler. */ 26 | public static final String PROFILER_RESULT_URL = 27 | "https://localhost/profiler-result"; 28 | 29 | /** 30 | * Initializes the engine. 31 | * 32 | * @since 2018/01/23 33 | */ 34 | public MockEngine() 35 | { 36 | super("mock"); 37 | } 38 | 39 | /** 40 | * {@inheritDoc} 41 | * @since 2018/01/23 42 | */ 43 | @Override 44 | protected IOpipeConfigurationBuilder generateConfig(Single __s) 45 | throws NullPointerException 46 | { 47 | if (__s == null) 48 | throw new NullPointerException(); 49 | 50 | IOpipeConfigurationBuilder rv = new IOpipeConfigurationBuilder(); 51 | 52 | rv.setEnabled(true); 53 | rv.setProjectToken(MockConnection.VALID_TOKEN); 54 | rv.setTimeOutWindow(150); 55 | rv.setServiceUrl(EVENT_URL); 56 | rv.setSignerUrl(PROFILER_URL); 57 | 58 | // Use the request handler from the single test 59 | rv.setRemoteConnectionFactory(new MockConnectionFactory()); 60 | 61 | return rv; 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/profiler/MemoryUsageStatistics.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.profiler; 2 | 3 | import java.lang.management.MemoryUsage; 4 | 5 | /** 6 | * This stores a single memory usage statistic. 7 | * 8 | * @since 2018/05/23 9 | */ 10 | public final class MemoryUsageStatistics 11 | { 12 | /** Initial memory amount. */ 13 | public final long initbytes; 14 | 15 | /** The used number of bytes. */ 16 | public final long usedbytes; 17 | 18 | /** The committed number of bytes. */ 19 | public final long committedbytes; 20 | 21 | /** The maximum number of bytes that can be used. */ 22 | public final long maxbytes; 23 | 24 | /** 25 | * Initializes the memory usage statistic. 26 | * 27 | * @param __i The initial number of bytes. 28 | * @param __u The used number of bytes. 29 | * @param __c The committed number of bytes. 30 | * @param __m The maximum number of bytes. 31 | * @since 2018/05/23 32 | */ 33 | public MemoryUsageStatistics(long __i, long __u, long __c, long __m) 34 | { 35 | this.initbytes = Math.max(-1, __i); 36 | this.usedbytes = Math.max(-1, __u); 37 | this.committedbytes = Math.max(-1, __c); 38 | this.maxbytes = Math.max(-1, __m); 39 | } 40 | 41 | /** 42 | * Initializes the memory usage from the given usage. 43 | * 44 | * @param __m The input memory usage. 45 | * @return Statistic for that usage or {@code null} if it is not valid. 46 | * @since 2018/05/23 47 | */ 48 | public static MemoryUsageStatistics from(MemoryUsage __m) 49 | { 50 | if (__m == null) 51 | return null; 52 | 53 | return new MemoryUsageStatistics(__m.getInit(), 54 | __m.getUsed(), 55 | __m.getCommitted(), 56 | __m.getMax()); 57 | } 58 | } 59 | 60 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/profiler/UptimeStatistics.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.profiler; 2 | 3 | import java.lang.management.ManagementFactory; 4 | import java.lang.management.RuntimeMXBean; 5 | 6 | /** 7 | * This contains information on the uptime of the virtual machine. 8 | * 9 | * @since 2018/05/22 10 | */ 11 | public final class UptimeStatistics 12 | { 13 | /** The start time of the virtual machine in milliseconds. */ 14 | public final long startms; 15 | 16 | /** The number of milliseconds the virtual machine has been up. */ 17 | public final long uptimems; 18 | 19 | /** 20 | * Initializes the uptime statistics. 21 | * 22 | * @param __s The start time in milliseconds. 23 | * @param __u The uptime in milliseconds. 24 | * @since 2018/05/22 25 | */ 26 | public UptimeStatistics(long __s, long __u) 27 | { 28 | this.startms = __s; 29 | this.uptimems = Math.max(-1, __u); 30 | } 31 | 32 | /** 33 | * Creates a snapshot of the uptime information. 34 | * 35 | * @return The uptime information or {@code null} if it is not valid. 36 | * @since 2018/05/22 37 | */ 38 | public static UptimeStatistics snapshot() 39 | { 40 | return UptimeStatistics.snapshot(ManagementFactory.getRuntimeMXBean()); 41 | } 42 | 43 | /** 44 | * Creates a snapshot of the uptime information. 45 | * 46 | * @param __bean The bean to obtain information from. 47 | * @return The uptime information or {@code null} if it is not valid. 48 | * @since 2018/05/22 49 | */ 50 | public static UptimeStatistics snapshot(RuntimeMXBean __bean) 51 | { 52 | if (__bean == null) 53 | return null; 54 | 55 | return new UptimeStatistics(__bean.getStartTime(), __bean.getUptime()); 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /src/test/resources/com/iopipe/eventinfo_s3.json: -------------------------------------------------------------------------------- 1 | { 2 | "Records": [ 3 | { 4 | "eventVersion": "2.0", 5 | "eventSource": "aws:s3", 6 | "awsRegion": "us-east-1", 7 | "eventTime": "1970-01-01T00:00:00.000Z", 8 | "eventName": "event-type", 9 | "userIdentity": { 10 | "principalId": "Amazon-customer-ID-of-the-user-who-caused-the-event" 11 | }, 12 | "requestParameters": { 13 | "sourceIPAddress": "ip-address-where-request-came-from" 14 | }, 15 | "responseElements": { 16 | "x-amz-request-id": "Amazon S3 generated request ID", 17 | "x-amz-id-2": "Amazon S3 host that processed the request" 18 | }, 19 | "s3": { 20 | "s3SchemaVersion": "1.0", 21 | "configurationId": "ID found in the bucket notification configuration", 22 | "bucket": { 23 | "name": "bucket-name", 24 | "ownerIdentity": { 25 | "principalId": "Amazon-customer-ID-of-the-bucket-owner" 26 | }, 27 | "arn": "bucket-ARN" 28 | }, 29 | "object": { 30 | "key": "object-key", 31 | "size": 10, 32 | "eTag": "object eTag", 33 | "versionId": "object version if bucket is versioning-enabled, otherwise null", 34 | "sequencer": "a string representation of a hexadecimal value used to determine event sequence, only used with PUTs and DELETEs" 35 | } 36 | } 37 | } 38 | ] 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/profiler/CompilerStatistics.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.profiler; 2 | 3 | import java.lang.management.CompilationMXBean; 4 | import java.lang.management.ManagementFactory; 5 | 6 | /** 7 | * This contains statistics on the compiler. 8 | * 9 | * @since 2018/05/22 10 | */ 11 | public final class CompilerStatistics 12 | { 13 | /** Time spent in milliseconds compiling. */ 14 | protected final long compilems; 15 | 16 | /** 17 | * Initializes the compiler statistics. 18 | * 19 | * @param __ms The time spent compiling. 20 | * @since 2018/05/22 21 | */ 22 | public CompilerStatistics(long __ms) 23 | { 24 | this.compilems = Math.max(-1, __ms); 25 | } 26 | 27 | /** 28 | * Returns a snapshot of the compiler statistics. 29 | * 30 | * @return The compiler statistics or {@code null} if none are available. 31 | * @since 2018/05/22 32 | */ 33 | public static CompilerStatistics snapshot() 34 | { 35 | // This is optional 36 | CompilationMXBean bean = ManagementFactory.getCompilationMXBean(); 37 | if (bean == null) 38 | return null; 39 | 40 | return CompilerStatistics.snapshot(bean); 41 | } 42 | 43 | /** 44 | * Returns a snapshot of the compiler statistics. 45 | * 46 | * @param __bean The bean to obtain the information from. 47 | * @return The compiler statistics or {@code null} if none are available. 48 | * @since 2018/05/22 49 | */ 50 | public static CompilerStatistics snapshot(CompilationMXBean __bean) 51 | { 52 | if (__bean == null) 53 | return null; 54 | 55 | // Might not be available 56 | try 57 | { 58 | return new CompilerStatistics(__bean.getTotalCompilationTime()); 59 | } 60 | 61 | // Not measureable 62 | catch (UnsupportedOperationException e) 63 | { 64 | return new CompilerStatistics(-1); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/eventinfo/APIGatewayDecoder.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.eventinfo; 2 | 3 | import com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent; 4 | 5 | /** 6 | * This class implements the decoder for API Gateway events. 7 | * 8 | * @since 2018/04/22 9 | */ 10 | public final class APIGatewayDecoder 11 | implements EventInfoDecoder 12 | { 13 | /** 14 | * {@inheritDoc} 15 | * @since 2018/05/02 16 | */ 17 | @Override 18 | public void accept(ValueAcceptor __a, Object __v) 19 | throws NullPointerException 20 | { 21 | if (__a == null || __v == null) 22 | throw new NullPointerException(); 23 | 24 | APIGatewayProxyRequestEvent v = (APIGatewayProxyRequestEvent)__v; 25 | 26 | __a.accept("httpMethod", 27 | v.getHttpMethod()); 28 | __a.accept("path", 29 | v.getPath()); 30 | __a.accept("requestContext.accountId", 31 | v.getRequestContext().getAccountId()); 32 | __a.accept("requestContext.httpMethod", 33 | v.getRequestContext().getHttpMethod()); 34 | __a.accept("requestContext.identity.userAgent", 35 | v.getRequestContext().getIdentity().getUserAgent()); 36 | __a.accept("requestContext.requestId", 37 | v.getRequestContext().getRequestId()); 38 | __a.accept("requestContext.resourcePath", 39 | v.getRequestContext().getResourcePath()); 40 | __a.accept("requestContext.stage", 41 | v.getRequestContext().getStage()); 42 | __a.accept("resource", 43 | v.getResource()); 44 | } 45 | 46 | /** 47 | * {@inheritDoc} 48 | * @since 2018/04/22 49 | */ 50 | @Override 51 | public final String[] decodes() 52 | { 53 | return new String[] 54 | { 55 | "com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent", 56 | }; 57 | } 58 | 59 | /** 60 | * {@inheritDoc} 61 | * @since 2018/04/23 62 | */ 63 | @Override 64 | public final String eventType() 65 | { 66 | return "apiGateway"; 67 | } 68 | } 69 | 70 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/http/RemoteRequest.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.http; 2 | 3 | /** 4 | * This is used to store a request which is sent to a remote server. 5 | * 6 | * This class is immutable. 7 | * 8 | * @since 2017/12/13 9 | */ 10 | public final class RemoteRequest 11 | extends RemoteBody 12 | { 13 | /** 14 | * Initializes the request with the given data. 15 | * 16 | * @param __t The mime type of the body. 17 | * @param __b The data making up the body. 18 | * @throws NullPointerException On null arguments. 19 | * @since 2018/02/24 20 | */ 21 | public RemoteRequest(String __t, byte[] __b) 22 | throws NullPointerException 23 | { 24 | super(__t, __b); 25 | } 26 | 27 | /** 28 | * Initializes the request with the given data. 29 | * 30 | * @param __t The mime type of the body. 31 | * @param __b The data making up the body. 32 | * @param __o The offset. 33 | * @param __l The length. 34 | * @throws ArrayIndexOutOfBoundsException If the offset and/or length 35 | * exceed the array bounds or are negative. 36 | * @throws NullPointerException On null arguments. 37 | * @since 2018/02/24 38 | */ 39 | public RemoteRequest(String __t, byte[] __b, int __o, int __l) 40 | throws ArrayIndexOutOfBoundsException, NullPointerException 41 | { 42 | super(__t, __b, __o, __l); 43 | } 44 | 45 | /** 46 | * Initializes the request with the given string. 47 | * 48 | * @param __t The mime type of the body. 49 | * @param __s The string to initialize the body with. 50 | * @throws NullPointerException On null arguments. 51 | * @since 2018/02/24 52 | */ 53 | public RemoteRequest(String __t, String __s) 54 | throws NullPointerException 55 | { 56 | super(__t, __s); 57 | } 58 | 59 | /** 60 | * {@inheritDoc} 61 | * @since 2018/02/24 62 | */ 63 | @Override 64 | public final boolean equals(Object __o) 65 | { 66 | return super.equals(__o) && (__o instanceof RemoteRequest); 67 | } 68 | } 69 | 70 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/__DoEmptyMethod__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.http.RemoteRequest; 4 | import com.iopipe.http.RemoteResult; 5 | import javax.json.JsonObject; 6 | 7 | /** 8 | * Tests an empty method which does nothing. 9 | * 10 | * @since 2018/01/23 11 | */ 12 | class __DoEmptyMethod__ 13 | extends Single 14 | { 15 | /** Was the function executed? */ 16 | protected final BooleanValue executedit = 17 | new BooleanValue("executedit"); 18 | 19 | /** Got mocked request? */ 20 | protected final BooleanValue errorwasnotsent = 21 | new BooleanValue("errorwasnotsent"); 22 | 23 | /** Got a result from the server okay? */ 24 | protected final BooleanValue remoterecvokay = 25 | new BooleanValue("remoterecvokay"); 26 | 27 | /** 28 | * Constructs the test. 29 | * 30 | * @since 2018/01/23 31 | */ 32 | __DoEmptyMethod__(Engine __e) 33 | { 34 | super(__e, "emptymethod"); 35 | } 36 | 37 | /** 38 | * {@inheritDoc} 39 | * @since 2018/01/23 40 | */ 41 | @Override 42 | public void end() 43 | { 44 | super.assertTrue(this.executedit); 45 | super.assertTrue(this.remoterecvokay); 46 | super.assertTrue(this.errorwasnotsent); 47 | } 48 | 49 | /** 50 | * {@inheritDoc} 51 | * @since 2018/01/23 52 | */ 53 | @Override 54 | public void remoteRequest(WrappedRequest __r) 55 | { 56 | StandardPushEvent event = (StandardPushEvent)__r.event; 57 | 58 | if (!event.hasError()) 59 | this.errorwasnotsent.set(true); 60 | } 61 | 62 | /** 63 | * {@inheritDoc} 64 | * @since 2018/01/23 65 | */ 66 | @Override 67 | public void remoteResult(WrappedResult __r) 68 | { 69 | if (__Utils__.isResultOkay(__r.result)) 70 | this.remoterecvokay.set(true); 71 | } 72 | 73 | /** 74 | * {@inheritDoc} 75 | * @since 2018/01/23 76 | */ 77 | @Override 78 | public void run(IOpipeExecution __e) 79 | throws Throwable 80 | { 81 | this.executedit.set(true); 82 | } 83 | } 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/generic/__JacksonConvert__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.generic; 2 | 3 | import com.fasterxml.jackson.databind.DeserializationFeature; 4 | import com.fasterxml.jackson.databind.JavaType; 5 | import com.fasterxml.jackson.datatype.joda.JodaModule; 6 | import com.fasterxml.jackson.databind.MapperFeature; 7 | import com.fasterxml.jackson.databind.ObjectMapper; 8 | import com.fasterxml.jackson.databind.type.TypeFactory; 9 | import java.lang.reflect.Type; 10 | 11 | /** 12 | * Converter which uses jackson. 13 | * 14 | * @since 2018/08/21 15 | */ 16 | final class __JacksonConvert__ 17 | extends ObjectTranslator 18 | { 19 | /** The object mapper used. */ 20 | protected final ObjectMapper mapper; 21 | 22 | /** The type that is used for the conversion process. */ 23 | protected final JavaType type; 24 | 25 | /** 26 | * Initializes the translator. 27 | * 28 | * @param __f The from type. 29 | * @param __t The to type. 30 | * @since 2018/08/21 31 | */ 32 | __JacksonConvert__(Type __f, Type __t) 33 | { 34 | super(__f, __t); 35 | 36 | // Setup mapper 37 | ObjectMapper mapper = new ObjectMapper(); 38 | this.mapper = mapper; 39 | 40 | // The case mappings for JSON are treated as case insensitive 41 | mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, 42 | true); 43 | mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, 44 | false); 45 | 46 | // Dates must be constructed 47 | mapper.registerModule(new JodaModule()); 48 | 49 | // Setup type that can be used to handle the given type 50 | TypeFactory factory = mapper.getTypeFactory(); 51 | JavaType type; 52 | this.type = (type = factory.constructType(__t)); 53 | } 54 | 55 | /** 56 | * {@inheritDoc} 57 | * @since 2018/08/21 58 | */ 59 | @Override 60 | public final Object translate(Object __f) 61 | { 62 | if (__f == null) 63 | return null; 64 | 65 | return this.mapper.convertValue(__f, this.type); 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/logger/LoggerPlugin.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.logger; 2 | 3 | import com.iopipe.IOpipeExecution; 4 | import com.iopipe.plugin.IOpipePlugin; 5 | import com.iopipe.plugin.IOpipePluginExecution; 6 | import com.iopipe.plugin.IOpipePluginPostExecutable; 7 | 8 | /** 9 | * This class contains the definition of the logger plugin. 10 | * 11 | * @since 2018/09/24 12 | */ 13 | public final class LoggerPlugin 14 | implements IOpipePlugin, IOpipePluginPostExecutable 15 | { 16 | /** 17 | * {@inheritDoc} 18 | * @since 2018/09/24 19 | */ 20 | @Override 21 | public final IOpipePluginExecution execute(IOpipeExecution __e) 22 | throws NullPointerException 23 | { 24 | if (__e == null) 25 | throw new NullPointerException(); 26 | 27 | return new LoggerExecution(__e); 28 | } 29 | 30 | /** 31 | * {@inheritDoc} 32 | * @since 2018/09/24 33 | */ 34 | @Override 35 | public final boolean enabledByDefault() 36 | { 37 | return false; 38 | } 39 | 40 | /** 41 | * {@inheritDoc} 42 | * @since 2018/09/24 43 | */ 44 | @Override 45 | public final Class executionClass() 46 | { 47 | return LoggerExecution.class; 48 | } 49 | 50 | /** 51 | * {@inheritDoc} 52 | * @since 2018/09/24 53 | */ 54 | @Override 55 | public final String homepage() 56 | { 57 | return "https://github.com/iopipe/iopipe-java/"; 58 | } 59 | 60 | /** 61 | * {@inheritDoc} 62 | * @since 2018/09/24 63 | */ 64 | @Override 65 | public final String name() 66 | { 67 | return "logger"; 68 | } 69 | 70 | /** 71 | * {@inheritDoc} 72 | * @since 2018/09/25 73 | */ 74 | @Override 75 | public void postExecute(IOpipePluginExecution __e) 76 | throws NullPointerException 77 | { 78 | if (__e == null) 79 | throw new NullPointerException(); 80 | 81 | ((LoggerExecution)__e).__post(); 82 | } 83 | 84 | /** 85 | * {@inheritDoc} 86 | * @since 2018/09/24 87 | */ 88 | @Override 89 | public final String version() 90 | { 91 | return "1.0.0"; 92 | } 93 | } 94 | 95 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/__DoThrowException__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.http.RemoteRequest; 4 | import com.iopipe.http.RemoteResult; 5 | import javax.json.JsonObject; 6 | 7 | /** 8 | * Tests throwing of an exception. 9 | * 10 | * @since 2018/01/23 11 | */ 12 | class __DoThrowException__ 13 | extends Single 14 | { 15 | /** Got mocked request? */ 16 | protected final BooleanValue errorwassent = 17 | new BooleanValue("errorwassent"); 18 | 19 | /** Got a result from the server okay? */ 20 | protected final BooleanValue remoterecvokay = 21 | new BooleanValue("remoterecvokay"); 22 | 23 | /** Has error auto label? */ 24 | protected final BooleanValue hasautolabel = 25 | new BooleanValue("hasautolabel"); 26 | 27 | /** 28 | * Constructs the test. 29 | * 30 | * @since 2018/01/23 31 | */ 32 | __DoThrowException__(Engine __e) 33 | { 34 | super(__e, "thrownexception"); 35 | } 36 | 37 | /** 38 | * {@inheritDoc} 39 | * @since 2018/01/23 40 | */ 41 | @Override 42 | public void end() 43 | { 44 | super.assertTrue(this.remoterecvokay); 45 | super.assertTrue(this.errorwassent); 46 | super.assertTrue(this.hasautolabel); 47 | } 48 | 49 | /** 50 | * {@inheritDoc} 51 | * @since 2018/01/23 52 | */ 53 | @Override 54 | public void remoteRequest(WrappedRequest __r) 55 | { 56 | StandardPushEvent event = (StandardPushEvent)__r.event; 57 | 58 | if (event.hasError()) 59 | this.errorwassent.set(true); 60 | 61 | if (event.labels.contains("@iopipe/error")) 62 | this.hasautolabel.set(true); 63 | } 64 | 65 | /** 66 | * {@inheritDoc} 67 | * @since 2018/01/23 68 | */ 69 | @Override 70 | public void remoteResult(WrappedResult __r) 71 | { 72 | if (__Utils__.isResultOkay(__r.result)) 73 | this.remoterecvokay.set(true); 74 | } 75 | 76 | /** 77 | * {@inheritDoc} 78 | * @since 2018/01/23 79 | */ 80 | @Override 81 | public void run(IOpipeExecution __e) 82 | throws Throwable 83 | { 84 | throw new MockException("Mock Exception"); 85 | } 86 | } 87 | 88 | 89 | -------------------------------------------------------------------------------- /.circleci/layers.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | # Need this to publish 4 | if ! which aws 5 | then 6 | echo "No AWS command" 7 | exit 1 8 | fi 9 | 10 | # Package JAR and place all dependencies into the target 11 | mvn clean 12 | mvn package -Dmaven.test.skip=true 13 | mvn dependency:copy-dependencies -DincludeScope=runtime -DoutputDirectory=target 14 | 15 | # Copy target JARs to library directory 16 | rm -rvf java 17 | mkdir -p java/lib/ 18 | cp -v target/*.jar java/lib/ 19 | rm -vf java/lib/*-sources.jar java/lib/*-javadoc.jar 20 | 21 | # ZIP it up 22 | rm -f java8.zip 23 | zip -rq java8.zip java 24 | 25 | # Unique identification for this release 26 | __gh="$(git rev-parse HEAD)" 27 | 28 | # The S3 file key 29 | __s3="iopipe-java8/$__gh.zip" 30 | 31 | # Upload for each region 32 | for __region in ap-northeast-1 ap-northeast-2 ap-south-1 ap-southeast-1 ap-southeast-2 ca-central-1 eu-central-1 eu-west-1 eu-west-2 eu-west-3 us-east-1 us-east-2 us-west-1 us-west-2 33 | do 34 | # The destination bucket, since it is region specific 35 | __bn="iopipe-layers-$__region" 36 | 37 | # Upload to S3 bucket first 38 | echo "Uploading to S3 in region $__region..." 39 | aws --region "$__region" s3 cp java8.zip "s3://$__bn/$__s3" 40 | 41 | # Publish layer, but we need the version 42 | echo "Publishing..." 43 | __ver="`aws lambda publish-layer-version \ 44 | --layer-name IOpipeJava8 \ 45 | --content "S3Bucket=$__bn,S3Key=$__s3" \ 46 | --description 'IOpipe Layer Java 8' \ 47 | --compatible-runtimes java8 \ 48 | --license-info 'Apache 2.0' \ 49 | --region $__region \ 50 | --output text \ 51 | --query Version`" 52 | if [ -z "$__ver" ] 53 | then 54 | echo "Failed to publish!" 55 | exit 2 56 | fi 57 | echo "Published version $__ver" 58 | 59 | # Set permissions 60 | echo "Setting permissions..." 61 | aws lambda add-layer-version-permission \ 62 | --layer-name IOpipeJava8 \ 63 | --version-number "$__ver" \ 64 | --statement-id public \ 65 | --action lambda:GetLayerVersion \ 66 | --principal "*" \ 67 | --region "$__region" 68 | echo "Permissions set" 69 | done 70 | 71 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/generic/__StringToConvert__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.generic; 2 | 3 | import java.lang.invoke.MethodHandle; 4 | import java.lang.reflect.Type; 5 | 6 | /** 7 | * This represents a conversion from a string to a given object. Note that 8 | * a method handle is used because the target is of any type which means that 9 | * there may or may be a method that exists. So this is different from 10 | * {@code __FunctionConvert__} since there may be a lack of a public 11 | * constructor or a lack of {@code valueOf(string)} and because there is no 12 | * publically known interface to handle these cases. 13 | * 14 | * @since 2018/08/24 15 | */ 16 | final class __StringToConvert__ 17 | extends ObjectTranslator 18 | { 19 | /** The method handle which generates the argument. */ 20 | protected final MethodHandle constructor; 21 | 22 | /** 23 | * Initializes the translator. 24 | * 25 | * @param __f The from type. 26 | * @param __t The to type. 27 | * @param __c The constructor to the method. 28 | * @throws NullPointerException On no handle was specified. 29 | * @since 2018/08/24 30 | */ 31 | __StringToConvert__(Type __f, Type __t, MethodHandle __c) 32 | throws NullPointerException 33 | { 34 | super(__f, __t); 35 | 36 | if (__c == null) 37 | throw new NullPointerException(); 38 | 39 | this.constructor = __c; 40 | } 41 | 42 | /** 43 | * {@inheritDoc} 44 | * @since 2018/08/24 45 | */ 46 | @Override 47 | public final Object translate(Object __f) 48 | { 49 | // Constructors and valueOf() may fail since they may require 50 | // an argument, but this method always maps to null anyway so 51 | if (__f == null) 52 | return null; 53 | 54 | try 55 | { 56 | return this.constructor.invoke((String)__f); 57 | } 58 | catch (Throwable t) 59 | { 60 | if (t instanceof RuntimeException) 61 | throw (RuntimeException)t; 62 | else if (t instanceof Error) 63 | throw (Error)t; 64 | else 65 | throw new RuntimeException("Object translator threw " + 66 | "checked exception.", t); 67 | } 68 | } 69 | } 70 | 71 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/profiler/MemoryStatistics.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.profiler; 2 | 3 | import java.lang.management.ManagementFactory; 4 | import java.lang.management.MemoryMXBean; 5 | 6 | /** 7 | * This contains statistics for the VM memory. 8 | * 9 | * @since 2018/05/22 10 | */ 11 | public final class MemoryStatistics 12 | { 13 | /** Heap memory usage. */ 14 | public final MemoryUsageStatistics heap; 15 | 16 | /** Non-heap memory usage. */ 17 | public final MemoryUsageStatistics nonheap; 18 | 19 | /** Pending finalization count. */ 20 | public final int pendingfinalizers; 21 | 22 | /** 23 | * Initializes the memory statistics. 24 | * 25 | * @param __h Heap usage. 26 | * @param __n Non-heap usage. 27 | * @param __f Pending finalizers. 28 | * @since 2018/05/24 29 | */ 30 | public MemoryStatistics(MemoryUsageStatistics __h, MemoryUsageStatistics __n, 31 | int __f) 32 | { 33 | this.heap = (__h != null ? __h : 34 | new MemoryUsageStatistics(-1, -1, -1, -1)); 35 | this.nonheap = (__n != null ? __n : 36 | new MemoryUsageStatistics(-1, -1, -1, -1)); 37 | this.pendingfinalizers = Math.max(-1, __f); 38 | } 39 | 40 | /** 41 | * Obtains a snapshot of the memory usage. 42 | * 43 | * @return The memory usage snapshot or {@code null} if it is not valid. 44 | * @since 2018/05/24 45 | */ 46 | public static MemoryStatistics snapshot() 47 | { 48 | return MemoryStatistics.snapshot( 49 | ManagementFactory.getMemoryMXBean()); 50 | } 51 | 52 | /** 53 | * Builds a snapshot from the given bean. 54 | * 55 | * @param __bean The bean to snapshot. 56 | * @return The snapshot of the given bean or {@code null} if it is not 57 | * valid. 58 | * @since 2018/05/24 59 | */ 60 | public static MemoryStatistics snapshot(MemoryMXBean __bean) 61 | { 62 | if (__bean == null) 63 | return null; 64 | 65 | return new MemoryStatistics( 66 | MemoryUsageStatistics.from(__bean.getHeapMemoryUsage()), 67 | MemoryUsageStatistics.from(__bean.getNonHeapMemoryUsage()), 68 | __bean.getObjectPendingFinalizationCount()); 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/profiler/ClassLoaderStatistics.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.profiler; 2 | 3 | import java.lang.management.ClassLoadingMXBean; 4 | import java.lang.management.ManagementFactory; 5 | 6 | /** 7 | * This class contains a snapshot of information on the class loader. 8 | * 9 | * @since 2018/05/22 10 | */ 11 | public final class ClassLoaderStatistics 12 | { 13 | /** Currently loaded classes. */ 14 | public final int current; 15 | 16 | /** Total number of classes loaded. */ 17 | public final long loaded; 18 | 19 | /** Total number of garbage collected classes. */ 20 | public final long unloaded; 21 | 22 | /** 23 | * Initializes the class loader statistics. 24 | * 25 | * @param __c The current number of classes loaded. 26 | * @param __l The number of classes loaded. 27 | * @param __u The number of classes unloaded. 28 | * @since 2018/05/22 29 | */ 30 | public ClassLoaderStatistics(int __c, long __l, long __u) 31 | { 32 | this.current = Math.max(0, __c); 33 | this.loaded = Math.max(0, __l); 34 | this.unloaded = Math.max(0, __u); 35 | } 36 | 37 | /** 38 | * Creates a snapshot of the class loader statistics. 39 | * 40 | * @return The generated statistics. 41 | * @return The generated statistics or {@code null} if no statistics were 42 | * generated. 43 | * @since 2018/05/22 44 | */ 45 | public static ClassLoaderStatistics snapshot() 46 | { 47 | return ClassLoaderStatistics.snapshot( 48 | ManagementFactory.getClassLoadingMXBean()); 49 | } 50 | 51 | /** 52 | * Creates a snapshot of the class loader statistics. 53 | * 54 | * @param __bean The bean to get information from. 55 | * @return The generated statistics or {@code null} if no statistics were 56 | * generated. 57 | * @since 2018/05/22 58 | */ 59 | public static ClassLoaderStatistics snapshot(ClassLoadingMXBean __bean) 60 | { 61 | if (__bean == null) 62 | return null; 63 | 64 | return new ClassLoaderStatistics( 65 | __bean.getLoadedClassCount(), 66 | __bean.getTotalLoadedClassCount(), 67 | __bean.getUnloadedClassCount()); 68 | } 69 | } 70 | 71 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/SimpleRequestStreamHandlerWrapper.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.amazonaws.services.lambda.runtime.Context; 4 | import com.amazonaws.services.lambda.runtime.RequestStreamHandler; 5 | import java.io.InputStream; 6 | import java.io.IOException; 7 | import java.io.OutputStream; 8 | 9 | /** 10 | * This class is used as a base to create simple instances of wrapped lambdas 11 | * which will provide measurements to the IOpipe service. 12 | * 13 | * This class may be used as a base to wrap requests. 14 | * 15 | * @since 2017/12/13 16 | */ 17 | public abstract class SimpleRequestStreamHandlerWrapper 18 | implements RequestStreamHandler 19 | { 20 | /** 21 | * This method is implemented by sub-classes and is used as the actual 22 | * entry point for lambdas. 23 | * 24 | * @param __exec The instance for the current lambda execution. The 25 | * {@link com.amazonaws.services.lambda.runtime.Context} object can be 26 | * obtained by invoking the {@link IOpipeExecution#context()} method on 27 | * the {@code __exec} parameter. 28 | * @param __in The input stream. 29 | * @param __out The output stream. 30 | * @throws IOException On read/write errors. 31 | * @since 2017/12/18 32 | */ 33 | protected abstract void wrappedHandleRequest(IOpipeExecution __exec, 34 | InputStream __in, OutputStream __out) 35 | throws IOException; 36 | 37 | /** 38 | * {@inheritDoc} 39 | * @since 2017/12/13 40 | */ 41 | @Override 42 | public final void handleRequest(InputStream __in, OutputStream __out, 43 | Context __context) 44 | throws IOException 45 | { 46 | try 47 | { 48 | IOpipeService.instance().run(__context, 49 | (__exec) -> 50 | { 51 | try 52 | { 53 | this.wrappedHandleRequest(__exec, __in, __out); 54 | return null; 55 | } 56 | catch (IOException e) 57 | { 58 | IOpipeWrappedException toss = 59 | new IOpipeWrappedException(e.getMessage(), e); 60 | throw toss; 61 | } 62 | }, __in); 63 | } 64 | catch (IOpipeWrappedException e) 65 | { 66 | throw (IOException)e.getCause(); 67 | } 68 | } 69 | } 70 | 71 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/eventinfo/EventInfoDecoder.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.eventinfo; 2 | 3 | /** 4 | * This interface represents a decoder for event types being input into the 5 | * executed method and contains the information that is needed to parse 6 | * fields accordingly. 7 | * 8 | * @since 2018/04/22 9 | */ 10 | public interface EventInfoDecoder 11 | { 12 | /** 13 | * Accepts the given value to decode events from. 14 | * 15 | * @param __a Where to store values. 16 | * @param __v The value to decode. 17 | * @throws NullPointerException On null arguments. 18 | * @since 2018/05/02 19 | */ 20 | public abstract void accept(ValueAcceptor __a, Object __v) 21 | throws NullPointerException; 22 | 23 | /** 24 | * Returns the class names which this provides a decoder for. 25 | * 26 | * @return The classes this decodes for. 27 | * @since 2018/11/20 28 | */ 29 | public abstract String[] decodes(); 30 | 31 | /** 32 | * Returns the event type string this will be specified under. 33 | * 34 | * @return The string which specified the event type. 35 | * @since 2018/04/23 36 | */ 37 | public abstract String eventType(); 38 | 39 | /** 40 | * Returns the slugified event type. 41 | * 42 | * For example {@code apiGateway} becomes {@code api-gateway}. 43 | * 44 | * @return The slugified event type. 45 | * @since 2018/07/16 46 | */ 47 | public default String slugifiedEventType() 48 | { 49 | // Use event type but fallback just in case it was never set 50 | String et = this.eventType(); 51 | if (et == null) 52 | et = "unknown"; 53 | 54 | // Just go through and add dashes before capitals 55 | StringBuilder sb = new StringBuilder(); 56 | for (int i = 0, n = et.length(); i < n; i++) 57 | { 58 | char c = et.charAt(i); 59 | 60 | // Prefix with dash? 61 | if (c >= 'A' && c <= 'Z') 62 | { 63 | // Never dash on first character 64 | if (i > 0) 65 | sb.append('-'); 66 | 67 | // Lowercase it 68 | c = (char)((c - 'A') + 'a'); 69 | } 70 | 71 | sb.append(c); 72 | } 73 | 74 | return sb.toString(); 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/eventinfo/SQSDecoder.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.eventinfo; 2 | 3 | import com.amazonaws.services.lambda.runtime.events.SQSEvent; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | /** 8 | * This decoded SQS events. 9 | * 10 | * @since 2018/08/02 11 | */ 12 | public final class SQSDecoder 13 | implements EventInfoDecoder 14 | { 15 | /** 16 | * {@inheritDoc} 17 | * @since 2018/08/02 18 | */ 19 | @Override 20 | public final void accept(ValueAcceptor __a, Object __v) 21 | throws NullPointerException 22 | { 23 | if (__a == null || __v == null) 24 | throw new NullPointerException(); 25 | 26 | SQSEvent e = (SQSEvent)__v; 27 | 28 | // No records used 29 | List records = e.getRecords(); 30 | if (records == null || records.isEmpty()) 31 | return; 32 | 33 | SQSEvent.SQSMessage record = records.get(0); 34 | 35 | __a.accept("awsRegion", 36 | record.getAwsRegion()); 37 | __a.accept("eventSourceARN", 38 | record.getEventSourceArn()); 39 | __a.accept("md5OfBody", 40 | record.getMd5OfBody()); 41 | __a.accept("messageId", 42 | record.getMessageId()); 43 | __a.accept("receiptHandle", 44 | record.getReceiptHandle()); 45 | 46 | Map attr = record.getAttributes(); 47 | if (attr != null) 48 | { 49 | __a.accept("attributes.ApproximateFirstReceiveTimestamp", 50 | attr.get("ApproximateFirstReceiveTimestamp")); 51 | __a.accept("attributes.ApproximateReceiveCount", 52 | attr.get("ApproximateReceiveCount")); 53 | __a.accept("attributes.SenderId", 54 | attr.get("SenderId")); 55 | __a.accept("attributes.SentTimestamp", 56 | attr.get("SentTimestamp")); 57 | } 58 | } 59 | 60 | /** 61 | * {@inheritDoc} 62 | * @since 2018/08/02 63 | */ 64 | @Override 65 | public final String[] decodes() 66 | { 67 | return new String[] 68 | { 69 | "com.amazonaws.services.lambda.runtime.events.SQSEvent", 70 | }; 71 | } 72 | 73 | /** 74 | * {@inheritDoc} 75 | * @since 2018/08/02 76 | */ 77 | @Override 78 | public final String eventType() 79 | { 80 | return "sqs"; 81 | } 82 | } 83 | 84 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/__DoRecursive__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.http.RemoteRequest; 4 | import com.iopipe.http.RemoteResult; 5 | 6 | /** 7 | * This checks to make sure that recursive calls operate correctly. 8 | * 9 | * @since 2018/08/17 10 | */ 11 | class __DoRecursive__ 12 | extends Single 13 | { 14 | /** Sent with no exception? */ 15 | protected final BooleanValue noerror = 16 | new BooleanValue("noerror"); 17 | 18 | /** Got a result from the server okay? */ 19 | protected final BooleanValue remoterecvokay = 20 | new BooleanValue("remoterecvokay"); 21 | 22 | /** Does the label exist? */ 23 | protected final BooleanValue haslabel = 24 | new BooleanValue("haslabel"); 25 | 26 | /** 27 | * Constructs the test. 28 | * 29 | * @param __e The owning engine. 30 | * @since 2018/08/17 31 | */ 32 | __DoRecursive__(Engine __e) 33 | { 34 | super(__e, "recursive"); 35 | } 36 | 37 | /** 38 | * {@inheritDoc} 39 | * @since 2018/08/17 40 | */ 41 | @Override 42 | public void end() 43 | { 44 | super.assertTrue(this.remoterecvokay); 45 | super.assertTrue(this.noerror); 46 | 47 | super.assertTrue(this.haslabel); 48 | } 49 | 50 | /** 51 | * {@inheritDoc} 52 | * @since 2018/08/17 53 | */ 54 | @Override 55 | public void remoteRequest(WrappedRequest __r) 56 | { 57 | StandardPushEvent event = (StandardPushEvent)__r.event; 58 | 59 | // It is invalid if there is an error 60 | if (!event.hasError()) 61 | this.noerror.set(true); 62 | 63 | // The label must be added 64 | if (event.labels.contains("squirrels")) 65 | this.haslabel.set(true); 66 | } 67 | 68 | /** 69 | * {@inheritDoc} 70 | * @since 2018/08/17 71 | */ 72 | @Override 73 | public void remoteResult(WrappedResult __r) 74 | { 75 | if (__Utils__.isResultOkay(__r.result)) 76 | this.remoterecvokay.set(true); 77 | } 78 | 79 | /** 80 | * {@inheritDoc} 81 | * @since 2018/08/17 82 | */ 83 | @Override 84 | public void run(IOpipeExecution __e) 85 | throws Throwable 86 | { 87 | IOpipeService.instance().run(__e.context(), (__x) -> 88 | { 89 | __x.label("squirrels"); 90 | return null; 91 | }); 92 | } 93 | } 94 | 95 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/eventinfo/SNSDecoder.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.eventinfo; 2 | 3 | import com.amazonaws.services.lambda.runtime.events.SNSEvent; 4 | import java.util.List; 5 | import java.util.Objects; 6 | 7 | /** 8 | * This class implements the decoder for SNS events. 9 | * 10 | * @since 2018/04/23 11 | */ 12 | public final class SNSDecoder 13 | implements EventInfoDecoder 14 | { 15 | /** 16 | * {@inheritDoc} 17 | * @since 2018/05/02 18 | */ 19 | @Override 20 | public void accept(ValueAcceptor __a, Object __v) 21 | throws NullPointerException 22 | { 23 | if (__a == null || __v == null) 24 | throw new NullPointerException(); 25 | 26 | SNSEvent v = (SNSEvent)__v; 27 | 28 | // Only record the first record 29 | List records = v.getRecords(); 30 | if (records == null || records.size() <= 0) 31 | return; 32 | SNSEvent.SNSRecord record = records.get(0); 33 | 34 | __a.accept("Records[0].EventSubscriptionArn", 35 | record.getEventSubscriptionArn()); 36 | 37 | SNSEvent.SNS sns = record.getSNS(); 38 | if (sns != null) 39 | { 40 | __a.accept("Records[0].Sns.MessageId", 41 | sns.getMessageId()); 42 | __a.accept("Records[0].Sns.Signature", 43 | sns.getSignature()); 44 | __a.accept("Records[0].Sns.SignatureVersion", 45 | sns.getSignatureVersion()); 46 | __a.accept("Records[0].Sns.SigningCertUrl", 47 | sns.getSigningCertUrl()); 48 | __a.accept("Records[0].Sns.UnsubscribeUrl", 49 | sns.getUnsubscribeUrl()); 50 | __a.accept("Records[0].Sns.Subject", 51 | sns.getSubject()); 52 | __a.accept("Records[0].Sns.Timestamp", 53 | Objects.toString(sns.getTimestamp(), null)); 54 | __a.accept("Records[0].Sns.TopicArn", 55 | sns.getTopicArn()); 56 | __a.accept("Records[0].Sns.Type", 57 | sns.getType()); 58 | } 59 | } 60 | 61 | /** 62 | * {@inheritDoc} 63 | * @since 2018/04/23 64 | */ 65 | @Override 66 | public final String[] decodes() 67 | { 68 | return new String[] 69 | { 70 | "com.amazonaws.services.lambda.runtime.events.SNSEvent", 71 | }; 72 | } 73 | 74 | /** 75 | * {@inheritDoc} 76 | * @since 2018/04/23 77 | */ 78 | @Override 79 | public final String eventType() 80 | { 81 | return "sns"; 82 | } 83 | } 84 | 85 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/__RequestSender__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.http.NullConnection; 4 | import com.iopipe.http.RemoteBody; 5 | import com.iopipe.http.RemoteConnection; 6 | import com.iopipe.http.RemoteConnectionFactory; 7 | import com.iopipe.http.RemoteException; 8 | import com.iopipe.http.RemoteRequest; 9 | import com.iopipe.http.RemoteResult; 10 | import com.iopipe.http.RequestType; 11 | import java.util.concurrent.atomic.AtomicInteger; 12 | import org.pmw.tinylog.Logger; 13 | 14 | /** 15 | * This class manages sending requests to the remote service. 16 | * 17 | * @since 2018/11/19 18 | */ 19 | final class __RequestSender__ 20 | { 21 | /** The connection to the server. */ 22 | protected final RemoteConnection connection; 23 | 24 | /** 25 | * Initializes the request sender. 26 | * 27 | * @param __con The remote service to connect to. 28 | * @throws NullPointerException On null arguments. 29 | * @since 2018/11/19 30 | */ 31 | __RequestSender__(RemoteConnection __con) 32 | throws NullPointerException 33 | { 34 | if (__con == null) 35 | throw new NullPointerException(); 36 | 37 | this.connection = __con; 38 | } 39 | 40 | /** 41 | * Sends the specified request to the server, using the request ID. 42 | * 43 | * @param __r The request to send to the server. 44 | * @return The result of the report. 45 | * @throws NullPointerException On null arguments. 46 | * @since 2017/12/15 47 | */ 48 | final RemoteResult __send(RemoteRequest __r) 49 | throws NullPointerException 50 | { 51 | if (__r == null) 52 | throw new NullPointerException(); 53 | 54 | // Send request 55 | try 56 | { 57 | RemoteResult result = this.connection.send(RequestType.POST, __r); 58 | 59 | // Only the 200 range is valid for okay responses 60 | int code = result.code(); 61 | if (!(code >= 200 && code < 300)) 62 | { 63 | // Only emit errors for failed requests 64 | Logger.error("Request {} failed with result {}.", 65 | __r, result); 66 | } 67 | 68 | return result; 69 | } 70 | 71 | // Failed to write to the server 72 | catch (RemoteException e) 73 | { 74 | Logger.error(e, "Request {} failed due to exception.", __r); 75 | 76 | return new RemoteResult(503, RemoteBody.MIMETYPE_JSON, ""); 77 | } 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/profiler/Tracker.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.profiler; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collection; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * This class keeps track of executions which have occured. 10 | * 11 | * @since 2018/02/12 12 | */ 13 | public final class Tracker 14 | { 15 | /** Method tracker. */ 16 | protected final MethodTracker methods = 17 | new MethodTracker(); 18 | 19 | /** Thread recordings. */ 20 | private final Map _threads = 21 | new HashMap<>(); 22 | 23 | /** 24 | * Returns the methods which have been tracked. 25 | * 26 | * @return The tracked methods. 27 | * @since 2018/02/19 28 | */ 29 | public MethodTracker methods() 30 | { 31 | return this.methods; 32 | } 33 | 34 | /** 35 | * Parses and keeps track of the specified stack trace. 36 | * 37 | * @param __abs The absolute time since the start of execution in 38 | * nanoseconds. 39 | * @param __rel The relative time since the last trace. 40 | * @param __thread The thread which was traced. 41 | * @throws NullPointerException On null arguments. 42 | * @since 2018/02/12 43 | */ 44 | public final void parseStackTrace(long __abs, int __rel, Thread __thread) 45 | throws NullPointerException 46 | { 47 | if (__thread == null) 48 | throw new NullPointerException(); 49 | 50 | TrackedThread stat; 51 | 52 | // In the future recording traces could be done in multiple threads 53 | Map threads = this._threads; 54 | synchronized (threads) 55 | { 56 | stat = threads.get(__thread); 57 | if (stat == null) 58 | threads.put(__thread, (stat = new TrackedThread(__thread, 59 | threads.size(), this.methods))); 60 | } 61 | 62 | // Record thread information 63 | stat.parseStackTrace(__abs, __rel); 64 | } 65 | 66 | /** 67 | * Returns the state information for each thread. 68 | * 69 | * @return The thread information. 70 | * @since 2018/02/19 71 | */ 72 | public final TrackedThread[] threads() 73 | { 74 | Map threads = this._threads; 75 | synchronized (threads) 76 | { 77 | Collection values = threads.values(); 78 | return values.toArray(new TrackedThread[values.size()]); 79 | } 80 | } 81 | } 82 | 83 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/eventinfo/EventInfoExecution.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.eventinfo; 2 | 3 | import com.iopipe.CustomMetric; 4 | import com.iopipe.IOpipeExecution; 5 | import com.iopipe.plugin.IOpipePluginExecution; 6 | import java.util.concurrent.atomic.AtomicReference; 7 | 8 | /** 9 | * This is the trace plugin which is used to track specific marks and measure 10 | * performance. 11 | * 12 | * @since 2018/04/22 13 | */ 14 | public class EventInfoExecution 15 | implements IOpipePluginExecution 16 | { 17 | /** The execution to track. */ 18 | protected final IOpipeExecution execution; 19 | 20 | /** Decoders to use for events. */ 21 | protected final EventInfoDecoders decoders; 22 | 23 | /** 24 | * Initializes the plugin state for a single execution. 25 | * 26 | * @param __exec The execution to record metrics into and where to get 27 | * the event source from. 28 | * @param __ds The decoders to use for events. 29 | * @throws NullPointerException On null arguments. 30 | * @since 2018/04/22 31 | */ 32 | public EventInfoExecution(IOpipeExecution __exec, EventInfoDecoders __ds) 33 | throws NullPointerException 34 | { 35 | if (__exec == null || __ds == null) 36 | throw new NullPointerException(); 37 | 38 | this.execution = __exec; 39 | this.decoders = __ds; 40 | } 41 | 42 | /** 43 | * Waits for the event info parsing thread to finish parsing the event 44 | * type and registers all of the custom metrics used. 45 | * 46 | * @since 2018/04/24 47 | */ 48 | final void __post() 49 | { 50 | // Do not try anything if there is no object to decode 51 | IOpipeExecution execution = this.execution; 52 | Object input = execution.input(); 53 | if (input == null) 54 | return; 55 | 56 | // Get decoder for this object 57 | EventInfoDecoder decoder = this.decoders.getDecoder(input.getClass()); 58 | if (decoder == null) 59 | return; 60 | 61 | // Parse the event 62 | ValueAcceptor va = new ValueAcceptor(decoder.eventType()); 63 | try 64 | { 65 | decoder.accept(va, input); 66 | } 67 | 68 | // Failed to decode 69 | catch (Throwable e) 70 | { 71 | return; 72 | } 73 | 74 | // Add all custom metrics 75 | execution.customMetrics(va.get()); 76 | execution.label("@iopipe/plugin-event-info"); 77 | execution.label("@iopipe/" + decoder.slugifiedEventType()); 78 | } 79 | } 80 | 81 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/TestPlugin.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.plugin.IOpipePlugin; 4 | import com.iopipe.plugin.IOpipePluginExecution; 5 | import com.iopipe.plugin.IOpipePluginPreExecutable; 6 | import com.iopipe.plugin.IOpipePluginPostExecutable; 7 | 8 | /** 9 | * This is a test plugin which exists within the test system. 10 | * 11 | * @since 2018/01/20 12 | */ 13 | public class TestPlugin 14 | implements IOpipePlugin, IOpipePluginPreExecutable, 15 | IOpipePluginPostExecutable 16 | { 17 | /** 18 | * {@inheritDoc} 19 | * @since 2018/01/20 20 | */ 21 | @Override 22 | public final IOpipePluginExecution execute(IOpipeExecution __e) 23 | throws NullPointerException 24 | { 25 | if (__e == null) 26 | throw new NullPointerException(); 27 | 28 | return new TestExecution(__e); 29 | } 30 | 31 | /** 32 | * {@inheritDoc} 33 | * @since 2018/01/20 34 | */ 35 | @Override 36 | public final Class executionClass() 37 | { 38 | return TestExecution.class; 39 | } 40 | 41 | /** 42 | * {@inheritDoc} 43 | * @since 2018/01/20 44 | */ 45 | @Override 46 | public final String homepage() 47 | { 48 | return "https://github.com/iopipe/iopipe-java"; 49 | } 50 | 51 | /** 52 | * {@inheritDoc} 53 | * @since 2018/01/20 54 | */ 55 | @Override 56 | public final String name() 57 | { 58 | return "test"; 59 | } 60 | 61 | /** 62 | * {@inheritDoc} 63 | * @since 2018/01/20 64 | */ 65 | @Override 66 | public final void preExecute(IOpipePluginExecution __e) 67 | throws NullPointerException 68 | { 69 | if (__e == null) 70 | throw new NullPointerException(); 71 | 72 | ((TestExecution)__e).execution(). 73 | customMetric("pre", "pre"); 74 | } 75 | 76 | /** 77 | * {@inheritDoc} 78 | * @since 2018/01/20 79 | */ 80 | @Override 81 | public final void postExecute(IOpipePluginExecution __e) 82 | throws NullPointerException 83 | { 84 | if (__e == null) 85 | throw new NullPointerException(); 86 | 87 | ((TestExecution)__e).execution(). 88 | customMetric("post", "post"); 89 | } 90 | 91 | /** 92 | * {@inheritDoc} 93 | * @since 2018/01/20 94 | */ 95 | @Override 96 | public final String version() 97 | { 98 | return "1.0.0"; 99 | } 100 | } 101 | 102 | -------------------------------------------------------------------------------- /src/test/resources/com/iopipe/eventinfo_apigateway.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "path": "/test/hello", 4 | "headers": { 5 | "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", 6 | "Accept-Encoding": "gzip, deflate, lzma, sdch, br", 7 | "Accept-Language": "en-US,en;q=0.8", 8 | "CloudFront-Forwarded-Proto": "https", 9 | "CloudFront-Is-Desktop-Viewer": "true", 10 | "CloudFront-Is-Mobile-Viewer": "false", 11 | "CloudFront-Is-SmartTV-Viewer": "false", 12 | "CloudFront-Is-Tablet-Viewer": "false", 13 | "CloudFront-Viewer-Country": "US", 14 | "Host": "wt6mne2s9k.execute-api.us-west-2.amazonaws.com", 15 | "Upgrade-Insecure-Requests": "1", 16 | "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48", 17 | "Via": "1.1 fb7cca60f0ecd82ce07790c9c5eef16c.cloudfront.net (CloudFront)", 18 | "X-Amz-Cf-Id": "nBsWBOrSHMgnaROZJK1wGCZ9PcRcSpq_oSXZNQwQ10OTZL4cimZo3g==", 19 | "X-Forwarded-For": "192.168.100.1, 192.168.1.1", 20 | "X-Forwarded-Port": "443", 21 | "X-Forwarded-Proto": "https" 22 | }, 23 | "pathParameters": { 24 | "proxy": "hello" 25 | }, 26 | "requestContext": { 27 | "accountId": "123456789012", 28 | "resourceId": "us4z18", 29 | "stage": "test", 30 | "requestId": "41b45ea3-70b5-11e6-b7bd-69b5aaebc7d9", 31 | "identity": { 32 | "cognitoIdentityPoolId": "", 33 | "accountId": "", 34 | "cognitoIdentityId": "", 35 | "caller": "", 36 | "apiKey": "", 37 | "sourceIp": "192.168.100.1", 38 | "cognitoAuthenticationType": "", 39 | "cognitoAuthenticationProvider": "", 40 | "userArn": "", 41 | "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36 OPR/39.0.2256.48", 42 | "user": "" 43 | }, 44 | "resourcePath": "/{proxy+}", 45 | "httpMethod": "GET", 46 | "apiId": "wt6mne2s9k" 47 | }, 48 | "resource": "/{proxy+}", 49 | "httpMethod": "GET", 50 | "queryStringParameters": { 51 | "name": "me" 52 | }, 53 | "stageVariables": { 54 | "stageVarName": "stageVarValue" 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/elsewhere/PublicClass.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.elsewhere; 2 | 3 | /** 4 | * This is a public class for testing. 5 | * 6 | * @since 2018/08/13 7 | */ 8 | public class PublicClass 9 | { 10 | /** 11 | * Private instance method. 12 | * 13 | * @param __s Input. 14 | * @return Output. 15 | * @since 2018/08/13 16 | */ 17 | private String instancePrivate(String __s) 18 | { 19 | return (__s != null ? __s.toLowerCase() : null); 20 | } 21 | 22 | /** 23 | * Package private instance method. 24 | * 25 | * @param __s Input. 26 | * @return Output. 27 | * @since 2018/08/13 28 | */ 29 | String instancePackagePrivate(String __s) 30 | { 31 | return (__s != null ? __s.toLowerCase() : null); 32 | } 33 | 34 | /** 35 | * Protected instance method. 36 | * 37 | * @param __s Input. 38 | * @return Output. 39 | * @since 2018/08/13 40 | */ 41 | protected String instanceProtected(String __s) 42 | { 43 | return (__s != null ? __s.toLowerCase() : null); 44 | } 45 | 46 | /** 47 | * Public instance method. 48 | * 49 | * @param __s Input. 50 | * @return Output. 51 | * @since 2018/08/13 52 | */ 53 | public String instancePublic(String __s) 54 | { 55 | return (__s != null ? __s.toLowerCase() : null); 56 | } 57 | 58 | /** 59 | * Private static method. 60 | * 61 | * @param __s Input. 62 | * @return Output. 63 | * @since 2018/08/13 64 | */ 65 | private static String staticPrivate(String __s) 66 | { 67 | return (__s != null ? __s.toLowerCase() : null); 68 | } 69 | 70 | /** 71 | * Package private static method. 72 | * 73 | * @param __s Input. 74 | * @return Output. 75 | * @since 2018/08/13 76 | */ 77 | static String staticPackagePrivate(String __s) 78 | { 79 | return (__s != null ? __s.toLowerCase() : null); 80 | } 81 | 82 | /** 83 | * Protected static method. 84 | * 85 | * @param __s Input. 86 | * @return Output. 87 | * @since 2018/08/13 88 | */ 89 | protected static String staticProtected(String __s) 90 | { 91 | return (__s != null ? __s.toLowerCase() : null); 92 | } 93 | 94 | /** 95 | * Public static method. 96 | * 97 | * @param __s Input. 98 | * @return Output. 99 | * @since 2018/08/13 100 | */ 101 | public static String staticPublic(String __s) 102 | { 103 | return (__s != null ? __s.toLowerCase() : null); 104 | } 105 | } 106 | 107 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/elsewhere/PackagePrivateClass.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.elsewhere; 2 | 3 | /** 4 | * This is a package private class for testing. 5 | * 6 | * @since 2018/08/13 7 | */ 8 | class PackagePrivateClass 9 | { 10 | /** 11 | * Private instance method. 12 | * 13 | * @param __s Input. 14 | * @return Output. 15 | * @since 2018/08/13 16 | */ 17 | private String instancePrivate(String __s) 18 | { 19 | return (__s != null ? __s.toLowerCase() : null); 20 | } 21 | 22 | /** 23 | * Package private instance method. 24 | * 25 | * @param __s Input. 26 | * @return Output. 27 | * @since 2018/08/13 28 | */ 29 | String instancePackagePrivate(String __s) 30 | { 31 | return (__s != null ? __s.toLowerCase() : null); 32 | } 33 | 34 | /** 35 | * Protected instance method. 36 | * 37 | * @param __s Input. 38 | * @return Output. 39 | * @since 2018/08/13 40 | */ 41 | protected String instanceProtected(String __s) 42 | { 43 | return (__s != null ? __s.toLowerCase() : null); 44 | } 45 | 46 | /** 47 | * Public instance method. 48 | * 49 | * @param __s Input. 50 | * @return Output. 51 | * @since 2018/08/13 52 | */ 53 | public String instancePublic(String __s) 54 | { 55 | return (__s != null ? __s.toLowerCase() : null); 56 | } 57 | 58 | /** 59 | * Private static method. 60 | * 61 | * @param __s Input. 62 | * @return Output. 63 | * @since 2018/08/13 64 | */ 65 | private static String staticPrivate(String __s) 66 | { 67 | return (__s != null ? __s.toLowerCase() : null); 68 | } 69 | 70 | /** 71 | * Package private static method. 72 | * 73 | * @param __s Input. 74 | * @return Output. 75 | * @since 2018/08/13 76 | */ 77 | static String staticPackagePrivate(String __s) 78 | { 79 | return (__s != null ? __s.toLowerCase() : null); 80 | } 81 | 82 | /** 83 | * Protected static method. 84 | * 85 | * @param __s Input. 86 | * @return Output. 87 | * @since 2018/08/13 88 | */ 89 | protected static String staticProtected(String __s) 90 | { 91 | return (__s != null ? __s.toLowerCase() : null); 92 | } 93 | 94 | /** 95 | * Public static method. 96 | * 97 | * @param __s Input. 98 | * @return Output. 99 | * @since 2018/08/13 100 | */ 101 | public static String staticPublic(String __s) 102 | { 103 | return (__s != null ? __s.toLowerCase() : null); 104 | } 105 | } 106 | 107 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/profiler/ProfilerPlugin.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.profiler; 2 | 3 | import com.iopipe.IOpipeConstants; 4 | import com.iopipe.IOpipeExecution; 5 | import com.iopipe.plugin.IOpipePlugin; 6 | import com.iopipe.plugin.IOpipePluginExecution; 7 | import com.iopipe.plugin.IOpipePluginPostExecutable; 8 | import com.iopipe.plugin.IOpipePluginPreExecutable; 9 | 10 | /** 11 | * This class provides access to the profiler plugin which is used to profile 12 | * method execution. 13 | * 14 | * @since 2018/02/07 15 | */ 16 | public class ProfilerPlugin 17 | implements IOpipePlugin, IOpipePluginPreExecutable, 18 | IOpipePluginPostExecutable 19 | { 20 | /** 21 | * {@inheritDoc} 22 | * @since 2018/02/07 23 | */ 24 | @Override 25 | public boolean enabledByDefault() 26 | { 27 | return false; 28 | } 29 | 30 | /** 31 | * {@inheritDoc} 32 | * @since 2018/02/07 33 | */ 34 | @Override 35 | public String homepage() 36 | { 37 | return "https://github.com/iopipe/iopipe-java"; 38 | } 39 | 40 | /** 41 | * {@inheritDoc} 42 | * @since 2018/02/07 43 | */ 44 | @Override 45 | public IOpipePluginExecution execute(IOpipeExecution __e) 46 | throws NullPointerException 47 | { 48 | return new ProfilerExecution(__e); 49 | } 50 | 51 | /** 52 | * {@inheritDoc} 53 | * @since 2018/02/07 54 | */ 55 | @Override 56 | public Class executionClass() 57 | { 58 | return ProfilerExecution.class; 59 | } 60 | 61 | /** 62 | * {@inheritDoc} 63 | * @since 2018/02/07 64 | */ 65 | @Override 66 | public String name() 67 | { 68 | return "profiler"; 69 | } 70 | 71 | /** 72 | * {@inheritDoc} 73 | * @since 2018/02/07 74 | */ 75 | @Override 76 | public void preExecute(IOpipePluginExecution __e) 77 | throws NullPointerException 78 | { 79 | if (__e == null) 80 | throw new NullPointerException(); 81 | 82 | ((ProfilerExecution)__e).__pre(); 83 | } 84 | 85 | /** 86 | * {@inheritDoc} 87 | * @since 2018/02/07 88 | */ 89 | @Override 90 | public void postExecute(IOpipePluginExecution __e) 91 | throws NullPointerException 92 | { 93 | if (__e == null) 94 | throw new NullPointerException(); 95 | 96 | ((ProfilerExecution)__e).__post(); 97 | } 98 | 99 | /** 100 | * {@inheritDoc} 101 | * @since 2018/02/07 102 | */ 103 | @Override 104 | public String version() 105 | { 106 | return "1.2.1"; 107 | } 108 | } 109 | 110 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # Java Maven CircleCI 2.0 configuration file 2 | # 3 | # Check https://circleci.com/docs/2.0/language-java/ for more details 4 | 5 | version: 2 6 | jobs: 7 | build: 8 | docker: 9 | - image: circleci/openjdk:8-jdk 10 | working_directory: ~/repo 11 | environment: 12 | MAVEN_OPTS: -Xmx3200m 13 | steps: 14 | - checkout 15 | 16 | - restore_cache: 17 | keys: 18 | - v1-dependencies-{{ checksum "pom.xml" }} 19 | 20 | - run: 21 | name: Install dependencies 22 | command: mvn dependency:go-offline 23 | 24 | - save_cache: 25 | paths: 26 | - ~/.m2 27 | key: v1-dependencies-{{ checksum "pom.xml" }} 28 | 29 | - run: 30 | name: Run tests 31 | command: mvn integration-test 32 | 33 | release: 34 | docker: 35 | - image: circleci/openjdk:8-jdk 36 | working_directory: ~/repo 37 | environment: 38 | MAVEN_OPTS: -Xmx3200m 39 | steps: 40 | - checkout 41 | - run: 42 | name: Maven release 43 | command: .circleci/release.sh 44 | publish: 45 | docker: 46 | - image: circleci/openjdk:8-jdk 47 | working_directory: ~/repo 48 | environment: 49 | MAVEN_OPTS: -Xmx3200m 50 | steps: 51 | - checkout 52 | - run: 53 | name: Install Python PIP 54 | command: sudo apt-get update && sudo apt-get install python-pip 55 | - run: 56 | name: Install publish dependencies 57 | command: sudo pip install -U awscli 58 | - run: 59 | name: Override AWS Credentials 60 | command: | 61 | echo 'export AWS_ACCESS_KEY_ID="$LAYER_AWS_ACCESS_KEY_ID"' >> $BASH_ENV 62 | echo 'export AWS_SECRET_ACCESS_KEY="$LAYER_SECRET_ACCESS_KEY"' >> $BASH_ENV 63 | - run: 64 | name: Publish layers 65 | command: .circleci/layers.sh 66 | 67 | workflows: 68 | version: 2 69 | build: 70 | jobs: 71 | - build 72 | release: 73 | jobs: 74 | - release: 75 | filters: 76 | tags: 77 | only: 78 | - /^\d{1,}\.\d{1,}\.\d{1,}\w{0,}$/ 79 | branches: 80 | ignore: 81 | - /.*/ 82 | publish: 83 | jobs: 84 | - publish: 85 | filters: 86 | tags: 87 | only: 88 | - /^\d{1,}\.\d{1,}\.\d{1,}\w{0,}$/ 89 | branches: 90 | ignore: 91 | - /.*/ 92 | 93 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/WrappedRequest.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.http.RemoteRequest; 4 | import com.iopipe.http.RequestType; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * This contains the request information. 10 | * 11 | * @since 2018/02/24 12 | */ 13 | public final class WrappedRequest 14 | { 15 | /** The URL. */ 16 | public final String url; 17 | 18 | /** The authorization token. */ 19 | public final String authtoken; 20 | 21 | /** The request type. */ 22 | public final RequestType type; 23 | 24 | /** The request being made. */ 25 | public final RemoteRequest request; 26 | 27 | /** The count of this request. */ 28 | public final int count; 29 | 30 | /** Decoded event data. */ 31 | public final Event event; 32 | 33 | /** 34 | * Initializes the wrapped request. 35 | * 36 | * @param __u The URL. 37 | * @param __a The authorization token. 38 | * @param __t The type of request. 39 | * @param __r The request being made. 40 | * @param __c The request count. 41 | * @since 2018/02/24 42 | */ 43 | public WrappedRequest(String __u, String __a, RequestType __t, 44 | RemoteRequest __r, int __c) 45 | { 46 | this.url = __u; 47 | this.authtoken = __a; 48 | this.type = __t; 49 | this.request = __r; 50 | this.count = __c; 51 | 52 | // Try to decode an event 53 | Event event = null; 54 | List oops = new ArrayList<>(); 55 | String body = __r.bodyAsString(); 56 | 57 | // Some data was PUT 58 | if (__t == RequestType.PUT) 59 | try 60 | { 61 | event = new PutEvent(__r.body()); 62 | } 63 | catch (RuntimeException e) 64 | { 65 | oops.add(e); 66 | } 67 | 68 | // Normal push event 69 | if (event == null) 70 | try 71 | { 72 | event = StandardPushEvent.decode(body); 73 | } 74 | catch (RuntimeException e) 75 | { 76 | oops.add(e); 77 | } 78 | 79 | // Profiler signer 80 | if (event == null) 81 | try 82 | { 83 | event = SignerEvent.decode(body); 84 | } 85 | catch (RuntimeException e) 86 | { 87 | oops.add(e); 88 | } 89 | 90 | // Failed to decode as something 91 | if (event == null) 92 | { 93 | RuntimeException t = new RuntimeException( 94 | "Could not determine event type."); 95 | 96 | for (Throwable h : oops) 97 | t.addSuppressed(h); 98 | 99 | throw t; 100 | } 101 | 102 | // Is valid 103 | this.event = event; 104 | } 105 | } 106 | 107 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/__DoInvalidToken__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.amazonaws.services.lambda.runtime.Context; 4 | import com.iopipe.http.RemoteRequest; 5 | import com.iopipe.http.RemoteResult; 6 | 7 | /** 8 | * Tests that an invalid token does not work. 9 | * 10 | * @since 2018/01/26 11 | */ 12 | class __DoInvalidToken__ 13 | extends Single 14 | { 15 | protected final BooleanValue executedmethod = 16 | new BooleanValue("executedmethod"); 17 | 18 | /** Successful execution of method even though it will fail. */ 19 | protected final BooleanValue noerror = 20 | new BooleanValue("noerror"); 21 | 22 | /** The server did not allow us to push an event. */ 23 | protected final BooleanValue remoterecvfailed = 24 | new BooleanValue("remoterecvfailed"); 25 | 26 | /** 27 | * Initializes the test. 28 | * 29 | * @param __e The owning engine. 30 | * @since 2018/01/26 31 | */ 32 | public __DoInvalidToken__(Engine __e) 33 | { 34 | super(__e, "invalidtoken"); 35 | } 36 | 37 | /** 38 | * {@inheritDoc} 39 | * @since 2018/01/26 40 | */ 41 | @Override 42 | public void end() 43 | { 44 | super.assertTrue(this.executedmethod); 45 | super.assertTrue(this.noerror); 46 | super.assertTrue(this.remoterecvfailed); 47 | } 48 | 49 | /** 50 | * {@inheritDoc} 51 | * @since 2018/01/26 52 | */ 53 | @Override 54 | public void modifyConfig(IOpipeConfigurationBuilder __cb) 55 | throws NullPointerException 56 | { 57 | if (__cb == null) 58 | throw new NullPointerException(); 59 | 60 | // Purposefully use an invalid token 61 | __cb.setProjectToken(MockConnection.INVALID_TOKEN); 62 | } 63 | 64 | /** 65 | * {@inheritDoc} 66 | * @since 2018/01/26 67 | */ 68 | @Override 69 | public void remoteRequest(WrappedRequest __r) 70 | { 71 | StandardPushEvent event = (StandardPushEvent)__r.event; 72 | 73 | // Even though the request will fail, it still must be sent without 74 | // error 75 | if (!event.hasError()) 76 | this.noerror.set(true); 77 | } 78 | 79 | /** 80 | * {@inheritDoc} 81 | * @since 2018/01/26 82 | */ 83 | @Override 84 | public void remoteResult(WrappedResult __r) 85 | { 86 | if (!__Utils__.isResultOkay(__r.result)) 87 | this.remoterecvfailed.set(true); 88 | } 89 | 90 | /** 91 | * {@inheritDoc} 92 | * @since 2018/01/26 93 | */ 94 | @Override 95 | public void run(IOpipeExecution __e) 96 | throws Throwable 97 | { 98 | this.executedmethod.set(true); 99 | } 100 | } 101 | 102 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/__DoLongValueCustomMetric__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.CustomMetric; 4 | import com.iopipe.http.RemoteRequest; 5 | import com.iopipe.http.RemoteResult; 6 | import java.util.Collections; 7 | import java.util.Map; 8 | import javax.json.JsonString; 9 | import javax.json.JsonNumber; 10 | import javax.json.JsonValue; 11 | 12 | /** 13 | * Ensures that custom metrics which really long values are not added. 14 | * 15 | * @since 2018/05/03 16 | */ 17 | class __DoLongValueCustomMetric__ 18 | extends Single 19 | { 20 | /** Sent with no exception? */ 21 | protected final BooleanValue noerror = 22 | new BooleanValue("noerror"); 23 | 24 | /** Got a result from the server okay? */ 25 | protected final BooleanValue remoterecvokay = 26 | new BooleanValue("remoterecvokay"); 27 | 28 | /** Is there a custom string? */ 29 | protected final BooleanValue hascustomstring = 30 | new BooleanValue("hascustomstring"); 31 | 32 | /** 33 | * Constructs the test. 34 | * 35 | * @param __e The owning engine. 36 | * @since 2018/05/03 37 | */ 38 | __DoLongValueCustomMetric__(Engine __e) 39 | { 40 | super(__e, "longcustommetricvalue"); 41 | } 42 | 43 | /** 44 | * {@inheritDoc} 45 | * @since 2018/05/03 46 | */ 47 | @Override 48 | public void end() 49 | { 50 | super.assertTrue(this.remoterecvokay); 51 | super.assertTrue(this.noerror); 52 | 53 | super.assertFalse(this.hascustomstring); 54 | } 55 | 56 | /** 57 | * {@inheritDoc} 58 | * @since 2018/05/03 59 | */ 60 | @Override 61 | public void remoteRequest(WrappedRequest __r) 62 | { 63 | StandardPushEvent event = (StandardPushEvent)__r.event; 64 | 65 | // It is invalid if there is an error 66 | if (!event.hasError()) 67 | this.noerror.set(true); 68 | 69 | for (CustomMetric m : event.custommetrics.values()) 70 | { 71 | if (m.hasString()) 72 | this.hascustomstring.set(true); 73 | } 74 | } 75 | 76 | /** 77 | * {@inheritDoc} 78 | * @since 2018/05/03 79 | */ 80 | @Override 81 | public void remoteResult(WrappedResult __r) 82 | { 83 | if (__Utils__.isResultOkay(__r.result)) 84 | this.remoterecvokay.set(true); 85 | } 86 | 87 | /** 88 | * {@inheritDoc} 89 | * @since 2018/05/03 90 | */ 91 | @Override 92 | public void run(IOpipeExecution __e) 93 | throws Throwable 94 | { 95 | __e.customMetric("long", String.join("", Collections.nCopies( 96 | IOpipeConstants.VALUE_CODEPOINT_LIMIT + 32, "a"))); 97 | } 98 | } 99 | 100 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/eventinfo/EventInfoPlugin.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.eventinfo; 2 | 3 | import com.iopipe.IOpipeConstants; 4 | import com.iopipe.IOpipeExecution; 5 | import com.iopipe.plugin.IOpipePlugin; 6 | import com.iopipe.plugin.IOpipePluginExecution; 7 | import com.iopipe.plugin.IOpipePluginPostExecutable; 8 | import com.iopipe.plugin.IOpipePluginPreExecutable; 9 | 10 | /** 11 | * This is the trace plugin which is used to track specific marks and measure 12 | * performance. 13 | * 14 | * @since 2018/04/22 15 | */ 16 | public class EventInfoPlugin 17 | implements IOpipePlugin, IOpipePluginPostExecutable 18 | { 19 | /** Default set of decoders, lazily initialized. */ 20 | private volatile EventInfoDecoders _decoders; 21 | 22 | /** 23 | * {@inheritDoc} 24 | * @since 2018/04/22 25 | */ 26 | @Override 27 | public boolean enabledByDefault() 28 | { 29 | return true; 30 | } 31 | 32 | /** 33 | * {@inheritDoc} 34 | * @since 2018/04/22 35 | */ 36 | @Override 37 | public IOpipePluginExecution execute(IOpipeExecution __e) 38 | { 39 | if (__e == null) 40 | throw new NullPointerException(); 41 | 42 | // Lazily initialize decoders since the plugin might not actually 43 | // be enabled 44 | EventInfoDecoders decoders = this._decoders; 45 | if (decoders == null) 46 | this._decoders = (decoders = new EventInfoDecoders()); 47 | 48 | return new EventInfoExecution(__e, decoders); 49 | } 50 | 51 | /** 52 | * {@inheritDoc} 53 | * @since 2018/04/22 54 | */ 55 | @Override 56 | public Class executionClass() 57 | { 58 | return EventInfoExecution.class; 59 | } 60 | 61 | /** 62 | * {@inheritDoc} 63 | * @since 2018/04/22 64 | */ 65 | @Override 66 | public String homepage() 67 | { 68 | return "https://github.com/iopipe/iopipe-java"; 69 | } 70 | 71 | /** 72 | * {@inheritDoc} 73 | * @since 2018/04/22 74 | */ 75 | @Override 76 | public String name() 77 | { 78 | return "event-info"; 79 | } 80 | 81 | /** 82 | * {@inheritDoc} 83 | * @since 2018/04/23 84 | */ 85 | @Override 86 | public void postExecute(IOpipePluginExecution __e) 87 | throws NullPointerException 88 | { 89 | if (__e == null) 90 | throw new NullPointerException(); 91 | 92 | ((EventInfoExecution)__e).__post(); 93 | } 94 | 95 | /** 96 | * {@inheritDoc} 97 | * @since 2018/04/22 98 | */ 99 | @Override 100 | public String version() 101 | { 102 | return "1.2.0"; 103 | } 104 | } 105 | 106 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/eventinfo/ValueAcceptor.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.eventinfo; 2 | 3 | import com.iopipe.CustomMetric; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | /** 8 | * This class is used to accept values which should be stored in custom 9 | * metrics in the generated report. 10 | * 11 | * @since 2018/05/02 12 | */ 13 | public final class ValueAcceptor 14 | { 15 | /** The event type used. */ 16 | protected final String eventtype; 17 | 18 | /** The key prefix. */ 19 | protected final String prefix; 20 | 21 | /** The target list for recorded metrics. */ 22 | private final List _metrics = 23 | new ArrayList<>(); 24 | 25 | /** 26 | * Initializes the value acceptor. 27 | * 28 | * @param __et The event type used. 29 | * @throws NullPointerException On null arguments. 30 | * @since 2018/05/02 31 | */ 32 | public ValueAcceptor(String __et) 33 | throws NullPointerException 34 | { 35 | if (__et == null) 36 | throw new NullPointerException(); 37 | 38 | this.eventtype = __et; 39 | 40 | // Generate prefix 41 | this.prefix = "@iopipe/event-info." + __et + "."; 42 | 43 | // Record initial metric 44 | this._metrics.add( 45 | new CustomMetric("@iopipe/event-info.eventType", __et)); 46 | } 47 | 48 | /** 49 | * Accepts the given key and value. 50 | * 51 | * @param __key The key. 52 | * @param __val The value, if this is {@code null} then nothing will be 53 | * reported. 54 | * @throws NullPointerException If no key was specified. 55 | * @since 2018/05/02 56 | */ 57 | public final void accept(String __key, String __val) 58 | throws NullPointerException 59 | { 60 | if (__key == null) 61 | throw new NullPointerException(); 62 | 63 | if (__val != null) 64 | this._metrics.add(new CustomMetric(this.prefix + __key, __val)); 65 | } 66 | 67 | /** 68 | * Accepts the given key and value. 69 | * 70 | * @param __key The key. 71 | * @param __val The value. 72 | * @throws NullPointerException If no key was specified. 73 | * @since 2018/05/02 74 | */ 75 | public final void accept(String __key, long __val) 76 | throws NullPointerException 77 | { 78 | if (__key == null) 79 | throw new NullPointerException(); 80 | 81 | this._metrics.add(new CustomMetric(this.prefix + __key, __val)); 82 | } 83 | 84 | /** 85 | * Returns all of the generated custom metrics. 86 | * 87 | * @return The array of created custom metrics. 88 | * @since 2018/05/02 89 | */ 90 | public final CustomMetric[] get() 91 | { 92 | List metrics = this._metrics; 93 | return metrics.toArray(new CustomMetric[metrics.size()]); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/profiler/GarbageCollectorStatistics.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.profiler; 2 | 3 | import java.lang.management.GarbageCollectorMXBean; 4 | import java.lang.management.ManagementFactory; 5 | import java.util.Arrays; 6 | import java.util.ArrayList; 7 | import java.util.Collections; 8 | import java.util.List; 9 | 10 | /** 11 | * Statistics for the garbage collector. 12 | * 13 | * @since 2018/05/22 14 | */ 15 | public final class GarbageCollectorStatistics 16 | { 17 | /** The name of the garbage collector. */ 18 | public final String name; 19 | 20 | /** The collection count. */ 21 | public final long count; 22 | 23 | /** The time spent collecting. */ 24 | public final long durationms; 25 | 26 | /** 27 | * Initializes invalid garbage collector statistics. 28 | * 29 | * @since 2018/05/24 30 | */ 31 | public GarbageCollectorStatistics() 32 | { 33 | this(null, -1, -1); 34 | } 35 | 36 | /** 37 | * Initializes the garbage collector statistics. 38 | * 39 | * @param __n The name of the collector. 40 | * @param __c The number of objects collected. 41 | * @param __ns The duration of collection. 42 | * @since 2018/05/22 43 | */ 44 | public GarbageCollectorStatistics(String __n, long __c, long __ns) 45 | { 46 | this.name = (__n != null ? __n : "Unknown"); 47 | this.count = Math.max(-1, __c); 48 | this.durationms = Math.max(-1, __ns); 49 | } 50 | 51 | /** 52 | * Creates snapshots of the garbage collector statistics. 53 | * 54 | * @return The snapshots which are available. 55 | * @since 2018/05/22 56 | */ 57 | public static GarbageCollectorStatistics[] snapshots() 58 | { 59 | return GarbageCollectorStatistics.snapshots( 60 | ManagementFactory.getGarbageCollectorMXBeans()); 61 | } 62 | 63 | /** 64 | * Creates snapshots of the given garbage collector beans. 65 | * 66 | * @param __beans The beans to snapshot. 67 | * @return The snapshotted beans. 68 | * @since 2018/05/22 69 | */ 70 | public static GarbageCollectorStatistics[] snapshots( 71 | List __beans) 72 | { 73 | if (__beans == null) 74 | return new GarbageCollectorStatistics[0]; 75 | 76 | int n = __beans.size(); 77 | List rv = new ArrayList<>(n); 78 | for (int i = 0; i < n; i++) 79 | { 80 | GarbageCollectorMXBean bean = __beans.get(i); 81 | if (bean == null || !bean.isValid()) 82 | continue; 83 | 84 | rv.add(new GarbageCollectorStatistics( 85 | bean.getName(), 86 | bean.getCollectionCount(), 87 | bean.getCollectionTime())); 88 | } 89 | 90 | return rv.toArray( 91 | new GarbageCollectorStatistics[rv.size()]); 92 | } 93 | } 94 | 95 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/__DoLabel__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.http.RemoteRequest; 4 | import com.iopipe.http.RemoteResult; 5 | import java.util.Map; 6 | import javax.json.JsonString; 7 | import javax.json.JsonNumber; 8 | import javax.json.JsonValue; 9 | 10 | /** 11 | * This performs the test of the labels which may be added to a report. 12 | * 13 | * @since 2018/04/11 14 | */ 15 | class __DoLabel__ 16 | extends Single 17 | { 18 | /** Sent with no exception? */ 19 | protected final BooleanValue noerror = 20 | new BooleanValue("noerror"); 21 | 22 | /** Got a result from the server okay? */ 23 | protected final BooleanValue remoterecvokay = 24 | new BooleanValue("remoterecvokay"); 25 | 26 | /** Does the label exist? */ 27 | protected final BooleanValue haslabel = 28 | new BooleanValue("haslabel"); 29 | 30 | /** Is this label supposed to appear in the dashboard? */ 31 | protected final boolean doshow; 32 | 33 | /** The label to add. */ 34 | protected final String label; 35 | 36 | /** 37 | * Constructs the test. 38 | * 39 | * @param __e The owning engine. 40 | * @param __show Show this in the dashboard. 41 | * @param __label The label to add. 42 | * @since 2018/04/11 43 | */ 44 | __DoLabel__(Engine __e, boolean __show, String __label) 45 | { 46 | super(__e, "label-" + __show + "-" + __label); 47 | 48 | this.doshow = __show; 49 | this.label = __label; 50 | } 51 | 52 | /** 53 | * {@inheritDoc} 54 | * @since 2018/04/11 55 | */ 56 | @Override 57 | public void end() 58 | { 59 | super.assertTrue(this.remoterecvokay); 60 | super.assertTrue(this.noerror); 61 | 62 | super.assertEquals(this.doshow, this.haslabel); 63 | } 64 | 65 | /** 66 | * {@inheritDoc} 67 | * @since 2018/04/11 68 | */ 69 | @Override 70 | public void remoteRequest(WrappedRequest __r) 71 | { 72 | StandardPushEvent event = (StandardPushEvent)__r.event; 73 | 74 | // It is invalid if there is an error 75 | if (!event.hasError()) 76 | this.noerror.set(true); 77 | 78 | // The label must be added 79 | if (event.labels.contains(this.label)) 80 | this.haslabel.set(true); 81 | } 82 | 83 | /** 84 | * {@inheritDoc} 85 | * @since 2018/04/11 86 | */ 87 | @Override 88 | public void remoteResult(WrappedResult __r) 89 | { 90 | if (__Utils__.isResultOkay(__r.result)) 91 | this.remoterecvokay.set(true); 92 | } 93 | 94 | /** 95 | * {@inheritDoc} 96 | * @since 2018/04/11 97 | */ 98 | @Override 99 | public void run(IOpipeExecution __e) 100 | throws Throwable 101 | { 102 | __e.label(this.label); 103 | } 104 | } 105 | 106 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/__DoConfigFileTest__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.http.RemoteRequest; 4 | import com.iopipe.http.RemoteResult; 5 | import com.iopipe.IOpipeConfiguration; 6 | import java.util.Map; 7 | import javax.json.JsonString; 8 | import javax.json.JsonNumber; 9 | import javax.json.JsonValue; 10 | 11 | /** 12 | * This performs a test to see if the config file works. 13 | * 14 | * @since 2018/10/31 15 | */ 16 | class __DoConfigFileTest__ 17 | extends Single 18 | { 19 | /** Sent with no exception? */ 20 | protected final BooleanValue noerror = 21 | new BooleanValue("noerror"); 22 | 23 | /** Got a result from the server okay? */ 24 | protected final BooleanValue remoterecvokay = 25 | new BooleanValue("remoterecvokay"); 26 | 27 | /** Has config option? */ 28 | protected final BooleanValue hasconfig = 29 | new BooleanValue("hasconfig"); 30 | 31 | /** Has missing config option? */ 32 | protected final BooleanValue hasnoconfig = 33 | new BooleanValue("hasnoconfig"); 34 | 35 | /** 36 | * Constructs the test. 37 | * 38 | * @param __e The owning engine. 39 | * @since 2018/10/31 40 | */ 41 | __DoConfigFileTest__(Engine __e) 42 | { 43 | super(__e, "configfile"); 44 | } 45 | 46 | /** 47 | * {@inheritDoc} 48 | * @since 2018/10/31 49 | */ 50 | @Override 51 | public void end() 52 | { 53 | super.assertTrue(this.remoterecvokay); 54 | super.assertTrue(this.noerror); 55 | super.assertTrue(this.hasconfig); 56 | super.assertTrue(this.hasnoconfig); 57 | } 58 | 59 | /** 60 | * {@inheritDoc} 61 | * @since 2018/10/31 62 | */ 63 | @Override 64 | public void remoteRequest(WrappedRequest __r) 65 | { 66 | StandardPushEvent event = (StandardPushEvent)__r.event; 67 | 68 | // It is invalid if there is an error 69 | if (!event.hasError()) 70 | this.noerror.set(true); 71 | } 72 | 73 | /** 74 | * {@inheritDoc} 75 | * @since 2018/10/31 76 | */ 77 | @Override 78 | public void remoteResult(WrappedResult __r) 79 | { 80 | if (__Utils__.isResultOkay(__r.result)) 81 | this.remoterecvokay.set(true); 82 | } 83 | 84 | /** 85 | * {@inheritDoc} 86 | * @since 2018/10/31 87 | */ 88 | @Override 89 | public void run(IOpipeExecution __e) 90 | throws Throwable 91 | { 92 | // Check config 93 | if ("squirrel".equals(IOpipeConfiguration.getVariable( 94 | "com.iopipe.cutestanimal", "IOPIPE_CUTEST_ANIMAL", "nope"))) 95 | this.hasconfig.set(true); 96 | 97 | // Check missing config 98 | if ("no!".equals(IOpipeConfiguration.getVariable( 99 | "asohdpuiashdpiusdapfiuhdsf", "ASOHDPUIASHDPIUSDAPFIUHDSF", "no!"))) 100 | this.hasnoconfig.set(true); 101 | } 102 | } 103 | 104 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/eventinfo/CloudFrontDecoder.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.eventinfo; 2 | 3 | import com.amazonaws.services.lambda.runtime.events.CloudFrontEvent; 4 | import java.util.List; 5 | import java.util.Map; 6 | 7 | /** 8 | * This class implements the decoder for cloud front events. 9 | * 10 | * @since 2018/04/23 11 | */ 12 | public final class CloudFrontDecoder 13 | implements EventInfoDecoder 14 | { 15 | /** 16 | * {@inheritDoc} 17 | * @since 2018/05/02 18 | */ 19 | @Override 20 | public void accept(ValueAcceptor __a, Object __v) 21 | throws NullPointerException 22 | { 23 | if (__a == null || __v == null) 24 | throw new NullPointerException(); 25 | 26 | CloudFrontEvent v = (CloudFrontEvent)__v; 27 | 28 | // There must be at least one record 29 | List records = v.getRecords(); 30 | if (records == null || records.size() <= 0) 31 | return; 32 | CloudFrontEvent.Record record = records.get(0); 33 | 34 | // All keys use this 35 | CloudFrontEvent.CF cf = record.getCf(); 36 | if (cf == null) 37 | return; 38 | 39 | // Record single event 40 | CloudFrontEvent.Config config = cf.getConfig(); 41 | if (config != null) 42 | __a.accept("Records[0].cf.config.distributionId", 43 | config.getDistributionId()); 44 | 45 | // Remaining requests 46 | CloudFrontEvent.Request request = cf.getRequest(); 47 | if (request != null) 48 | { 49 | __a.accept("Records[0].cf.request.clientIp", 50 | request.getClientIp()); 51 | 52 | Map> headers = 53 | request.getHeaders(); 54 | if (headers != null) 55 | { 56 | List hosts = headers.get("host"); 57 | if (hosts != null && hosts.size() >= 1) 58 | __a.accept("Records[0].cf.request.headers.host[0].value", 59 | hosts.get(0).getValue()); 60 | 61 | List useragents = 62 | headers.get("user-agent"); 63 | if (useragents != null && useragents.size() >= 1) 64 | __a.accept("Records[0].cf.request.headers." + 65 | "[\"user-agent\"][0].value", 66 | useragents.get(0).getValue()); 67 | } 68 | 69 | __a.accept("Records[0].cf.request.method", 70 | request.getMethod()); 71 | __a.accept("Records[0].cf.request.uri", 72 | request.getUri()); 73 | } 74 | } 75 | 76 | /** 77 | * {@inheritDoc} 78 | * @since 2018/04/23 79 | */ 80 | @Override 81 | public final String[] decodes() 82 | { 83 | return new String[] 84 | { 85 | "com.amazonaws.services.lambda.runtime.events.CloudFrontEvent", 86 | }; 87 | } 88 | 89 | /** 90 | * {@inheritDoc} 91 | * @since 2018/04/23 92 | */ 93 | @Override 94 | public final String eventType() 95 | { 96 | return "cloudFront"; 97 | } 98 | } 99 | 100 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/profiler/BufferPoolStatistics.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.profiler; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.lang.management.BufferPoolMXBean; 6 | import java.lang.management.ManagementFactory; 7 | 8 | /** 9 | * This contains statistics on the buffer pool. 10 | * 11 | * @since 2108/05/27 12 | */ 13 | public final class BufferPoolStatistics 14 | { 15 | /** The name of the pool. */ 16 | public final String name; 17 | 18 | /** The number of objects in the pool. */ 19 | public final long count; 20 | 21 | /** The memory used in the pool. */ 22 | public final long usedbytes; 23 | 24 | /** The capacity of the pool in bytes. */ 25 | public final long capacitybytes; 26 | 27 | /** 28 | * Initializes an unknown buffer pool statistic. 29 | * 30 | * @since 2018/05/30 31 | */ 32 | public BufferPoolStatistics() 33 | { 34 | this(null, -1, -1, -1); 35 | } 36 | 37 | /** 38 | * Initializes the buffer pool statistics. 39 | * 40 | * @param __name The name of the pool. 41 | * @param __count The objects in the pool. 42 | * @param __usedbytes The number of used bytes. 43 | * @param __capacitybytes The capacity of the pool. 44 | * @since 2018/05/27 45 | */ 46 | public BufferPoolStatistics(String __name, long __count, long __usedbytes, 47 | long __capacitybytes) 48 | { 49 | this.name = (__name != null ? __name : "Unknown"); 50 | this.count = Long.max(-1, __count); 51 | this.usedbytes = Long.max(-1, __usedbytes); 52 | this.capacitybytes = Long.max(-1, __capacitybytes); 53 | } 54 | 55 | /** 56 | * Obtains a snapshot of the statistics. 57 | * 58 | * @return The buffer pool statistics or {@code null} if it is not valid. 59 | * @since 2018/05/27 60 | */ 61 | public static BufferPoolStatistics[] snapshots() 62 | { 63 | return BufferPoolStatistics.snapshots( 64 | ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class)); 65 | } 66 | 67 | /** 68 | * Obtains the snapshots of the given beans. 69 | * 70 | * @param __beans The beans to snapshot. 71 | * @return The snapshotted beans. 72 | * @since 2018/05/30 73 | */ 74 | public static BufferPoolStatistics[] snapshots( 75 | List __beans) 76 | { 77 | if (__beans == null) 78 | return new BufferPoolStatistics[0]; 79 | 80 | int n = __beans.size(); 81 | List rv = new ArrayList<>(n); 82 | for (int i = 0; i < n; i++) 83 | { 84 | BufferPoolMXBean bean = __beans.get(i); 85 | if (bean == null) 86 | continue; 87 | 88 | rv.add(new BufferPoolStatistics( 89 | bean.getName(), 90 | bean.getCount(), 91 | bean.getMemoryUsed(), 92 | bean.getTotalCapacity())); 93 | } 94 | 95 | return rv.toArray( 96 | new BufferPoolStatistics[rv.size()]); 97 | } 98 | } 99 | 100 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/IOpipePlugin.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin; 2 | 3 | import com.iopipe.IOpipeExecution; 4 | import java.lang.ref.Reference; 5 | 6 | /** 7 | * This interface represents the base of a plugin and is used to manage and 8 | * create executable instances of plugins as they are needed. 9 | * 10 | * If it is required that state be initialized before execution begins then 11 | * {@link IOpipePluginPreExecutable} may be implemented. 12 | * 13 | * If it is required that finalization be performed after execution ends then 14 | * {@link IOpipePluginPostExecutable} may be implemented. 15 | * 16 | * This class is used with {@link java.util.ServiceLoader} to locate services. 17 | * 18 | * @see IOpipePluginPreExecutable 19 | * @see IOpipePluginPostExecutable 20 | * @since 2018/01/20 21 | */ 22 | public interface IOpipePlugin 23 | { 24 | /** 25 | * This creates a new execution for the given plugin which allows it to 26 | * store state for a single execution of a method. This is only initialized 27 | * when it is needed and as such if it is required that it be initialized 28 | * before the execution of a method then {@link IOpipePluginPreExecutable} 29 | * should be implemented. 30 | * 31 | * @param __e The execution state which the plugin will be executing under. 32 | * @return The execution instance for this plugin. 33 | * @throws NullPointerException This may be thrown if the execution is 34 | * required. 35 | * @since 2018/01/20 36 | */ 37 | public abstract IOpipePluginExecution execute(IOpipeExecution __e) 38 | throws NullPointerException; 39 | 40 | /** 41 | * This returns the class type of the plugin execution object, this is 42 | * used to determine which state to obtain when a plugin state is 43 | * requested. 44 | * 45 | * @return The class type of the execution class. 46 | * @since 2018/01/20 47 | */ 48 | public abstract Class executionClass(); 49 | 50 | /** 51 | * Return the name of this plugin. 52 | * 53 | * @return The name of this plugin. 54 | * @since 2018/01/20 55 | */ 56 | public abstract String name(); 57 | 58 | /** 59 | * Returns the version of this plugin. 60 | * 61 | * @return The plugin version. 62 | * @since 2018/01/20 63 | */ 64 | public abstract String version(); 65 | 66 | /** 67 | * Should this plugin be enabled by default? 68 | * 69 | * The default implementation is that plugins are disabled by default. 70 | * 71 | * @return {@code true} if it is enabled by default. 72 | * @since 2018/01/20 73 | */ 74 | public default boolean enabledByDefault() 75 | { 76 | return false; 77 | } 78 | 79 | /** 80 | * Return the homepage where this plugin is located, this is optional. 81 | * 82 | * @return The homepage for this plugin or {@code null} if there is none. 83 | * @since 2018/01/20 84 | */ 85 | public default String homepage() 86 | { 87 | return null; 88 | } 89 | } 90 | 91 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/__DoLongNameCustomMetric__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.CustomMetric; 4 | import com.iopipe.http.RemoteRequest; 5 | import com.iopipe.http.RemoteResult; 6 | import java.util.Collections; 7 | import java.util.Map; 8 | import javax.json.JsonString; 9 | import javax.json.JsonNumber; 10 | import javax.json.JsonValue; 11 | 12 | /** 13 | * Ensures that custom metrics which really long names are not added. 14 | * 15 | * @since 2018/04/11 16 | */ 17 | class __DoLongNameCustomMetric__ 18 | extends Single 19 | { 20 | /** Sent with no exception? */ 21 | protected final BooleanValue noerror = 22 | new BooleanValue("noerror"); 23 | 24 | /** Got a result from the server okay? */ 25 | protected final BooleanValue remoterecvokay = 26 | new BooleanValue("remoterecvokay"); 27 | 28 | /** Is there a custom string? */ 29 | protected final BooleanValue hascustomstring = 30 | new BooleanValue("hascustomstring"); 31 | 32 | /** Is there a custom number? */ 33 | protected final BooleanValue hascustomnumber = 34 | new BooleanValue("hascustomnumber"); 35 | 36 | /** 37 | * Constructs the test. 38 | * 39 | * @param __e The owning engine. 40 | * @since 2018/04/11 41 | */ 42 | __DoLongNameCustomMetric__(Engine __e) 43 | { 44 | super(__e, "longcustommetric"); 45 | } 46 | 47 | /** 48 | * {@inheritDoc} 49 | * @since 2018/04/11 50 | */ 51 | @Override 52 | public void end() 53 | { 54 | super.assertTrue(this.remoterecvokay); 55 | super.assertTrue(this.noerror); 56 | 57 | super.assertFalse(this.hascustomstring); 58 | super.assertFalse(this.hascustomnumber); 59 | } 60 | 61 | /** 62 | * {@inheritDoc} 63 | * @since 2018/04/11 64 | */ 65 | @Override 66 | public void remoteRequest(WrappedRequest __r) 67 | { 68 | StandardPushEvent event = (StandardPushEvent)__r.event; 69 | 70 | // It is invalid if there is an error 71 | if (!event.hasError()) 72 | this.noerror.set(true); 73 | 74 | for (CustomMetric m : event.custommetrics.values()) 75 | { 76 | if (m.hasString()) 77 | this.hascustomstring.set(true); 78 | 79 | if (m.hasLong()) 80 | this.hascustomnumber.set(true); 81 | } 82 | } 83 | 84 | /** 85 | * {@inheritDoc} 86 | * @since 2018/04/11 87 | */ 88 | @Override 89 | public void remoteResult(WrappedResult __r) 90 | { 91 | if (__Utils__.isResultOkay(__r.result)) 92 | this.remoterecvokay.set(true); 93 | } 94 | 95 | /** 96 | * {@inheritDoc} 97 | * @since 2018/04/11 98 | */ 99 | @Override 100 | public void run(IOpipeExecution __e) 101 | throws Throwable 102 | { 103 | __e.customMetric(String.join("", Collections.nCopies( 104 | IOpipeConstants.NAME_CODEPOINT_LIMIT + 32, "a")), "Very long!"); 105 | __e.customMetric(String.join("", Collections.nCopies( 106 | IOpipeConstants.NAME_CODEPOINT_LIMIT + 32, "b")), 12345678); 107 | } 108 | } 109 | 110 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/trace/TraceMeasurement.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.trace; 2 | 3 | import com.iopipe.IOpipeConstants; 4 | import com.iopipe.IOpipeExecution; 5 | import com.iopipe.PerformanceEntry; 6 | import java.lang.ref.Reference; 7 | import java.lang.ref.WeakReference; 8 | import java.util.concurrent.atomic.AtomicBoolean; 9 | 10 | /** 11 | * This class measures a duration of time and is intended to be used with 12 | * try-with-resources to measure how long a given block of code takes to 13 | * execute. 14 | * 15 | * The measurement may only be closed once. 16 | * 17 | * @since 2018/01/19 18 | */ 19 | public final class TraceMeasurement 20 | implements AutoCloseable 21 | { 22 | /** Is this measurement to be enabled? */ 23 | protected final boolean enabled; 24 | 25 | /** The name of this trace. */ 26 | protected final String name; 27 | 28 | /** The start time of this measurement, used to count duration. */ 29 | protected final long startns; 30 | 31 | /** Reference to the execution. */ 32 | protected final Reference execref; 33 | 34 | /** Has this been closed? */ 35 | private final AtomicBoolean _closed = 36 | new AtomicBoolean(); 37 | 38 | /** 39 | * Initializes the measurement tracking. 40 | * 41 | * @param __enabled Is this enabled? 42 | * @param __m Where measurements are to be placed. 43 | * @param __name The name of this trace. 44 | * @throws NullPointerException On null arguments. 45 | * @since 2018/01/19 46 | */ 47 | public TraceMeasurement(boolean __enabled, IOpipeExecution __m, 48 | String __name) 49 | throws NullPointerException 50 | { 51 | if (__m == null || __name == null) 52 | throw new NullPointerException(); 53 | 54 | this.enabled = __enabled; 55 | this.execref = new WeakReference<>(__m); 56 | this.name = __name; 57 | 58 | // Initialize start time 59 | long startns = System.nanoTime(); 60 | this.startns = startns; 61 | 62 | // Create initial start mark if this is enabled 63 | if (__enabled) 64 | __m.addPerformanceEntry(new PerformanceEntry("start:" + __name, 65 | "mark", startns, System.currentTimeMillis(), 0)); 66 | } 67 | 68 | /** 69 | * {@inheritDoc} 70 | * @since 2018/01/19 71 | */ 72 | @Override 73 | public void close() 74 | { 75 | if (this.enabled) 76 | if (this._closed.compareAndSet(false, true)) 77 | { 78 | // There are two end marks, one for the end mark and the 79 | // actual duration but they end at the same time 80 | long endns = System.nanoTime(), 81 | endms = System.currentTimeMillis(); 82 | 83 | // Must be valid 84 | IOpipeExecution measurement = this.execref.get(); 85 | if (measurement == null) 86 | return; 87 | 88 | String name = this.name; 89 | 90 | measurement.addPerformanceEntry(new PerformanceEntry( 91 | "end:" + name, "mark", endns, endms, 0)); 92 | measurement.addPerformanceEntry(new PerformanceEntry( 93 | "measure:" + name, "measure", endns, endms, 94 | endns - this.startns)); 95 | } 96 | } 97 | } 98 | 99 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/__DoColdStartAutoLabel__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.http.RemoteRequest; 4 | import com.iopipe.http.RemoteResult; 5 | import com.iopipe.IOpipeConfigurationBuilder; 6 | import java.util.Map; 7 | import javax.json.JsonString; 8 | import javax.json.JsonNumber; 9 | import javax.json.JsonValue; 10 | 11 | /** 12 | * Tests that coldstarts are given an auto label. 13 | * 14 | * @since 2018/07/16 15 | */ 16 | class __DoColdStartAutoLabel__ 17 | extends Single 18 | { 19 | /** Sent with no exception? */ 20 | protected final BooleanValue noerror = 21 | new BooleanValue("noerror"); 22 | 23 | /** Got a result from the server okay? */ 24 | protected final BooleanValue remoterecvokay = 25 | new BooleanValue("remoterecvokay"); 26 | 27 | /** Has coldstart? */ 28 | protected final BooleanValue hascoldstart = 29 | new BooleanValue("hascoldstart"); 30 | 31 | /** Does the label exist? */ 32 | protected final BooleanValue haslabel = 33 | new BooleanValue("haslabel"); 34 | 35 | /** 36 | * Constructs the test. 37 | * 38 | * @param __e The owning engine. 39 | * @since 2018/07/16 40 | */ 41 | __DoColdStartAutoLabel__(Engine __e) 42 | { 43 | super(__e, "coldstartautolabel"); 44 | } 45 | 46 | /** 47 | * {@inheritDoc} 48 | * @since 2018/07/16 49 | */ 50 | @Override 51 | public void end() 52 | { 53 | super.assertTrue(this.remoterecvokay); 54 | super.assertTrue(this.noerror); 55 | 56 | super.assertTrue(this.hascoldstart); 57 | super.assertTrue(this.haslabel); 58 | 59 | // These conditions must be the same 60 | super.assertEquals(this.hascoldstart.get(), this.haslabel); 61 | } 62 | 63 | /** 64 | * {@inheritDoc} 65 | * @since 2018/07/17 66 | */ 67 | @Override 68 | public void modifyConfig(IOpipeConfigurationBuilder __cb) 69 | throws NullPointerException 70 | { 71 | if (__cb == null) 72 | throw new NullPointerException(); 73 | 74 | __cb.setUseLocalColdStart(true); 75 | } 76 | 77 | /** 78 | * {@inheritDoc} 79 | * @since 2018/07/16 80 | */ 81 | @Override 82 | public void remoteRequest(WrappedRequest __r) 83 | { 84 | StandardPushEvent event = (StandardPushEvent)__r.event; 85 | 86 | // It is invalid if there is an error 87 | if (!event.hasError()) 88 | this.noerror.set(true); 89 | 90 | // Must be a cold start, for sanity 91 | if (event.coldstart) 92 | this.hascoldstart.set(true); 93 | 94 | // The label must be added 95 | if (event.labels.contains("@iopipe/coldstart")) 96 | this.haslabel.set(true); 97 | } 98 | 99 | /** 100 | * {@inheritDoc} 101 | * @since 2018/07/16 102 | */ 103 | @Override 104 | public void remoteResult(WrappedResult __r) 105 | { 106 | if (__Utils__.isResultOkay(__r.result)) 107 | this.remoterecvokay.set(true); 108 | } 109 | 110 | /** 111 | * {@inheritDoc} 112 | * @since 2018/07/16 113 | */ 114 | @Override 115 | public void run(IOpipeExecution __e) 116 | throws Throwable 117 | { 118 | } 119 | } 120 | 121 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/__DoDiskReportCheck__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.http.RemoteRequest; 4 | import com.iopipe.http.RemoteResult; 5 | import java.util.Map; 6 | import javax.json.JsonString; 7 | import javax.json.JsonNumber; 8 | import javax.json.JsonValue; 9 | 10 | /** 11 | * This checks that disk usage was reported. 12 | * 13 | * @since 2018/05/17 14 | */ 15 | class __DoDiskReportCheck__ 16 | extends Single 17 | { 18 | /** Sent with no exception? */ 19 | protected final BooleanValue noerror = 20 | new BooleanValue("noerror"); 21 | 22 | /** Got a result from the server okay? */ 23 | protected final BooleanValue remoterecvokay = 24 | new BooleanValue("remoterecvokay"); 25 | 26 | /** Is there total space? */ 27 | protected final BooleanValue hastotal = 28 | new BooleanValue("hastotal"); 29 | 30 | /** Is there positive non-zero total space? */ 31 | protected final BooleanValue nonzeropositivetotal = 32 | new BooleanValue("nonzeropositivetotal"); 33 | 34 | /** Is there used space? */ 35 | protected final BooleanValue hasused = 36 | new BooleanValue("hasused"); 37 | 38 | /** Is there precentage used? */ 39 | protected final BooleanValue haspercent = 40 | new BooleanValue("haspercent"); 41 | 42 | /** 43 | * Constructs the test. 44 | * 45 | * @param __e The owning engine. 46 | * @since 2018/05/17 47 | */ 48 | __DoDiskReportCheck__(Engine __e) 49 | { 50 | super(__e, "diskreport"); 51 | } 52 | 53 | /** 54 | * {@inheritDoc} 55 | * @since 2018/05/17 56 | */ 57 | @Override 58 | public void end() 59 | { 60 | super.assertTrue(this.remoterecvokay); 61 | super.assertTrue(this.noerror); 62 | 63 | super.assertTrue(this.hastotal); 64 | super.assertTrue(this.nonzeropositivetotal); 65 | super.assertTrue(this.hasused); 66 | super.assertTrue(this.haspercent); 67 | } 68 | 69 | /** 70 | * {@inheritDoc} 71 | * @since 2018/05/17 72 | */ 73 | @Override 74 | public void remoteRequest(WrappedRequest __r) 75 | { 76 | StandardPushEvent event = (StandardPushEvent)__r.event; 77 | 78 | // It is invalid if there is an error 79 | if (!event.hasError()) 80 | this.noerror.set(true); 81 | 82 | StandardPushEvent.Disk usage = event.disk; 83 | if (usage == null) 84 | return; 85 | 86 | if (usage.totalmib >= 0) 87 | this.hastotal.set(true); 88 | 89 | if (usage.usedmib >= 0) 90 | this.hasused.set(true); 91 | 92 | if (!Double.isNaN(usage.usedpercentage)) 93 | this.haspercent.set(true); 94 | 95 | if (Math.signum(usage.usedpercentage) >= 0) 96 | this.nonzeropositivetotal.set(true); 97 | } 98 | 99 | /** 100 | * {@inheritDoc} 101 | * @since 2018/05/17 102 | */ 103 | @Override 104 | public void remoteResult(WrappedResult __r) 105 | { 106 | if (__Utils__.isResultOkay(__r.result)) 107 | this.remoterecvokay.set(true); 108 | } 109 | 110 | /** 111 | * {@inheritDoc} 112 | * @since 2018/05/17 113 | */ 114 | @Override 115 | public void run(IOpipeExecution __e) 116 | throws Throwable 117 | { 118 | } 119 | } 120 | 121 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/__DoGenericHandler__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.amazonaws.services.lambda.runtime.Context; 4 | import com.amazonaws.services.lambda.runtime.RequestHandler; 5 | import com.iopipe.generic.EntryPoint; 6 | import com.iopipe.generic.GenericAWSRequestHandler; 7 | import java.io.ByteArrayInputStream; 8 | import java.io.ByteArrayOutputStream; 9 | import java.io.InputStream; 10 | import java.io.IOException; 11 | import java.io.OutputStream; 12 | import com.iopipe.http.RemoteRequest; 13 | import com.iopipe.http.RemoteResult; 14 | 15 | /** 16 | * Checks to ensure the generic handler works. 17 | * 18 | * @since 2018/08/17 19 | */ 20 | class __DoGenericHandler__ 21 | extends Single 22 | { 23 | /** Sent with no exception? */ 24 | protected final BooleanValue noerror = 25 | new BooleanValue("noerror"); 26 | 27 | /** Got a result from the server okay? */ 28 | protected final BooleanValue remoterecvokay = 29 | new BooleanValue("remoterecvokay"); 30 | 31 | /** Does the label exist? */ 32 | protected final BooleanValue haslabel = 33 | new BooleanValue("haslabel"); 34 | 35 | /** 36 | * Constructs the test. 37 | * 38 | * @param __e The owning engine. 39 | * @since 2018/08/17 40 | */ 41 | __DoGenericHandler__(Engine __e) 42 | { 43 | super(__e, "generichandler"); 44 | } 45 | 46 | /** 47 | * {@inheritDoc} 48 | * @since 2018/08/17 49 | */ 50 | @Override 51 | public void end() 52 | { 53 | super.assertTrue(this.remoterecvokay); 54 | super.assertTrue(this.noerror); 55 | 56 | super.assertTrue(this.haslabel); 57 | } 58 | 59 | /** 60 | * {@inheritDoc} 61 | * @since 2018/08/17 62 | */ 63 | @Override 64 | public void remoteRequest(WrappedRequest __r) 65 | { 66 | StandardPushEvent event = (StandardPushEvent)__r.event; 67 | 68 | // It is invalid if there is an error 69 | if (!event.hasError()) 70 | this.noerror.set(true); 71 | 72 | // The label must be added 73 | if (event.labels.contains("squirrels")) 74 | this.haslabel.set(true); 75 | } 76 | 77 | /** 78 | * {@inheritDoc} 79 | * @since 2018/08/17 80 | */ 81 | @Override 82 | public void remoteResult(WrappedResult __r) 83 | { 84 | if (__Utils__.isResultOkay(__r.result)) 85 | this.remoterecvokay.set(true); 86 | } 87 | 88 | /** 89 | * {@inheritDoc} 90 | * @since 2018/08/17 91 | */ 92 | @Override 93 | public void run(IOpipeExecution __e) 94 | throws Throwable 95 | { 96 | // Run output 97 | __e.label((String)(new GenericAWSRequestHandler( 98 | EntryPoint.newAWSEntryPoint(Handler.class, "handleRequest")). 99 | handleRequest("SQUIRRELS", __e.context()))); 100 | } 101 | 102 | /** 103 | * Handler for requests. 104 | * 105 | * @since 2018/08/17 106 | */ 107 | public static final class Handler 108 | implements RequestHandler 109 | { 110 | /** 111 | * {@inheritDoc} 112 | * @since 2018/08/17 113 | */ 114 | @Override 115 | public final String handleRequest(String __in, Context __ctx) 116 | { 117 | return __in.toLowerCase(); 118 | } 119 | } 120 | } 121 | 122 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/__DoCustomMetric__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.http.RemoteRequest; 4 | import com.iopipe.http.RemoteResult; 5 | import java.util.Collections; 6 | import java.util.Map; 7 | import javax.json.JsonString; 8 | import javax.json.JsonNumber; 9 | import javax.json.JsonValue; 10 | 11 | /** 12 | * Tests that custom metrics are recorded properly. 13 | * 14 | * @since 2018/01/26 15 | */ 16 | class __DoCustomMetric__ 17 | extends Single 18 | { 19 | /** Sent with no exception? */ 20 | protected final BooleanValue noerror = 21 | new BooleanValue("noerror"); 22 | 23 | /** Got a result from the server okay? */ 24 | protected final BooleanValue remoterecvokay = 25 | new BooleanValue("remoterecvokay"); 26 | 27 | /** Is there a custom string? */ 28 | protected final BooleanValue hascustomstring = 29 | new BooleanValue("hascustomstring"); 30 | 31 | /** Is there a custom number? */ 32 | protected final BooleanValue hascustomnumber = 33 | new BooleanValue("hascustomnumber"); 34 | 35 | /** Is there an auto label? */ 36 | protected final BooleanValue hasautolabel = 37 | new BooleanValue("hasautolabel"); 38 | 39 | /** 40 | * Constructs the test. 41 | * 42 | * @param __e The owning engine. 43 | * @since 2018/01/26 44 | */ 45 | __DoCustomMetric__(Engine __e) 46 | { 47 | super(__e, "custommetric"); 48 | } 49 | 50 | /** 51 | * {@inheritDoc} 52 | * @since 2018/01/26 53 | */ 54 | @Override 55 | public void end() 56 | { 57 | super.assertTrue(this.remoterecvokay); 58 | super.assertTrue(this.noerror); 59 | 60 | super.assertTrue(this.hascustomstring); 61 | super.assertTrue(this.hascustomnumber); 62 | super.assertTrue(this.hasautolabel); 63 | } 64 | 65 | /** 66 | * {@inheritDoc} 67 | * @since 2018/01/26 68 | */ 69 | @Override 70 | public void remoteRequest(WrappedRequest __r) 71 | { 72 | StandardPushEvent event = (StandardPushEvent)__r.event; 73 | 74 | // It is invalid if there is an error 75 | if (!event.hasError()) 76 | this.noerror.set(true); 77 | 78 | for (CustomMetric m : event.custommetrics.values()) 79 | { 80 | if (m.hasString()) 81 | this.hascustomstring.set(true); 82 | 83 | if (m.hasLong()) 84 | this.hascustomnumber.set(true); 85 | } 86 | 87 | if (event.labels.contains("@iopipe/metrics")) 88 | this.hasautolabel.set(true); 89 | } 90 | 91 | /** 92 | * {@inheritDoc} 93 | * @since 2018/01/26 94 | */ 95 | @Override 96 | public void remoteResult(WrappedResult __r) 97 | { 98 | if (__Utils__.isResultOkay(__r.result)) 99 | this.remoterecvokay.set(true); 100 | } 101 | 102 | /** 103 | * {@inheritDoc} 104 | * @since 2018/01/26 105 | */ 106 | @Override 107 | public void run(IOpipeExecution __e) 108 | throws Throwable 109 | { 110 | __e.customMetric("string", "Squirrels are cute!"); 111 | __e.customMetric("number", 6012716073268438380L); 112 | 113 | // Add a metric with a very long name 114 | __e.customMetric(String.join("", Collections.nCopies( 115 | IOpipeConstants.NAME_CODEPOINT_LIMIT + 32, "a")), "Very long!"); 116 | } 117 | } 118 | 119 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/profiler/__Poller__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.profiler; 2 | 3 | import java.util.concurrent.atomic.AtomicBoolean; 4 | 5 | /** 6 | * This class polls a thread group 7 | * 8 | * @since 2018/02/12 9 | */ 10 | final class __Poller__ 11 | implements Runnable 12 | { 13 | /** The tracker to write to. */ 14 | protected final Tracker tracker; 15 | 16 | /** The thread group to poll for events. */ 17 | protected final ThreadGroup group; 18 | 19 | /** Should execution stop? */ 20 | final AtomicBoolean _stop = 21 | new AtomicBoolean(); 22 | 23 | /** 24 | * Initializes the thread poller. 25 | * 26 | * @param __t The tracker state. 27 | * @param __g The group to poll. 28 | * @throws NullPointerException On null arguments. 29 | * @since 2018/02/12 30 | */ 31 | __Poller__(Tracker __t, ThreadGroup __g) 32 | throws NullPointerException 33 | { 34 | if (__t == null || __g == null) 35 | throw new NullPointerException(); 36 | 37 | this.tracker = __t; 38 | this.group = __g; 39 | } 40 | 41 | /** 42 | * {@inheritDoc} 43 | * @since 2018/02/12 44 | */ 45 | @Override 46 | public void run() 47 | { 48 | ThreadGroup group = this.group; 49 | Tracker tracker = this.tracker; 50 | AtomicBoolean stop = this._stop; 51 | 52 | // Used as temporary storage for active thread enumeration 53 | Thread[] threads = new Thread[1]; 54 | 55 | // Used to measure how long a method has been in execution 56 | long basetime = System.nanoTime(), 57 | lasttime = basetime; 58 | 59 | // Keep polling threads 60 | int samplerate = ProfilerExecution.SAMPLE_RATE, 61 | resttime = 0; 62 | for (;;) 63 | { 64 | // Sleep for the sample rate time using the higher precision 65 | // sleep 66 | if (resttime > 0) 67 | try 68 | { 69 | Thread.sleep(resttime / 1_000_000, 70 | resttime % 1_000_000); 71 | } 72 | catch (InterruptedException e) 73 | { 74 | // Ignore 75 | } 76 | 77 | // Stop polling? 78 | if (stop.get()) 79 | break; 80 | 81 | // Calculate how long the method has been running, this is used 82 | // to measure real time 83 | long nowtime = System.nanoTime(), 84 | runtime = nowtime - basetime; 85 | int reltime = (int)(nowtime - lasttime); 86 | lasttime = nowtime; 87 | 88 | // Try to resize the array based on the number of active threads 89 | int guessedactivecount = group.activeCount(); 90 | if (guessedactivecount > threads.length) 91 | threads = new Thread[guessedactivecount]; 92 | 93 | // Enumerate all active threads 94 | int count = group.enumerate(threads, false); 95 | 96 | // Handle traces for all threads 97 | for (int i = 0; i < count; i++) 98 | { 99 | Thread thread = threads[i]; 100 | tracker.parseStackTrace(runtime, reltime, thread); 101 | } 102 | 103 | // Rest for a duration so that the next sample is the sampling 104 | // rate after this one 105 | resttime = samplerate - (int)(System.nanoTime() - nowtime); 106 | if (resttime > samplerate) 107 | resttime = samplerate; 108 | } 109 | } 110 | } 111 | 112 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/__DoGenericObjectTranslate__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.generic.ObjectTranslator; 4 | import com.iopipe.http.RemoteRequest; 5 | import com.iopipe.http.RemoteResult; 6 | import java.lang.reflect.Type; 7 | import java.util.Map; 8 | import javax.json.JsonString; 9 | import javax.json.JsonNumber; 10 | import javax.json.JsonValue; 11 | import org.pmw.tinylog.Logger; 12 | 13 | /** 14 | * Tests that the generic object translator works properly and is able to 15 | * translates objects to other types. 16 | * 17 | * @since 2018/08/20 18 | */ 19 | class __DoGenericObjectTranslate__ 20 | extends Single 21 | { 22 | /** Sent with no exception? */ 23 | protected final BooleanValue noerror = 24 | new BooleanValue("noerror"); 25 | 26 | /** Got a result from the server okay? */ 27 | protected final BooleanValue remoterecvokay = 28 | new BooleanValue("remoterecvokay"); 29 | 30 | /** The JSON file. */ 31 | protected final String file; 32 | 33 | /** The to class. */ 34 | protected final Type to; 35 | 36 | /** 37 | * Constructs the test. 38 | * 39 | * @param __e The owning engine. 40 | * @param __file The JSON file to read. 41 | * @param __to The to class. 42 | * @since 2018/08/20 43 | */ 44 | __DoGenericObjectTranslate__(Engine __e, String __file, Type __to) 45 | { 46 | super(__e, "objtrans-" + __file + "-" + __to.toString()); 47 | 48 | this.file = __file; 49 | this.to = __to; 50 | } 51 | 52 | /** 53 | * {@inheritDoc} 54 | * @since 2018/08/20 55 | */ 56 | @Override 57 | public void end() 58 | { 59 | super.assertTrue(this.remoterecvokay); 60 | super.assertTrue(this.noerror); 61 | } 62 | 63 | /** 64 | * {@inheritDoc} 65 | * @since 2018/08/20 66 | */ 67 | @Override 68 | public void remoteRequest(WrappedRequest __r) 69 | { 70 | StandardPushEvent event = (StandardPushEvent)__r.event; 71 | 72 | // It is invalid if there is an error 73 | if (!event.hasError()) 74 | this.noerror.set(true); 75 | } 76 | 77 | /** 78 | * {@inheritDoc} 79 | * @since 2018/08/20 80 | */ 81 | @Override 82 | public void remoteResult(WrappedResult __r) 83 | { 84 | if (__Utils__.isResultOkay(__r.result)) 85 | this.remoterecvokay.set(true); 86 | } 87 | 88 | /** 89 | * {@inheritDoc} 90 | * @since 2018/08/20 91 | */ 92 | @Override 93 | public void run(IOpipeExecution __e) 94 | throws Throwable 95 | { 96 | // Get basic object translation (may go to hashmap or similar) 97 | Object basic = __DoEventInfoPlugin__.__convert(Object.class, 98 | this.file); 99 | 100 | // Translate it 101 | Object target = ObjectTranslator.translator(basic.getClass(), 102 | this.to).translate(basic); 103 | 104 | // Debug log 105 | Logger.debug("Object translated {} {}/[Wanted: {}] | `{}` -> `{}`", 106 | basic.getClass(), target.getClass(), this.to, basic, target); 107 | __e.customMetric("source.class", basic.getClass().getName()); 108 | __e.customMetric("source.value", basic.toString()); 109 | __e.customMetric("target.class", target.getClass().getName()); 110 | __e.customMetric("target.value", target.toString()); 111 | } 112 | } 113 | 114 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/http/ServiceConnection.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.http; 2 | 3 | import java.io.IOException; 4 | import java.util.Objects; 5 | import okhttp3.HttpUrl; 6 | import okhttp3.MediaType; 7 | import okhttp3.OkHttpClient; 8 | import okhttp3.Request; 9 | import okhttp3.RequestBody; 10 | import okhttp3.Response; 11 | import okhttp3.ResponseBody; 12 | 13 | /** 14 | * This class sends requests to the remote server. 15 | * 16 | * @since 2017/12/17 17 | */ 18 | public final class ServiceConnection 19 | implements RemoteConnection 20 | { 21 | /** The OkHttp client manager. */ 22 | protected final OkHttpClient client; 23 | 24 | /** The URL to connect to. */ 25 | protected final HttpUrl url; 26 | 27 | /** The optional authorization token. */ 28 | protected final String authtoken; 29 | 30 | /** 31 | * Initializes the class for sending requests. 32 | * 33 | * @param __cl The pool where connections are sourced from. 34 | * @param __url The remote URL to send requests to. 35 | * @param __auth The optional authorization token. 36 | * @throws NullPointerException On null arguments except for 37 | * {@code __auth}. 38 | * @since 2017/12/17 39 | */ 40 | public ServiceConnection(OkHttpClient __cl, HttpUrl __url, String __auth) 41 | throws NullPointerException 42 | { 43 | if (__cl == null || __url == null) 44 | throw new NullPointerException(); 45 | 46 | this.client = __cl; 47 | this.url = __url; 48 | this.authtoken = __auth; 49 | } 50 | 51 | /** 52 | * {@inheritDoc} 53 | * @since 2018/02/24 54 | */ 55 | @Override 56 | public final RemoteResult send(RequestType __t, RemoteRequest __r) 57 | throws NullPointerException, RemoteException 58 | { 59 | if (__t == null || __r == null) 60 | throw new NullPointerException(); 61 | 62 | try 63 | { 64 | Request.Builder request = new Request.Builder(); 65 | 66 | request.url(this.url); 67 | 68 | String authtoken = this.authtoken; 69 | if (authtoken != null) 70 | request.header("Authorization", authtoken); 71 | 72 | String mimetype = __r.mimeType(); 73 | RequestBody body; 74 | if (mimetype == null || mimetype.isEmpty()) 75 | body = RequestBody.create(null, __r.body()); 76 | else 77 | body = RequestBody.create(MediaType.parse(mimetype), 78 | __r.body()); 79 | 80 | switch (__t) 81 | { 82 | case POST: 83 | request.post(body); 84 | break; 85 | 86 | case PUT: 87 | request.put(body); 88 | break; 89 | 90 | default: 91 | throw new RemoteException("Unsupported type: " + __t); 92 | } 93 | 94 | // Send request 95 | Response hr = this.client.newCall(request.build()).execute(); 96 | 97 | // Decode response 98 | try (ResponseBody rb = hr.body()) 99 | { 100 | if (rb == null) 101 | return new RemoteResult(hr.code(), "", new byte[0]); 102 | else 103 | return new RemoteResult(hr.code(), 104 | Objects.toString(rb.contentType(), 105 | RemoteBody.MIMETYPE_JSON), rb.bytes()); 106 | } 107 | } 108 | catch (IOException e) 109 | { 110 | throw new RemoteException("Could not send request.", e); 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/generic/GenericAWSRequestStreamHandler.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.generic; 2 | 3 | import com.amazonaws.services.lambda.runtime.Context; 4 | import com.amazonaws.services.lambda.runtime.RequestStreamHandler; 5 | import com.iopipe.IOpipeService; 6 | import com.iopipe.IOpipeWrappedException; 7 | import java.lang.invoke.MethodHandle; 8 | import java.io.InputStream; 9 | import java.io.IOException; 10 | import java.io.OutputStream; 11 | 12 | /** 13 | * This class uses a generic request handler for AWS to forward and wrap 14 | * another method without writing a wrapper. 15 | * 16 | * @since 2018/08/09 17 | */ 18 | public final class GenericAWSRequestStreamHandler 19 | implements RequestStreamHandler 20 | { 21 | /** The handle used for entry. */ 22 | protected final MethodHandle handle; 23 | 24 | /** 25 | * Initializes the entry point for the generic stream handler using the 26 | * default system provided entry point. 27 | * 28 | * @throws InvalidEntryPointException If the entry point is not valid. 29 | * @since 2018/08/13 30 | */ 31 | public GenericAWSRequestStreamHandler() 32 | throws InvalidEntryPointException 33 | { 34 | this(EntryPoint.defaultAWSEntryPoint()); 35 | } 36 | 37 | /** 38 | * Initializes the stream handler with the given entry point. 39 | * 40 | * @param __cl The entry class. 41 | * @param __m The entry method. 42 | * @throws InvalidEntryPointException If the entry point is not valid. 43 | * @throws NullPointerException On null arguments. 44 | * @since 2018/08/24 45 | */ 46 | public GenericAWSRequestStreamHandler(Class __cl, String __m) 47 | throws InvalidEntryPointException, NullPointerException 48 | { 49 | this(EntryPoint.newAWSEntryPoint(__cl, __m)); 50 | } 51 | 52 | /** 53 | * Initializes the stream handler with the given entry point. 54 | * 55 | * @param __e The entry point to use. 56 | * @throws NullPointerException On null arguments. 57 | * @since 2018/08/13 58 | */ 59 | public GenericAWSRequestStreamHandler(EntryPoint __e) 60 | throws NullPointerException 61 | { 62 | if (__e == null) 63 | throw new NullPointerException(); 64 | 65 | this.handle = __e.handleWithNewInstance(); 66 | } 67 | 68 | /** 69 | * {@inheritDoc} 70 | * @since 2018/08/09 71 | */ 72 | @Override 73 | public final void handleRequest(InputStream __in, OutputStream __out, 74 | Context __context) 75 | throws IOException 76 | { 77 | try 78 | { 79 | IOpipeService service = IOpipeService.instance(); 80 | service.run(__context, (__exec) -> 81 | { 82 | try 83 | { 84 | this.handle.invoke(__in, __out, __context); 85 | } 86 | catch (Throwable e) 87 | { 88 | throw new IOpipeWrappedException(e.getMessage(), e); 89 | } 90 | 91 | return null; 92 | }, __in); 93 | } 94 | catch (IOpipeWrappedException e) 95 | { 96 | Throwable t = e.getCause(); 97 | if (t instanceof IOException) 98 | throw (IOException)t; 99 | else if (t instanceof RuntimeException) 100 | throw (RuntimeException)t; 101 | else if (t instanceof Error) 102 | throw (Error)t; 103 | throw e; 104 | } 105 | } 106 | } 107 | 108 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/MockConnection.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.http.RemoteBody; 4 | import com.iopipe.http.RemoteConnection; 5 | import com.iopipe.http.RemoteException; 6 | import com.iopipe.http.RemoteRequest; 7 | import com.iopipe.http.RemoteResult; 8 | import com.iopipe.http.RequestType; 9 | import java.util.function.Consumer; 10 | import javax.json.JsonObject; 11 | import javax.json.JsonString; 12 | 13 | /** 14 | * This implements a basic connection which only checks if the token is valid 15 | * and if it is it will return success or failure. 16 | * 17 | * @since 2017/12/13 18 | */ 19 | public final class MockConnection 20 | implements RemoteConnection 21 | { 22 | /** This is the token which is considered to be valid for the service. */ 23 | public static final String VALID_TOKEN = 24 | "ThisIsNotARealIOpipeTokenAndIsUsedForTesting"; 25 | 26 | /** This is an invalid project token. */ 27 | public static final String INVALID_TOKEN = 28 | "ThisIsAnInvalidTokenAndIsNotCorrect"; 29 | 30 | /** The remote URL. */ 31 | protected final String url; 32 | 33 | /** The authorization token. */ 34 | protected final String authtoken; 35 | 36 | /** 37 | * Initializes the mock connection. 38 | * 39 | * @param __url The remote URL. 40 | * @param __auth The authorization token. 41 | * @throws NullPointerException If no URL was specified. 42 | * @since 2018/02/24 43 | */ 44 | public MockConnection(String __url, String __auth) 45 | throws NullPointerException 46 | { 47 | if (__url == null) 48 | throw new NullPointerException(); 49 | 50 | this.url = __url; 51 | this.authtoken = __auth; 52 | } 53 | 54 | /** 55 | * {@inheritDoc} 56 | * @since 2018/02/24 57 | */ 58 | @Override 59 | public RemoteResult send(RequestType __t, RemoteRequest __r) 60 | throws NullPointerException, RemoteException 61 | { 62 | if (__t == null || __r == null) 63 | throw new NullPointerException(); 64 | 65 | // Check the authorization token 66 | String url = this.url; 67 | if (url.equals(MockEngine.EVENT_URL)) 68 | { 69 | if (MockConnection.VALID_TOKEN.equals(((JsonString) 70 | ((JsonObject)__r.bodyAsJsonStructure()).get("client_id")). 71 | getString())) 72 | return new RemoteResult(202, "text/plain", "Accepted"); 73 | return new RemoteResult(401, RemoteBody.MIMETYPE_JSON, 74 | "{\"message\":\"Invalid client id sent.\"}"); 75 | } 76 | 77 | // Profiling URL 78 | else if (url.equals(MockEngine.PROFILER_URL)) 79 | { 80 | // Authorization must be sent 81 | if (!MockConnection.VALID_TOKEN.equals(this.authtoken)) 82 | return new RemoteResult(403, RemoteBody.MIMETYPE_JSON, 83 | "{\"message\":\"Not authorized.\"}"); 84 | 85 | // Use a mocked upload URL 86 | return new RemoteResult(201, RemoteBody.MIMETYPE_JSON, 87 | "{\"signedRequest\":\"" + MockEngine.PROFILER_RESULT_URL + 88 | "\", \"jwtAccess\":\"token\", " + 89 | "\"url\":\"http://localhost/snapshot\"}"); 90 | } 91 | 92 | // Profiling URL result 93 | else if (url.equals(MockEngine.PROFILER_RESULT_URL)) 94 | { 95 | return new RemoteResult(200, "", ""); 96 | } 97 | 98 | // Unknown 99 | else 100 | throw new RemoteException("Unknown remote URL: " + url); 101 | } 102 | } 103 | 104 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/http/RemoteResult.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.http; 2 | 3 | import java.lang.ref.Reference; 4 | import java.lang.ref.WeakReference; 5 | 6 | /** 7 | * This is used to store the result of a request made to the service. 8 | * 9 | * This class is immutable. 10 | * 11 | * @since 2017/12/13 12 | */ 13 | public final class RemoteResult 14 | extends RemoteBody 15 | { 16 | /** The response code of the result. */ 17 | protected final int code; 18 | 19 | /** String representation. */ 20 | private Reference _string; 21 | 22 | /** 23 | * Initializes the request with the given data. 24 | * 25 | * @param __c The status code of the result. 26 | * @param __t The mime type of the body. 27 | * @param __b The data making up the body. 28 | * @throws NullPointerException On null arguments. 29 | * @since 2018/02/24 30 | */ 31 | public RemoteResult(int __c, String __t, byte[] __b) 32 | throws NullPointerException 33 | { 34 | super(__t, __b); 35 | 36 | this.code = __c; 37 | } 38 | 39 | /** 40 | * Initializes the request with the given data. 41 | * 42 | * @param __c The status code of the result. 43 | * @param __t The mime type of the body. 44 | * @param __b The data making up the body. 45 | * @param __o The offset. 46 | * @param __l The length. 47 | * @throws ArrayIndexOutOfBoundsException If the offset and/or length 48 | * exceed the array bounds or are negative. 49 | * @throws NullPointerException On null arguments. 50 | * @since 2018/02/24 51 | */ 52 | public RemoteResult(int __c, String __t, byte[] __b, int __o, int __l) 53 | throws ArrayIndexOutOfBoundsException, NullPointerException 54 | { 55 | super(__t, __b, __o, __l); 56 | 57 | this.code = __c; 58 | } 59 | 60 | /** 61 | * Initializes the request with the given string. 62 | * 63 | * @param __c The status code of the result. 64 | * @param __t The mime type of the body. 65 | * @param __s The string to initialize the body with. 66 | * @throws NullPointerException On null arguments. 67 | * @since 2018/02/24 68 | */ 69 | public RemoteResult(int __c, String __t, String __s) 70 | throws NullPointerException 71 | { 72 | super(__t, __s); 73 | 74 | this.code = __c; 75 | } 76 | 77 | /** 78 | * Returns the status code of the result. 79 | * 80 | * @return The result status code. 81 | * @since 2018/02/24 82 | */ 83 | public final int code() 84 | { 85 | return this.code; 86 | } 87 | 88 | /** 89 | * {@inheritDoc} 90 | * @since 2018/02/24 91 | */ 92 | @Override 93 | public final boolean equals(Object __o) 94 | { 95 | if (this == __o) 96 | return true; 97 | 98 | if (!(__o instanceof RemoteResult)) 99 | return false; 100 | 101 | RemoteResult o = (RemoteResult)__o; 102 | return super.equals(o) && 103 | this.code == o.code; 104 | } 105 | 106 | /** 107 | * {@inheritDoc} 108 | * @since 2018/02/24 109 | */ 110 | @Override 111 | public final String toString() 112 | { 113 | Reference ref = this._string; 114 | String rv; 115 | 116 | if (ref == null || null == (rv = ref.get())) 117 | this._string = new WeakReference<>((rv = 118 | String.format("{result=%d, type=%s, body=%d bytes}", 119 | this.code, this.mimetype, this.body().length))); 120 | 121 | return rv; 122 | } 123 | } 124 | 125 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/SignerEvent.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import java.io.IOException; 4 | import java.io.StringReader; 5 | import java.util.Map; 6 | import javax.json.Json; 7 | import javax.json.JsonArray; 8 | import javax.json.JsonNumber; 9 | import javax.json.JsonObject; 10 | import javax.json.JsonString; 11 | import javax.json.JsonStructure; 12 | import javax.json.JsonValue; 13 | 14 | /** 15 | * This represents a request that was made to the signer for profiler data 16 | * upload, it is given a URL of data. 17 | * 18 | * @since 2018/07/16 19 | */ 20 | public final class SignerEvent 21 | implements Event 22 | { 23 | /** The ARN. */ 24 | public final String arn; 25 | 26 | /** The request ID. */ 27 | public final String requestid; 28 | 29 | /** The timestamp. */ 30 | public final long timestamp; 31 | 32 | /** The extension. */ 33 | public final String extension; 34 | 35 | /** 36 | * Initializes the signer event. 37 | * 38 | * @param __arn The passed ARN. 39 | * @param __requestid The request ID. 40 | * @param __timestamp The timestamp used. 41 | * @param __extension The extension used. 42 | * @since 2018/07/16 43 | */ 44 | public SignerEvent(String __arn, String __requestid, long __timestamp, 45 | String __extension) 46 | { 47 | this.arn = __arn; 48 | this.requestid = __requestid; 49 | this.timestamp = __timestamp; 50 | this.extension = __extension; 51 | } 52 | 53 | /** 54 | * Decodes the specified event. 55 | * 56 | * @param __data The event to decode. 57 | * @return The decoded event. 58 | * @throws NullPointerException On null arguments. 59 | * @since 2018/07/16 60 | */ 61 | public static SignerEvent decode(String __data) 62 | throws NullPointerException 63 | { 64 | if (__data == null) 65 | throw new NullPointerException(); 66 | 67 | try (StringReader r = new StringReader(__data)) 68 | { 69 | return SignerEvent.decode( 70 | ((JsonObject)(Json.createReader(r).read()))); 71 | } 72 | } 73 | 74 | /** 75 | * Decodes the specified event. 76 | * 77 | * @param __data The event to decode. 78 | * @return The decoded event. 79 | * @throws NullPointerException On null arguments. 80 | * @since 2018/07/16 81 | */ 82 | public static SignerEvent decode(JsonObject __data) 83 | throws NullPointerException 84 | { 85 | if (__data == null) 86 | throw new NullPointerException(); 87 | 88 | String arn = null; 89 | String requestid = null; 90 | long timestamp = Long.MIN_VALUE; 91 | String extension = null; 92 | 93 | for (Map.Entry e : __data.entrySet()) 94 | { 95 | JsonValue v = e.getValue(); 96 | 97 | String k; 98 | switch ((k = e.getKey())) 99 | { 100 | case "arn": 101 | arn = ((JsonString)v).getString(); 102 | break; 103 | 104 | case "requestId": 105 | requestid = ((JsonString)v).getString(); 106 | break; 107 | 108 | case "timestamp": 109 | timestamp = ((JsonNumber)v).longValue(); 110 | break; 111 | 112 | case "extension": 113 | extension = ((JsonString)v).getString(); 114 | break; 115 | 116 | // Unknown 117 | default: 118 | throw new RuntimeException( 119 | "Invalid key in Signer event: " + k); 120 | } 121 | } 122 | 123 | return new SignerEvent(arn, requestid, timestamp, extension); 124 | } 125 | } 126 | 127 | -------------------------------------------------------------------------------- /src/main/java/com/iopipe/plugin/eventinfo/S3Decoder.java: -------------------------------------------------------------------------------- 1 | package com.iopipe.plugin.eventinfo; 2 | 3 | import com.amazonaws.services.lambda.runtime.events.S3Event; 4 | import com.amazonaws.services.s3.event.S3EventNotification; 5 | import java.util.List; 6 | import java.util.Objects; 7 | 8 | /** 9 | * This class implements the decoder for S3 events. 10 | * 11 | * @since 2018/04/23 12 | */ 13 | public final class S3Decoder 14 | implements EventInfoDecoder 15 | { 16 | /** 17 | * {@inheritDoc} 18 | * @since 2018/05/02 19 | */ 20 | @Override 21 | public void accept(ValueAcceptor __a, Object __v) 22 | throws NullPointerException 23 | { 24 | if (__a == null || __v == null) 25 | throw new NullPointerException(); 26 | 27 | S3EventNotification v = (S3EventNotification)__v; 28 | 29 | // Is there going to be any at all? 30 | List records = 31 | v.getRecords(); 32 | if (records == null || records.size() <= 0) 33 | return; 34 | S3EventNotification.S3EventNotificationRecord record = records.get(0); 35 | 36 | __a.accept("Records[0].awsRegion", 37 | record.getAwsRegion()); 38 | __a.accept("Records[0].eventName", 39 | record.getEventName()); 40 | __a.accept("Records[0].eventTime", 41 | Objects.toString(record.getEventTime(), null)); 42 | 43 | S3EventNotification.RequestParametersEntity rparms = 44 | record.getRequestParameters(); 45 | if (rparms != null) 46 | { 47 | __a.accept("Records[0].requestParameters.sourceIPAddress", 48 | rparms.getSourceIPAddress()); 49 | } 50 | 51 | S3EventNotification.ResponseElementsEntity rese = 52 | record.getResponseElements(); 53 | if (rese != null) 54 | { 55 | __a.accept("Records[0].responseElements[\"x-amz-id-2\"]", 56 | rese.getxAmzId2()); 57 | __a.accept("Records[0].responseElements[\"x-amz-request-id\"]", 58 | rese.getxAmzRequestId()); 59 | } 60 | 61 | S3EventNotification.S3Entity sthree = record.getS3(); 62 | if (sthree != null) 63 | { 64 | S3EventNotification.S3BucketEntity bucket = sthree.getBucket(); 65 | if (bucket != null) 66 | { 67 | __a.accept("Records[0].s3.bucket.arn", 68 | bucket.getArn()); 69 | __a.accept("Records[0].s3.bucket.name", 70 | bucket.getName()); 71 | } 72 | 73 | S3EventNotification.S3ObjectEntity object = sthree.getObject(); 74 | if (object != null) 75 | { 76 | __a.accept("Records[0].s3.object.key", 77 | object.getKey()); 78 | __a.accept("Records[0].s3.object.sequencer", 79 | object.getSequencer()); 80 | __a.accept("Records[0].s3.object.size", 81 | object.getSize()); 82 | } 83 | } 84 | 85 | S3EventNotification.UserIdentityEntity uie = record.getUserIdentity(); 86 | if (uie != null) 87 | { 88 | __a.accept("Records[0].userIdentity.principalId", 89 | uie.getPrincipalId()); 90 | } 91 | } 92 | 93 | /** 94 | * {@inheritDoc} 95 | * @since 2018/04/23 96 | */ 97 | @Override 98 | public final String[] decodes() 99 | { 100 | return new String[] 101 | { 102 | "com.amazonaws.services.lambda.runtime.events.S3Event", 103 | "com.amazonaws.services.s3.event.S3EventNotification", 104 | }; 105 | } 106 | 107 | /** 108 | * {@inheritDoc} 109 | * @since 2018/04/23 110 | */ 111 | @Override 112 | public final String eventType() 113 | { 114 | return "s3"; 115 | } 116 | } 117 | 118 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | education, socio-economic status, nationality, personal appearance, race, 10 | religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at dev@iopipe.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/__DoGenericEntryPoint__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.elsewhere.Classes; 4 | import com.iopipe.generic.EntryPoint; 5 | import com.iopipe.http.RemoteRequest; 6 | import com.iopipe.http.RemoteResult; 7 | import java.lang.invoke.MethodHandle; 8 | 9 | /** 10 | * Checks to make sure entry points are working. 11 | * 12 | * @since 2018/08/17 13 | */ 14 | class __DoGenericEntryPoint__ 15 | extends Single 16 | { 17 | /** The methods to be tested for entry points. */ 18 | private static Object[] _METHODS = 19 | { 20 | Classes.PACKAGE_PRIVATE, "instancePrivate", 21 | Classes.PACKAGE_PRIVATE, "instancePackagePrivate", 22 | Classes.PACKAGE_PRIVATE, "instanceProtected", 23 | Classes.PACKAGE_PRIVATE, "instancePublic", 24 | Classes.PACKAGE_PRIVATE, "staticPrivate", 25 | Classes.PACKAGE_PRIVATE, "staticPackagePrivate", 26 | Classes.PACKAGE_PRIVATE, "staticProtected", 27 | Classes.PACKAGE_PRIVATE, "staticPublic", 28 | Classes.PUBLIC, "instancePrivate", 29 | Classes.PUBLIC, "instancePackagePrivate", 30 | Classes.PUBLIC, "instanceProtected", 31 | Classes.PUBLIC, "instancePublic", 32 | Classes.PUBLIC, "staticPrivate", 33 | Classes.PUBLIC, "staticPackagePrivate", 34 | Classes.PUBLIC, "staticProtected", 35 | Classes.PUBLIC, "staticPublic", 36 | }; 37 | 38 | /** Sent with no exception? */ 39 | protected final BooleanValue noerror = 40 | new BooleanValue("noerror"); 41 | 42 | /** Got a result from the server okay? */ 43 | protected final BooleanValue remoterecvokay = 44 | new BooleanValue("remoterecvokay"); 45 | 46 | /** Methods executed. */ 47 | protected final IntegerValue count = 48 | new IntegerValue("count"); 49 | 50 | /** 51 | * Constructs the test. 52 | * 53 | * @param __e The owning engine. 54 | * @since 2018/08/17 55 | */ 56 | __DoGenericEntryPoint__(Engine __e) 57 | { 58 | super(__e, "entrypoint"); 59 | } 60 | 61 | /** 62 | * {@inheritDoc} 63 | * @since 2018/08/17 64 | */ 65 | @Override 66 | public void end() 67 | { 68 | super.assertTrue(this.remoterecvokay); 69 | super.assertTrue(this.noerror); 70 | 71 | super.assertEquals(_METHODS.length / 2, this.count); 72 | } 73 | 74 | /** 75 | * {@inheritDoc} 76 | * @since 2018/08/17 77 | */ 78 | @Override 79 | public void remoteRequest(WrappedRequest __r) 80 | { 81 | StandardPushEvent event = (StandardPushEvent)__r.event; 82 | 83 | // It is invalid if there is an error 84 | if (!event.hasError()) 85 | this.noerror.set(true); 86 | } 87 | 88 | /** 89 | * {@inheritDoc} 90 | * @since 2018/08/17 91 | */ 92 | @Override 93 | public void remoteResult(WrappedResult __r) 94 | { 95 | if (__Utils__.isResultOkay(__r.result)) 96 | this.remoterecvokay.set(true); 97 | } 98 | 99 | /** 100 | * {@inheritDoc} 101 | * @since 2018/08/17 102 | */ 103 | @Override 104 | public void run(IOpipeExecution __e) 105 | throws Throwable 106 | { 107 | for (int i = 0, n = _METHODS.length; i < n; i += 2) 108 | { 109 | String form = (((Class)_METHODS[i]).getName()) + _METHODS[i + 1]; 110 | 111 | try 112 | { 113 | EntryPoint ep = EntryPoint.newAWSEntryPoint((Class)_METHODS[i], 114 | (String)_METHODS[i + 1]); 115 | 116 | if ("squirrel".equals(ep.handleWithNewInstance().invoke("SQUIRREL", null))) 117 | this.count.incrementAndGet(); 118 | } 119 | catch (Throwable t) 120 | { 121 | throw new RuntimeException(t); 122 | } 123 | } 124 | } 125 | } 126 | 127 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/__DoGenericStreamHandler__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.amazonaws.services.lambda.runtime.Context; 4 | import com.amazonaws.services.lambda.runtime.RequestStreamHandler; 5 | import com.iopipe.generic.EntryPoint; 6 | import com.iopipe.generic.GenericAWSRequestStreamHandler; 7 | import java.io.ByteArrayInputStream; 8 | import java.io.ByteArrayOutputStream; 9 | import java.io.InputStream; 10 | import java.io.IOException; 11 | import java.io.OutputStream; 12 | import com.iopipe.http.RemoteRequest; 13 | import com.iopipe.http.RemoteResult; 14 | 15 | /** 16 | * Checks to ensure the generic stream handler works. 17 | * 18 | * @since 2018/08/17 19 | */ 20 | class __DoGenericStreamHandler__ 21 | extends Single 22 | { 23 | /** Sent with no exception? */ 24 | protected final BooleanValue noerror = 25 | new BooleanValue("noerror"); 26 | 27 | /** Got a result from the server okay? */ 28 | protected final BooleanValue remoterecvokay = 29 | new BooleanValue("remoterecvokay"); 30 | 31 | /** Does the label exist? */ 32 | protected final BooleanValue haslabel = 33 | new BooleanValue("haslabel"); 34 | 35 | /** 36 | * Constructs the test. 37 | * 38 | * @param __e The owning engine. 39 | * @since 2018/08/17 40 | */ 41 | __DoGenericStreamHandler__(Engine __e) 42 | { 43 | super(__e, "genericstreamhandler"); 44 | } 45 | 46 | /** 47 | * {@inheritDoc} 48 | * @since 2018/08/17 49 | */ 50 | @Override 51 | public void end() 52 | { 53 | super.assertTrue(this.remoterecvokay); 54 | super.assertTrue(this.noerror); 55 | 56 | super.assertTrue(this.haslabel); 57 | } 58 | 59 | /** 60 | * {@inheritDoc} 61 | * @since 2018/08/17 62 | */ 63 | @Override 64 | public void remoteRequest(WrappedRequest __r) 65 | { 66 | StandardPushEvent event = (StandardPushEvent)__r.event; 67 | 68 | // It is invalid if there is an error 69 | if (!event.hasError()) 70 | this.noerror.set(true); 71 | 72 | // The label must be added 73 | if (event.labels.contains("squirrels")) 74 | this.haslabel.set(true); 75 | } 76 | 77 | /** 78 | * {@inheritDoc} 79 | * @since 2018/08/17 80 | */ 81 | @Override 82 | public void remoteResult(WrappedResult __r) 83 | { 84 | if (__Utils__.isResultOkay(__r.result)) 85 | this.remoterecvokay.set(true); 86 | } 87 | 88 | /** 89 | * {@inheritDoc} 90 | * @since 2018/08/17 91 | */ 92 | @Override 93 | public void run(IOpipeExecution __e) 94 | throws Throwable 95 | { 96 | ByteArrayInputStream bin = new ByteArrayInputStream( 97 | "SQUIRRELS".getBytes()); 98 | ByteArrayOutputStream bout = new ByteArrayOutputStream(); 99 | 100 | // Run output 101 | new GenericAWSRequestStreamHandler( 102 | EntryPoint.newAWSEntryPoint(Handler.class, "handleRequest")). 103 | handleRequest(bin, bout, __e.context()); 104 | 105 | // Check output 106 | bout.flush(); 107 | __e.label(new String(bout.toByteArray())); 108 | } 109 | 110 | /** 111 | * Handler for requests. 112 | * 113 | * @since 2018/08/17 114 | */ 115 | public static final class Handler 116 | implements RequestStreamHandler 117 | { 118 | /** 119 | * {@inheritDoc} 120 | * @since 2018/08/16 121 | */ 122 | @Override 123 | public final void handleRequest(InputStream __in, 124 | OutputStream __out, Context __ctx) 125 | throws IOException 126 | { 127 | for (;;) 128 | { 129 | int c = __in.read(); 130 | 131 | if (c < 0) 132 | break; 133 | 134 | if (c >= 'A' && c <= 'Z') 135 | c = (c - 'A') + 'a'; 136 | __out.write(c); 137 | } 138 | } 139 | } 140 | } 141 | 142 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/__DoPluginTest__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.iopipe.CustomMetric; 4 | import com.iopipe.http.RemoteRequest; 5 | import com.iopipe.http.RemoteResult; 6 | import java.util.Map; 7 | import javax.json.JsonObject; 8 | import javax.json.JsonString; 9 | import javax.json.JsonValue; 10 | 11 | /** 12 | * Tests that the test plugin runs its pre and post methods. 13 | * 14 | * @since 2018/01/26 15 | */ 16 | class __DoPluginTest__ 17 | extends Single 18 | { 19 | /** Is the plugin enabled? */ 20 | protected final boolean enabled; 21 | 22 | /** Sent with no exception? */ 23 | protected final BooleanValue noerror = 24 | new BooleanValue("noerror"); 25 | 26 | /** Got a result from the server okay? */ 27 | protected final BooleanValue remoterecvokay = 28 | new BooleanValue("remoterecvokay"); 29 | 30 | /** Was the plugin specified? */ 31 | protected final BooleanValue pluginspecified = 32 | new BooleanValue("pluginspecified"); 33 | 34 | /** Pre-execution made? */ 35 | protected final BooleanValue madepre = 36 | new BooleanValue("madepre"); 37 | 38 | /** Post-execution made? */ 39 | protected final BooleanValue madepost = 40 | new BooleanValue("madepost"); 41 | 42 | /** 43 | * Constructs the test. 44 | * 45 | * @param __e The owning engine. 46 | * @param __enabled Is the plugin enabled? 47 | * @since 2018/01/26 48 | */ 49 | __DoPluginTest__(Engine __e, boolean __enabled) 50 | { 51 | super(__e, "testplugin-" + (__enabled ? "enabled" : "disabled")); 52 | 53 | this.enabled = __enabled; 54 | } 55 | 56 | /** 57 | * {@inheritDoc} 58 | * @since 2018/01/26 59 | */ 60 | @Override 61 | public void end() 62 | { 63 | super.assertTrue(this.remoterecvokay); 64 | super.assertTrue(this.noerror); 65 | super.assertTrue(this.pluginspecified); 66 | 67 | // Depends on the enabled state of the plugin 68 | boolean enabled = this.enabled; 69 | 70 | super.assertEquals(enabled, this.madepre); 71 | super.assertEquals(enabled, this.madepost); 72 | } 73 | 74 | /** 75 | * {@inheritDoc} 76 | * @since 2018/01/26 77 | */ 78 | @Override 79 | public void modifyConfig(IOpipeConfigurationBuilder __cb) 80 | throws NullPointerException 81 | { 82 | if (__cb == null) 83 | throw new NullPointerException(); 84 | 85 | __cb.setPluginEnabled("test", this.enabled); 86 | } 87 | 88 | /** 89 | * {@inheritDoc} 90 | * @since 2018/01/26 91 | */ 92 | @Override 93 | public void remoteRequest(WrappedRequest __r) 94 | { 95 | StandardPushEvent event = (StandardPushEvent)__r.event; 96 | 97 | // It is invalid if there is an error 98 | if (!event.hasError()) 99 | this.noerror.set(true); 100 | 101 | // See if the test plugin was specified 102 | StandardPushEvent.Plugin plugin = event.plugins.get("test"); 103 | if (plugin != null) 104 | this.pluginspecified.set(true); 105 | 106 | // Check if pre and post calls were made 107 | if (event.custommetrics.get("pre") != null) 108 | this.madepre.set(true); 109 | 110 | if (event.custommetrics.get("post") != null) 111 | this.madepost.set(true); 112 | } 113 | 114 | /** 115 | * {@inheritDoc} 116 | * @since 2018/01/26 117 | */ 118 | @Override 119 | public void remoteResult(WrappedResult __r) 120 | { 121 | if (__Utils__.isResultOkay(__r.result)) 122 | this.remoterecvokay.set(true); 123 | } 124 | 125 | /** 126 | * {@inheritDoc} 127 | * @since 2018/01/26 128 | */ 129 | @Override 130 | public void run(IOpipeExecution __e) 131 | throws Throwable 132 | { 133 | // Do nothing, this just tests that the pre and post calls 134 | // were made. 135 | } 136 | } 137 | 138 | -------------------------------------------------------------------------------- /src/test/java/com/iopipe/__DoTimeOut__.java: -------------------------------------------------------------------------------- 1 | package com.iopipe; 2 | 3 | import com.amazonaws.services.lambda.runtime.Context; 4 | import com.iopipe.http.RemoteRequest; 5 | import com.iopipe.http.RemoteResult; 6 | 7 | /** 8 | * Tests that timeout occurs. 9 | * 10 | * @since 2018/01/26 11 | */ 12 | class __DoTimeOut__ 13 | extends Single 14 | { 15 | /** The extra amount of time to sleep to log timeout. */ 16 | private static final int _EXTRA_SLEEP_TIME = 17 | 500; 18 | 19 | /** Requests transmitted. */ 20 | protected final IntegerValue xmitcount = 21 | new IntegerValue("xmitcount"); 22 | 23 | /** Has an error value been sent? */ 24 | protected final BooleanValue haserror = 25 | new BooleanValue("haserror"); 26 | 27 | /** Got a result from the server okay? */ 28 | protected final BooleanValue remoterecvokay = 29 | new BooleanValue("remoterecvokay"); 30 | 31 | /** Is there an auto label? */ 32 | protected final BooleanValue hasautolabel = 33 | new BooleanValue("hasautolabel"); 34 | 35 | /** 36 | * Initializes the test. 37 | * 38 | * @param __e The owning engine. 39 | * @since 2018/01/26 40 | */ 41 | public __DoTimeOut__(Engine __e) 42 | { 43 | super(__e, "timeout"); 44 | } 45 | 46 | /** 47 | * {@inheritDoc} 48 | * @since 2018/01/26 49 | */ 50 | @Override 51 | public void end() 52 | { 53 | super.assertTrue(this.remoterecvokay); 54 | 55 | super.assertTrue(this.haserror); 56 | super.assertEquals(1, this.xmitcount); 57 | super.assertTrue(this.hasautolabel); 58 | } 59 | 60 | /** 61 | * {@inheritDoc} 62 | * @since 2018/01/26 63 | */ 64 | @Override 65 | public void modifyConfig(IOpipeConfigurationBuilder __cb) 66 | throws NullPointerException 67 | { 68 | if (__cb == null) 69 | throw new NullPointerException(); 70 | 71 | // Do not wait a long time for the default timeout window to expire 72 | // just make it shorter 73 | __cb.setTimeOutWindow(1000); 74 | } 75 | 76 | /** 77 | * {@inheritDoc} 78 | * @since 2018/01/26 79 | */ 80 | @Override 81 | public void remoteRequest(WrappedRequest __r) 82 | { 83 | StandardPushEvent event = (StandardPushEvent)__r.event; 84 | 85 | // Increment count 86 | int now = this.xmitcount.incrementAndGet(); 87 | 88 | // Only consider the first request 89 | if (now == 1) 90 | { 91 | // It must have an error condition 92 | if (event.hasError()) 93 | this.haserror.set(true); 94 | 95 | if (event.labels.contains("@iopipe/timeout")) 96 | this.hasautolabel.set(true); 97 | } 98 | } 99 | 100 | /** 101 | * {@inheritDoc} 102 | * @since 2018/01/26 103 | */ 104 | @Override 105 | public void remoteResult(WrappedResult __r) 106 | { 107 | if (__Utils__.isResultOkay(__r.result)) 108 | this.remoterecvokay.set(true); 109 | } 110 | 111 | /** 112 | * {@inheritDoc} 113 | * @since 2018/01/26 114 | */ 115 | @Override 116 | public void run(IOpipeExecution __e) 117 | throws Throwable 118 | { 119 | // Wait until the remaining time to expire 120 | for (;;) 121 | { 122 | // Determine how long to sleep for 123 | Context c = __e.context(); 124 | int sleepdur = c.getRemainingTimeInMillis(); 125 | 126 | // Finished sleeping 127 | if (sleepdur <= 0 || sleepdur == Integer.MAX_VALUE) 128 | break; 129 | 130 | // Sleep 131 | if ((sleepdur += _EXTRA_SLEEP_TIME) > 0) 132 | try 133 | { 134 | Thread.sleep(sleepdur); 135 | } 136 | catch (InterruptedException e) 137 | { 138 | } 139 | } 140 | 141 | // For for some more to make sure it does actually time out 142 | try 143 | { 144 | Thread.sleep(_EXTRA_SLEEP_TIME); 145 | } 146 | catch (InterruptedException e) 147 | { 148 | } 149 | } 150 | } 151 | 152 | --------------------------------------------------------------------------------