Skip to content

Instantly share code, notes, and snippets.

@mremond
Last active January 7, 2024 14:29
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save mremond/a5c1c25aad11dfc40ae7b4f18c000942 to your computer and use it in GitHub Desktop.
Save mremond/a5c1c25aad11dfc40ae7b4f18c000942 to your computer and use it in GitHub Desktop.
Writing a Tsung Plugin

Writing a Tsung plugin

This is a simple tutorial on writing a tsung plugin and a repost of our ProcessOne tutorial.

Since tsung is used to test servers lets define a simple server for testing. myserver.erl provides 3 operations: echo, add and subtract.

myserver.erl assumes the first byte to be a control instruction followed by 2 or more byte data. The echo operation merely returns the byte data while add and subtract performs these operations on the 2 byte data before returning the results. See the code of myserver.erl for details.

We assume the source files for tsung-1.2.1 are available. This example was compiled using Erlang OTP R11B-3.

Step 0. Download the source code for this tutorial

The source code for this tutorial is available for download as tarball (tutorial_tsung_1.tgz).

Step 1. Create tsung configuration file

Based on the 3 operations we want to test we define the myclient.xml which will take place of tsung.xml. You will notice myclient.xml looks very much like any normal tsung configuration file. The main difference is in the session definition. Here we use the ts_myclient type. Here is the session definition:

<session probability="100" name="myclient-example" type="ts_myclient"> 

This indicates which plugin tsung should call when creating a server request. We choose to name this plugin ts_myclient.

The next difference is within the request element. Here we define a ‘myclient’ element indicates the operations to test followed by the relevant data.

Notice that myclient has 2 attributes: type and arith (optional).

Step 2. Update DTD

We now need to modify the tsung-1.0.dtd or validation would fail.

In the request element we add the myclient tag:

<!ELEMENT request ( match*, dyn_variable*, ( http | jabber | raw | pgsql | myclient ) )> 

Next, we create the myclient element:

<!ELEMENT myclient (#PCDATA) > 

Followed by defining the attributes list for myclient.

<!ATTLIST myclient
         arith       (add | sub) #IMPLIED
         type        (echo | compute) #REQUIRED > 

Next, we add the ts_myclient option into the element’s type attribute list.

type     (ts_http | ts_jabber | ts_pgsql | ts_myclient ) #IMPLIED 

We do the same to the session’s type attribute list.

type         (ts_jabber | ts_http | ts_raw | ts_pgsql | ts_myclient ) #REQUIRED>

Step 3. Create include file

In PATH/include create the include file ts_myclient.hrl. This include file should have a minimum of two records:

  • myclient_request: for storing request information parsed from tsung configuration. Will be use to generate server requests.
  • myclient_dyndata: for storing dynamic information. Not used in this case.

Step 4. Config reader

Create the ts_config_myclient.erl in PATH/src/tsung_controller to parse the XML file. This file must export parse_config/2. ts_config_myclient:parse_config/2 is called from ts_config:parse/1.

However trying to run ts_config:parse/1 seperately seem to throw an undefined case error.

The important function definition is:

parse_config(Element = #xmlElement{name=myclient}, ...) 

Within this pattern we gather the various attributes, echo, compute, add, sub, and data creating a myclient_request record as needed. Notice for the case of type compute we parse the data into a list of 2 integers. Ensure you keep any data manipulation here consistant with calls in ts_myclient:get_message/1.

If your configuration file support several element types then you will need a parse_config function for each.

Step 5. ts_myclient

The final file to create is ts_myclient.erl in PATH/src/tsung.

The get_message/1 function builds the actual data to be transmitted to the server. The function returns a binary even if your protocol uses strings.

In ts_myclient:get_message/1, you can see how we create the message from the myclient_request record. Compare this with myserver:test/3 and myserver:test/1.

parse/2 deals with server responses. It is possible to parse the return data and update monitoring parameters. In the ts_myclient:parse/1, we count the number of single and multi bytes returned from the server. Obviously these must match echo and add / _sub calls.

The ts_mon:add/1 parameters are restricted to:

  1. {count, Type} – increments a running counter
  2. {sum, Type, Val} – adds Val to running counter
  3. {sample_counter, Type, Value} – updates sample_counter
  4. {sample, Type, Value} – updates counter

Step 6. Build and install

Return to PATH and type make followed by make install.

There is no need to update any makefile.

Step 7. Running

Start myserver then call myserver:server() in the erlang shell to start listening to the socket.

sh> erl -s myserver start_link
1> myserver:server(). 

Run Tsung, passing it myclient.xml:

sh> tsung -f myclient.xml
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment