Gatling/AppMon 6.2 integration

Gatling is an open-source load testing framework. Using the Automation Library for AppMon 6.2, it is fairly easy to drive integration from any Gatling scenario written in Scala.

AppMon uses the Java automation library in the context of a Gatling/Scala script. According to the Scala Web Site: “Scala runs on the JVM, so Java and Scala stacks can be freely mixed for totally seamless integration.”

To do this, add the com.dynatrace.diagnostics.automation.jar automation library to your project’s classpath. This lets you use the RESTEndpoint object provided by the library.

// AppMon automation library

import com.dynatrace.diagnostics.automation.rest.sdk.RESTEndpoint
// AppMon Server REST URL  
val dt_server = "http://localhost:8020"  

// AppMon User  
val dt_user = "admin"  

// AppMon Password  
val dt_pwd = "admin"  

// Create an endpoint to send commands to AppMon Server
// using server address and credentials.

val endPoint = new RESTEndpoint(dt_user, dt_pwd, dt_server)

Use hooks to start/stop session recording and switch configuration

Before actually starting the test, you can use the before hook to:

When the test is done, use the after hook to:

  • Stop session recording to close the session.
  • Switch back to default configuration to revert DTAM to its defaults settings regarding transaction capturing details.
val dt_profile = "easyTravel" // System Profile  
 
  // if you are not sure about the System Profile name, you can use the following call  
  // to get a list of created System Profiles:  
  //  
  //    endPoint.getProfiles()  
  //  
val dt_presentableName = "Session1"         // User-readable presentable name for the session to be stored.  
val dt_description = "My Load Test Session" // Description for the session to be stored  
val dt_recordingOption = "all"              // all : All PurePaths including time series,  
                                            // violations : Only PurePaths marked as violated, including time series.  
                                            // timeseries : Time series only.  
val dt_isSessionLocked = false              // true to lock the session that is recorded, otherwise false  
val dt_isTimestamp = true                   // true to append <u>timestamp</u> information to the recorded session name, otherwise false  
before {   
  // Optional: switch to a specific configuration  
  // to allow for specific details level in captured data  
  // Note: make sure you created such configuration in AppMon before using it.  
  endPoint.activateConfiguration(dt_profile, "myCustomConfigurationName")  
    
  // If you are not sure about the Configuration name,  
  // you can use the following call to get a list of  
  // created Configurations for this System Profile:  
  //  
  // endPoint.getConfigurations(dt_profile)   

// start AppMon session recording for this test  
   endPoint.startRecording(  dt_profile  
                            , dt_presentableName  
                            , dt_description  
                            , dt_recordingOption  
                            , dt_isSessionLocked  
                            , dt_isTimestamp  
                            )  
    }
after {  
    // stop AppMon session recording for this test  
    endPoint.stopRecording(dt_profile)  
   
    // switch back to default AppMon configuration  
    endPoint.activateConfiguration(dt_profile, "Default")  
  }

Register test run

When using Gatling to run Web API tests, this interface creates a new test run with metadata. When this method is called, the response contains a unique ID for your test metadata on the AppMon Server. This ID is often referred to as testRunId. The AppMon Server uses the ID to distinguish test executions. Specify it in the request headers (see below) when executing your tests.

 val dt_versionMajor = "1"          // Major version
 val dt_versionMinor = "0"          // Minor version
 val dt_versionRevision  = "0"      // Revision 
 val dt_versionBuild  = "1"         // Build number  
 val dt_versionMilestone  = "1"     // Milestone  
 val dt_marker  = "1.0.0.1.1"       // Special version marker,
                                    // used in the heat-field of the Test Results dashlet chart.  
 val dt_category = "webapi"         // Category of the test. Valid value is one of  
                                    // "unit", "uidriven", "performance", "load" or "webapi".  
 val dt_platform = "Linux"          // The platform the test runs on.  
                                    // If not defined here, the platform is detected by the library.  
 val dt_loadTestName = "MyLoadTest" // The name of the load test.  
                                    // This field is only used for the "load" category.  

/* start a new test and register it with AppMon */  
 val dt_testrunid=endPoint.startTest( 
                         dt_profile  
                       , dt_versionMajor  
                       , dt_versionMinor  
                       , dt_versionRevision  
                       , dt_versionBuild  
                       , dt_versionMilestone  
                       , dt_marker  
                       , dt_category  
                       , dt_platform  
                       , dt_loadTestName  
                       , null  
                       )

Use header tags to convey context information with your requests

By default, AppMon labels recorded web requests from their URIs. In order to give them meaningful names (such as step names in a test scenario), a specific header tag can be added to the web requests.

This tag can also include a reference to the testrunid to indicate the test run a particular web request is part of.

Assemble the tag

The following helper function builds a AppMon header tag with the expected format, from the provided context data.

See Integration with Web Load Testing and Monitoring Tools and Web API tests for more information.

 /* 
NA     The timer Name of the request.  
         This can be the timer or transaction name used in the load test script to identify the response time measure, or the document/page title, or any other human-readable URL encoded identifier for that document.  
         NA=<timername>  
         Required

TR     TestRunId, from a registered test run  
       TR=<TestRunId>  
       Required

PC     The Page Context contains information about what document in the currently processed page is loaded.  
         The following syntax is recommended, though not required:  
         - If it is a named frame, then the value starts with the frame name.  
         - The document number, unique for the page, is appended after a period.  
         If embedded documents are cached, this number need not be progressive.  
         PC=<FrameName>.<DocId>  
         optional

VU     The unique number of the Virtual User that sends the request.  
       VU=<Id> 
       optional

ID     The unique request ID (serial number).  
       This string should be unique for one web request or a set of web requests that together make up a step/transaction execution.  
       ID=<Id> 
       optional

SI     The Source ID can be used to identify the product that triggered the request:  
       For example WLT (Web Load Testing), SYM  (dynaTrace Synthetic Monitoring), BB (Backbone), or LM (Last Mile).   
       optional

GR     Geographic Region, useful only for the Synthetic Monitoring solution.  
       This contains arbitrary text.  
       optional

AN     Agent Name: the logical name of the Agent from which the request originated.  
       This information is used by Synthetic Monitoring.    
       optional

SN     Script Name.  
       This groups a set of requests that make up a <u>multi</u>-step transaction, for example making an online purchase.  
       optional

TE     Test Name is the name of the entire load test.  
       It uniquely identifies a test run. 
       optional
*/

 def dt_tag(  
            NA:String  
            , TR:String 
            , PC:String=""  
            , VU:String=""  
            , ID:String=""  
            , SI:String=""  
            , GR:String=""  
            , AN:String=""  
            , SN:String=""
            , TE:String=""  
            )  
  : Map[String, String] =  
  {  
    var value:String = "NA="+NA+";TR="+TR+";RC=200;VU="+VU+";PC="+PC+";ID="+PC+";SI="+SI+";GR="+GR+";AN="+AN+";SN="+SN+";TE="+TE  

    return Map("x-dynaTrace" -> value)  
   }

Use the tag

When issuing HTTP requests, add the AppMon tag in the header by calling the aforementioned helper function. Then provide the name, testRunId and other optional contextual data:

    val chain_0 = exec(http("request_0")
                .get("/")  
                .headers(dt_tag("step name",dt_testrunid, ""))  
                    )

Analyze results in AppMon

Web API test

Load test