Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 1030 lines (802 sloc) 44.094 kb
ecb2b19 Initial Iago Import
James Waldrop authored
1 <a name="Top"></a>
2
880304a @WamBamBoozle tiny edit to README
WamBamBoozle authored
3 # Iago, A Load Generator
8b81e77 @caniszczyk Add Travis CI support
caniszczyk authored
4 [![Build Status](https://secure.travis-ci.org/twitter/iago.png)](http://travis-ci.org/twitter/iago)
ecb2b19 Initial Iago Import
James Waldrop authored
5
6 * <a href="#Iago Quick Start">Iago Quick Start</a>
7 - <a href="#Iago Prerequisites">Iago Prerequisites</a>
8 - <a href="#Preparing Your Test">Preparing Your Test</a>
9 - <a href="#Executing Your Test">Executing Your Test</a>
10 * <a href="#Iago Overview">Iago Overview</a>
11 - <a href="#Supported Services">Supported Services</a>
12 - <a href="#Transaction Requirements">Transaction Requirements</a>
13 - <a href="#Sources of Transactions">Sources of Transactions</a>
14 * <a href="#Iago Architecture Overview">Iago Architecture Overview</a>
15 * <a href="#Implementing Your Test">Implementing Your Test</a>
16 - <a href="#Scala Example">Scala Example</a>
17 - <a href="#Scala Thrift Example">Scala Thrift Example</a>
18 - <a href="#Java Example">Java Example</a>
19 - <a href="#Java Thrift Example">Java Thrift Example</a>
20 - <a href="#Code Annotations for the Examples">Code Annotations for the Examples</a>
21 * <a href="#Configuring Your Test">Configuring Your Test</a>
b0f261a @WamBamBoozle fixed documenation hyperlinks. Added FinagleService & RefCountedService
WamBamBoozle authored
22 - <a href="#Specifying_Victims">Specifying Victims</a>
23 - <a href="#extension_point_parameters">Extension Point Parameters</a>
24 - <a href="#sending_large_messages">Sending Large Messages</a>
25 * <a href="#weighted_requests">Weighted Requests</a>
26 * <a href="#metrics">Metrics</a>
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
27 * <a href="#tracing">Tracing</a>
b0f261a @WamBamBoozle fixed documenation hyperlinks. Added FinagleService & RefCountedService
WamBamBoozle authored
28 * <a href="#artifacts">What Files Are Created?</a>
29 * <a href="#ChangeLog">ChangeLog</a>
ecb2b19 Initial Iago Import
James Waldrop authored
30 * <a href="#Contributing">Contributing to Iago</a>
31
32 <a name="Iago Quick Start"></a>
33
34 ## Iago Quick Start
35
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
36 Please join [iago-users@googlegroups.com](https://groups.google.com/d/forum/iago-users) for updates and to ask questions.
3603b6e open source release
James Waldrop authored
37
b64a15e @lahosken fix things that tripped me up while learning Parrot
lahosken authored
38 If you are already familiar with the Iago Load Generation tool, follow these steps to get started; otherwise, start with the <a href="http://twitter.github.com/iago/">Iago Overview</a> and perhaps <a href="http://twitter.github.com/iago/philosophy.html">Iago Philosophy</a>, also known as "Why Iago?". For questions, please contact [iago-users@googlegroups.com](https://groups.google.com/d/forum/iago-users).
ecb2b19 Initial Iago Import
James Waldrop authored
39
40 <a name="Iago Prerequisites"></a>
41
42 ### Iago Prerequisites
43
44 1. Download and unpack the Iago distribution.
8e03ca4 @travisbrown Update Scala version in README
travisbrown authored
45 We support Scala 2.10 and recommend you clone the latest master: <a href="https://github.com/twitter/iago/zipball/master">master</a>.
ecb2b19 Initial Iago Import
James Waldrop authored
46
b64a15e @lahosken fix things that tripped me up while learning Parrot
lahosken authored
47 2. Read the documentation.
ecb2b19 Initial Iago Import
James Waldrop authored
48
49 <a name="Preparing Your Test"></a>
50
51 ### Preparing Your Test
52
53 1. Identify your transaction source; see <a href="#Transaction Requirements">Transaction Requirements</a> and <a href="#Sources of Transactions">Sources of Transactions</a> for more information.
54 2. In Scala, extend the Iago server's `RecordProcessor` or `ThriftRecordProcessor` class, or in Java, extend `LoadTest` or `ThriftLoadTest`; see <a href="#Implementing Your Test">Implementing Your Test</a> for more information.
55 3. Create a `launcher.scala` file in your Iago `config` directory with the appropriate settings; see <a href="#Configuring Your Test">Configuring Your Test</a> for more information.
56
57 <a name="Executing Your Test"></a>
58
59 ### Executing Your Test
60
b64a15e @lahosken fix things that tripped me up while learning Parrot
lahosken authored
61 Launch Iago from the distribution with `java` `-jar` *iago_jar* `-f` *your_config*. This will create the Iago processes for you and configure it to use your transactions. To kill a running job, add `-k` to your launch parameters: `java` `-jar` *iago_jar* `-f` *your_config* `-k`.
ecb2b19 Initial Iago Import
James Waldrop authored
62
8ed7d9b fix typo
Soheil authored
63 If you launch your Iago job on your local machine and an old Iago job is still running, it probably won't get far: it will attempt to re-use a port and fail. You want to kill the running job, as described above.
e694344 @lahosken corrections, clarifications
lahosken authored
64
65 <em>If you build via Maven,</em> then you might wonder "How do I launch Iago 'from the distribution'?" The steps are:
66 <pre>
67 % <kbd>mvn package -DskipTests</kbd>
68 % <kbd>mkdir tmp; cd tmp</kbd>
69 % <kbd>unzip ../target/iago-<var>version</var>-package-dist.zip</kbd>
70 % <kbd>java -jar iago-<var>version</var>.jar -f config/<var>my_config</var>.scala</kbd>
71 </pre>
72 Don't assume that you can skip the package/unzip steps if you're just changing a config file. You need to re-package and unzip again.
ecb2b19 Initial Iago Import
James Waldrop authored
73
74 If you are using Iago as a library, for example, in the case of testing over the Thrift protocol or building more complex tests with HTTP or Memcached/Kestrel, you should instead add a task to your project's configuration. See <a href="#Configuring Your Test">Configuring Your Test</a> for more information.
75
76 [Top](#Top)
77
78 <a name="Iago Overview"></a>
79
80 ## Iago Overview
81
82 Iago is a load generation tool that replays production or synthetic traffic against a given target. Among other things, it differs from other load generation tools in that it attempts to hold constant the transaction rate. For example, if you want to test your service at 100K requests per minute, Iago attempts to achieve that rate.
83
84 Because Iago replays traffic, you must specify the source of the traffic. You use a transaction log as the source of traffic, in which each transaction generates a _request_ to your service that your service processes.
85
86 Replaying transactions at a fixed rate enables you to study the behavior of your service under an anticipated load. Iago also allows you to identify bottlenecks or other issues that may not be easily observable in a production environment in which your maximum anticipated load occurs only rarely.
87
88 [Top](#Top)
89
90 <a name="Supported Services"></a>
91
92 ### Supported Services
93
d2757e8 @lahosken add some material to "Services" section. Links to Transport class' sourc...
lahosken authored
94 Iago can generate service requests that travel the net in different ways and are in different formats. The code that does this is in a Transport, a class that extends <code>ParrotTransport</code>. Iago comes with several Transports already defined. When you configure your test, you will need to set some parameters; to understand which of those parameters are used and how they are used, you probably want to look at the source code for your test's Transport class.
ecb2b19 Initial Iago Import
James Waldrop authored
95
d2757e8 @lahosken add some material to "Services" section. Links to Transport class' sourc...
lahosken authored
96 * HTTP: Use <a href="https://github.com/twitter/iago/blob/master/src/main/scala/com/twitter/parrot/server/FinagleTransport.scala">FinagleTransport</a>
97 * Thrift: Use <a href="https://github.com/twitter/iago/blob/master/src/main/scala/com/twitter/parrot/server/ThriftTransport.scala">ThriftTransport</a>
98 * Memcached: Use <a href="https://github.com/twitter/iago/blob/master/src/main/scala/com/twitter/parrot/server/MemcacheTransport.scala">MemcacheTransport</a>
99 * Kestrel: Use <a href="https://github.com/twitter/iago/blob/master/src/main/scala/com/twitter/parrot/server/KestrelTransport.scala">KestrelTransport</a>
100 * UDP: Use <a href="https://github.com/twitter/iago/blob/master/src/main/scala/com/twitter/parrot/server/ParrotUdpTransport.scala">ParrotUdpTransport</a>
ecb2b19 Initial Iago Import
James Waldrop authored
101
102 Your service is typically an HTTP or Thrift service written in either Scala or Java.
103
104 [Top](#Top)
105
106 <a name="Transaction Requirements"></a>
107
108 ### Transaction Requirements
109
110 For replay, Iago recommends you scrub your logs to only include requests which meet the following requirements:
111
112 * **Idempotent**, meaning that re-execution of a transaction any number of times yields the same result as the initial execution.
113 * **Commutative**, meaning that transaction order is not important. Although transactions are initiated in replay order, Iago's internal behavior may change the actual execution order to guarantee the transaction rate. Also, transactions that implement `Future` responses are executed asynchronously. You can achieve ordering, if required, by using Iago as a library and initiating new requests in response to previous ones. Examples of this are available.
114
115 [Top](#Top)
116
117 <a name="Sources of Transactions"></a>
118
119 ### Sources of Transactions
120
121 Transactions typically come from logs, such as the following:
122
123 * Web server logs capture HTTP transactions.
124 * Proxy server logs can capture transactions coming through a server. You can place a proxy server in your stack to capture either HTTP or Thrift transactions.
125 * Network sniffers can capture transactions as they come across a physical wire. You can program the sniffer to create a log of transactions you identify for capture.
126
127 In some cases, transactions do not exist. For example, transactions for your service may not yet exist because they are part of a new service, or you are obligated not to use transactions that contain sensitive information. In such cases, you can provide _synthetic_ transactions, which are transactions that you create to model the operating environment for your service. When you create synthetic transactions, you must statistically distribute your transactions to match the distribution you expect when your service goes live.
128
129 [Top](#Top)
130
131 <a name="Iago Architecture Overview"></a>
132
133 ## Iago Architecture Overview
134
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
135 Iago consists of _feeders_ and _servers_. A _feeder_ reads your transaction source. A _server_ formats and delivers requests to the service you want to test. The feeder contains a `Poller` object, which is responsible for guaranteeing _cachedSeconds_ worth of transactions in the pipeline to the Iago servers.
136
137 Metrics are available in logs and in graphs as described in [Metrics](#metrics).
ecb2b19 Initial Iago Import
James Waldrop authored
138
139 The Iago servers generate requests to your service. Together, all Iago servers generate the specified number of requests per minute. A Iago server's `RecordProcessor` object executes your service and maps the transaction to the format required by your service.
140
b0f261a @WamBamBoozle fixed documenation hyperlinks. Added FinagleService & RefCountedService
WamBamBoozle authored
141 The feeder polls its servers to see how much data they need to maintain _cachedSeconds_ worth of data. That is how we can have many feeders that need not coordinate with each other.
142
143 Ensuring that we go through every last message is important when we are writing traffic summaries in the record processor, especially when the data set is small. The parrot feeder shuts down due to running out of time, running out of data, or both. When the feeder runs out of data we
144
145 - make sure that all the data in parrot feeder's internal queues are sent to the parrot server
146 - make sure all the data held in the parrot servers cache is sent
147 - wait until we get a response for all pending messages or until the reads time out
148
149 When the parrot feeder runs out of time (the duration configuration) the data in the feeder's internal queues are ignored, otherwise the same process as above occurs.
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
150
151
ecb2b19 Initial Iago Import
James Waldrop authored
152 [Top](#Top)
153
154 <a name="Implementing Your Test"></a>
155
156 ## Implementing Your Test
157
158 The following sections show examples of implementing your test in both Scala and Java. See <a href="#Code Annotations for the Examples">Code Annotations for the Examples</a> for information about either example.
159
160 [Top](#Top)
161
162 <a name="Scala Example"></a>
163
164 ### Scala Example
165
166 <p>To implement a load test in Scala, you must extend the Iago server's <code>RecordProcessor</code> class to specify how to map transactions into the requests that the Iago server delivers to your service. The following example shows a <code>RecordProcessor</code> subclass that implements a load test on an <code>EchoService</code> HTTP service:</p>
167
168 ```scala
169 package com.twitter.example
170
171 import org.apache.thrift.protocol.TBinaryProtocol
172
173 import com.twitter.parrot.processor.RecordProcessor // 1
174 import com.twitter.parrot.thrift.ParrotJob // 2
175 import com.twitter.parrot.server.{ParrotRequest,ParrotService} // 3
176 import com.twitter.logging.Logger
177 import org.jboss.netty.handler.codec.http.HttpResponse
178
179 import thrift.EchoService
180
181 class EchoLoadTest(parrotService: ParrotService[ParrotRequest, HttpResponse]) extends RecordProcessor {
182 val client = new EchoService.ServiceToClient(service, new TBinaryProtocol.Factory()) // 4
183 val log = Logger.get(getClass)
184
185 def processLines(job: ParrotJob, lines: Seq[String]) { // 5
186 lines map { line =>
187 client.echo(line) respond { rep =>
188 if (rep == "hello") {
189 client.echo("IT'S TALKING TO US") // 6
190 }
191 log.info("response: " + rep) // 7
192 }
193 }
194 }
195 }
196 ```
197
198 [Top](#Top)
199
200 <a name="Scala Thrift Example"></a>
201
202 ### Scala Thrift Example
203
204 <p>To implement a Thrift load test in Scala, you must extend the Iago server's <code>Thrift RecordProcessor</code> class to specify how to map transactions into the requests that the Iago server delivers to your service. The following example shows a <code>ThriftRecordProcessor</code> subclass that implements a load test on an <code>EchoService</code> Thrift service:</p>
205
206 ```scala
207 package com.twitter.example
208
209 import org.apache.thrift.protocol.TBinaryProtocol
210
211 import com.twitter.parrot.processor.ThriftRecordProcessor // 1
212 import com.twitter.parrot.thrift.ParrotJob // 2
213 import com.twitter.parrot.server.{ParrotRequest,ParrotService} // 3
214 import com.twitter.logging.Logger
215
216 import thrift.EchoService
217
218 class EchoLoadTest(parrotService: ParrotService[ParrotRequest, Array[Byte]]) extends ThriftRecordProcessor(parrotService) {
219 val client = new EchoService.ServiceToClient(service, new TBinaryProtocol.Factory()) // 4
220 val log = Logger.get(getClass)
221
222 def processLines(job: ParrotJob, lines: Seq[String]) { // 5
223 lines map { line =>
224 client.echo(line) respond { rep =>
225 if (rep == "hello") {
226 client.echo("IT'S TALKING TO US") // 6
227 }
228 log.info("response: " + rep) // 7
229 }
230 }
231 }
232 }
233 ```
234
235 [Top](#Top)
236
237
238 <a name="Java Example"></a>
239
240 ### Java Example
241
242 <p>To implement a load test in Java, you must extend the Iago server's <code>LoadTest</code> class to specify how to map transactions into the requests that the Iago server delivers to your service. The <code>LoadTest</code> class provides Java-friendly type mappings for the underlying Scala internals. The following example shows a <code>LoadTest</code> subclass that implements a load test on an <code>EchoService</code> HTTP service: </p>
243
244 ```java
245 package com.twitter.jexample;
246
247 import com.twitter.example.thrift.EchoService;
248 import com.twitter.parrot.processor.LoadTest; // 1
249 import com.twitter.parrot.thrift.ParrotJob; // 2
250 import com.twitter.parrot.server.ParrotRequest; // 3
251
252 import com.twitter.parrot.server.ParrotService; // 3
253 import com.twitter.util.Future;
254 import com.twitter.util.FutureEventListener;
255 import org.apache.thrift.protocol.TBinaryProtocol;
4ac838d @eliocapelati Just a small fix on README
eliocapelati authored
256 import org.jboss.netty.handler.codec.http.HttpResponse;
ecb2b19 Initial Iago Import
James Waldrop authored
257
258 import java.util.List;
259
260 public class EchoLoadTest extends LoadTest {
261 EchoService.ServiceToClient client = null;
262
263 public EchoLoadTest(ParrotService<ParrotRequest, HttpResponse> parrotService) {
264 super(parrotService);
265 client = new EchoService.ServiceToClient(service(), new TBinaryProtocol.Factory()); // 4
266 }
267
268 public void processLines(ParrotJob job, List<String> lines) { // 5
269 for(String line: lines) {
270 Future<String> future = client.echo(line);
271 future.addEventListener(new FutureEventListener<String>() {
272 public void onSuccess(String msg) {
273 System.out.println("response: " + msg);
274 }
275
276 public void onFailure(Throwable cause) {
277 System.out.println("Error: " + cause);
278 }
279 });
280 }
281 }
282 }
283 ```
284
285 [Top](#Top)
286
287 <a name="Java Example"></a>
288
289 ### Java Thrift Example
290
291 <p>To implement a Thrift load test in Java, you must extend the Iago server's <code>ThriftLoadTest</code> class to specify how to map transactions into the requests that the Iago server delivers to your service. The <code>ThriftLoadTest</code> class provides Java-friendly type mappings for the underlying Scala internals. The following example shows a <code>ThriftLoadTest</code> subclass that implements a load test on an <code>EchoService</code> Thrift service: </p>
292
293 ```java
294 package com.twitter.jexample;
295
296 import com.twitter.example.thrift.EchoService;
297 import com.twitter.parrot.processor.ThriftLoadTest; // 1
298 import com.twitter.parrot.thrift.ParrotJob; // 2
299 import com.twitter.parrot.server.ParrotRequest; // 3
300 import com.twitter.parrot.server.ParrotService; // 3
301 import com.twitter.util.Future;
302 import com.twitter.util.FutureEventListener;
303 import org.apache.thrift.protocol.TBinaryProtocol;
304
305 import java.util.List;
306
307 public class EchoLoadTest extends ThriftLoadTest {
308 EchoService.ServiceToClient client = null;
309
310 public EchoLoadTest(ParrotService<ParrotRequest, byte[]> parrotService) {
311 super(parrotService);
312 client = new EchoService.ServiceToClient(service(), new TBinaryProtocol.Factory()); // 4
313 }
314
9c7cfa0 @nkiesel fix HTML-encoding in preformatted code
nkiesel authored
315 public void processLines(ParrotJob job, List<String> lines) { // 5
ecb2b19 Initial Iago Import
James Waldrop authored
316 for(String line: lines) {
9c7cfa0 @nkiesel fix HTML-encoding in preformatted code
nkiesel authored
317 Future<String> future = client.echo(line);
318 future.addEventListener(new FutureEventListener<String>() {
ecb2b19 Initial Iago Import
James Waldrop authored
319 public void onSuccess(String msg) {
320 System.out.println("response: " + msg);
321 }
322
323 public void onFailure(Throwable cause) {
324 System.out.println("Error: " + cause);
325 }
326 });
327 }
328 }
329 }
330 ```
331
332 [Top](#Top)
333
334 <a name="Code Annotations for the Examples"></a>
335
336 ### Code Annotations for the Examples
337
338 You define your Iago subclass to execute your service and map transactions to requests for your service:
339
340 1. Import `com.twitter.parrot.processor.RecordProcessor` (Scala) or `LoadTest` (Java), whose instance will be executed by a Iago server.
341 2. Import `com.twitter.parrot.thrift.ParrotJob`, which contains the Iago server class.
342 3. Import `com.twitter.parrot.server.ParrotService` and `com.twitter.parrot.server.ParrotRequest`
343 4. Create an instance of your service to be placed under test. Your service is a client of the Iago service.
344 5. Define a `processLines` method to format the request and and execute your service.
345 6. Optionally, you can initiate a new request based on the response to a previous one.
346 7. Optionally, do something with the response. In this example, the response is logged.
347
348 [Top](#Top)
349
350 <a name="Configuring Your Test"></a>
351
352 ## Configuring Your Test
353
3ed0a3c @lahosken Maybe that advice about how to configure belongs in the configuring sect...
lahosken authored
354 To configure your test, create a `launcher.scala` file that that creates a `ParrotLauncherConfig` instance with the configuration parameters you want to set.
355
356 There are several parameters to set. A good one to <a href="#Supported Services">figure out early is <code>transport</code></a>; that will in turn help you to find out what, e.g., <code>responseType</code> you need.
357
358 The following example shows parameters for testing a Thrift service:
ecb2b19 Initial Iago Import
James Waldrop authored
359
360 ```scala
361 import com.twitter.parrot.config.ParrotLauncherConfig
362
363 new ParrotLauncherConfig {
364 distDir = "."
365 jobName = "load_echo"
366 port = 8080
367 victims = "localhost"
368 log = "logs/yesterday.log"
369 requestRate = 1
370 numInstances = 1
371 duration = 5
3ed0a3c @lahosken Maybe that advice about how to configure belongs in the configuring sect...
lahosken authored
372 timeUnit = "MINUTES" // affects duration; does not affect requestRate
ecb2b19 Initial Iago Import
James Waldrop authored
373
374 imports = "import com.twitter.example.EchoLoadTest"
375 responseType = "Array[Byte]"
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
376 transport = "ThriftTransportFactory(this)"
ecb2b19 Initial Iago Import
James Waldrop authored
377 loadTest = "new EchoLoadTest(service.get)"
378 }
379 ```
380
381 **Note:** For a sample configuration file, see `config/launcher.scala` within the Iago distribution</a>.
382
383 You can specify any of the following parameters:
384
385 <table border="1" cellpadding="1">
386 <thead>
387 <tr>
388 <th>Parameter</th>
389 <th>Description</th>
390 <th>Required or<br/>Default Value</th>
391 </tr>
392 </thead>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
393
ecb2b19 Initial Iago Import
James Waldrop authored
394 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
395 <td><code>createDistribution</code></td>
396 <td><p>You can use this field to create your own distribution rate, instead of having a constant flow. You will need to create a subclass of RequestDistribution and import it.</p>
397 <p><b>Example: </b><pre>createDistribution = """createDistribution = {
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
398 rate => new MyDistribution(rate)
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
399 }"""</pre></p></td>
400 <td><i>""</i></td>
ecb2b19 Initial Iago Import
James Waldrop authored
401 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
402
ecb2b19 Initial Iago Import
James Waldrop authored
403 <tr>
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
404 <td><code>customLogSource</code></td> <td><p>A string with Scala code that will be put into the
405 Feeder config. You can use this to get Iago to read in compressed files. Iago can read LZO
406 compressed files using its built-in LzoFileLogSource.</p>
407 <p><b>Example:</b><pre>customLogSource = """
408 if(inputLog.endsWith(".lzo")) {
409 logSource = Some(new com.twitter.parrot.feeder.LzoFileLogSource(inputLog))
410 }"""
411 </pre></p></td> <td><i>""</i></td>
412 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
413
ecb2b19 Initial Iago Import
James Waldrop authored
414 <tr>
415 <td><code>distDir</code></td>
416 <td><p>The subdirectory of your project you're running from, if any.</p>
417 <p><b>Example: </b><code>distDir = "target"</code></p></td>
418 <td><i>"."</i></td>
419 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
420
ecb2b19 Initial Iago Import
James Waldrop authored
421 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
422 <td><code>doConfirm</code></td>
423 <td><p>If set to false, you will not be asked to confirm the run.</p>
424 <p><b>Example: </b><code>doConfirm = false</code></p></td>
425 <td><i>true</i></td>
ecb2b19 Initial Iago Import
James Waldrop authored
426 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
427
ecb2b19 Initial Iago Import
James Waldrop authored
428 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
429 <td><code>duration</code></td>
430 <td><p>An integer value that specifies the time to run the test in <code>timeUnit</code> units.</p>
431 <p><b>Example: </b><code>duration = 5</code></p></td>
432 <td><code>&nbsp;</code></td>
ecb2b19 Initial Iago Import
James Waldrop authored
433 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
434
ecb2b19 Initial Iago Import
James Waldrop authored
435 <tr>
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
436 <td><code>feederXmx</code></td>
437 <td><p>Defines feeder heap size. Suggested not to be higher than 4 GB (will cause issues scheduling)</p>
438 <p><b>Example: </b><code>feederXmx = 2048</code></p></td>
439 <td><i>1744</i></td>
440 </tr>
441
442 <tr>
ecb2b19 Initial Iago Import
James Waldrop authored
443 <td><code>header</code></td>
444 <td><p>A string value that specifies the HTTP Host header.</p>
445 <p><b>Example: </b><code>header = "api.yourdomain.com"</code></p></td>
3a3e27b @lahosken Fix a couple of config doc mistakes.
lahosken authored
446 <td><code>""</code></td>
ecb2b19 Initial Iago Import
James Waldrop authored
447 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
448
ecb2b19 Initial Iago Import
James Waldrop authored
449 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
450 <td><code>hostConnectionCoresize</code></td>
451 <td><p>Number of connections per host that will be kept open, once established, until they hit max idle time or max lifetime</p>
452 <p><b>Example: </b><code>hostConnectionCoresize = 1</code></p></td>
453 <td><i>1</i></td>
ecb2b19 Initial Iago Import
James Waldrop authored
454 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
455
ecb2b19 Initial Iago Import
James Waldrop authored
456 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
457 <td><code>hostConnectionIdleTimeInMs</code></td>
458 <td><p>For any connection > coreSize, maximum amount of time, in milliseconds, between requests we allow before shutting down the connection</p>
459 <p><b>Example: </b><code>hostConnectionIdleTimeInMs = 50000</code></p></td>
460 <td><i>60000</i></td>
ecb2b19 Initial Iago Import
James Waldrop authored
461 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
462
ecb2b19 Initial Iago Import
James Waldrop authored
463 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
464 <td><code>hostConnectionLimit</code></td>
465 <td><p>Limit on the number of connections per host</p>
466 <p><b>Example: </b><code>hostConnectionLimit = 4</code></p></td>
467 <td><i>Integer.MAX_VALUE</i></td>
ecb2b19 Initial Iago Import
James Waldrop authored
468 </tr>
469 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
470 <td><code>hostConnectionMaxIdleTimeInMs</code></td>
471 <td><p>The maximum time in milliseconds that any connection (including within core size) can stay idle before shutdown</p>
472 <p><b>Example: </b><code>hostConnectionMaxIdleTimeInMs = 500000</code></p></td>
473 <td><i>300000</i></td>
ecb2b19 Initial Iago Import
James Waldrop authored
474 </tr>
475 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
476 <td><code>hostConnectionMaxLifeTimeInMs</code></td>
477 <td><p>The maximum time in milliseconds that a connection will be kept open</p>
478 <p><b>Example: </b><code>hostConnectionMaxLifeTimeInMs = 10000</code></p></td>
479 <td><i>Integer.MAX_VALUE</i></td>
480 </tr>
481
482 <tr>
483 <td><code>jobName</code></td>
484 <td><p>A string value that specifies the the name of your test. This is used for two things:
485 <ol>
486 <li>if the parrot feeder is configured to find its servers using zookeeper, and/or </li>
487 <li>when using mesos it is part of the job names generated. A job name of "foo" results in mesos job sharding groups "parrot_server_foo" and "parrot_feeder_foo".</li>
488 </ol>
489 </p>
490 <p><b>Example: </b><code>jobName = "testing_tasty_new_feature"</code></p></td>
491 <td><b>Required</b></td>
ecb2b19 Initial Iago Import
James Waldrop authored
492 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
493
494 <tr>
495 <td><code>localMode</code></td>
496 <td><p>Should Iago attempt to run locally or to use the cluster via mesos?</p>
497 <p><b>Example: </b><code>localMode = true</code></p></td>
498 <td><i>false</i></td>
499 </tr>
500
501 <tr>
502 <td><code>log</code></td>
503 <td><p>A string value that specifies the complete path to the log you want Iago to replay. If localMode=true then the log should be on your local file system. The log should have at least 1000 items or you should change the <code>reuseFile</code> parameter.</p>
504 <p><b>Example: </b><code>log = "logs/yesterday.log"</code></p>
505 <p><p>If localMode=false (the default), then the parrot launcher will copy your log file when attempts to make a package for mesos. You can avoid this, and should, by storing your log file in HDFS.<p><b>Example: </b><code>log = "hdfs://hadoop-example.com/yesterday.log"</code></p></td>
506 <td><b>Required</b></td>
507 </tr>
508
ecb2b19 Initial Iago Import
James Waldrop authored
509 <tr>
510 <td><code>loggers</code></td>
511 <td><p>A List of LoggerFactories; allows you to define the type and level of logging you want</p>
e694344 @lahosken corrections, clarifications
lahosken authored
512 <p><b>Example:</b></p>
513 <pre>import com.twitter.logging.LoggerFactory
514 import com.twitter.logging.config._
515
516 new ParrotLauncherConfig {
517 ...
518 loggers = new LoggerFactory(
519 level = Level.DEBUG,
520 handlers = new ConsoleHandlerConfig()
521 )
522 } </pre></td>
ecb2b19 Initial Iago Import
James Waldrop authored
523 <td><i>Nil</i></td>
524 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
525
ecb2b19 Initial Iago Import
James Waldrop authored
526 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
527 <td><code>maxRequests</code></td>
528 <td><p>An integer value that specifies the total number of requests to submit to your service.</p>
529 <p><b>Example: </b><code>maxRequests = 10000</code></p></td>
52c22c2 Default maxRequests to Integer.MAX_VALUE rather than 1000 to allow it to...
Michael Zalimeni authored
530 <td><code>Integer.MAX_VALUE</code></td>
ecb2b19 Initial Iago Import
James Waldrop authored
531 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
532
ecb2b19 Initial Iago Import
James Waldrop authored
533 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
534 <td><code>requestRate</code></td>
535 <td><p>An integer value that specifies the number of requests per second to submit to your service.</p>
536 <p><b>Example: </b><code>requestRate = 10</code></p>
537 <p>Note: if using multiple server instances, requestRate is per-instance, not aggregate.</p></td>
ecb2b19 Initial Iago Import
James Waldrop authored
538 <td><code>1</code></td>
539 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
540
ecb2b19 Initial Iago Import
James Waldrop authored
541 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
542 <td><code>reuseFile</code></td>
543 <td><p>A boolean value that specifies whether or not to stop the test when the input log has been read through. Setting this value to true will result in Iago starting back at the beginning of the log when it exhausts the contents. If this is true, your log file should at least be 1,000 lines or more.</p>
544 <p><b>Example: </b><code>reuseFile = false</code></p></td>
545 <td><code>true</code></td>
546 </tr>
547
548 <tr>
549 <td><code>scheme</code></td>
550 <td><p>A string value that specifies the scheme portion of a URI.</p>
551 <p><b>Example: </b><code>scheme = "http"</code></p></td>
ecb2b19 Initial Iago Import
James Waldrop authored
552 <td><code>http</code></td>
553 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
554
ecb2b19 Initial Iago Import
James Waldrop authored
555 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
556 <td><code>serverXmx</code></td>
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
557 <td><p>Defines server heap size. Suggested not to be higher than 8 GB (will cause issues scheduling)</p>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
558 <p><b>Example: </b><code>serverXmx = 5000</code></p></td>
559 <td><i>4000</i></td>
ecb2b19 Initial Iago Import
James Waldrop authored
560 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
561
562 <tr>
563 <td><code>requestTimeoutInMs</code></td>
564 <td>
565 <p>(From the Finagle Documentation) The request timeout is the time given to a *single* request (if there are retries, they each get a fresh request timeout). The timeout is applied only after a connection has been acquired. That is: it is applied to the interval between the dispatch of the request and the receipt of the response.</p>
566 <p>Note that parrot servers will not shut down until every response from every victim has come in. If you've modified your record processor to write test summaries this can be an issue.</p>
567 <p><b>Example: </b><code>requestTimeoutInMs = 3000 // if the victim doesn't respond in three seconds, stop waiting</code></p>
568 </td>
a4602db @WamBamBoozle honor timeouts, shutdown differently for timouts vs EOF
WamBamBoozle authored
569 <td><code>30000 // 30 seconds</code></td>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
570 </tr>
571
ecb2b19 Initial Iago Import
James Waldrop authored
572 <tr>
573 <td><code>reuseConnections</code></td>
574 <td><p>A boolean value that specifies whether connections to your service's hosts can be reused. A value of <code>true</code> enables reuse. Setting this to false greatly increases your use of ephemeral ports and can result in port exhaustion, causing you to achieve a lower rate than requested</p>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
575 <p>This is only implemented for FinagleTransport.</p>
ecb2b19 Initial Iago Import
James Waldrop authored
576 <p><b>Example: </b><code>reuseConnections = false</code></p></td>
577 <td><code>true</code></td>
578 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
579
ecb2b19 Initial Iago Import
James Waldrop authored
580 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
581 <td><code>thriftClientId</code></td>
582 <td><p>If you are making Thrift requests, your clientId</p>
583 <p><b>Example: </b><code>thriftClientId = "projectname.staging"</code></p></td>
584 <td><i>""</i></td>
ecb2b19 Initial Iago Import
James Waldrop authored
585 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
586
ecb2b19 Initial Iago Import
James Waldrop authored
587 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
588 <td><code>timeUnit</code></td>
589 <td><p>A string value that specifies time unit of the <code>duration</code>. It contains one of the following values:
590 <ul>
591 <li> "MINUTES"
592 <li> "HOURS"
593 <li> "DAYS"
594 </ul></p>
595 <p><b>Example: </b><code>timeUnit = "MINUTES"</code></p></td>
596 <td><code>&nbsp;</code></td>
ecb2b19 Initial Iago Import
James Waldrop authored
597 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
598
599
ecb2b19 Initial Iago Import
James Waldrop authored
600 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
601 <td><code>traceLevel</code></td>
602 <td><p>A <code>com.twitter.logging.Level</code> subclass. Controls the level of "debug logging" for servers and feeders.</p>
603 <p><b>Example:</b>
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
604 <pre>traceLevel = com.twitter.logging.Level.TRACE</pre>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
605 </p></td>
606 <td><code>Level.INFO</code></td>
ecb2b19 Initial Iago Import
James Waldrop authored
607 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
608
ecb2b19 Initial Iago Import
James Waldrop authored
609 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
610 <td><code>verboseCmd</code></td>
611 <td><p>A boolean value that specifies the level of feedback from Iago. A value of <code>true</code> specifies maximum feedback.</p>
612 <p><b>Example: </b><code>verboseCmd = true</code></p></td>
613 <td><code>false</code></td>
ecb2b19 Initial Iago Import
James Waldrop authored
614 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
615 </tbody>
616 </table>
617
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
618 <a name="Specifying_Victims"></a>
619
620 #### [Specifying Victims]
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
621
622 The point of Iago is to load-test a service. Iago calls these "victims".
623
624
625 Victims may be a
ecb2b19 Initial Iago Import
James Waldrop authored
626
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
627 1. single host:port pair
628 2. list of host:port pairs
629 3. a zookeeper serverset
630
631 Note that ParrotUdpTransport can only handle a single host:port pair. The other transports that come with Iago, being Finagle based, do not have this limitation.
632
633 <table border="1" cellpadding="6">
634 <thead>
ecb2b19 Initial Iago Import
James Waldrop authored
635 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
636 <th>Parameter</th>
637 <th>Description</th>
638 <th>Required or<br/>Default Value</th>
ecb2b19 Initial Iago Import
James Waldrop authored
639 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
640 </thead>
641
ecb2b19 Initial Iago Import
James Waldrop authored
642 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
643   <td><code>victims</code></td>
644   <td><p>A list of host:port pairs:</p>
645   <code>victims="example.com:80 example2.com:80"</code>
646   <p/><p>A zookeeper server set:</p>
647   <code>victims="/some/zookeeper/path"</code>
648   </td>
649   <td><b>Required</b></td>
ecb2b19 Initial Iago Import
James Waldrop authored
650 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
651
ecb2b19 Initial Iago Import
James Waldrop authored
652 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
653 <td><code>port</code></td>
654 <td><p>An integer value that specifies the port on which to deliver requests to the <code>victims</code>.</p>
655 <p>The port is used for two things: to provide a port if none were specified in victims, and to provide a port for the host header using a FinagleTransport.</p>
656 <p><b>Example: </b><code>port = 9000</code></p></td>
657 <td><b>Required</b></td>
ecb2b19 Initial Iago Import
James Waldrop authored
658 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
659
ecb2b19 Initial Iago Import
James Waldrop authored
660 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
661 <td><code>victimClusterType</code></td>
662 <td>
663 <p>When victimClusterType is "static", we set victims and port. victims can be a single host name, a host:port pair, or a list of host:port pairs separated with commas or spaces.</p>
664 <p>When victimClusterType is "sdzk" (which stands for "service discovery zookeeper") the victim is considered to be a server set, referenced with victims, victimZk, and victimZkPort.</p></td>
665 <td>Default: <code>"static"</code></td>
ecb2b19 Initial Iago Import
James Waldrop authored
666 </tr>
667 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
668 <td><code>victimZk</code></td>
669 <td><p>the host name of the zookeeper where your serverset is registered</p></td>
670 <td><p>Default is <code>"sdzookeeper.local.twitter.com"</code></p></td>
ecb2b19 Initial Iago Import
James Waldrop authored
671 </tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
672
ecb2b19 Initial Iago Import
James Waldrop authored
673 <tr>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
674 <td><code>victimZkPort</code></td>
675 <td><p>The port of the zookeeper where your serverset is registered</p></td>
676 <td><p>Default: <code>2181</code></p></td>
ecb2b19 Initial Iago Import
James Waldrop authored
677 </tr>
678 </table>
679
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
680 <a name="extension_point_parameters"></a>
681
682 #### [Extension Point Parameters]
ecb2b19 Initial Iago Import
James Waldrop authored
683
684 <p><strong>Alternative Use:</strong> You can specify the following <em>extension point</em> parameters to configure projects in which Iago is used as both a feeder and server. The Iago feeder provides the log lines to your project, which uses these log lines to form requests that the Iago server then handles:</p>
685
686 <table border="1" cellpadding="6">
687 <thead>
688 <tr>
689 <th>Parameter</th>
690 <th>Description</th>
691 <th>Required or<br/>Default Value</th>
692 </tr>
693 </thead>
694 <tr>
695 <td><code>imports</code></td>
696 <td><p>Imports from this project to Iago</p>
697 <p><b>Example: </b>If <code>ProjectX</code> includes Iago as a dependency, you would specify: <br/>
698 <code>import org.jboss.netty.handler.codec.http.HttpResponse <br/>
699 import com.twitter.<i>projectX</i>.util.ProcessorClass</code></p></td>
700 <td><code>import org.jboss.netty.handler.codec.http.HttpResponse<br/>
701 import com.twitter.parrot.util.LoadTestStub</code></td>
702 </tr>
703 <tr>
704 <td><code>requestType</code></td>
705 <td><p>The request type of requests from Iago.</p>
706 <p><b>Examples:</b>
707 <ul>
708 <li> <code>ParrotRequest</code> for most services (including HTTP and Thrift)
709 </ul> </p>
710 </td>
711 <td><code>ParrotRequest</code></td>
712 </tr>
713 <tr>
714 <td><code>responseType</code></td>
715 <td><p>The response type of responses from Iago.</p>
716 <p><b>Examples:</b>
717 <ul>
718 <li> <code>HttpResponse</code> for an HTTP service
719 <li> <code>Array[Byte]</code> for a Thrift service
720 </ul> </p>
721 </td>
722 <td><code>HttpResponse</code></td>
723 </tr>
724 <tr>
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
725 <td><code>transport</code></td>
726 <td>
727 <p>The kind of transport to the server, which matches the <code>responseType</code> you want.</p>
728 <p><b>Example:</b><code>transport = "ThriftTransportFactory(this)"</code></p>
729 <p>The Thrift Transport will send your request and give back <code>Future[Array[Byte]]</code>.</p>
730 </td>
731 <td><code>FinagleTransport</code></td>
ecb2b19 Initial Iago Import
James Waldrop authored
732 </tr>
733 <tr>
734 <td><code>loadTest</code></td>
735 <td><p>Your processor for the Iago feeder's lines, which converts the lines into requests and sends them to the Iago server.</p>
736 <p><b>Example: </b><code>new LoadTestStub(service.get)</code></p></td>
737 <td><code>new LoadTestStub(service.get)</code></td>
738 </tr>
739 </tbody>
740 </table>
741
742 [Top](#Top)
743
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
744 <a name="sending_large_messages"></a>
745
746 #### [Sending Large Messages]
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
747
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
748 By default, the parrot feeder sends a thousand messages at a time to each connected parrot server until the parrot server has twenty seconds worth of data. This is a good strategy when messages are small (less than a kilobyte). When messages are large, the parrot server will run out of memory. Consider an average message size of 100k, then the feeder will be maintaining an output queue for each connected parrot server of 100 million bytes. For the parrot server, consider a request rate of 2000, then 2000 * 20 * 100k = 4 gigabytes (at least). The following parameters help with large messages:
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
749
750 <table border="1" cellpadding="6">
751 <thead>
752 <tr>
753 <th>Parameter</th>
754 <th>Description</th>
755 <th>Required or<br/>Default Value</th>
756 </tr>
757 </thead>
758 <tr>
759 <td><code>batchSize</code></td>
760 <td>
761 <p>how many messages the parrot feeder sends at one time to the
762 parrot server. For large messages, setting this to 1 is
763 recommended.</p></td>
764 <td>Default: <code>1000</code></td>
765 </tr>
766 <tr>
767 <td><code>cachedSeconds</code></td>
a4602db @WamBamBoozle honor timeouts, shutdown differently for timouts vs EOF
WamBamBoozle authored
768 <td><p>How many seconds worth of data the parrot server will attempt to cache. Setting this to 1 for large messages is recommended. The consequence is that, if the parrot feeder garbage-collects, there will be a corresponding pause in traffic to your service unless cachedSeconds is set to a value larger than a typical feeder gc. This author has never observed a feeder gc exceeding a fraction of a second.</p></td>
769 <td><p>Default is <code>20</code></p></td>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
770 </tr>
771 </table>
ecb2b19 Initial Iago Import
James Waldrop authored
772
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
773 [Top](#Top)
774
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
775 <a name="weighted_requests"></a>
776
777 #### [Weighted Requests]
b0f261a @WamBamBoozle fixed documenation hyperlinks. Added FinagleService & RefCountedService
WamBamBoozle authored
778
779 Some applications must make bulk requests to their service. In other words, a single meta-request in the input log may result in several requests being satisfied by the victim. A weight field to ParrotRequest was added so that the RecordProcessor can set and use that weight to control the send rate in the RequestConsumer. For example, a request for 17 messages would be given a weight of 17 which would cause the RequestConsumer to sample the request distribution 17 times yielding a consistent distribution of load on the victim.
780
781 [Top](#Top)
782
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
783 <a name="metrics"></a>
784
785 ## [Metrics]
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
786
787 Iago uses [Ostrich](https://github.com/twitter/ostrich) to record its metrics. Iago is configured so that a simple graph server is available as long as the parrot server is running. If you are using localMode=true, then the default place for this is
788
789 &nbsp;&nbsp;[http://localhost:9994/graph/](http://localhost:9994/graph/)
790
791 One metric of particular interest is
792
793 &nbsp;&nbsp;[http://localhost:9994/graph/?g=metric:client/request_latency_ms](http://localhost:9994/graph/?g=metric:client/request_latency_ms)
794
795 Request latency is the time it takes to queue the request for sending until the response is received. See the [Finagle User Guide](http://twitter.github.io/finagle/guide/Metrics.html) for more about the individual metrics.
796
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
797
cbf6173 @julianrendell Updating readme with some more details about stats; adding links to Ragg...
julianrendell authored
798 Other metrics of interest:
799
800 <table border="1" cellpadding="6">
801 <thead>
802 <tr>
803 <th>Statistic</th>
804 <th>Description</th>
805 </tr>
806 </thead>
807 <tr>
497b0bf @julianrendell fixing formatting. Also - this info is just a copy of messages in the us...
julianrendell authored
808 <td><code>connection_duration</code></td>
cbf6173 @julianrendell Updating readme with some more details about stats; adding links to Ragg...
julianrendell authored
809 <td>duration of a connection from established to closed?</td>
810 </tr>
811 <tr>
497b0bf @julianrendell fixing formatting. Also - this info is just a copy of messages in the us...
julianrendell authored
812 <td><code>connection_received_bytes</code></td>
cbf6173 @julianrendell Updating readme with some more details about stats; adding links to Ragg...
julianrendell authored
813 <td>bytes received per connection</td>
814 </tr>
815 <tr>
497b0bf @julianrendell fixing formatting. Also - this info is just a copy of messages in the us...
julianrendell authored
816 <td><code>connection_requests</code></td>
cbf6173 @julianrendell Updating readme with some more details about stats; adding links to Ragg...
julianrendell authored
817 <td>Number of connection requests that your client did, ie. you can have a pool of 1 connection and the connection can be closed 3 times, so the "connection_requests" would be 4 (even if connections = 1)</td>
818 </tr>
819 <tr>
497b0bf @julianrendell fixing formatting. Also - this info is just a copy of messages in the us...
julianrendell authored
820 <td><code>connection_sent_bytes</code></td>
cbf6173 @julianrendell Updating readme with some more details about stats; adding links to Ragg...
julianrendell authored
821 <td>bytes send per connection</td>
822 </tr>
823 <tr>
497b0bf @julianrendell fixing formatting. Also - this info is just a copy of messages in the us...
julianrendell authored
824 <td><code>connections</code></td>
cbf6173 @julianrendell Updating readme with some more details about stats; adding links to Ragg...
julianrendell authored
825 <td>is the current number of connections between client and server</td>
826 </tr>
827 <tr>
497b0bf @julianrendell fixing formatting. Also - this info is just a copy of messages in the us...
julianrendell authored
828 <td><code>handletime_us</code></td>
cbf6173 @julianrendell Updating readme with some more details about stats; adding links to Ragg...
julianrendell authored
829 <td>time to process the response from the server (ie. execute all the chained map/flatMap)</td>
830 </tr>
831 <tr>
497b0bf @julianrendell fixing formatting. Also - this info is just a copy of messages in the us...
julianrendell authored
832 <td><code>pending</code></td>
cbf6173 @julianrendell Updating readme with some more details about stats; adding links to Ragg...
julianrendell authored
833 <td>Number of pending requests (ie. requests without responses)</td>
834 </tr>
835 <tr>
497b0bf @julianrendell fixing formatting. Also - this info is just a copy of messages in the us...
julianrendell authored
836 <td><code>request_concurrency</code></td>
cbf6173 @julianrendell Updating readme with some more details about stats; adding links to Ragg...
julianrendell authored
837 <td>is the current number of connections being processed by finagle</td>
838 </tr>
839 <tr>
497b0bf @julianrendell fixing formatting. Also - this info is just a copy of messages in the us...
julianrendell authored
840 <td><code>request_latency_ms</code></td>
cbf6173 @julianrendell Updating readme with some more details about stats; adding links to Ragg...
julianrendell authored
841 <td>the time of everything between request/response.</td>
842 </tr>
843 <tr>
497b0bf @julianrendell fixing formatting. Also - this info is just a copy of messages in the us...
julianrendell authored
844 <td><code>request_queue_size</code></td>
cbf6173 @julianrendell Updating readme with some more details about stats; adding links to Ragg...
julianrendell authored
845 <td>Number of requests waiting to be handled by the server</td>
846 </tr>
847 <tr>
848 </table>
849
850
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
851 ### [Raggiana]
852
853 Raggiana is a simple standalone Finagle stats viewer.
854
855 You can use Raggiana to view the stats log, <a href="#artifacts">parrot-server-stats.log</a>, generated by Iago.
856
857 You can clone it from
858
859 https://github.com/twitter/raggiana
860
861 or, just use it directly at
862
863 http://twitter.github.io/raggiana
864
865 [Top](#Top)
866
867 <a name="tracing"></a>
868
869 ## [Tracing]
870
871 Parrot works with [Zipkin](http://twitter.github.io/zipkin/), a distributed tracing system.
cbf6173 @julianrendell Updating readme with some more details about stats; adding links to Ragg...
julianrendell authored
872
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
873 [Top](#Top)
874
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
875 <a name="artifacts"></a>
876
877 ## [What Files Are Created?]
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
878
879 The Iago launcher creates the following files
880
881 config/target/parrot-feeder.scala
882 config/target/parrot-server.scala
883 scripts/common.sh
884 scripts/parrot-feeder.sh
885 scripts/parrot-server.sh
886
887 The Iago feeder creates
888
889 parrot-feeder.log
890 gc-feeder.log
891
892 The Iago server creates
893
894 parrot-server.log
895 parrot-server-stats.log
896 gc-server.log
897
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
898 The logs are rotated by size. Each individual log can be up to 100 megabytes before being rotated. There are 6 rotations maintained.
899
900 The stats log, `parrot-server-stats.log`, is a minute-by-minute dump of all the statistics (or <a
901 href="#metrics">Metrics</a>) maintained by the Iago server. Each entry is for the time period since
902 the previous one. That is, all entries in `parrot-server-stats.log` need to be accumulated to match
903 the final values reported by [http://localhost:9994/stats.txt](http://localhost:9994/stats.txt).
904
905 [Top](#Top)
906
907 ## Using Iago as a Library
908
909 While Iago provides everything you need to target your API with a large distributed loadtest with just a small log processor,
910 it also exposes a library of classes for log processing, traffic replay, & load generation. These can be used in your Iago configuration or incorporated in your application as a library.
911
912 parrot/server:
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
913
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
914 * ParrotRequest: Parrot's internal representation of a request
915 * ParrotTransport (FinagleTransport, KestrelTransport, MemcacheTransport, ParrotUdpTransport, ThriftTransport): Interchangeable transport layer for requests to be sent. Parrot contains transport implementations for the following protocols: HTTP (FinagleTransport), Kestrel, Memcache, raw UDP and Thrift.
916 * RequestConsumer: Queues ParrotRequests and sends them out on a ParrotTransport at a rate determined by RequestDistribution
917 * RequestQueue: A wrapper/control layer for RequestConsumer
918 * ParrotService (ParrotThriftService): Enqueues ParrotRequests to a RequestQueue. ParrotThriftService implements finagle's Service interface for use with finagle thrift clients.
cbf6173 @julianrendell Updating readme with some more details about stats; adding links to Ragg...
julianrendell authored
919
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
920 parrot/util:
921
922 * RequestDistribution: A function specifying the time to arrival of the next request, used to control the request rate. Instances include
923 * UniformDistribution: Sends requests at a uniform rate
924 * PoissonProcess: Sends requests at approximatly constant rate randomly varying using a poisson process. This is the default.
925 * SinusoidalPoissonProcess: Like PoissonProcess but varying the rate sinusoidally.
926 * SlowStartPoissonProcess: Same as PoissonProcess but starting with a gradual ramp from initial rate to final rate. It will then hold steady at the final rate until time runs out.
927 * InfiniteRampPoissonProcess: a two staged ramped distribution. Ideal for services that need a warm-up period before ramping up. The rate continues to increase until time runs out.
928
929 You may also find the LogSource and RequestProcessor interfaces discussed earlier useful.
930
931 Examples:
932 <pre>
933 // Make 1000 HTTP requests at a roughly constant rate of 10/sec
934
935 // construct the transport and queue
936 val client =
937 ClientBuilder()
938 .codec(http())
939 .hosts("twitter.com:80")
940 .build()
941 val transport = new FinagleTransport(FinagleService(client))
942 val consumer = new RequestConsumer(() => new PoissionProcess(10)
943 // add 1000 requests to the queue
944 for (i <- (1 to 1000)) {
945 consumer.offer(new ParrotRequest(uri= Uri("/jack/status/20", Nil))
946 }
947 // start sending
948 transport.start()
949 consumer.start()
950 // wait for the comsumer to exhaust the queue
951 while(consumer.size > 0) {
952 Thread.sleep(100)
953 }
954 // shutdown
955 consumer.shutdown()
956 transport.close()
957 </pre>
958
959 <pre>
960 // Call a thrift service with a sinusoidally varying rate
961
962 // Configure cluster for the service using zookeeper
963 val zk = "zookeeper.example.com"
964 val zkPort = 2181
965 val path = "my/env/role/service"
966 val zookeeperClient = new ZooKeeperClient(Amount.of(1, Time.SECONDS),
967 Seq(InetSocketAddress.createUnresolved(zk, zkPort)).asJava)
968 val serverSet = new ServerSetImpl(zookeeperClient, path)
969 val cluster = new ZookeeperServerSetCluster(serverSet)
970
971 // create transport and queue
972 val client =
973 ClientBuilder()
974 .codec(ThriftClientFramedCodec)
975 .cluster(cluster)
976 .build()
977 val transport = new ThriftTransport(client)
978 val createDistribution = () => new SinusoidalPoisionProccess(10, 20, 60.seconds)
979 val queue = new RequestQueue(new RequestConsumer(createDistribution, transport), transport)
980 // create the service and processor
981 val service = transport.createService(queue)
982 val processor = new EchoLoadTest(service)
983 // start sending
984 transport.start()
985 consumer.start()
986 // Fill the queue from a logfile
987 val source = new LogSourceImpl("some_file.txt")
988 while (source.hasNext) {
989 processor.processLines(Seq(source.next))
990 }
991 // wait for the comsumer to exhaust the queue
992 while(consumer.size > 0) {
993 Thread.sleep(100)
994 }
995 // shutdown
996 consumer.shutdown()
997 transport.close()
998 </pre>
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
999
1000 [Top](#Top)
1001
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
1002 <a name="ChangeLog"></a>
1003
1004 ## [ChangeLog]
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
1005
a4602db @WamBamBoozle honor timeouts, shutdown differently for timouts vs EOF
WamBamBoozle authored
1006 2013-06-25 release 0.6.7
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
1007
a4602db @WamBamBoozle honor timeouts, shutdown differently for timouts vs EOF
WamBamBoozle authored
1008 * graceful shutdown for small log sources
1009 * dropped vestigial parser config
1010 * weighted parrot requests
3eff4c3 @WamBamBoozle big
WamBamBoozle authored
1011 * supporting large requests (BlobStore): new configurations cachedSeconds & mesosRamInMb
1012 * launcher changes: configurable proxy, create config directory if needed, and handle errors better (don't hang)
1013 * serversets as victims
1014 * make local logs work with non-local distribution directories
1015 * kestrel transport transactional get support
1016 * check generated config files *before* launch
1017 * LzoFileLogSource for iago
1018 * Thrift over TLS
1019 * traceLevel config
1020
1021 [Top](#Top)
1022
ff22764 @WamBamBoozle Iago 0.6.14
WamBamBoozle authored
1023 <a name="Contributing"></a>
1024
1025 ## [Contributing to Iago]
ecb2b19 Initial Iago Import
James Waldrop authored
1026
1027 Iago is open source, hosted on Github <a href="http://github.com/twitter/iago">here</a>.
1028 If you have a contribution to make, please fork the repo and submit a pull request.
1029
Something went wrong with that request. Please try again.