<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/">
    <channel>
        <title>ngrinder</title>
        <link>http://www.cubrid.org/?mid=wiki_ngrinder</link>
        <description>ngrinder</description>
        <language>en</language>
        <pubDate>Wed, 20 Jun 2012 00:48:07 -0800</pubDate>
        <lastBuildDate>Tue, 18 Jun 2013 08:00:21 -0800</lastBuildDate>
        <generator>XpressEngine 1.4.4.1</generator>
                        										        <item>
            <title>nGrinder 3.2.1 Release Note</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=ngrinder-3-2-1-release-note</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=ngrinder-3-2-1-release-note</guid>
                                    <description><![CDATA[<blockquote class="q4"><div>nGrinder 3.2.1 is the bug fix and minor enhancement release. We applied previous nGrinder 3.2 version internally for 1 month and found several enhancement points. This made this version more concrete and workable in the large deployment.</div>

</blockquote><p></p>

<ul>
<li>If you want to see more generic product info, please visit http://nhnopensource.org/ngrinder &nbsp;<br /><br /></li>
</ul>
<p></p>

<h3>1. Release Info</h3><div><div><ul>
<li>Version : 3.2.1</li>
<li>Release Date : 2013.06.21</li>
</ul>
</div>

</div>

<h3>2. Changes</h3><h4>outline</h4><div><ul>
<li>Almost all of HTML pages are rewritten to follow the HTML standard. Now it supports IE10 perfectly.</li>
<li>Now you can see the scripting error in the agent log to easily find the scripting problem.</li>
<li>Groovy Engine becomes more concrete. Now each thread use its own JUnit Runner object so that each test is thread safe.</li>
<li>In addition, @RunRate annotation for each test method is available to control the run frequency.</li>
<li>It loads Groovy script with UTF-8 encoding as well so that a user can write the CJK characters.</li>
<li>The available agent memory is calculated more accurately. Instead of using free memory, now it uses actual free memory.</li>
<li>Each performance test page retrieval becomes speedy even when there are many files in SVN.</li>
<li>And minor UI enhancement as a</li>

</ul>
<h4>Bug</h4>
<ul>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-600">NGRINDER-600</a>] -         Fix IE10 compatibility issue
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-608">NGRINDER-608</a>] -         Make the memory setting more concrete for test process
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-610">NGRINDER-610</a>] -         Fix typo errors
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-612">NGRINDER-612</a>] -         Make controller's ip configurable
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-613">NGRINDER-613</a>] -         Make script error transferred from agent
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-614">NGRINDER-614</a>] -         Fix checkstyle issue
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-615">NGRINDER-615</a>] -         Make startime null when test is scheduled
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-616">NGRINDER-616</a>] -         Make monitoring data failure concrete
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-617">NGRINDER-617</a>] -         Fix wrong classpath filtering in the process execution
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-618">NGRINDER-618</a>] -         Dynamic system configuration update is not working after the first update.
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-622">NGRINDER-622</a>] -         Add host settings for groovy maven project  in quicktest
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-625">NGRINDER-625</a>] -         Make groovy tc thread use diffrent test object
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-629">NGRINDER-629</a>] -         Clean up the url after upload files
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-630">NGRINDER-630</a>] -         Use UTF-8 for groovy class loading
</li>
</ul>
    
<h4>        Improvement
</h4>
<ul>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-609">NGRINDER-609</a>] -         Speed up the perf test detail page view
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-611">NGRINDER-611</a>] -         Clean up ftl files
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-619">NGRINDER-619</a>] -         Make the easier method name filtering for record 
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-620">NGRINDER-620</a>] -         Increase the default max vuser to 2000
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-621">NGRINDER-621</a>] -         Elaborate script template
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-623">NGRINDER-623</a>] -         Shrink the script editor when expanding validation result panel
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-624">NGRINDER-624</a>] -         Enable runNumber in groovy script in JUnitContext
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-627">NGRINDER-627</a>] -         Make groovy runner efficient
</li>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-628">NGRINDER-628</a>] -         Enable the package folder structure for groovy maven project
</li>
</ul>
    
<h4>        New Feature
</h4>
<ul>
<li>[<a href="http://jira.cubrid.org/browse/NGRINDER-626">NGRINDER-626</a>] -         Add @RunRate annotation to control the run frequency for each @Test method<br /><br /></li>
</ul>
<ul>
</ul>
<div><h3>3. OS, DBMS supports</h3><div><ul>
<li>Linux, Windows, Mac OSX is supported.</li>
<li>Supports CUBRID, H2 as DB. The default DBMS is H2.</li>
</ul>
</div>

<h3>4. Requirements</h3><div><ul>
<li>Be required over Oracle JDK 1.6 version.</li>
<li>Tomcat 6.X later</li>
</ul>
</div>

<h3>5. Downloads</h3><div><ul>
<li><a href="http://sourceforge.net/projects/ngrinder/files/ngrinder-3.2.1/" target="_self">http://sourceforge.net/projects/ngrinder/files/ngrinder-3.2.1/</a></li>
</ul>
</div>

<h3>6. References</h3><div><ul>
<li>Release Note: <a href="/wiki_ngrinder/entry/ngrinder-3-2-1-release-note" target="_self">http://www.cubrid.org/wiki_ngrinder/entry/ngrinder-3-2-1-release-note</a></li>
<li>Manuals:</li>
<ul>
<li>Installation Guide : <a href="/wiki_ngrinder/entry/installation-guide" target="_self">http://www.cubrid.org/wiki_ngrinder/entry/installation-guide</a></li>
<li>Administration Guide : <a href="/wiki_ngrinder/entry/administration-guide" target="_self">http://www.cubrid.org/wiki_ngrinder/entry/administration-guide</a></li>
<li>User's Guide : <a href="/wiki_ngrinder/entry/user-guide" target="_self">http://www.cubrid.org/wiki_ngrinder/entry/user-guide</a></li>
</ul>
<li>Project: <a href="/wiki_ngrinder/entry/ngrinder-devzone" target="_self">http://www.cubrid.org/wiki_ngrinder/entry/ngrinder-devzone</a></li>
<li>Issue tracker: <a href="http://jira.cubrid.org/browse/NGRINDER" target="_self">http://jira.cubrid.org/browse/NGRINDER</a>, <a href="https://github.com/nhnopensource/ngrinder/issues" target="_self">https://github.com/nhnopensource/ngrinder/issues</a></li>
<li>Source repository: <a href="https://github.com/nhnopensource/ngrinder" target="_self">https://github.com/nhnopensource/ngrinder</a></li>
<li>Tag : <a href="https://github.com/nhnopensource/ngrinder/archive/nGrinder3.2.1_20130621.zip" target="_self">https://github.com/nhnopensource/ngrinder/archive/nGrinder3.2.1_20130621.zip</a></li>
<li>Mailing List : <a href="http://ngrinder.642.n7.nabble.com/" target="_self">http://ngrinder.642.n7.nabble.com/</a></li>
</ul>
</div>

</div>

<div><br /></div>

<ul>
</ul>
</div>]]></description>
                        <pubDate>Tue, 18 Jun 2013 07:00:01 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>release-note</category>
                                </item>
        										        <item>
            <title>nGrinder Release Notes</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=ngrinder-release-notes</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=ngrinder-release-notes</guid>
                                    <description><![CDATA[<ul>
<li>[nGrinder 3.2.1 Release Note] -&nbsp;Jun. 18. 2013</li>
<li>[nGrinder 3.2 Release Note] -&nbsp;May. 28. 2013</li>
<li>[nGrinder 3.1.3 Release Note] -&nbsp;March. 29. 2013</li>
<li>[nGrinder 3.1.2 Release Note] -&nbsp;February. 22. 2013</li>
<li>[nGrinder 3.1.1 Release Note] - January 31, 2013</li>
<li>[nGrinder 3.1 Release Note] - January 5, 2013</li>
<li>[nGrinder 3.0.4 Release Note] - Dec 04, 2012</li>
<li>[nGrinder 3.0.3 Release Note] - November 23, 2012</li>
<li>[nGrinder 3.0.2 Release Note] - November 16, 2012</li>
<li>[nGrinder 3.0.1 Release Note] - October 31, 2012</li>
<li>[nGrinder 3.0 Release Note] - October 29, 2012</li>
</ul>
<p><br /></p>]]></description>
                        <pubDate>Sun, 28 Oct 2012 18:41:50 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>release-note</category>
                                </item>
        										        <item>
            <title>nGrinder DevZone</title>
            <dc:creator>CUBRID</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=ngrinder-devzone</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=ngrinder-devzone</guid>
                                    <description><![CDATA[<p><img alt="ngrinder_logo.png" src="/files/attach/images/379199/651/379/ngrinder_logo.png" width="730" height="158" editor_component="image_link"/>     <br /></p>  <p><font color="#000000"><strong>nGrinder</strong></font> (pronounced as en-g-ra-in-der) is a stress tests platform that enables you to create test scripts, execute tests, monitor target servers and generate results simultaneously. The open-source nGrinder offers easy ways to conduct stress tests by eliminating inconveniences and providing integrated environments. It uses the renowned performance test tool, <a href="http://grinder.sourceforge.net" target="_blank"><strong>The Grinder</strong></a>, as its internal engine.</p>  <p>This is the tool developed by the service provider who really runs frequent load testing not by tool vendor. A breakthrough feature of nGrinder 3.X is support for concurrent tests which means that multiple users can run different tests at the same time! And it's cloud friendly and has attractive interface !</p>

<p>nGrinder is being developed by NHN Korea and NHN China together.</p>  <p>&nbsp;</p>  <table border="0" cellspacing="0" cellpadding="4" width="702"><tbody>     <tr>       <td valign="top" width="336" class="">         <ul>           <li><a href="http://www.nhnopensource.org/ngrinder" target="_blank">Official Home Page</a> </li>            <li>[Architecture] </li>            <li>[Screen Shot] </li>            <li>[Guide]</li>            <ul>             <li>[Installation Guide] </li>              <li>[Admin Guide] </li>              <li>[User Guide] </li>
<li>[Scripting Guide]</li>
<li><a href="/wiki_ngrinder/entry/recorder" target="_self">Recorder Guide</a></li>           </ul>            <li>[Presentations]</li>
<li>[Professional Service]</li>
</ul>
</td><td valign="top" width="364" class=""><ul>
<li>[nGrinder Release Notes|Release Notes]</li>
<li><a href="http://sourceforge.net/projects/ngrinder/files" target="_blank">Downloads</a> </li>            <li>[Road Map] </li>            <li>[Dev Document] </li>            <li><a href="http://ngrinder-dev.642.n7.nabble.com/" target="_self">Mailing List</a></li>            <li><a href="http://jira.cubrid.org/browse/NGRINDER" target="_blank">Issue Tracker</a></li>            <li>[Frequently Asked Question] </li>
<li>[How to Use Windows LiveWriter in nGrinder wiki|Wiki Guide]</li>
<li>[Who uses nGrinder]</li>
<li>[Help nGrinder]</li>
</ul>
</td></tr></tbody></table>]]></description>
                        <pubDate>Wed, 20 Jun 2012 18:23:28 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>architecture</category>
                                </item>
        										        <item>
            <title>Recorder Recording Guide</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=recorder-recording-guide</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=recorder-recording-guide</guid>
                                    <description><![CDATA[<h2>Filtering</h2>
<p>If you ran the example following [Recorder Quick Start], you may have been&nbsp;surprised&nbsp;by&nbsp;overwhelmingly&nbsp;long generated scripts. It is because there are actually many HTTP/HTTPS messages even in a single web browsing which you&nbsp;didn't&nbsp;notice before. Do we have to include all these in the script? Sometimes it is useless to include all these in the performance test. <br />High load services usually use CDN(Content Delivery Network)s for static resources like images or javascripts. CDNs are located in multiple sites and the most close site is automatically selected depending from where the calls are made. In addition, CDNs usually have the very efficient content delivery mechanism enough to handle high loads. Moreover, they charge the fee depending on the how many contents are delivered.&nbsp; So it’s really necessary to simulate the call to here? You can not even control the content delivery logics if there are some performance issues. </p>
<p>Usually developers might want to run the performance test on the web servers under their controls. Therefore, nGrinder Recorder includes several filtering features.</p>
<h3>Host name filter</h3>
<p><a href="/files/attach/images/379199/624/636/image_4.png"><img width="732" height="204" title="image" style="BORDER-LEFT-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 0px; PADDING-TOP: 0px; PADDING-LEFT: 0px; DISPLAY: inline; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px" alt="image" src="/files/attach/images/379199/624/636/image_thumb_1.png" border="0" editor_component="image_link" /></a></p>
<p>nGrinder Recorder recognizes the host names to which the proxy is connecting and how many calls are made. On the right panel there is a table which lists up the connected hosts and connection counts. When you don’t start Recording yet, this panel shows connected hosts but call count.</p>
<p><a href="/files/attach/images/379199/624/636/image_6.png"><img width="730" height="221" title="image" style="BORDER-LEFT-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 0px; PADDING-TOP: 0px; PADDING-LEFT: 0px; DISPLAY: inline; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px" alt="image" src="/files/attach/images/379199/624/636/image_thumb_2.png" border="0" editor_component="image_link" /></a></p>
<p>If you start Recording, it shows the recorded call count in “R” column.&nbsp; You can examine the host names and uncheck all hosts which you don’t interested in.</p>
<p><a href="/files/attach/images/379199/624/636/image_12.png"><img width="731" height="348" title="image" style="BORDER-LEFT-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 0px; PADDING-TOP: 0px; PADDING-LEFT: 0px; DISPLAY: inline; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px" alt="image" src="/files/attach/images/379199/624/636/image_thumb_5.png" border="0" editor_component="image_link" /></a></p>
<p>The&nbsp;easiest&nbsp;way to achieve this is to click “Unselect All” button downside and check the interested host one by one.</p>
<h3>Resource type filter</h3>
<p>There is one more method to filter out unnecessary static resources. At the downside of the right panel, there is a filter based on file types. “Recorded Type” panel lists the general static resource content type.</p>
<p><a href="/files/attach/images/379199/624/636/image_14.png"><img width="199" height="131" title="image" style="BORDER-LEFT-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 0px; PADDING-TOP: 0px; PADDING-LEFT: 0px; DISPLAY: inline; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px" alt="image" src="/files/attach/images/379199/624/636/image_thumb_6.png" border="0" editor_component="image_link" /></a>&nbsp;<a href="/files/attach/images/379199/624/636/image_18.png"><img width="198" height="129" title="image" style="BORDER-LEFT-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 0px; PADDING-TOP: 0px; PADDING-LEFT: 0px; MARGIN: 0px; DISPLAY: inline; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px" alt="image" src="/files/attach/images/379199/624/636/image_thumb_8.png" border="0" editor_component="image_link" /></a></p>
<p>If you uncheck Record Type like above, nGrinder Recorder won't record the HTTP messages which URL paths end with well known static resource type names (like .png, .css, .js) or response content type has the well known static resource content type string (like text/javascript). Even if you uncheck some of these during recording session, the previously recorded messages are not removed in the memory. However eventually it will be not included in the final script. If you check them again and generate a script, the script will contain the previously recorded messages. </p>
<h3>Reset Recording</h3>
<p>You can&nbsp;completely&nbsp;remove all recording by selecting “Clear all recording” sub-menu which is popped up in “Reset” button.</p>
<p><a href="/files/attach/images/379199/624/636/image_38.png"><img width="294" height="161" title="image" style="BORDER-LEFT-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 0px; PADDING-TOP: 0px; PADDING-LEFT: 0px; MARGIN: 0px; DISPLAY: inline; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px" alt="image" src="/files/attach/images/379199/624/636/image_thumb_16.png" border="0" editor_component="image_link" /></a></p>
<p>There are several sub menus in Reset button. Each has the different action like below.</p>
<table width="752" bordercolor="#000000" style="BORDER-COLLAPSE: collapse" border="1" cellspacing="0" cellpadding="4">
<tbody>
<tr style="COLOR: white; BACKGROUND-COLOR: black">
<td width="217" valign="top">Submenu name</td>
<td width="533" valign="top">Action</td></tr>
<tr>
<td width="217" valign="top">Clear all recording</td>
<td width="533" valign="top">Clear all recorded messages. However it doesn't change the filter.</td></tr>
<tr>
<td width="217" valign="top">Clear all filters</td>
<td width="533" valign="top">Clear all filters. However it doesn't change the recorded messages.</td></tr>
<tr>
<td width="217" valign="top">Clear connection count</td>
<td width="533" valign="top">Make the all connection count 0 in the filter panel.</td></tr>
<tr>
<td width="217" valign="top">Reset browser cache</td>
<td width="533" valign="top">Delete all browser cache so that the browser can actually make a call to the given resources.</td></tr>
<tr>
<td width="217" valign="top">Reset cookies</td>
<td width="533" valign="top">Delete all saved cookies from the browser so that the browser is not&nbsp;interfered&nbsp;by the&nbsp;previously&nbsp;issued cookies.</td></tr></tbody></table>
<h2>Script Generation</h2>
<p>When a user clicks “Stop&nbsp;Recording” button, the recorded HTTP/HTTPS messages are transformed to The Grinder script. The script generated by nGrinder Recorder is little bit different from TCPProxy provides. We made the script template little bit more compact than what TCPProxy generates.</p>
<p><a href="/files/attach/images/379199/624/636/image_22.png"><img width="753" height="254" title="image" style="BORDER-LEFT-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 0px; PADDING-TOP: 0px; PADDING-LEFT: 0px; DISPLAY: inline; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px" alt="image" src="/files/attach/images/379199/624/636/image_thumb_10.png" border="0" editor_component="image_link" /></a></p>
<p>Be aware that “Stop Recording”&nbsp;doesn't&nbsp;mean “Reset Recording”. If you click Start Recording again, it continues to record the messages appending to existing recording. It’s because there are many reasons to pause the recording (A user might fall down by too much overwork) </p>
<h3>Add sleep time</h3>
<p><a href="/files/attach/images/379199/624/636/image_24.png"><img width="204" height="61" title="image" align="left" style="BORDER-LEFT-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 0px; FLOAT: left; PADDING-TOP: 0px; PADDING-LEFT: 0px; MARGIN: 0px 10px 0px 0px; DISPLAY: inline; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px" alt="image" src="/files/attach/images/379199/624/636/image_thumb_11.png" border="0" editor_component="image_link" /></a></p>
<p>There are one option for script generation. If you check “Add sleep time” in Script Generation Options option groups, the actual&nbsp;waiting&nbsp;time during&nbsp;recording&nbsp;are included in the unit of milliseconds at the final script like following.</p>
<p>&nbsp;</p>
<p><a href="/files/attach/images/379199/624/636/image_26.png"><img width="747" height="391" title="image" style="BORDER-LEFT-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 0px; PADDING-TOP: 0px; PADDING-LEFT: 0px; DISPLAY: inline; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px" alt="image" src="/files/attach/images/379199/624/636/image_thumb_12.png" border="0" editor_component="image_link" /></a></p>
<p>If you went to the toilet after starting&nbsp;recording, Recorded sleep time might be very long. Please check the how long the script sleep between calls before running a script in nGrinder Controller. </p>
<p><span style="FONT-SIZE: 20px; COLOR: rgb(0,0,0)">Mobile Web Page Recording</span></p>
<p>nGrinder Recorder supports the user agent string manipulation which means you can navigate the mobile site which detects the browser type and send the appropriate contents. You can select the mobile user agent. Then even if you navigate the <a href="http://www.amazon.com">www.amazon.com</a>, Then the mobile page is sent from the server like below.</p>
<p>&nbsp;<a href="/files/attach/images/379199/624/636/image_2.png"><img width="255" height="261" title="image" style="BORDER-LEFT-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 0px; PADDING-TOP: 0px; PADDING-LEFT: 0px; DISPLAY: inline; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px" alt="image" src="/files/attach/images/379199/624/636/image_thumb.png" border="0" editor_component="image_link" /></a>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img width="408" height="259" alt="image_thumb.png" src="/files/attach/images/379199/624/636/image_thumb_3.png" editor_component="image_link" /></p>
<p>If you don’t want to use this fake browser technique but the real mobile browser from your devices, you can record the messages by configuring your mobile devices proxy settings.</p>
<table width="752" bordercolor="#000000" style="BORDER-COLLAPSE: collapse" border="1" cellspacing="0" cellpadding="4">
<colgroup>
<col width="300" />
<col width="300" /></colgroup>
<tbody>
<tr style="COLOR: white; BACKGROUND-COLOR: black">
<th>IOS</th>
<th>Android</th></tr>
<tr>
<td>
<ul>
<li>Go to the Settings Application </li>
<li>Go to General &lt; Network &lt; Wi-Fi </li>
<li>Select Wi-Fi connection you want to use with HTTP Proxy and connect. </li>
<li>Edit Wi-Fi connection, scroll down and find "Proxy HTTP" and press on "Manual"", here we need to fill all proxy connection settings. </li>
<li>Set server as 10.66.9.95 </li>
<li>Set port as 10288 </li>
<li>Disable authentication </li>
</ul>
</td>
<td>
<ul>
<li>Open the Applications tab and tap Settings. </li>
<li>Tap Wireless &amp; networks. </li>
<li>Make sure the wireless network is enabled, and connected to the network for which you want to set the proxy server. </li>
<li>Tap Wi-Fi settings. </li>
<li>In the list of available networks, tap and hold the network to which you are connected, until a menu shows. </li>
<li>Tap Modify Network. </li>
<li>Tap Proxy Settings, and then Manual. </li>
<li>Set server as 10.66.9.95 </li>
<li>Set port as 10288 </li>
<li>Tab Save </li>
</ul>
</td></tr></tbody></table>
<p>If you set up above, you can record the messages from your devices, just as you did in the embedded browser.</p>
<h2>HTTPS Handling</h2>
<p>nGrinder Recorder supports HTTPS as well but very limited way. As described in <a href="/wiki_ngrinder/entry/recorder-limitation">Recorder Limitation</a>, the private self-signed ceritificate is used to intercept the HTTPS messages. So you may see following alerts whenever you access HTTPS sites. </p>
<p><img width="746" height="423" alt="image_thumb_1.png" src="/files/attach/images/379199/624/636/image_thumb_1_1.png" editor_component="image_link" /> <br /></p>
<p>To avoid this alert, you have to import the self signed certificate in the trusted certificates. Check out [Recorder-How to import self-signed certificates]</p>
<p>nGrinder Recorder provides another way to work around this issue. Actually this method is introduced by TCPProxy and nGrinder uses it with little modification. If you are going to test your own HTTPS server, you might have already the valid certificate. You can provide this instead of embedded certificate for the proxy to use. You can refer how to provide your own certificate in [Recorder Installation].</p>]]></description>
                        <pubDate>Tue, 16 Apr 2013 00:00:43 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>recorder</category>
                                </item>
        										        <item>
            <title>Recorder Limitation</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=recorder-limitation</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=recorder-limitation</guid>
                                    <description><![CDATA[<h2>Features per OS</h2>
<p>Due to the embedded browser component's limitation, nGrinder Recorder has a different feature set depending on OS.</p>
<p></p>
<table width="666" bordercolor="#000000" style="FONT-SIZE: 15px; FONT-FAMILY: Calibri, 'Times New Roman', Arial, Tahoma; COLOR: rgb(19,18,18); LINE-HEIGHT: 20px; WIDTH: 694px; BACKGROUND-COLOR: rgb(244,247,250)" border="1" cellspacing="0" cellpadding="4">
<tbody>
<tr style="COLOR: white; BACKGROUND-COLOR: black">
<td width="158" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">Features</td>
<td width="141" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">Windows</td>
<td width="165" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">MAC</td>
<td width="200" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">Linux</td></tr>
<tr>
<td width="158" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">Proxy</td>
<td width="141" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">O</td>
<td width="165" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">O</td>
<td width="200" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">O</td></tr>
<tr>
<td width="158" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">Embedded Browser</td>
<td width="141" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">O</td>
<td width="165" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">△</td>
<td width="200" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">△ (Crashed&nbsp;Frequently)</td></tr>
<tr>
<td width="158" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">HTTPS support</td>
<td width="141" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">O</td>
<td width="165" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">X</td>
<td width="200" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">O<span class="Apple-tab-span" style="WHITE-SPACE: pre">	</span></td></tr>
<tr>
<td width="158" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">Flash support</td>
<td width="141" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">O</td>
<td width="165" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">X</td>
<td width="200" valign="top" style="PADDING-BOTTOM: 3px; PADDING-TOP: 3px; PADDING-LEFT: 3px; PADDING-RIGHT: 3px">X</td></tr></tbody></table>
<p></p>
<p>We're highly recommending you to use Windows when recording the user interaction. If you like to use MAC or Linux, use the separate browser with proxy settings. Refer [Recorder-Recording Guide For Non Window User].</p>
<h2>Missing Recorded Element</h2>
<p>nGrinder Recorder does not guarantee to generate the perfectly executable scripts. It's a just helper application with which a user can easily start to write scripts. Even though nGrinder Recorder contains embedded browser component, nGrinder Recorder doesn't use this component very much much information. As you can find in&nbsp;<a href="/wiki_ngrinder/entry/recorder-architecture" target="_blank">nGrinder Recorder Architecture</a>, the actual recording is performed in HTTP/HTTPS messages level not the browser events level. This causes some information loss. For example, The web pages in browsers can create cookies in javascript. nGrinder Recorder can understand cookies generated only by server but browser. Therefore this cookie processing code won't show up in the finally generated script. The users should add the client side cookie generation code by themselves.</p>

<pre class="brush: py;"># User need to write his own cookie handling code to complement the missing part.
threadContext = HTTPPluginControl.getThreadHTTPClientContext()
expiryDate = Date()
expiryDate.year += 10
cookie = Cookie("key", "value","localhost", "/", expiryDate, 0)
CookieModule.addCookie(cookie, threadContext)</pre>
<p>Only information which nGrinder Recorder&nbsp;currently&nbsp;takes from the embedded browser is the click events to separate messages into the multiple pages. Following is the code generated by nGrinder Recorder.</p>

<pre class="brush: py;">class TestRunner:
    """A TestRunner instance is created for each worker thread."""
    def __init__(self) :
        grinder.statistics.delayReports=True
        pass
    
    def __call__(self) :
        try : 
            # Following two pages are created because a user click the mouse.
            self.page1()
            self.page2()
            grinder.statistics.forLastTest.success = 1
        except Exception, e:
            err(e.message)
            grinder.statistics.forLastTest.success = 0

    def page1(self) :
        ##########################################################################################
        # http://img.naver.net/static/newsstand/up/2012/1119/nsd102245777.gif
        ##########################################################################################
        grinder.sleep(54)
        result = request_img_naver_net.GET(
                "/static/newsstand/up/2012/1119/nsd102245777.gif",
                None,    
                headers0
            ) 
        self.checkResponse(result, 200,  "http://img.naver.net/static/newsstand/up/2012/1119/nsd102245777.gif")

        ##########################################################################################
        # http://img.naver.net/thumb.opencast/opencast01/n/a/naver_story/20130411/17442431363707.jpg
        ##########################################################################################
        self.token_type = 'f10060'  
        result = request_img_naver_net.GET(
                "/thumb.opencast/opencast01/n/a/naver_story/20130411/17442431363707.jpg?type=%s"
                    % (self.token_type),
                None,    
                headers0
            ) 
        self.checkResponse(result, 200,  "http://img.naver.net/thumb.opencast/opencast01/n/a/naver_story/20130411/17442431363707.jpg")</pre>
<h2>HTTPS messages</h2>
<p>When users try to record HTTPS messages, The browsers may show the following security alert. </p>
<p align="center"><a href="/files/attach/images/379199/226/634/image_2.png"><img width="386" height="306" title="image" style="BORDER-LEFT-WIDTH: 0px; BORDER-RIGHT-WIDTH: 0px; BACKGROUND-IMAGE: none; BORDER-BOTTOM-WIDTH: 0px; PADDING-TOP: 0px; PADDING-LEFT: 0px; DISPLAY: inline; PADDING-RIGHT: 0px; BORDER-TOP-WIDTH: 0px" alt="image" src="/files/attach/images/379199/226/634/image_thumb.png" border="0"  editor_component="image_link" /></a></p>
<p>This alert is popped up because the proxy uses a self-signed private certificate between the browser and proxy HTTPS communication to capture HTTPS messages. The certificate issued by the web server is used only in the&nbsp;communication&nbsp;between the proxy and target web server. The proxy decodes the messages from the target server&nbsp; with the valid&nbsp;certificate and records the messages. Then the proxy encodes the message with the The Grinder embedding self-signed certificate and sends it back to the browsers. From the perspective of browsers,&nbsp;browsers&nbsp;don’t aware of this proxy behavior. They just show the alert messages because they think the messages are encoded by the wrong&nbsp;certificate. Currently only IE engine among our embedded browser engines allows users to accepts the invalid certificate while browsing HTTPS sites. Which means only windows supports both HTTP and HTTPS recording. In OS X, users should use the separate browsers not embedded browser if they want to record HTTPS as well. The general web browser has a way to accept the self-signed certificate. See [Recorder-How to import self signed certificates].</p>
<p>The messages used in the mobile devices can also be captured by setting the mobile device’s network configuration. However the most of all mobile browsers may reject the messages encoded with a private certificate. There might be no way to show these HTTPS pages in the mobile devices. If someone knows how to configure it, please let us know.</p>
<p>Only way to browse these is to let the proxy use the valid certificate when it returns back the HTTPS messages to the browsers. See Configuration section in [Recorder-Installation].</p>]]></description>
                        <pubDate>Fri, 12 Apr 2013 07:42:51 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>recorder</category>
                                </item>
        										        <item>
            <title>How to add custom monitor data</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=how-to-add-custom-monitor-data</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=how-to-add-custom-monitor-data</guid>
                                    <description><![CDATA[<h3>Custom monitoring</h3><p>From nGrinder 3.1.3, nGrinder support the custom monitoring for targets. It can be used if you want to monitor target server statuses which are not provided as default by nGrinder monitor. All you need to do is to use any tools you like to collect the monitor data with some internal time. (It might be best if you set it as same as the sampling interval of nGrinder test.) and the data should be saved in:</p>  <p><ul>
<li>${ngrinder_agent_home}/monitor/custom.data</li>
</ul>
</p>  <p>The content of this file can have several monitoring values separated with “,” in the single line &nbsp;like below:</p>  <p>315630613,1123285602,1106612131</p>  <p>Then you need to make sure the file is being updated during the test running. If you have a shell script named "update.sh" which updates custom.data file, you can run it regularly by <br /><ul>
<li>watch -n 1 update.sh</li>
</ul>nGrinder monitor reads custom.data file periodically if exists and send data to nGrinder controller. <br />After the test finished, you can see the chart for these data in the target monitoring page of the detailed test report:</p>  <p><a href="/files/attach/images/379199/619/625/image_4.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="/files/attach/images/379199/619/625/image_thumb_1.png" width="674" height="576" editor_component="image_link" /></a> </p>  <p>Find there are charts named “CUSTOM MONITOR DATA 1”, “CUSTOM MONITOR DATA 2” .., till “CUSTOM MONITOR DATA 5”. nGrinder monitor can collect at most 5 custom data.&nbsp;</p>

<h3>How to collect JVM status</h3>  <p>In the following guide, I will use java to get the java VM running information with JMX. If the target server is a java application like tomcat, we can use the way in this guide to get the VM running information of tomcat, and display the data in chart in the final report. As I said above, I will use JMX to get the VM data. But in the normal we will not enable the JMX server of tomcat. So we will use attach API to attach to the target process, and&nbsp; enable the “management-agent”, and then we can connect with JMX to the target process.</p>  <p>You can find the VMMonitor.java from <a href="https://gist.github.com/Mavlarn/5289680" target="_blank">gist</a>. Be aware about the code that, in java VM, for different java version and different GC setting, the GC names will be different. So in this code, I get the GC names of current Java VM, and using these names to get target process GC information with JMX. So the Java environment you use to run this code should be same as that you run the target tomcat. And the VM option like “-server” or GC setting should also be same. Otherwise, you can not get the GC names of target tomcat process.</p>  <p>And below, we will use this code to get the GC information of target process and save into custom.data file. The new code is as below:</p>  <pre class="brush: java; auto-links: false;">import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine;

/**
 * Class description.
 * 
 * @author Mavlarn
 */
public class GCMonitor {

    public static Set&lt;String&gt; youngGCNames = new HashSet&lt;String&gt;();
    public static Set&lt;String&gt; oldGCNames = new HashSet&lt;String&gt;();

    static {
        // Oracle (Sun) HotSpot
        youngGCNames.add("Copy"); // -XX:+UseSerialGC
        youngGCNames.add("ParNew"); // -XX:+UseParNewGC
        youngGCNames.add("PS Scavenge"); // -XX:+UseParallelGC

        // Oracle (BEA) JRockit
        youngGCNames.add("Garbage collection optimized for short pausetimes Young Collector"); // -XgcPrio:pausetime
        youngGCNames.add("Garbage collection optimized for throughput Young Collector"); // -XgcPrio:throughput
        youngGCNames.add("Garbage collection optimized for deterministic pausetimes Young Collector"); // -XgcPrio:deterministic

        // Oracle (Sun) HotSpot
        oldGCNames.add("MarkSweepCompact"); // -XX:+UseSerialGC
        oldGCNames.add("PS MarkSweep"); // -XX:+UseParallelGC and
                                        // (-XX:+UseParallelOldGC or -XX:+UseParallelOldGCCompacting)
        oldGCNames.add("ConcurrentMarkSweep"); // -XX:+UseConcMarkSweepGC

        // Oracle (BEA) JRockit
        oldGCNames.add("Garbage collection optimized for short pausetimes Old Collector"); // -XgcPrio:pausetime
        oldGCNames.add("Garbage collection optimized for throughput Old Collector"); // -XgcPrio:throughput
        oldGCNames.add("Garbage collection optimized for deterministic pausetimes Old Collector"); // -XgcPrio:deterministic
    }

    static final String CONNECTOR_ADDRESS = "com.sun.management.jmxremote.localConnectorAddress";

    public static void main(String[] args) throws InterruptedException {
        if (args == null || args.length == 0) {
            System.err.println("Please specify the target PID to attach.");
            return;
        }

        // attach to the target application
        VirtualMachine vm;
        try {
            vm = VirtualMachine.attach(args[0]]);
        } catch (AttachNotSupportedException e) {
            System.err.println("Target application doesn't support attach API.");
            e.printStackTrace();
            return;
        } catch (IOException e) {
            System.err.println("Error during attaching to target application.");
            e.printStackTrace();
            return;
        }

        try {
            // get the connector address
            String connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
            MBeanServerConnection serverConn;
            // no connector address, so we start the JMX agent
            if (connectorAddress == null) {
                String agent = vm.getSystemProperties().getProperty("java.home") + File.separator + "lib"
                        + File.separator + "management-agent.jar";
                vm.loadAgent(agent);
                // agent is started, get the connector address
                connectorAddress = vm.getAgentProperties().getProperty(CONNECTOR_ADDRESS);
            }

            // establish connection to connector server
            JMXServiceURL url = new JMXServiceURL(connectorAddress);
            JMXConnector connector = JMXConnectorFactory.connect(url);
            serverConn = connector.getMBeanServerConnection();
            ObjectName objName = new ObjectName(ManagementFactory.RUNTIME_MXBEAN_NAME);

            // Get standard attribute "VmVendor"
            String vendor = (String) serverConn.getAttribute(objName, "VmVendor");
            System.out.println("vendor:" + vendor);

            String[] gcNames = getGCNames();
            while(true) {
                long minorGCCount = 0;
                long minorGCTime = 0;
                long fullGCCount = 0;
                long fullGCTime = 0;
                
                for (String currName : gcNames) {
                    objName = new ObjectName("java.lang:type=GarbageCollector,name=" + currName);
                    Long collectionCount = (Long) serverConn.getAttribute(objName, "CollectionCount");
                    Long collectionTime = (Long) serverConn.getAttribute(objName, "CollectionTime");
                    if (youngGCNames.contains(currName)) {
                        minorGCCount = collectionCount;
                        minorGCTime = collectionTime;
                    } else if (oldGCNames.contains(currName)) {
                        fullGCCount = collectionCount;
                        fullGCTime = collectionTime;
                    }
                    StringBuilder sb = new StringBuilder("[");
                    sb.append(getGCType(currName)).append("	: ");
                    sb.append("Count=" + collectionCount);
                    sb.append(" 	GCTime=" + collectionTime);
                    sb.append("]");
                    System.out.println(sb.toString());
                }
                StringBuilder valueStr = new StringBuilder();
                //custom data format is:
                //minorGCCount,minorGCTime,fullGCCount,fullGCTime
                valueStr.append(minorGCCount);
                valueStr.append(",");
                valueStr.append(minorGCTime);
                valueStr.append(",");
                valueStr.append(fullGCCount);
                valueStr.append(",");
                valueStr.append(fullGCTime);
                writeToFile(valueStr.toString());
                Thread.sleep(1000); //sleep one second.
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String getGCType(String name) {
        if (youngGCNames.contains(name)) {
            return "Minor GC";
        } else if (oldGCNames.contains(name)) {
            return "Full GC";
        } else {
            return name;
        }
    }

    public static String[] getGCNames() {
        List&lt;GarbageCollectorMXBean&gt; gcmbeans = ManagementFactory.getGarbageCollectorMXBeans();
        String[] rtnName = new String[gcmbeans.size()];
        int index = 0;
        for (GarbageCollectorMXBean gc : gcmbeans) {
            rtnName[index] = gc.getName();
            index++;
        }
        return rtnName;
    }
    
    public static void writeToFile(String gcData) {
        String currDir = System.getProperty("user.dir");
        BufferedWriter writer = null;
        
        try {
            File customFile = new File(currDir + File.separator + "custom.data");
            if (!customFile.exists()) {
                customFile.createNewFile();
            }
            writer = new BufferedWriter(new FileWriter(customFile));
            writer.write(gcData);
            writer.flush();
        } catch (IOException e) {
            System.err.println("Error to read custom monitor data:" + e.getMessage());
        } finally {
            if (writer != null) {
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}</pre>

<p>Some comments about the code are:</p>

<p>a) We need to pass the target process ID as arguments to run.</p>

<p>b) This code should be run under same java environment and VM option with the target process. Otherwise, the attaching will properly fail. And if the target tomcat process is running with “-server” option, also be aware to set “-server” option to run this java code.</p>

<p>Because under different java version and setting, the GC names will be different, I founded some names and their types(minor or full GCl). They are not complete and maybe not very correct. If you use IBM JVM, you should modify the code by yourself.</p>

<p>c) The custom values format is “minorGCCount,minorGCTime,fullGCCount,fullGCTime”.</p>

<p>d) This java code should be run in “${ngrinder_agent}/monitor/” directory. Because in the code, it will create custom.data file in current directory.</p>

<p>e) To compile the code, it needs “tools.jar” of JDK.&nbsp; You need to compile it like this:</p>

<pre class="brush: bash; auto-links: false;">javac -cp /home/ngrinder/jdk1.6.0_38/lib/tools.jar GCMonitor.java

#get target tomcat process ID, it is 24003
java -cp /home/ngrinder/jdk1.6.0_38/lib/tools.jar: GCMonitor  24003</pre>

<p>&nbsp;</p>

<p>Then you should see the output in console as below:</p>

<pre class="brush: bash; auto-links: false;">current dir:/home/ngrinder/.ngrinder_agent/monitor
[Minor GC       : Count=3564    GCTime=27850]
[Full GC        : Count=166     GCTime=65525]
[Minor GC       : Count=3564    GCTime=27850]
[Full GC        : Count=166     GCTime=65525]</pre>

<p>And in custom.data file, the content is:</p>

<pre class="brush: bash; auto-links: false;">3564,27850,166,65525</pre>

<p></p>

<p></p>

<p>&nbsp;</p>

<p>Then, create a new test on nGrinder and set the target host properly. You can see the chart in test report:</p>

<p><a href="/files/attach/images/379199/619/625/image_6.png"><img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="/files/attach/images/379199/619/625/image_thumb_2.png" width="558" height="568" editor_component="image_link" /></a> </p>

<p>(Because the GC count is not changed very much, so we can not see much difference from the chart.)</p>

<p>&nbsp;In this way, you can add any kind of custom monitor data and check it from test report.</p>]]></description>
                        <pubDate>Mon, 01 Apr 2013 22:31:18 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>monitor</category>
                                </item>
        										        <item>
            <title>Scripting Guide</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=scripting-guide</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=scripting-guide</guid>
                                    <description><![CDATA[<blockquote class="q4"><p>nGrinder 3.2 and later supports not only Jython but also Groovy as scripting language. If you want to know about Groovy scripting, please refer [Groovy Script]</p>

</blockquote><blockquote class="q4"><ul>
<li>You can see various <a href="http://grinder.sourceforge.net/g3/script-gallery.html" target="_self">The Grinder script samples</a>.</li>
<li>You can check <a href="http://grinder.sourceforge.net/g3/script-javadoc/index.html" target="_self">The Grinder APIs</a>.</li>
</ul>
</blockquote><div><br /></div>More practical ways for the advanced nGrinder user are...&nbsp;<br /><ul>
<li>Do you want to know what script types nGrinder supports?</li>
<ul>
<li>[Jython Script Structure]</li>
<li>[Groovy Script Structure]</li>
</ul>
<li>Do you want to ramp-up more precisely?&nbsp;</li>
<ul>
<li>[How to ramp up by threads]</li>
</ul>
<li>Do you need a custom dns entry? Need to change the /etc/hosts file in the agents? You can configure target host fields for this. You don't need root permission in agent machines.</li>
<ul>
<li>[How to change DNS]</li>
</ul>
<li>Do you need to use your own jar or py? Read followings.&nbsp;</li>
<ul>
<li>[How to use library]</li>
</ul>
<li>Do you need to load your own xml or txt file? Read followings.&nbsp;</li>
<ul>
<li>[How to use resources]</li>
</ul>
<li>Do you need to simulate the multiple user scenario in the different run weight?</li>
<ul>
<li>[How to run the multiple tests with different weight]</li>
</ul>
<li>Do you need to adjust the logger level to only see the errors? Read followings.</li>
<ul>
<li>[How to adjust logger level]</li>
</ul>
<li>Do you need to test DB performance? Doesn't nGrinder seems to support this? No.. You can still test it with nGrinder</li>
<ul>
<li>[Using nGrinder to perform db load test]</li>
</ul>
<li>Do you need to parse data retrieved from server?&nbsp;<br /></li>
<ul>
<li>[How to parse JSON]</li>
<li>[How to parse XML]</li>
</ul>
</ul>
<div><ul>
<li>Do you need to define your own statistic?&nbsp;<br /></li>
<ul>
<li>[User defined statistic in ngrinder]</li>
</ul>
<li>Do you cope with the big response like movie or file download?</li>
<ul>
<li>[How to handle the big response]</li>
</ul>
<li>Do you need you test a socket.io app?</li>
</ul>
<div><ul>
<ul>
<li style="margin-top: 7px; margin-right: 0px; margin-bottom: 7px; margin-left: 0px; "><a href="/wiki_ngrinder/entry/using-ngrinder-to-perform-load-test-for-a-socket-io-app" target="_self">How to test a socket.io app</a></li>
<li style="margin-top: 7px; margin-right: 0px; margin-bottom: 7px; margin-left: 0px; "><a href="/wiki_ngrinder/entry/using-ngrinder-to-perform-load-test-for-socket-io-app-python-version" target="_self">How to test a socket.io app&nbsp;- Python version</a></li>
</ul>
</ul>
</div>

<div><br /></div>

<br /><ul>
<ul>
</ul>
</ul>
</div>

<div><br /></div>

<div><br /></div>

<ul>
<ul>
</ul>
</ul>
<p></p>]]></description>
                        <pubDate>Sun, 18 Nov 2012 18:05:40 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>script guide</category>
                                </item>
        										        <item>
            <title>User Account Share</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=user-account-share</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=user-account-share</guid>
                                    <description><![CDATA[<p style="text-align: left"></p>  <blockquote style="text-align: justify; line-height: normal; background-color: rgb(238,238,238); color: rgb(68,68,68); margin-left: 0px; font-size: 12px; margin-right: 0px" class="q4">   <ul style="line-height: 20px; font-family: calibri, &amp;#39;Times New Roman&amp;#39;, arial, tahoma; color: rgb(19,18,18); font-size: 15px; -webkit-margin-before: 0.3px; -webkit-margin-after: 0.3px">     <li style="text-align: left; -webkit-margin-before: 0.3px; -webkit-margin-after: 0.3px">This feature is available from 3.1 </li>   </ul>    <p style="line-height: 20px; margin-top: 7px; font-family: calibri, &amp;#39;Times New Roman&amp;#39;, arial, tahoma; margin-bottom: 7px; color: rgb(19,18,18); font-size: 15px; -webkit-margin-before: 0.3px; -webkit-margin-after: 0.3px"></p> </blockquote>  <p></p>  <p><span style="font-size: 14px;">Users can share their account with others by User Account Share feature.&nbsp;</span><span style="font-size: 14px">If a user share his permissions to others, the other users can switch to his account anytime the others want. This feature is extremely useful when the developers in a team should work on the same script.</span></p>  <p><a href="/files/attach/images/379199/404/545/image_18.png"><img style="border-bottom: 0px; border-left: 0px; margin: 10px auto; display: block; float: none; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="/files/attach/images/379199/404/545/image_thumb_8.png" width="539" height="482" editor_component="image_link" /></a> </p>  <p> If you want to share own permissions to other user, &nbsp;press <strong>Profile </strong>and select whom you want to share your account. &nbsp;In above case, Juno make his account shared by Mavlarn and Alex.</p>  <p><a href="/files/attach/images/379199/404/545/image_20.png"><img style="border-bottom: 0px; border-left: 0px; margin: 10px auto; display: block; float: none; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="/files/attach/images/379199/404/545/image_thumb_9.png" width="642" height="177" editor_component="image_link" /></a> </p>  <p><a href="/files/attach/images/379199/404/545/image_22.png"><img style="border-bottom: 0px; border-left: 0px; margin: 10px auto; display: block; float: none; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="/files/attach/images/379199/404/545/image_thumb_10.png" width="642" height="181" editor_component="image_link" /></a>When Mavlarn and Alex login, they can see Juno in the Switch To Other User menu.</p>  <p><a href="/files/attach/images/379199/404/545/image_24.png"><img style="border-bottom: 0px; border-left: 0px; margin: 10px auto; display: block; float: none; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="/files/attach/images/379199/404/545/image_thumb_11.png" width="642" height="173" editor_component="image_link" /></a> </p>  <p></p>  <p></p>  <p></p>  <p></p>  <p></p>  <p></p>  <p></p>  <p></p>  <p></p>  <p></p>  <p></p>  <p></p>  <p><strong>Note:</strong></p>  <blockquote>   <p>Admins can switch other users by default.<br />Admins / Users can not switch to admins.</p>

</blockquote>]]></description>
                        <pubDate>Sun, 06 Jan 2013 20:00:09 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>user-guide</category>
                                </item>
        										        <item>
            <title>Test Configuration</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=test-configuration</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=test-configuration</guid>
                                    <description><![CDATA[<h3>Test List</h3>
<p>User can create/stop/delete a test in this page. The ball color changes depending on the test status and it will refresh every 5 seconds. By hovering on it, you can see each test status.</p>
<p><a href="files/attach/images/379199/001/445/image_6.png"><img editor_component="image_link" height="423" width="702" src="http://www.cubrid.org/files/attach/images/379199/001/445/image_thumb_2.png" alt="image" border="0" title="image" style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;"/></a></p>
<p>&nbsp;</p>
<h3>Test configuration</h3>
<p>Test configuration is a critical aspect of a test. This sets the test duration, agent count, number of processes and threads etc in the test before running the test. Of course there are also more specific configuration items to satisfy a range of users.   <br />&nbsp;<a href="files/attach/images/379199/001/445/image_8.png"><img editor_component="image_link" height="657" width="702" src="http://www.cubrid.org/files/attach/images/379199/001/445/image_thumb_3.png" alt="image" border="0" title="image" style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;"/></a></p>
<table width="700" cellpadding="2" cellspacing="0" border="0">
<tbody>
<tr>
<td width="182" valign="top">Fields</td>
<td width="518" valign="top">Description</td>
</tr>
<tr>
<td width="182" valign="top">Agent</td>
<td width="518" valign="top" class="">The number of agents should be used.</td>
</tr>
<tr>
<td width="182" valign="top">Vuser per agent</td>
<td width="518" valign="top" class="">The number of virtual users in each agent , which is multiplied by process count and thread count.           <br />You can configure them in greater detail by clicking the + button.
<p>In the nGrinder stress test, all agents will have multiple processes and threads to simulate concurrent users.</p>

</td></tr><tr><td width="182" valign="top">Processes (Hidden)</td>
<td width="518" valign="top" class="">The number of worker processes the agent should start.</td>
</tr>
<tr>
<td width="182" valign="top">Threads (Hidden)</td>
<td width="518" valign="top" class="">The number of worker threads that each worker processe should start.</td>
</tr>
<tr>
<td width="182" valign="top">Script</td>
<td width="518" valign="top" class="">Test script to be used.</td>
</tr>
<tr>
<td width="182" valign="top">Target Host</td>
<td width="518" valign="top" class="">For every test, we can set the target host; it should be same as the host you access in your test script. nGrinder controller will start the monitoring task on the given target host when a test begins to run. Then, you can check the performance chart in the detailed test report.           <br />[NOTE]            <br />We implemented customized DNS resolution feature with the target host. This means we can just input a domain and IP mapping here not touching /etc/hosts file. This will be useful for some http servers, which have no DNS domain.            <br /></td>
</tr>
<tr>
<td width="182" valign="top">Duration</td>
<td width="518" valign="top" class="">Specify how long the test will be executed.</td>
</tr>
<tr>
<td width="182" valign="top">Run Count</td>
<td width="518" valign="top" class="">Specify how many test runs will be executed.</td>
</tr>
<tr>
<td width="182" valign="top">Ignore Sample Count</td>
<td width="518" valign="top" class="">Specify How many samples will be ignored during TPS samplings.</td>
</tr>
</tbody>
</table>
<p>&nbsp;If you check "Enable Ramp-up", you can specify a gradual initialization of the process.</p>
<p><a href="files/attach/images/379199/001/445/image_10.png"><img editor_component="image_link" height="595" width="461" src="http://www.cubrid.org/files/attach/images/379199/001/445/image_thumb_4.png" alt="image" border="0" title="image" style="background-image: none; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;"/></a></p>
<table width="702" cellpadding="2" cellspacing="0" border="0">
<tbody>
<tr>
<td width="182" valign="top">Fields</td>
<td width="518" valign="top" class="">Description</td>
</tr>
<tr>
<td width="182" valign="top">Ramp-Up</td>
<td width="518" valign="top" class="">This means increasing the number of processes in every interval.</td>
</tr>
<tr>
<td width="182" valign="top">Initial Sleep Time</td>
<td width="518" valign="top" class="">&nbsp;</td>
</tr>
<tr>
<td width="182" valign="top">Initial Processes</td>
<td width="518" valign="top" class="">This property sets the initial number of worker processes to start.</td>
</tr>
<tr>
<td width="182" valign="top">Processes Every</td>
<td width="518" valign="top" class="">This property sets the interval in milliseconds at which the agent starts new worker processes.</td>
</tr>
</tbody>
</table>
<p>Please remember this is process ramp-up not thread ramp-up!!.. So you must have enough process count to increase the count gradually. If you set up 1 agent, 10 processes and 2 threads and you set the&nbsp;1 in&nbsp;Ramp-Up, the count of vuser will be increased like 2, 4, 6, 8.... If you set 2 agents, it will be 4, 8, 12, 16...</p>
<p>The count of processes should be less than 10. Too many processes requires much agent memory. So you may not configure very smooth ramp-up. If you need to have more smooth ramp-up, please consider the <a href="how-to-ramp-up-by-threads" target="_blank">thread ramp-up</a>.</p>
<p>Currently, there will initially be a maximum of 10 tests running simultaneously by default, and one user can only run one test at the same time. All the agents will be assigned automatically to run some test. If there are not enough agents to run one test, that test will be delayed for several minutes, and then stopped as an error.   <br />When a user creates a test, the user can choose just to save the test or prepare it to run. If it is prepared to run, the test (including its configuration) cannot be modified. But the user can clone this test and create a new test with the same configuration.    <br />The test can also be scheduled to run later, rather than starting immediately.</p>
<p><a href="files/attach/images/379199/001/445/image_14.png"><img editor_component="image_link" height="105" width="702" src="http://www.cubrid.org/files/attach/images/379199/001/445/image_thumb_6.png" alt="image" border="0" title="image" style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;"/></a></p>
<p><a href="files/attach/images/379199/001/445/image_16.png"><img editor_component="image_link" height="104" width="702" src="http://www.cubrid.org/files/attach/images/379199/001/445/image_thumb_7.png" alt="image" border="0" title="image" style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;"/></a></p>
<p>After the test is started, the test running tab will be enabled and you can check the running status via this page.   <br /> When the test is finished, you can then check the report and the detailed report.    <br />&nbsp; <br /><a href="files/attach/images/379199/001/445/image_18.png"><img editor_component="image_link" height="589" width="702" src="http://www.cubrid.org/files/attach/images/379199/001/445/image_thumb_8.png" alt="image" border="0" title="image" style="background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;"/></a></p>
<p>At the bottom right, you can download the log file for each agent. Using this file, you can identify script execution problems.</p>]]></description>
                        <pubDate>Mon, 08 Oct 2012 20:49:36 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>user-guide</category>
                                </item>
        										        <item>
            <title>Upgrade guide</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=upgrade-guide</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=upgrade-guide</guid>
                                    <description><![CDATA[<p>nGrinder supports easy upgrade. Actually you don't need any additional step except just replacing nGrinder binaries. When nGrinder starts up, it upgrades the database automatically and use the ${NGRINDER_HOME}/.ngrinder folder content&nbsp;continuously.</p>

<p><br /></p>

<h3>How to upgrade controller</h3><p>Nothing is really necessary to upgrade controller. Just replace ngrinder-controller-{VERSION}.war in the your tomcat webapps folder. When you restart the tomcat, nGrinder detects the current database schema version and try to upgrade it to the version you're installing. Just it works.</p>

<div><br /></div>

<h3>How to upgrade agent</h3><p>If you're upgrading controller, mostly previous version agents are just working with later nGrinder controller version if we don't mention it. If you'd like to upgrade the agent, just replace the current agent binary with the newer version. And run run_agent.sh or run_agent.bat.<br /></p>

<div>That's it.&nbsp;</div>]]></description>
                        <pubDate>Tue, 20 Nov 2012 21:47:27 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>admin-guide</category>
                                </item>
        										        <item>
            <title>Advanced Controller Configuration</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=advanced-ngrinder-controller-configuration</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=advanced-ngrinder-controller-configuration</guid>
                                    <description><![CDATA[<p>This chapter describes the advanced nGrinder controller configuration. You may not need to read this guide if you are not system admi. However if you want to run nGrinder as the cloud based service or calibrate the behavior, you should read this chapter.</p>  <h2>${NGRINDER_HOME} - nGrinder Controller Home</h2>  <p>If you start tomcat with "catalina.sh start" or "startup.sh", nGrinder will create ${user.home}/.ngrinder&nbsp;directory&nbsp;into user’s home&nbsp;directory&nbsp;after it starts up successfully. this&nbsp;directory&nbsp;contains the configuration files and data.    <br />Following is .ngrinder default location.</p>  <blockquote>   <ul>     <li>Window7 &nbsp; : C:&#92;Users&#92;${user.home}&#92;.ngrinder </li>      <li>Unix/Linux :${user.home}/.ngrinder </li>   </ul> </blockquote>  <p>But if you like to assign the other directory for this, please set Environment Variables “<strong>NGRINDER_HOME</strong>” before running tomcat.     <br /></p>  <h2>Advanced Configuration</h2>  <p>${NGRINER_HOME} contains the following files and directories.</p>  <ul style="margin-right: 0px" dir="ltr">   <li><strong>database.conf</strong> – This contains the database configuration. You can modify this file when you need to use the other DB. The default DB nGrinder uses is H2.       <pre class="brush: plain;">database=H2
database_username=admin
database_password=admin</pre>

    <blockquote class="q4">
      <p>NOTE: If you like to use Cubrid for database, you need to add following configuration more</p>
    </blockquote>

    <pre class="brush: plain;">database_url={your_cubrid_host_ip_or_name}:{cubrid_port_maybe_33000}:{dbname}</pre>

    <blockquote class="q4">
      <p>NOTE: If you want to duplicate Cubrid DB with HA. Please enables HA in cubrid following the <a href="/manual/843/en/CUBRID%20HA" target="_blank">link</a> and add the alternatives db address in database.conf</p>
    </blockquote>

    <pre class="brush: plain;">database_url_option=&amp;althosts={you_cubrid_secondary_host_ip_or_name}:{cubrid_port_maybe_33000}</pre>
  </li>

  <li>
    <blockquote class="q4">
      <p>NOTE: Currently, we just support 2 types of database, H2,and Cubrid. If you want to use other DB, please modify org.ngrinder.infra.config.Database class to add a new one like Mysql. Or make a official request to us.</p>
    </blockquote>
  </li>

  <li><strong>system.conf</strong> – This file contains the general policy and configuration settings for nGrinder controller. You can modify these settings to calibrate nGrinder controller behavior. 

    




&nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 




&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 




&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 




&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 
&nbsp; &nbsp; &nbsp; &nbsp; <table border="1" cellspacing="0" cellpadding="1" width="702"><tbody>
        <tr>
          <th valign="top" width="216">
            <p><b>Name</b></p>
          </th>

          <td valign="top" width="59">
            <p><b>Since</b></p>
          </td>

          <th valign="top" width="161">
            <p><b>Default Value</b></p>
          </th>

          <th valign="top" width="264" class="">
            <p><b>Description</b></p>
          </th>
        </tr>

        <tr>
          <td valign="top" width="218">
            <p>verbose</p>
          </td>

          <td valign="top" width="59">3.0</td>

          <td valign="top" width="161" class="">
            <p>false</p>
          </td>

          <td valign="top" width="263" class="">
            <p>Set true to print the more detailed log.</p>
          </td>
        </tr><tr><td valign="top" width="218" class=""><p>usage.report &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</p>

</td><td valign="top" width="59" class="">3.2</td><td valign="top" width="161" class=""><span style="line-height: 25px;">true</span><br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</td><td valign="top" width="263" class=""><span style="line-height: 25px;">Set false if you don't want to report ngrinder usage to google analytics.</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</td></tr>
        <tr>
          <td valign="top" width="218" class="xe_selected_cell">
            <p>security</p>
          </td>

          <td valign="top" width="59" class="xe_selected_cell">3.0.1</td>

          <td valign="top" width="161" class="xe_selected_cell">
            <p>false</p>

</td><td valign="top" width="263" class="xe_selected_cell"><p>You can specify whether nGrinder controller uses security mode or not. When the security mode is activated, Each test script is limited to access limited range of targets. Please refer [Script Security]</p>
          </td>
        </tr>

        <tr>
          <td valign="top" width="218" class="xe_selected_cell">
            <p>agent.max.size</p>
          </td>

          <td valign="top" width="59" class="xe_selected_cell">3.0</td>

          <td valign="top" width="161" class="xe_selected_cell">
            <p>10</p>
          </td>

          <td valign="top" width="263" class="xe_selected_cell">
            <p>The maximum number of agents attached into one test. This is useful when you like to make nGrinder shared by more user. With this option, each test can use only limited number of agents. For example, if your nGrinder instance has 15 agents in total and you set this field 5, you can guarantee 3 users can run performance tests concurrently.</p>
          </td>
        </tr>

        <tr>
          <td valign="top" width="218" class="xe_selected_cell">
            <p>agent.max.vuser</p>
          </td>

          <td valign="top" width="59" class="xe_selected_cell">3.0</td>

          <td valign="top" width="161" class="xe_selected_cell">
            <p>1000</p>
          </td>

          <td valign="top" width="263" class="xe_selected_cell">
            <p>The maximum number of vuser which can be created per one agent. If your agent machine spec is good enough, you can increase this.</p>
          </td>
        </tr>

        <tr>
          <td valign="top" width="218" class="xe_selected_cell">
            <p>agent.max.runcount</p>
          </td>

          <td valign="top" width="59" class="xe_selected_cell">3.0</td>

          <td valign="top" width="161" class="xe_selected_cell">
            <p>10000</p>
          </td>

          <td valign="top" width="263" class="xe_selected_cell">
            <p>The maximum runcount of test per ech agent.</p>
          </td>
        </tr>

        <tr>
          <td valign="top" width="218" class="xe_selected_cell">
            <p>agent.max.hour</p>
          </td>

          <td valign="top" width="59" class="xe_selected_cell">3.0</td>

          <td valign="top" width="161" class="xe_selected_cell">
            <p>8</p>
          </td>

          <td valign="top" width="263" class="xe_selected_cell">
            <p>The maximum running hour of each test</p>
          </td>
        </tr>

        <tr>
          <td valign="top" width="218" class="xe_selected_cell">
            <p>ngrinder.console.portbase</p>
          </td>

          <td valign="top" width="59" class="xe_selected_cell">3.0</td>

          <td valign="top" width="161" class="xe_selected_cell">
            <p>12000</p>
          </td>

          <td valign="top" width="263" class="xe_selected_cell">
            <p>The starting port number of console which will be mapped to each test.</p>

            <p>You need to restart nGrinder to apply the this configuration.</p>
          </td>
        </tr>

        <tr>
          <td valign="top" width="218" class="xe_selected_cell">
            <p>ngrinder.max.concurrenttest</p>
          </td>

          <td valign="top" width="59" class="xe_selected_cell">3.0</td>

          <td valign="top" width="161" class="xe_selected_cell">
            <p>10</p>
          </td>

          <td valign="top" width="263" class="xe_selected_cell">
            <p>How many concurrent tests are allowed in nGrinder.</p>
          </td>
        </tr>

        <tr>
          <td valign="top" width="218" class="xe_selected_cell">
            <p>ngrinder.max.waitingmilliseconds</p>
          </td>

          <td valign="top" width="59" class="xe_selected_cell">3.0</td>

          <td valign="top" width="161" class="xe_selected_cell">
            <p>5000</p>
          </td>

          <td valign="top" width="263" class="xe_selected_cell">
            <p>How many milliseconds console will wait until all agents are connected.</p>
          </td>
        </tr>

        <tr>
          <td valign="top" width="218" class="xe_selected_cell">
            <p>ngrinder.frontpage.rss</p>
          </td>

          <td valign="top" width="59" class="xe_selected_cell">3.0</td>

          <td valign="top" width="161" class="xe_selected_cell">
            <p>http://www.cubrid.org/ 
              <br />wiki_ngrinder/rss</p>
          </td>

          <td valign="top" width="290" class="xe_selected_cell">
            <p>You can point your own rss page on the nGrinder front page.</p>
          </td>
        </tr>

        <tr>
          <td valign="top" class="xe_selected_cell">ngrinder.help.url</td>

          <td valign="top" class="xe_selected_cell">3.1</td>

          <td valign="top" class="xe_selected_cell">http://www.cubrid.org/ 
            <br />wiki_ngrinder/entry/user-guide</td>

          <td valign="top" class="xe_selected_cell">If you want to provide your own custom help page. please modify this.</td>
        </tr>

        <tr>
          <td valign="top" width="218" class="xe_selected_cell">ngrinder.langauge.default</td>

          <td valign="top" width="59" class="xe_selected_cell">3.1</td>

          <td valign="top" width="161" class="xe_selected_cell">en</td>

          <td valign="top" width="290" class="xe_selected_cell">language default en/kr/cn is available. This is useful when you're installing custom SSO plugin.</td>
        </tr>

        <tr>
          <td valign="top" width="218" class="xe_selected_cell">ngrinder.security.sha256</td>

          <td valign="top" width="59" class="xe_selected_cell">3.1</td>

          <td valign="top" width="161" class="xe_selected_cell">false</td>

          <td valign="top" width="290" class="xe_selected_cell">
            <p>By default, nGrinder uses sha1 to encode passwords. If you nedd shar256, please set true.</p>

            <p>You need to reinstall nGrinder to apply the this configuration.</p>
          </td>
        </tr>

        <tr>
          <td valign="top" width="218" class="xe_selected_cell">ngrinder.dist.logback</td>

          <td valign="top" width="59" class="xe_selected_cell">3.1.1</td>

          <td valign="top" width="161" class="xe_selected_cell">true</td>

          <td valign="top" width="290" class="xe_selected_cell">
            <p>To be compatible with old agents (before 3.1.1), please set this true.&nbsp; <br /> If you use the latest version of agents, just set it false.</p>
          </td>
        </tr>

        <tr>
          <td valign="top" width="218" class="xe_selected_cell">ngrinder.dist.safe</td>

          <td valign="top" width="59" class="xe_selected_cell">3.1.1</td>

          <td valign="top" width="161" class="xe_selected_cell">false</td>

          <td valign="top" width="290" class="xe_selected_cell">
            <p> From 3.1.1, nGrinder doesn't check the file distribution result to speed up the test execution.
              <br />If your agent is located in the far places or you distribute big files everyday, you'd better to change this to true. </p>
          </td>
        </tr>

        <tr>
          <td valign="top" width="218" class="xe_selected_cell">ngrinder.dist.safe.region</td>

          <td valign="top" width="59" class="xe_selected_cell">3.1.1</td>

          <td valign="top" width="161" class="xe_selected_cell">false</td>

          <td valign="top" width="290" class="xe_selected_cell">
            <p> If a some region has the slow connection speed, set true.</p>
          </td>
        </tr>

        <tr>
          <td valign="top" width="218" class="xe_selected_cell">ngrinder.dist.safe.threashhold</td>

          <td valign="top" width="59" class="xe_selected_cell">3.1.1</td>

          <td valign="top" width="161" class="xe_selected_cell">1000000</td>

          <td valign="top" width="290" class="xe_selected_cell">
            <p> Set the safe distribution threshold to enable safe distribution for specific transfer size by force.</p>
          </td>
        </tr>

        <tr>
          <td valign="top" colspan="4" class="xe_selected_cell">The followings are related to the clustering. It should be very carefully set. 
            <br /># You can refer http://www.cubrid.org/wiki_ngrinder/entry/controller-clustering-guide</td>
        </tr>

        <tr>
          <td valign="top" width="218" class="xe_selected_cell">ngrinder.cluster.mode</td>

          <td valign="top" width="59" class="xe_selected_cell">3.1</td>

          <td valign="top" width="161" class="xe_selected_cell">false</td>

          <td valign="top" width="290" class="xe_selected_cell">
            <p>if you want to enable nGrinder controller clustering mode, Set true.</p>

            <p>You need to restart nGrinder to apply the this configuration.</p>
          </td>
        </tr>

        <tr>
          <td valign="top" width="218" class="xe_selected_cell">ngrinder.cluster.uris</td>

          <td valign="top" width="59" class="xe_selected_cell">3.1</td>

          <td valign="top" width="161" class="xe_selected_cell">none</td>

          <td valign="top" width="290" class="xe_selected_cell">
            <p>All controller IPs which belong to the cluster.</p>

            <p>You need to restart nGrinder to apply this configuration.</p>
          </td>
        </tr>

        <tr>
          <td valign="top" width="218" class="xe_selected_cell">ngrinder.cluster.listener.port</td>

          <td valign="top" width="59" class="xe_selected_cell">3.1</td>

          <td valign="top" width="161" class="xe_selected_cell">40003</td>

          <td valign="top" width="290" class="xe_selected_cell">
            <p>Communication port for Cache&nbsp;synchronization&nbsp;in the cluster.</p>

            <p>You need to restart nGrinder to apply the this configuration.</p>
          </td>
        </tr>
      </tbody></table>
  </li>

  <li><strong>process_and_thread_policy.js</strong> – This file defines the logic to determine the count of processes and threads for the given vuser count.&nbsp;<span style="line-height: 25px;">This file provides the flexibility to configure default process and thread allocation scheme.&nbsp;User&nbsp;usually&nbsp;don’t know which process and thread combination provides the best performance.&nbsp;Therefore, nGrinder let a user just input expected vuser per agent and configure the process and thread count automatically. </span><br /><span style="line-height: 25px;">The default content is like following.<br /></span><span style="font-size: 14px; font-weight: bold; line-height: 26px; text-transform: uppercase; color: rgb(0, 0, 0);">NGrinder&nbsp; 3.0</span></li>
</ul>
<ul style="margin-right: 0px" dir="ltr"><li><pre class="brush: js;">function getProcessCount(total) {
    if (total &lt; 2) {
        return 1;
    }
    
    return 2;
}

function getThreadCount(total) {
    if (total &lt; 2) {
        return 1;
    }
    return parseInt(total / 2 + 0.5);
}</pre>

    <h4>nGrinder; 3.1 </h4>
      <pre class="brush: js;">function getProcessCount(total) {
    if (total &lt; 2) {
        return 1;
    }
    if (total &gt; 80) {
        return parseInt(total / 30);
    }
    return 2;
}

function getThreadCount(total) {
    if (total &lt; 2) {
        return 1;
    }
        if (total &gt; 80) {
        return parseInt(total / (parseInt(total / 30)));
        }
    return parseInt(total / 2 + 0.5);
}</pre>
<h4>nGrinder 3.1.1</h4>
<pre class="brush: bash;">function getProcessCount(total) {
    if (total &lt; 2) {
        return 1;
    }
    
    var processCount = 2;

    if (total &gt; 80) {
        processCount = parseInt(total / 40) + 1;
    }
    
    if (processCount &gt; 20) {
        processCount = 20;
    }
    return processCount;
}

function getThreadCount(total) {
    var processCount = getProcessCount(total);
    return parseInt(total / processCount);
}</pre>
<h4>nGrinder 3.2</h4>
<pre class="brush: bash;">function getProcessCount(total) {
	if (total &lt; 2) {
		return 1;
	}
	
	var processCount = 2;

	if (total &gt; 80) {
		processCount = parseInt(total / 40) + 1;
	}
	
	if (processCount &gt; 10) {
		processCount = 10;
	}
	return processCount;
}

function getThreadCount(total) {
	var processCount = getProcessCount(total);
	return parseInt(total / processCount);
}
</pre>
      <br />You can freely rewrite this methods to fit your needs.
  </li>

  <li>
    <div><strong>grinder.properties</strong> – This file defines the default underlying The Grinder behavior. You can configure The Grinder behavior with this file. Some are overloaded by nGrinder runtime but some are not. In most cases, the admin doesn't need to change this file. 

      <br />Please refer <a href="http://grinder.sourceforge.net/g3/properties.html">http://grinder.sourceforge.net/g3/properties.html</a> for detail.</div>
  </li>

  <li>
    <div><strong>plugins folder</strong> – In this folder, you can locate nGrinder plugin. Just drop the plugin into this folder. If you want to check the available plugin, refer [nGrinder Plugins]</div>

</li>
</ul>

<h2>Data Structure</h2>

<p>In ${NGRINDER_HOME}, there are some folders to store data used in nGrinder. Followings are description for them.</p>

<table border="0" cellspacing="0" cellpadding="2" width="568"><tbody>
    <tr>
      <td valign="top" width="110">Folder name</td>

      <td valign="top" width="456">Description</td>
    </tr>

    <tr>
      <td valign="top" width="110">logs</td>

      <td valign="top" width="456" class="xe_selected_cell">This store the nGrinder logs. nGrinder intercepts the tomcat log and saves the log in ngrinder.log file. This log contains only controller related logs. You can also monitor the content of this file through the admin menu.</td>
    </tr>

    <tr>
      <td valign="top" width="110">perftest</td>

      <td valign="top" width="456" class="xe_selected_cell">This folder stores the each performance test related data. 
        <ul>
          <li>perftest/{testid}/dist : contains the files to be distributed. </li>

          <li>perftest/{testid}/logs : contains the logs from agents. </li>

          <li>perftest/{testid}/report : contains the statistics for the test. </li>
        </ul>
      </td>
    </tr>

    <tr>
      <td valign="top" width="110">repos</td>

      <td valign="top" width="456" class="xe_selected_cell">This folder stores the each user's svn repository.</td>
    </tr>

    <tr>
      <td valign="top" width="110">script</td>

      <td valign="top" width="456" class="xe_selected_cell">This folder stores the script validation related resources.</td>
    </tr>

    <tr>
      <td valign="top" width="110">db</td>

      <td valign="top" width="456" class="xe_selected_cell">This folder store the H2 database data. </td>
    </tr>
  </tbody></table>]]></description>
                        <pubDate>Wed, 26 Sep 2012 06:46:48 -0800</pubDate>
                        <category>ngrinder</category>
                                </item>
        										        <item>
            <title>Controller Clustering Guide</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=controller-clustering-guide</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=controller-clustering-guide</guid>
                                    <description><![CDATA[<p><span class="Apple-style-span" style="font-family: Calibri, 'Times New Roman', Tahoma, sans-serif; font-size: 14px; color: rgb(0, 0, 0); line-height: normal; "></span></p>

<blockquote class="q4" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; font-size: 12px; color: rgb(68, 68, 68); text-align: justify; border-left-width: 1px; border-left-style: solid; border-left-color: rgb(217, 217, 217); border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-top-color: rgb(217, 217, 217); border-right-color: rgb(217, 217, 217); border-bottom-color: rgb(217, 217, 217); background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(238, 238, 238); background-position: initial initial; background-repeat: initial initial; "><p style="line-height: 20px; font-family: Calibri, 'Times New Roman', Arial, Tahoma; font-size: 15px; display: block; margin-top: 7px; margin-bottom: 7px; -webkit-margin-start: 0px; -webkit-margin-end: 0px; -webkit-margin-before: 0.3px; -webkit-margin-after: 0.3px; text-align: justify; margin-right: 0px; margin-left: 0px; color: rgb(19, 18, 18); ">Change list:</p>

<p style="line-height: 20px; font-family: Calibri, 'Times New Roman', Arial, Tahoma; font-size: 15px; display: block; margin-top: 7px; margin-bottom: 7px; -webkit-margin-start: 0px; -webkit-margin-end: 0px; -webkit-margin-before: 0.3px; -webkit-margin-after: 0.3px; text-align: justify; margin-right: 0px; margin-left: 0px; color: rgb(19, 18, 18); "></p>

<ul style="color: rgb(19, 18, 18); font-family: Calibri, 'Times New Roman', Arial, Tahoma; line-height: 20px; font-size: 15px; -webkit-margin-before: 0.3px; -webkit-margin-after: 0.3px; "><li style="text-align: left; line-height: 20px; font-family: Calibri, 'Times New Roman', Arial, Tahoma; font-size: 15px; -webkit-margin-before: 0.3px; -webkit-margin-after: 0.3px; ">This feature is available from 3.1</li>
</ul>
<p style="line-height: 20px; font-family: Calibri, 'Times New Roman', Arial, Tahoma; font-size: 15px; display: block; margin-top: 7px; margin-bottom: 7px; -webkit-margin-start: 0px; -webkit-margin-end: 0px; -webkit-margin-before: 0.3px; -webkit-margin-after: 0.3px; text-align: justify; margin-right: 0px; margin-left: 0px; color: rgb(19, 18, 18); "></p>

</blockquote><p style="line-height: 20px; font-family: Calibri, 'Times New Roman', Arial, Tahoma; font-size: 15px; display: block; margin-top: 7px; margin-bottom: 7px; -webkit-margin-start: 0px; -webkit-margin-end: 0px; -webkit-margin-before: 0.3px; -webkit-margin-after: 0.3px; text-align: justify; margin-right: 0px; margin-left: 0px; color: rgb(19, 18, 18); "><br /></p>

<p></p>

<p>We enhanced nGrinder to support clustering from 3.1.</p>  <p>If you don’t know about nGrinder cluster, please refer to [Cluster Architecture]. Following shows how to set up nGrinder cluster mode. Assuming you have been familiar with nGrinder in single instance mode.&nbsp;All nGrinder controllers should use the same DB and file system in cluster mode. What we should do at first is to make a shared folder on the NFS and make all controllers point this as ${NGRINDER_HOME}. And edit&nbsp;${NGRINDER_HOME}/system.conf like followings. &nbsp;</p>  <pre class="brush: bash;"># if you want to enable ngrinder controller clustering. please enable below. 
ngrinder.cluster.mode=true

# list of controller IPs
ngrinder.cluster.uris=xx.xx.xx.xx;xx.xx.xx.xx

# cache cluster listener port.
ngrinder.cluster.listener.port=40003</pre>

<p>Next step is to create the each controller's specific information. For this ${NGRINDER_EX_HOME}/system-ex.conf file is used. Not like ${NGRINDER_HOME}, ${NGRINDER_EX_HOME} is not automatically created by nGrinder. Therefore you should make it in the local file system not to be shared by other controller.&nbsp;Create&nbsp;${NGRINDER_EX_HOME}/system-ex.conf file and specify the region name here. The controller which reads this configuration will act as specified region controller.</p>

<pre class="brush: bash;"># Region setting of this controller.
# When running nGrinder in cluster mode, the ${NGRINDER_HOME} should be shared by other controllers.
# We expect this to be done by running ${NGRINDER_HOME} on NFS. 
# However region setting can not be set on ${NGRINDER_HOME} because each controller in cluster must have its own configuration.
# Therefore, nGrinder supports one more configuration store folder ${NGRINDER_EX_HOME}
# Please locate following setting in the ${NGRINDER_EX_HOME}(by default ${user.home}/.ngrinder_ex)/system-ex.conf
ngrinder.cluster.region=Beijing</pre>

<p>After finish this configuration, just restart all nGrinder controllers and login again.&nbsp;We will see this icon at headline!</p>

<p><a href="/files/attach/images/379199/150/524/image_4.png"></a><img style="border-right-width: 0px; margin: 10px auto; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" src="/files/attach/images/379199/150/524/image_thumb_1.png" width="642" height="309" editor_component="image_link" /></p>

<p>If you want to put the L4 or load balancer in front of all controllers, you should set it up as sticky session so that each client connects only one controller. Otherwise, users may login again whenever they access difference controller.</p>

<p>After the controller configuration, you should also set the region name to all agents. As you should know, we should set the connecting controller IP &nbsp;in each agents. Now there are several controllers. So you should choose one of them depending on what region you want this agent to serve for. You need to add the not only connecting controller IP but also region name this controller handles.</p>

<blockquote class="q4" style="padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(217, 217, 217); border-right-color: rgb(217, 217, 217); border-bottom-color: rgb(217, 217, 217); border-left-color: rgb(217, 217, 217); background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(238, 238, 238); text-align: justify; "><ol style="color: rgb(71, 71, 71); font-size: 13px; "><ul>
<li style="margin-top: 7px; margin-right: 0px; margin-bottom: 7px; margin-left: 0px; color: rgb(71, 71, 71); font-family: arial, verdana, sans-serif; font-size: 13px; line-height: normal; ">agent.console.ip=controller ip</li>
<li style="margin-top: 7px; margin-right: 0px; margin-bottom: 7px; margin-left: 0px; ">agent.console.port=&nbsp;controller port</li>
<li style="margin-top: 7px; margin-right: 0px; margin-bottom: 7px; margin-left: 0px; color: rgb(71, 71, 71); font-family: arial, verdana, sans-serif; font-size: 13px; line-height: normal; ">agent.region=controller region name</li>
</ul>
</ol>

<p style="margin-top: 7px; margin-right: 0px; margin-bottom: 7px; margin-left: 0px; line-height: 20px; font-family: Calibri, 'Times New Roman', Arial, Tahoma; font-size: 15px; display: block; -webkit-margin-start: 0px; -webkit-margin-end: 0px; -webkit-margin-before: 0.3px; -webkit-margin-after: 0.3px; text-align: justify; color: rgb(19, 18, 18); "></p>

</blockquote><p></p>

<p>If this agent is [User Agent], it should be like:</p>

<p><span class="Apple-style-span" style="line-height: normal; "></span></p>

<blockquote class="q4" style="padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px; margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: rgb(217, 217, 217); border-right-color: rgb(217, 217, 217); border-bottom-color: rgb(217, 217, 217); border-left-color: rgb(217, 217, 217); background-image: initial; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: rgb(238, 238, 238); text-align: justify; background-position: initial initial; background-repeat: initial initial; "><ol style="color: rgb(71, 71, 71); font-size: 13px; "><ul>
<li style="margin-top: 7px; margin-right: 0px; margin-bottom: 7px; margin-left: 0px; color: rgb(71, 71, 71); font-family: arial, verdana, sans-serif; font-size: 13px; line-height: normal; ">agent.console.ip=controller ip</li>
<li style="margin-top: 7px; margin-right: 0px; margin-bottom: 7px; margin-left: 0px; ">agent.console.port=&nbsp;controller port</li>
<li style="margin-top: 7px; margin-right: 0px; margin-bottom: 7px; margin-left: 0px; color: rgb(71, 71, 71); font-family: arial, verdana, sans-serif; font-size: 13px; line-height: normal; ">agent.region={controller region name}_owned_{userID}</li>
</ul>
</ol>
</blockquote><p></p>

<ol>
<ul>
</ul>
</ol>
<p></p>]]></description>
                        <pubDate>Wed, 12 Dec 2012 01:13:13 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>user-guide</category>
                        <category>cluster</category>
                                </item>
        										        <item>
            <title>Cluster Architecture</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=cluster-architecture</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=cluster-architecture</guid>
                                    <description><![CDATA[<p>From nGrinder&nbsp;version 3.1, we introduced nGrinder controller clustering, which make the performance test can be executed by one of the clustered controller and support multiple set of agents(named region) to be used.</p>  <p>Below is the architecture without cluster supports.</p>  <p><a href="/files/attach/images/379199/772/545/image_10.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="/files/attach/images/379199/772/545/image_thumb_4.png" width="664" height="326" editor_component="image_link" /></a></p>  <ol>   <li>nGrinder uses an embedded svn server(SVNKit DAV) to manage script files. The svn repositories are stored in ${NGRINDER_HOME} directory.</li>    <li>nGrinder uses EhCache to improve the data retrieval performance from DB and SVN repositories.</li>    <li>nGrinder uses Spring Security to protect the system and uses Atlassian Plugin Framework for extensibility.</li> </ol>  <p>If you enable clustering mode by configuring the system.conf (See <a href="/wiki_ngrinder/entry/controller-clustering-guide" target="_blank">link</a>) and install nGrinder into multiple machine, the system architect is&nbsp;changed&nbsp;as below:</p>  <p><a href="/files/attach/images/379199/772/545/image_17.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="/files/attach/images/379199/772/545/image_thumb_7.png" width="665" height="361" editor_component="image_link" /></a></p>  <ol>   <li>All the controllers in the cluster shares the same DB and file system. All ngrinder controller should point same&nbsp;${NGRINDER_HOME} folder which should be shared by NFS.</li>    <li>Each controllers can have its own&nbsp;special&nbsp;properties and&nbsp;log&nbsp;output folder. This information will be saved in ${NGRINDER_EX_HOME} in the each controller.</li>    <li>All controllers replicates the EhCache to each other to make some data to be&nbsp;visible&nbsp;in all controllers in cluster.</li> </ol>          <p>Each controller can serve nGrinder web content&nbsp;equally&nbsp;but handles the different test set depending the region. We don't provide any session clustering by default. So you may suffer login problem because sessions stored in a controller are not replicated to the other controllers. You may need to configure this by&nbsp;referring&nbsp;<a href="http://tomcat.apache.org/tomcat-6.0-doc/cluster-howto.html" target="_self">Tomcat Session Clustering Guide</a> or use the sticky session on L4. If you are not a expert on this, Just let users to connect only one controller. It's the&nbsp;easiest. :-)</p>

<p>How to configure the clustering? Check [Controller Clustering Guide]</p>]]></description>
                        <pubDate>Mon, 07 Jan 2013 00:39:06 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>architecture</category>
                                </item>
        										        <item>
            <title>Technology Stack</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=technology-stack</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=technology-stack</guid>
                                    <description><![CDATA[<h3>Client Tier</h3>  <ul>   <li><strong>Bootstrap</strong> : Bootstrap has a lot of predefined web style(js, css etc ), it is sleek and intuitive.We uses it span all over the nGrinder web pages. </li>    <li><strong>Bootstrap-slider</strong>:Bootstrap-slider is a beauty of Bootstrap UI widgets. We use this for test duration setting in Test Configuration.</li>    <li><strong>Jquery</strong> :jQuery is a lightweight JavaScript library,it make much easier to use JS on nGrinder web pages. </li>    <li><strong>Jquery Validate</strong> : Jquery Validate is an excellent tool for web pages to validate data entries at the client side. </li>    <li><strong>Datatables</strong> : DataTables is a highly flexible JS tool which will add advanced interaction controls to any HTML table. </li>    <li><strong>Select2</strong> : Select2 is jQuery based replacement for select boxes which supports searching and infinite scrolling of results. </li>    <li><strong>JqPlot</strong> :&nbsp; jqPlot could generate pure client-side JS charts in web pages and therefore all nGrinder data chart are implemented with JqPlot. </li>    <li><strong>CodeMirror</strong> :CodeMirror is an excellent code editor with syntax highlighting in the browser.We use it in nGrinder Script Editor. </li> </ul>  <h3>Controller Tier</h3>  <ul>   <li><strong>FreeMarker</strong> :FreeMarker is a Java-based template engine focusing on MVC framework and nGrinder web pages is used it as a template engine. </li>    <li><strong>Spring Security</strong> :&nbsp; Spring Security is&nbsp;not only&nbsp;a powerful and highly authentication and access-control framework, but also one of the most mature and widely used security framework. Therefore it protects nGrinder from illegal access. </li>    <li><strong>Spring MVC</strong> : Spring MVC provides rich functionality for building robust web applications. nGrinder uses wonderfully its annotation based configuration.</li>    <li><strong>GSon</strong> :Gson is a Java library that can be used to convert Java Objects into its JSON representation, and vice versa. </li>    <li><strong>SVNKit Dav</strong> : We use this for serving the underlying SVN content thought web.</li> </ul>  <h3>Service Tier</h3>  <ul>   <li><strong>Grinder</strong> : Grinder is a java load Testing framework which nGrinder mainly use. Without Grinder, no nGrinder exists</li>    <li><strong>Atlassian Plugin Framework</strong> :We use this framework to make the plugin development easier. It's not so heavy weight and easy to use!</li>    <li><strong>Spring</strong>&nbsp; : Spring Framework provides a comprehensive programming and configuration model for J2ee applications and nGrinder use as a its base architecture. </li>    <li><strong>EhCache</strong> : Ehcache has excellent Spring integration. nGrinder uses this to speed up the data retrieval and to&nbsp;synchronize&nbsp;data between controllers in cluster mode.</li> </ul>  <h3>Data Tier</h3>  <ul>   <li><strong>Spring Data</strong> :Spring Data simplifies the development of JPA-based data access layer. nGrinder uses RDBMS but this enables the RDBMS access without single line of SQL.</li>    <li><strong>Hibernate</strong> : Hibernate is a powerful technology for persisting data,and it is Spring Data back-end within nGrinder. </li>    <li><strong>H2</strong> : H2 is one of two databases nGrinder supports and H2 is used as a default DB. </li>    <li><strong>Cubrid</strong> :Cubrid is one of two databases nGrinder supports. It's stable enough and supports HA.</li>    <li><strong>Liquibase</strong> : Liquibase is an open source that automates database schema updates. It supports almost all kinds of major databases. </li>
<li><strong>SVNKit </strong>: SVNKit is a pure Java toolkit which implements all subversion features and provides APIs to work with Subversion.</li> </ul>  <hr />  <div>&nbsp;</div>  <p>&nbsp;</p>

<p><a href="/files/attach/images/379199/163/548/image_4.png"><img style="border-right-width: 0px; margin: 5px 15px 5px 45px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="left" src="/files/attach/images/379199/163/548/image_thumb_1.png" width="65" height="38" editor_component="image_link" /></a> </p>  <p><a href="/files/attach/images/379199/163/548/image_2.png"><img style="border-right-width: 0px; margin: 5px 15px 5px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="left" src="/files/attach/images/379199/163/548/image_thumb.png" width="62" height="37" editor_component="image_link" /></a> </p>  <p></p>  <p></p>  <p><a href="/files/attach/images/379199/163/548/image_6.png"><img style="border-right-width: 0px; margin: 5px 15px 5px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="left" src="/files/attach/images/379199/163/548/image_thumb_2.png" width="60" height="38" editor_component="image_link" /></a> </p>  <p><a href="/files/attach/images/379199/163/548/image_8.png"><img style="border-right-width: 0px; margin: 5px 10px 5px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="left" src="/files/attach/images/379199/163/548/image_thumb_3.png" width="64" height="40" editor_component="image_link" /></a> </p>  <p>&nbsp;</p>  <p><br /></p>  <p><a href="/files/attach/images/379199/163/548/image30.png"><img style="border-right-width: 0px; margin: 5px 15px 5px 45px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="left" src="/files/attach/images/379199/163/548/image30_thumb.png" width="64" height="40" editor_component="image_link" /></a></p>  <p><a href="/files/attach/images/379199/163/548/image43.png"><img style="border-right-width: 0px; margin: 5px 15px 5px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="left" src="/files/attach/images/379199/163/548/image43_thumb.png" width="62" height="42" editor_component="image_link" /></a></p>  <p><a href="/files/attach/images/379199/163/548/image25.png"><img style="border-right-width: 0px; margin: 5px 15px 5px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="left" src="/files/attach/images/379199/163/548/image25_thumb.png" width="62" height="39" editor_component="image_link" /></a></p>  <p><a href="/files/attach/images/379199/163/548/image1.png"><img style="border-right-width: 0px; margin: 5px 15px 5px 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="image" border="0" alt="image" align="left" src="/files/attach/images/379199/163/548/image1_thumb.png" width="66" height="42" editor_component="image_link" /></a></p>]]></description>
                        <pubDate>Tue, 08 Jan 2013 21:45:44 -0800</pubDate>
                        <category>ngrinder</category>
                                </item>
        										        <item>
            <title>Philosophy</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=philosophy</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=philosophy</guid>
                                    <description><![CDATA[<ul>   <li>Reliability over Accuracy</li>    <li>TPS over VUser</li>
<li>Code is always better than GUI Editor</li>
<li>Do not limit!!</li>    <li>File System is faster than DB if we use it correctly. </li>    <li>Convention over Configuration </li>    <li>Open Closed policy by Plugin Model </li>    <li>One shot Installation </li>    <li>Need to add code? Remove same amount of code first. </li> </ul>]]></description>
                        <pubDate>Sun, 13 Jan 2013 23:30:37 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>architecture</category>
                                </item>
        										        <item>
            <title>General Administration Guide</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=administration-guide</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=administration-guide</guid>
                                    <description><![CDATA[<h2>First Access</h2>  <p>Depending on how you have configured Tomcat, you may use a different URL to access the main page of nGrinder. If you didn’t change ${TOMCAT_HOME}/conf/server.xml and&nbsp;didn't&nbsp;change nGrinder controller war file name to ROOT.war, nGrinder should have the following URL.</p>

<blockquote class="q4">http://your_server_host:8080/ngrinder-controller</blockquote>  <p>Once you access the URL, you can see the login page.</p>  <p><a href="/files/attach/images/379199/166/438/image_4.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="/files/attach/images/379199/166/438/image_thumb_1.png" width="702" height="462" editor_component="image_link" /></a></p>  <h2>Login with Default Account</h2>  <p>nGrinder creates 4 users at the first run. The predefined IDs are as follows.<br />Each has name that reflects its role.</p>  <ul>   <li>admin, user, superuser, system </li>    <li>Initial password is the same as name </li> </ul>  <p>There are 4 user types (referred to as Roles)</p>  <p>   </p>

<table border="0" cellspacing="0" cellpadding="2" width="500"><tbody>       <tr>         <td valign="top" width="162" class=""><strong>Role</strong></td>          <td valign="top" width="338" class=""><strong>Description</strong></td>       </tr>        <tr>         <td valign="top" width="162" class="">ADMIN</td>          <td valign="top" width="338" class="">Manage nGrinder system including : User Management, Test Observation, Test Report Statistics and Agent Management, etc.</td>       </tr>        <tr>         <td valign="top" width="162" class="">USER</td>          <td valign="top" width="338" class="">Test script, and then get its report data files.</td>       </tr>        <tr>         <td valign="top" width="162" class="">SYSTEM_USER</td>          <td valign="top" width="338" class="">Reserved for internal use</td>       </tr>        <tr>         <td valign="top" width="162" class="">SUPER_USER</td>          <td valign="top" width="338" class="">Observe whole tests executed in nGrinder instance but can not configure the system.</td>       </tr>     </tbody></table><p>To configure the system, you need to log in with an admin account. </p>

<blockquote class="q4"><p><b><span style="color: rgb(255, 0, 0); ">NOTE: &nbsp;Please don’t forget to change your password when you log in for the first time. If you leave your account with the default password, your nGrinder instance can be used by a hacker for a DDOS attack.</span></b></p>

</blockquote><p></p>  <h2></h2>  <h2>Manage Agents</h2>  <p>Agent management in the admin menu offers agent operation and monitoring functions.&nbsp;Even when you have configured the agent to connect the controller, you need to approve each agent in the controller to make it effective. This step is required to prevent abnormal agents trying to connect to the controller from abusing the controller.</p>  <p><a href="/files/attach/images/379199/166/438/image_6.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="/files/attach/images/379199/166/438/image_thumb_2.png" width="702" height="528" editor_component="image_link" /></a></p>  <p>If you are admin, the menu above should be visible. You can click the Agent Management menu to manage agents.&nbsp;</p>  <p><a href="/files/attach/images/379199/166/438/image_8.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="/files/attach/images/379199/166/438/image_thumb_3.png" width="702" height="299" editor_component="image_link" /></a></p>  <p>Then, you should see the screen shown above. This shows the statuses of the attached agent. If we just allow all agent connections, there would be a potential risk. For this reason, nGrinder only uses approved agents. If you confirm that the agents listed here are OK, you can approve them. Some agents can be only used for specific users. Please refer to [User Agent] for details.</p>

<p>You can monitor agent performance status by clicking each IP.</p>  <p><a href="/files/attach/images/379199/166/438/image_10.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="/files/attach/images/379199/166/438/image_thumb_4.png" width="702" height="606" editor_component="image_link" /></a></p>  <p>This graph shows the performance of each agent in the last 1 minute.</p>  <h2>User Management</h2>  <p>Admin can create/delete and modify users through the user management menu. Each user can also modify his/her own profile as well.</p>  <p><a href="/files/attach/images/379199/166/438/image_12.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="/files/attach/images/379199/166/438/image_thumb_5.png" width="702" height="343" editor_component="image_link" /></a></p>  <p>&nbsp;</p>  <h2>Script Console</h2>  <p>This is a useful admin tool for debugging. Admin can input Jython code to monitor and control nGrinder internal status. for example:</p>  <pre class="brush: py;">print agentManager.getAllAttachedAgents()</pre>

<p><a href="/files/attach/images/379199/166/438/image_14.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="/files/attach/images/379199/166/438/image_thumb_6.png" width="702" height="405" editor_component="image_link" /></a></p>

<p>It is important to know what you can refer in the script. The following variables are available.</p>

<ul>
  <li>applicationContext (org.springframework.context.ApplicationContext) </li>

  <li>agentManager (org.ngrinder.perftest.service.AgentManager) </li>

  <li>consoleManager (org.ngrinder.perftest.service.ConsoleManager) </li>

  <li>userService (org.ngrinder.user.service.UserService) </li>

  <li>perfTestService (org.ngrinder.perftest.service.PerfTestService) </li>

  <li>fileEntryService (org.ngrinder.script.service.FileEntryService) </li>

  <li>config (org.ngrinder.infra.config.Config) </li>

  <li>pluginManager (org.ngrinder.infra.plugin.PluginManager) </li>
</ul>

<p>Please refer to nGrinder javadoc to learn the available classes and methods.</p>

<h2>Log monitoring</h2>

<p>Sometime it’s important to see the server log to identify a problem and send a bug reports to the developers.</p>

<p>Instead of catalina.out which tomcat uses by default, nGrinder intercepts the logging system and writes a log in the ${NGRINDER_HOME}/logs/ngrinder.log file.</p>

<p>You can see the currently printing logs in the Log Monitoring menu. This is refreshed every 5 seconds in order to show the latest available logs.</p>

<p><a href="/files/attach/images/379199/166/438/image_16.png"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px" title="image" border="0" alt="image" src="/files/attach/images/379199/166/438/image_thumb_7.png" width="702" height="417" editor_component="image_link" /></a></p>

<h2>Test Policies</h2>

<p>Sometimes, you need to configure whole test execution policy. For example, you can set the maximum count of agents that each test can use. Or you can limit the max concurrent number of tests to minimize network loads. These kinds of policies can be configured by configuring the ${NGRINDER_HOME}/system.properties file.</p>

<p>For further details, please refer [Advanced Controller Configuration].</p>]]></description>
                        <pubDate>Thu, 27 Sep 2012 22:22:06 -0800</pubDate>
                        <category>ngrinder</category>
                                </item>
        										        <item>
            <title>nGrinder 3.1.1 Release Note</title>
            <dc:creator>CUBRID</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=ngrinder-3-1-1-release-note</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=ngrinder-3-1-1-release-note</guid>
                                    <description><![CDATA[<div><blockquote class="q4"><div>We proudly release nGrinder 3.1.1 to speed up the test execution and enhance the usability. With some bug fix, the following improvements are included. To ugrade to this version, you should delete the current version first and install this. In addition, you should delete the previous ${NGRINDER_HOME}/process_and_thread_policy.js in advance to experience the better process and thread calculation introduced by nGrinder 3.1.1.</div>

</blockquote><h3>1. Release Info</h3><div><ul s=""><li>Version : 3.1.1</li>
<li>Release Date : 2013.01.31</li>
</ul>
</div>

<h3>2. Changes</h3></div>

<div><h4>Outline</h4><ul>
<li>Speed up the test execution. Now all tests will take 5 seconds to execute a test.</li>
<li>Embed jython 2.5.3 and json.jar as the default libraries.</li>
<li>Make the agent take less memory. now agent processes need 50MB at minimum</li>
<li>Shows the response byte per second and mean time to first byte in the test running panel.</li>
<li>Change the default QnA site into nabble not github.</li>
<li>Change Process and Thread calculation logic more stable to support more than 300 users. Please delete the previous ${NGRINDER_HOME}/process_and_thread_policy.js in advance.</li>
</ul>
<h4>Details</h4><ul>
<li>Bugs Fix</li>
<ul>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-482" target="_self">NGRINDER-482</a> - Add grinder.processes and grinder.threads as properties during script validation</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-488" target="_self">NGRINDER-488</a> - Add a error message when there are no sampling was performed.</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-496" target="_self">NGRINDER-496</a> - Make user not to be able to change the underlying SecurityManager&nbsp;</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-497" target="_self">NGRINDER-497</a> - Make the current pc IP resolution more stable</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-498" target="_self">NGRINDER-498</a> - Make security mode work</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-504" target="_self">NGRINDER-504</a> - Show script initialize error in log</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-505" target="_self">NGRINDER-505</a> - Test Comment should not be cloned</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-506" target="_self">NGRINDER-506</a> - Block duplicated validation</li>
</ul>
<li>Improvement</li>
<ul>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-478" target="_self">NGRINDER-478</a> - Distribute the un-predefined resources (e.g images)&nbsp;</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-479" target="_self">NGRINDER-479</a> - Speed up nGrinder performance reducing distribution cost (4~6sec)<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; - Add json.jar library as default lib as well.</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-480" target="_self">NGRINDER-480</a> - Make each perftest folder distributed in several folders</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-481" target="_self">NGRINDER-481</a> - Move the question mark in logs to just right of log title</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-483" target="_self">NGRINDER-483</a> - Make nabble as a QnA Site</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-484" target="_self">NGRINDER-484</a> - Resolve locale cookie conflict issue&nbsp;</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-485" target="_self">NGRINDER-485</a> - Add cacheManager be accessible &nbsp;from the script console&nbsp;</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-489" target="_self">NGRINDER-489</a> - Add control.followRedirects and to control.timeout in the basic template script</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-490" target="_self">NGRINDER-490</a> - Make all external links opened in the separate window</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-491" target="_self">NGRINDER-491</a> - Make the minimum Xms smaller to support more processes.</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-492" target="_self">NGRINDER-492</a> - Make sure the script is saved when user leave the script editor without save.</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-494" target="_self">NGRINDER-494</a> - Increase the default vuser count to 300</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-495" target="_self">NGRINDER-495</a> - Modify the process and thread policy to support 1000 vusers</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-499" target="_self">NGRINDER-499</a> - Include jython-2.5.3.jar as default lib</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-500" target="_self">NGRINDER-500</a> - Modify test termination condition as half of test failures for last 10 sec</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-502" target="_self">NGRINDER-502</a> - Add the mean time to first byte and response byte per second.</li>
<li><a href="http://jira.cubrid.org/browse/NGRINDER-504" target="_self">NGRINDER-503</a> - Make ngrinder supports more than 2 billion test&nbsp;</li>
</ul>
</ul>
<h3>3. OS, DBMS supports</h3><div><ul>
<li>Linux, Windows, Mac OSX is supported.</li>
<li>Supports CUBRID, H2 as DB. The default DBMS is H2.</li>
</ul>
</div>

<h3>4. Requirements</h3><div><ul>
<li>Be required over Oracle JDK 1.6 version.</li>
<li>Tomcat 6.X later in advance.</li>
</ul>
</div>

<h3>5. Downloads</h3><div><ul>
<li><a href="http://sourceforge.net/projects/ngrinder/files/ngrinder-3.1.1/" target="_self">http://sourceforge.net/projects/ngrinder/files/ngrinder-3.1.1/</a></li>
</ul>
</div>

<h3>6. References</h3><div><ul>
<li>Release Note: <a href="/wiki_ngrinder/entry/ngrinder-3-1-1-release-note" target="_self">http://www.cubrid.org/wiki_ngrinder/entry/ngrinder-3-1-1-release-note</a></li>
<li>Manuals:</li>
<ul>
<li>Installation Guide : <a href="/wiki_ngrinder/entry/installation-guide" target="_self">http://www.cubrid.org/wiki_ngrinder/entry/installation-guide</a></li>
<li>Administration Guide : <a href="/wiki_ngrinder/entry/administration-guide" target="_self">http://www.cubrid.org/wiki_ngrinder/entry/administration-guide</a></li>
<li>User's Guide : <a href="/wiki_ngrinder/entry/user-guide" target="_self">http://www.cubrid.org/wiki_ngrinder/entry/user-guide</a></li>
</ul>
<li>Project: <a href="/wiki_ngrinder/entry/ngrinder-devzone" target="_self">http://www.cubrid.org/wiki_ngrinder/entry/ngrinder-devzone</a></li>
<li>Issue tracker: <a href="http://jira.cubrid.org/browse/NGRINDER" target="_self">http://jira.cubrid.org/browse/NGRINDER</a>, <a href="https://github.com/nhnopensource/ngrinder/issues" target="_self">https://github.com/nhnopensource/ngrinder/issues</a></li>
<li>Source repository: <a href="https://github.com/nhnopensource/ngrinder" target="_self">https://github.com/nhnopensource/ngrinder</a></li>
<li>Tag :&nbsp;<a href="https://github.com/nhnopensource/ngrinder/zipball/nGrinder3.1.1_20130131" target="_self">https://github.com/nhnopensource/ngrinder/zipball/nGrinder3.1.1_20130131</a></li>
<li>Mailing List : <a href="http://ngrinder.642.n7.nabble.com/" target="_self">http://ngrinder.642.n7.nabble.com/</a></li>
</ul>
</div>

<div><ul>
</ul>
</div>

<ul>
<ul>
</ul>
</ul>
</div>]]></description>
                        <pubDate>Wed, 30 Jan 2013 06:21:41 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>release-note</category>
                                </item>
        										        <item>
            <title>Virtual User</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=virtual-user</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=virtual-user</guid>
                                    <description><![CDATA[<p>Virtual Users in nGrinder is mapped into threads. If there are 1000 threads which runs a script, which means there are 1000 virtual users.&nbsp;nGrinder has a little different&nbsp;approach&nbsp;from other&nbsp;performance&nbsp;test tools. Instead of mimicking the user real behavior, we focus on how to make the server reach its limit. So we don't recommend to use think time concept in the scripts.</p>
<p>However if you want to simulate real user behaviors and really want to run the script with the huge count of virtual users, follow the below instructions. For example... if you want to have 10000 vusers,</p>
<blockquote class="q4"><ol>
<li>Prepare the 2 good agent machines. You may need machines with 2 cores and 6G memory.</li>
<li>Write the script with Groovy (Groovy script is more efficient than Jython)</li>
<li>Increase the vuser limit by setting&nbsp;<span style="color: #131212; font-family: Calibri, 'Times New Roman', Arial, Tahoma; font-size: 15px; line-height: 20px; text-align: justify;">agent.max.vuser to 5000 in system.conf file.</span></li>
<li><span style="color: #131212; font-family: Calibri, 'Times New Roman', Arial, Tahoma; font-size: 15px; line-height: 20px; text-align: justify;">Simulate thinking time with grinder.sleep(how_much_sleep_in_milliseconds) in the script</span></li>
<li><span style="color: #131212; font-family: Calibri, 'Times New Roman', Arial, Tahoma; font-size: 15px; line-height: 20px; text-align: justify;">When you configure the vuser count, please set the process around 10 and thread&nbsp;</span><span style="color: #131212; font-family: Calibri, 'Times New Roman', Arial, Tahoma; font-size: 15px; line-height: 20px; text-align: justify;">around</span><span style="color: #131212; font-family: Calibri, 'Times New Roman', Arial, Tahoma; font-size: 15px; line-height: 20px; text-align: justify;">&nbsp; 5</span><span style="color: #131212; font-family: Calibri, 'Times New Roman', Arial, Tahoma; font-size: 15px; line-height: 20px; text-align: justify;">00.</span></li>
</ol>
</blockquote>
<p><span style="color: #131212; font-family: Calibri, 'Times New Roman', Arial, Tahoma; font-size: 15px; line-height: 20px; text-align: justify;">It is always possible for a test to cause the memory related problem. So you need to set process and thread count very carefully.<br /></span><span style="color: #131212; font-family: Calibri, 'Times New Roman', Arial, Tahoma; font-size: 15px; line-height: 20px; text-align: justify;">Please refer [Process And Thread] for detail. &nbsp;</span><span style="color: rgb(19, 18, 18); font-family: Calibri, 'Times New Roman', Arial, Tahoma; font-size: 15px; line-height: 20px; text-align: justify;">If you need more vusers, please consider add more agents.<br /></span></p>

<p><span style="color: rgb(19, 18, 18); font-family: Calibri, 'Times New Roman', Arial, Tahoma; font-size: 15px; line-height: 20px; text-align: justify;">Actually in our company NHN, we set the vuser limit as 2000 with 4GB ram and 2 core CPU agent machines. nGrinder agents are very stable with that number. We expect that 8000 vusers can be run if you have 8GB and 4 core CPU machines.&nbsp;</span></p>
<p style="text-align: justify;"><span style="color: #131212; font-family: Calibri, 'Times New Roman', Arial, Tahoma;"><span style="font-size: 15px; line-height: 20px;">If you don't know how much vusers you should use, there is a good vuser calculator in <a href="http://www.webperformance.com/library/tutorials/CalculateNumberOfLoadtestUsers/" target="_blank">our competitor's site</a>.&nbsp;</span><span style="font-size: 15px; line-height: 20px;">&nbsp; &nbsp;</span></span><span style="color: #131212; font-family: Calibri, 'Times New Roman', Arial, Tahoma; font-size: 15px; line-height: 20px;">It's really good products. :-)&nbsp;</span></p>]]></description>
                        <pubDate>Mon, 21 Jan 2013 05:59:24 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>user-guide</category>
                                </item>
        										        <item>
            <title>Process and Thread</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=process-and-thread</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=process-and-thread</guid>
                                    <description><![CDATA[<p>nGrinder uses processes and threads to simulate multiple users. For example, if you set up a test like following. Only one agent will be activated and 1 process will be invoked then this process will include 2 running threads. Each thread acts like a user. So 2 virtual users are running. If you increase agent count to 2, you will have 4 vusers in total.</p>
<p><a href="/files/attach/images/379199/932/555/image_2.png"><img style="background-image: none; padding-left: 0px; padding-right: 0px; display: block; padding-top: 0px; border: 0px; margin-left: auto; margin-right: auto;" title="image" border="0" alt="image" src="http://www.cubrid.org/files/attach/images/379199/932/555/image_thumb.png" width="477" height="135" editor_component="image_link" /></a></p>
<p>If you put the virtual user count in Vuser per agent field, nGrinder calculates the appropriate processes and threads. For example if you put 100 in the field, it will turn to 99. It’s because 3 processes and 33 threads will be used. You can configure process-thread count calculation logic by <a href="/wiki_ngrinder/entry/advanced-ngrinder-controller-configuration">configuring process_and_thread_policy.js</a>.&nbsp;<strong></strong></p>
<p>Processes more than 10 easily cause thrashing by memory swapping in the agent if your agent has less than 4GB memory. If there are many number of processes, they would exceed the agent machine’s physical memory size. Please set it less than 10. If you increase the thread number more than 200, it might cause problems either. The threads belong to one process share the same heap. It’s&nbsp;obvious&nbsp;to see the OOM error if a lot of threads occupies the process memory.</p>
<p>Therefore, you have to set process and thread count with care. If you have no idea on this, Just let the nGrinder calculate automatically.</p>

<p>NEWS!! we have some experiment how many vusers a agent can handle. 4000 vusers can be supported by a single 4GB memory agent if each test doesn't use takes much memories. If you like to increase the&nbsp;max vuser limitation, please configure agent.max.vuser in system.conf.</p>]]></description>
                        <pubDate>Wed, 16 Jan 2013 04:36:36 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>user-guide</category>
                                </item>
        										        <item>
            <title>Recorder-Recording Guide For Non Window user</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=recorder-recording-guide-for-non-window-user</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=recorder-recording-guide-for-non-window-user</guid>
                                    <description><![CDATA[<p>nGrinder Recorder only provides its full&nbsp;functionality&nbsp;in Windows due to serious missing features of the internal components. So Linux and Mac users may not enjoy full nGrinder functionality and need some additional configurations to make nGrinder Recorder do its job.</p>  <p>In Mac and Linux, the embedded browsers(JxBrowser) are also initialized. However we found there are some&nbsp;frequent crash during navagation and HTTPS messages are not recorded because there are no way to work around the private&nbsp;certificate&nbsp;issue. Therefore, we highly recommend you to use the separated browsers(Firefox or Safari) connecting to the proxy instead of using the embedded browser. Following shows how to do it.</p>  <p><a href="/files/attach/images/379199/565/637/image_2.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="/files/attach/images/379199/565/637/image_thumb.png" width="636" height="480" editor_component="image_link" /></a></p>  <p>As you can see below, the proxy is initiated using 10288 port.</p>  <p><a href="/files/attach/images/379199/565/637/image_4.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="/files/attach/images/379199/565/637/image_thumb_1.png" width="636" height="119" editor_component="image_link" /></a></p>  <p>If you like to record HTTP/HTTPS with Firefox, Open Firefox and go to Preferences and Select Advanced ==&gt; Settings in the popup window.</p>  <p><a href="/files/attach/images/379199/565/637/image_10.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="/files/attach/images/379199/565/637/image_thumb_4.png" width="128" height="151" editor_component="image_link" /></a>&nbsp; <a href="/files/attach/images/379199/565/637/image_8.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="/files/attach/images/379199/565/637/image_thumb_3.png" width="503" height="152" editor_component="image_link" /></a></p>  <p>Set up the both HTTP and HTTPS proxies for both to the given port.</p>  <p><a href="/files/attach/images/379199/565/637/image_12.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="/files/attach/images/379199/565/637/image_thumb_5.png" width="638" height="378" editor_component="image_link" /></a></p>  <p>Then, navigate the web using the separate browser. Don’t forget that you should click Start Record button before navigation.</p>  <p><a href="/files/attach/images/379199/565/637/image_14.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="/files/attach/images/379199/565/637/image_thumb_6.png" width="637" height="318" editor_component="image_link" /></a></p>  <p>Then click "Stop Recording" in nGrinder Recorder. Then you can see the recorded script.</p>  <p><a href="/files/attach/images/379199/565/637/image_16.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="/files/attach/images/379199/565/637/image_thumb_7.png" width="636" height="477" editor_component="image_link" /></a></p>

<p>Please don’t forget to disable proxy settings when stopping recording. Otherwise you can not browse the Internet afterwards.</p>  <p>When you navigate HTTPS sites, you may see the following alert page. It’s because HTTPS messages are encrypted by the self-signed certificate which nGrinder issued. To ignore this, you should click “I Understand the Risks” and add the exception.</p>  <p><a href="/files/attach/images/379199/565/637/image_18.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="/files/attach/images/379199/565/637/image_thumb_8.png" width="640" height="478" editor_component="image_link" /></a></p>]]></description>
                        <pubDate>Tue, 16 Apr 2013 18:46:52 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>recorder</category>
                                </item>
        										        <item>
            <title>Recorder Architecture</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=recorder-architecture</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=recorder-architecture</guid>
                                    <description><![CDATA[<p><img alt="recorder-architecture.png" src="/files/attach/images/379199/770/633/recorder-architecture.png" width="754" height="566" editor_component="image_link" />     <br /></p>  <p>nGrinder Recorder initiates JXBrowser and TCPProxy when the user starts nGrinder Recorder. A proxy is initiated with the default proxy port 10288. If the port is occupied by the other programs, it automatically selects the available port. Then this proxy port is assigned to JXBrowser instances(embeddable native web browser component). All requests from JXBrowsers go through the attached proxy port. The proxy monitors the messages sent to the proxy port and put the connection target information into ConnectionFilter component so that a user can select which messages should be recorded depending on the target web server. When a user starts recording, all messages which is not filtered are saved in HTTPRecording component. TCPProxy looks message contents both in requests and responses, and saves&nbsp;meaningful&nbsp;message information (like URL, HTTP headers and form data) into HTTPRecording component. Recording includes messages not only HTTP but also HTTPS as well.</p>  <p>However when you browse HTTPS web site, you may see alert message box. Basically HTTPS messages are &nbsp;protected by the certificate from the target web server. The proxy in the middle of messaging can not intercept HTTPS messages to see the message content in the normal way. TCPProxy which nGrinder Recorder is based on solves this by using the private certificate between the browser and TCPProxy. HTTPS messages between a browser and DelegateSSLEngine(in TCPproxy) is encoded by the private certificate issued by TCPProxy. Therefore DelegateSSLEngine can see the message contents. Then, it sends and&nbsp;receives&nbsp;the message to/from the target web server by encoding/decoding the requests/responses with the web server issued certificate. It causes the browser side warning message. See more details about this in <a href="/wiki_ngrinder/entry/recorder-limitation" target="_blank">Recoder Limitation</a>. </p>  <p>When a user stop the recording, the recorded messages are analyzed to generate more generic script. In this step, the relations between requests/responses are linked as much as possible. Finally these are passed to HTTPRecordingResultProcessorWithFreeMarker component. Finally, HTTPRecordingResultProcessorWithFreeMarker processes them with the script template written in FreeMarker formats to generate Jython or Groovy scripts.</p>]]></description>
                        <pubDate>Fri, 12 Apr 2013 00:27:43 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>recorder</category>
                        <category>architecture</category>
                                </item>
        										        <item>
            <title>Recorder</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=recorder</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=recorder</guid>
                                    <description><![CDATA[<p><b>nGrinder Recorder</b> is a <b>helper application</b> to create the Grinder script based on the user browser interaction. It records HTTP/HTTPS messages sent from/to the browser and creates the <a href="http://grinder.sourceforge.net/" target="_blank">The Grinder</a> compatible script. It’s based on <a href="http://grinder.sourceforge.net/g3/tcpproxy.html" target="_blank">TCPProxy</a> which The Grinder project provides. We found out that TCPProxy is very powerful but little bit difficult to run because it’s command line based. &nbsp;Moreover, the generated script was more complex than we expected. Therefore we started to build new The Grinder script recording tool named "nGrinder Recorder". It's implemented with the built-in web browser and java webstart technology. You can just record the script by just few clicks.&nbsp;</p>

<blockquote class="q4"><p>We<strong>&nbsp;don’t put much energy on this product</strong>. We believe the manually written script is always better than generated script. Therefore we didn't try to make this as a complete and bug free sw.</p> </blockquote>  <p style="text-align: center"><a href="/files/attach/images/379199/994/631/image_2.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/994/631/image_thumb.png" width="735" height="418" editor_component="image_link" /></a></p>  <p>&nbsp;</p>  <ul>   <li>[Recorder-Architecture] </li>    <li>[Recorder-Limitation] </li>
<li>[Recorder-ScreenShot]</li>    <li>[Recorder-Installation] </li>    <li>[Recorder-Quick-Start] </li>    <li>[Recorder-Recording-Guide] </li>    <li>[Recorder-Recording-Guide-For-Non-Window-User] </li>    <li>[Recorder-Generated Test Script Structure] </li> </ul>]]></description>
                        <pubDate>Tue, 09 Apr 2013 22:46:01 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>recorder</category>
                                </item>
        										        <item>
            <title>Recorder Installation</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=recorder-installation</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=recorder-installation</guid>
                                    <description><![CDATA[<h3>Prerequsite</h3>  <ul>   <li>nGrinder Recorder can run in Windows / OS X / Linux because it is implemented in Java. At least you requires followings to run nGrinder Recorder.      <ul>       <li>Java Runtime (over 1.6) </li>        <li>GUI enabled env (not supporting headless OS) </li>     </ul>   </li>    <li>However, Some major features of nGrinder Recorder can work in Windows due to some bugs in internal components.      <br />We’ll continue to work to make some disabled features work in the other OS.&nbsp;</li>
<ul>
<li>Check out [Recorder-Limitation] first.<span style="line-height: 25px;">&nbsp;</span></li>
</ul>
</ul>  <h3>Installation</h3>  <ul>   <li>Currently nGrinder Recorder is provided in the form of java webstart.&nbsp; You can install it just by double-clicking thd downloaded jnlp file from URL in the browser.      <ul>       <li><a href="http://ngrinder-demo.nhnopensource.org/jnlp/recorder/ngrinder-recorder.jnlp" target="_self">http://ngrinder-demo.nhnopensource.org/jnlp/recorder/ngrinder-recorder.jnlp</a></li>     </ul>   </li>    <li>Then the following warning message will show up.&nbsp; <br /><a href="/files/attach/images/379199/812/633/image_6.png"><img width="341" height="231" title="image" style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" alt="image" src="/files/attach/images/379199/812/633/image_thumb_2.png" border="0" editor_component="image_link" /></a> </li>    <li>Check “Always trust content from the publisher” and click Run. nGrinder Recorder requires full permission in your PC because the <a href="http://www.teamdev.com/downloads/jxbrowser/docs/JxBrowser-PGuide.html#jws" target="_blank">underlying JXBrowser requires it</a>. </li>    <li>Then..&nbsp; If your PC’s firewall monitors the port&nbsp;opening, the security alert&nbsp;message may come up. You should allow nGrinder Recorder to open the port appropriately.      <br /><a href="/files/attach/images/379199/812/633/image_8.png"><img width="340" height="244" title="image" style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" alt="image" src="/files/attach/images/379199/812/633/image_thumb_3.png" border="0" editor_component="image_link" /></a> </li>    <li>If you can see the following window, You’re ready to use nGrinder Recorder.&nbsp; <br /><a href="/files/attach/images/379199/812/633/image_10.png"><img width="573" height="380" title="image" style="border-width: 0px; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" alt="image" src="/files/attach/images/379199/812/633/image_thumb_4.png" border="0" editor_component="image_link" /></a> </li>    <li>Copy the downloaded jnlp file into somewhere in your desktop to run nGrinder next time. </li> </ul>  <h3>Configuration</h3>  <ul>   <li>Just like nGrinder Controller and Agent, nGrinder Recorder uses the configuration in the ${user.home}/.ngrinder_recorder folder.&nbsp; You can open recorder.conf file to configure followings. However it's not necessary.<ul>
</ul>
<table width="666" bordercolor="#000000" style="border-collapse: collapse;" border="1" cellspacing="0" cellpadding="4"><tbody>         <tr style="color: white; background-color: black;">           <td width="250" valign="top">key</td>            <td width="440" valign="top">value</td>         </tr>          <tr>           <td width="250" valign="top">recorder.additional.headers</td>            <td width="440" valign="top">The recorder only records the limited set of headers. If you want to record more headers, you can specify this value with header names separated by comma. Check the detailed info <a href="http://grinder.sourceforge.net/g3/tcpproxy.html#additional-headers" target="_blank">here</a>.</td>         </tr>          <tr>           <td width="250" valign="top">keystore.password </td>            <td width="440" valign="top">A user can provide the same certificate which is used already for the webserver HTTPS communication.&nbsp; A user should locates the keystore in the ${user.home}/.ngrinder_recorder/keystore file. Then specify the password of this keystore here.</td>         </tr>          <tr>           <td width="250" valign="top">keystore.type </td>            <td width="440" valign="top">A user can specify the keystore type. The default value is jks.</td>         </tr>       </tbody>             </table>   </li> </ul>
Then go to [Recorder Quick Start]&nbsp;for your first recording.]]></description>
                        <pubDate>Fri, 12 Apr 2013 00:34:55 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>recorder</category>
                                </item>
        										        <item>
            <title>Groovy Script Structure</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=groovy-script-structure</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=groovy-script-structure</guid>
                                    <description><![CDATA[<p>Not like [Jython Script Structure], Groovy Script Structure is based on JUnit. It’s because we want to reuse existing JUnit experiences as much as possible. Several IDEs already well integrate JUnit and let a user to run the test case directly. If you created Goorvy Maven Project in script creation dialog box in nGrinder, you can enjoy the this&nbsp;excellent&nbsp;approach in your current IDE. </p>  <p>For now, I’d like to explain the basic Groovy script&nbsp;structure. This is applied whether&nbsp;you choose Groovy Script or Groovy Maven Project.    <br />Following is a base template for groovy script.</p>  <pre class="brush: groovy;">import static net.grinder.script.Grinder.grinder
import static org.junit.Assert.*
import static org.hamcrest.Matchers.*
import net.grinder.plugin.http.HTTPRequest
import net.grinder.script.GTest
import net.grinder.script.Grinder
import net.grinder.scriptengine.groovy.junit.GrinderRunner
import net.grinder.scriptengine.groovy.junit.annotation.BeforeThread
import net.grinder.scriptengine.groovy.junit.annotation.BeforeProcess

import org.junit.BeforeClass
import org.junit.Test
import org.junit.runner.RunWith

import HTTPClient.HTTPResponse

/**
 * A simple example using the HTTP plugin that shows the retrieval of a
 * single page via HTTP.
 *
 * This script is auto generated by ngrinder.
 *
 * @author ${userName}
 */
@RunWith(GrinderRunner)
class Test1 {

    public static GTest test;
    public static HTTPRequest request;

    // This method is executed once per a process. 
    @BeforeProcess
    public static void beforeClass() {
        test = new GTest(1, "${name}");
        request = new HTTPRequest();
        test.record(request);
        grinder.logger.info("before process.");
    }

    // This method is executed once per a thread. 
    @BeforeThread
    public void beforeThread() {
        grinder.statistics.delayReports=true;
        grinder.logger.info("before thread.");
    }

    // This method is continuously executed until you stop the test 
    @Test
    public void test(){
        HTTPResponse result = request.GET("${url}");
        if (result.statusCode == 301 || result.statusCode == 302) {
            grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", result.statusCode);
        } else {
            assertThat(result.statusCode, is(200));
        }
    }
}</pre>

<p>The Groovy test case in nGrinder should be annotated with @RunWith(GroovyRunner). When you run this script in JUnit Runner of each IDE, this part makes GroovyRunner to control the JUnit behavior and mount the grinder context on JUnit. 
  <br />@Test annotated methods are subject to be executed repeatedly. As you can see above, you can assert the test result using JUnit assertion. If the assertion is failed, the last test bounded to this thread will be evaluated as a failure.</p>

<p>Instead of @BeforeClass @Before @AfterClass @After annotations which are used &nbsp;in the generic JUnit tests, Groovy test case in nGrinder uses its own annotation to control script behaviors.</p>

<table cellspacing="0" cellpadding="2" width="750" border="0"><tbody>
    <tr>
      <td valign="top" width="150">&nbsp;</td>

      <td valign="top" width="177">Description</td>

      <td valign="top" width="123">Applied to</td>

      <td valign="top" width="298">Usage</td>
    </tr>

    <tr>
      <td valign="top" width="150">@BeforeProcess</td>

      <td valign="top" width="177">Define behaviors which should be executed before the process is invoked</td>

      <td valign="top" width="123">static method</td>

      <td valign="top" width="298">Load resource files which are shared by threads 
        <br />Define GTest and instrument the test target using record method.</td>
    </tr>

    <tr>
      <td valign="top" width="150">@AfterProcess</td>

      <td valign="top" width="177">Define behaviors which should be executed after the process is terminated</td>

      <td valign="top" width="123">static method</td>

      <td valign="top" width="298">Close resource files.</td>
    </tr>

    <tr>
      <td valign="top" width="150">@BeforeThread</td>

      <td valign="top" width="177">Define behaviors which should be executed before the each thread is executed.</td>

      <td valign="top" width="123">member method</td>

      <td valign="top" width="298">Login the target system. 
        <br />Set up the thread bounded values. (For example, Cookie Handler)</td>
    </tr>

    <tr>
      <td valign="top" width="150">@AfterThread</td>

      <td valign="top" width="177">Define behaviors which should be exeucted after the each thread is exeucted</td>

      <td valign="top" width="123">member method</td>

      <td valign="top" width="298">Logout the target system</td>
    </tr>

    <tr>
      <td valign="top" width="150">@Before</td>

      <td valign="top" width="177">Define behaviors which should be executed before every @Test annotated method are executed. </td>

      <td valign="top" width="123">member method</td>

      <td valign="top" width="298">Common logic which is shared by the multiple @Test annotated methods. 
        <br />Variable set up</td>
    </tr>

    <tr>
      <td valign="top" width="150">@After</td>

      <td valign="top" width="177">Define behaviors which should be executed after every @Test annotated methods are executed. </td>

      <td valign="top" width="123">member method</td>

      <td valign="top" width="298">Not used much..</td>
    </tr>

    <tr>
      <td valign="top" width="150">@Test</td>

      <td valign="top" width="177">Define the test behavior. Excuted muliple times</td>

      <td valign="top" width="123">member method</td>

      <td valign="top" width="298">Test body</td>
    </tr>
  </tbody></table>

<p>The&nbsp;execution&nbsp;flow can be illustrated by following.</p>

<p><a href="/files/attach/images/379199/508/651/image_8.png"><img title="image" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="image" src="/files/attach/images/379199/508/651/image_thumb_3.png" width="746" height="366" editor_component="image_link" /></a></p>

<p>In the test case sample, Please look below part carefully.</p>

<pre class="brush: groovy;">    public static GTest test;
    public static HTTPRequest request;<br />
    // This method is executed once per a process. 
    @BeforeProcess
    public static void beforeProcess() {
        // Instead of Test in Jython, GTest is used here
        // It's because the identifier "Test" is alredy used by the @Test 
        // GTest is the replacement to avoid the naming confliction.
        test = new GTest(1, "test name");
        request = new HTTPRequest();
        test.record(request);
        grinder.logger.info("before process.");
    }</pre>

<p>In @BeforeProcess annotated method, it defines GTest instance and records the HTTPRequest instance to sense any calls on HTTPRequest instance and save it in the static member variable(request). 
  <br />It’s the first step of test statistic preparation. Any method calls on request variable will increase the TPS. If you want to record multiple HTTPRequest instances using multiple GTest named&nbsp;differently, You can just add GTest instance in another member variables and invoke record method on different HTTPRequest instance. &nbsp;</p>

<p>You can define the multiple test methods in a single test case class as well. Just add @Test annotation on those like the following.&nbsp; <br /></p>

<pre class="brush: groovy;">    @Test
    public void testGoogle(){
        HTTPResponse result = request.GET("http://www.google.com");
        if (result.statusCode == 301 || result.statusCode == 302) {
            grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", result.statusCode);
        } else {
            assertThat(result.statusCode, is(200));
        }
    }

    @Test
    public void testYahoo(){
        HTTPResponse result = request.GET("http://www.yahoo.com");
        if (result.statusCode == 301 || result.statusCode == 302) {
            grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", result.statusCode);
        } else {
            assertThat(result.statusCode, is(200));
        }
    }</pre>

<p>However, you should aware nGrinder GroovyRunner creates only one test case object per a thread not like that generic JUnit test cases which creates a separate test case object for each @Test annotated method. So if each @Test annotated methods share member variables, they can affect each other. It’s intended. In nGrinder test case, it’s very likely each @Test method relies on the previous @Test annotated method execution result. Therefore, if you save the previous test result in the member&nbsp;variable&nbsp;and refer it to decide to continue to next test method, you can easily implement the test dependency. </p>

<pre class="brush: groovy;">    private boolean googleResult;
    
    @Test
    public void testGoogle(){
        googleResult = false;
        HTTPResponse result = request.GET("http://www.google.com");
        if (result.statusCode == 301 || result.statusCode == 302) {
            grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", result.statusCode);
        } else {
            assertThat(result.statusCode, is(200));
        }
        googleResult = true;
    }

    @Test
    public void testYahoo(){
        if (!googleResult) {
            grinder.logger.warn("Just return. Because prev google test is failed.");
            return;
        }
        HTTPResponse result = request.GET("http://www.yahoo.com");
        if (result.statusCode == 301 || result.statusCode == 302) {
            grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", result.statusCode);
        } else {
            assertThat(result.statusCode, is(200));
        }
    }</pre>

<p>How can you use library and resources?&nbsp; If you don’t use [Groovy Maven Structure] yet, you can refer [Jython Script Structure] to how to include them in your script. It’s exactly same as Jython way.
However if you use Maven structure plus Groovy, you can enjoy the easier library dependency setting and run the JUnit test in your IDE. Interested in this?
Then continue to see the [Groovy Maven Structure] to know how to enable this for you.</p>]]></description>
                        <pubDate>Mon, 06 May 2013 06:29:47 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>script guide</category>
                        <category>groovy</category>
                                </item>
        										        <item>
            <title>Import Groovy Maven Project in IDE</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=import-groovy-maven-project-in-ide</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=import-groovy-maven-project-in-ide</guid>
                                    <description><![CDATA[<blockquote class="q4"><p>Groovy Maven Project is structured for users to easily import the project into IDE. If you already have an IDE which supports Groovy and Maven, you can easily import it. However if you don’t have it yet, please follow the instruction in [Install Groovy IDE] first.&nbsp;</p>

</blockquote><p>If you have installed the Eclipse based Groovy IDE and created Groovy Maven Project in nGrinder subversion, you can import the Groovy Maven Project using the subversion client in Eclipse.</p>  <p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="/files/attach/images/379199/570/652/image_2.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/570/652/image_thumb.png" width="744" height="216" editor_component="image_link" /></a></p>  <p>Notice that there is the subversion URL field in the script management page in nGrinder. The above screenshot shows the our test instance. In this instance, the created Groovy Maven project can be accessed through http://ngrinder-staging.nhncorp.com:8080/svn/admin/project URL according to the above page .    <br />OK. Let’s import the project.</p>  <ol>   <li>Open your Eclipse and Choose File ==&gt; Others ==&gt; Maven ==&gt; Check out Maven Projects from SCM      <br /><a href="/files/attach/images/379199/570/652/image_4.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/570/652/image_thumb_1.png" width="477" height="265" editor_component="image_link" /></a>       <br /></li>    <li>Select svn in the SVN URL and type the SVN URL provided in nGrinder. Then click Finish.      <br /><a href="/files/attach/images/379199/570/652/image_6.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/570/652/image_thumb_2.png" width="527" height="342" editor_component="image_link" /></a> </li>    <li>Then the project will be imported.      <br /><a href="/files/attach/images/379199/570/652/image_8.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/570/652/image_thumb_3.png" width="240" height="147" editor_component="image_link" /></a> </li>    <li>Enable Groovy on this project.      <br /><a href="/files/attach/images/379199/570/652/image_10.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/570/652/image_thumb_4.png" width="576" height="169" editor_component="image_link" /></a> </li>    <li>Remove groovy libraries from classpath by selecting "Groovy ==&gt; Remove Groovy libraries from classpath".      <br />It's because there is a conflict between groovy libraries provided by Maven and Eclipse.       <br /><a href="/files/attach/images/379199/570/652/image_18.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/570/652/image_thumb_8.png" width="654" height="66" editor_component="image_link" /></a> </li>    <li>Select the Groovy test case and Select Run As ==&gt; JUnit Test.<br /><a href="/files/attach/images/379199/570/652/image_12.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/570/652/image_thumb_5.png" width="576" height="193" editor_component="image_link" /></a> </li>    <li>Then you might see the following error. It’s because the specialized nGrinder JUnit Runner(named GrinderRunner) needs a special JVM argument for instrumentation<br /><a href="/files/attach/images/379199/570/652/image_14.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/570/652/image_thumb_6.png" width="379" height="316" editor_component="image_link" /></a> </li>    <li>Check the error message and add the JVM argument following the instruction. Select Run As ==&gt; Run Configurations ==&gt; Select Test1 ==&gt; Select Arguments panel.      <br /><a href="/files/attach/images/379199/570/652/image_16.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/570/652/image_thumb_7.png" width="795" height="407" editor_component="image_link" /></a>       <br />Please be aware that the argument varies depending on the user account. So provide the exact argument which is shown in the JUnit error message. This setting should be provided for every JUnit test running set.&nbsp;If you like to make it as a default vm option for every test run. You can set it up in the global configuration. Please check [Install Groovy IDE] for details. </li>    <li>Then run as JUnit test again.      <br /><a href="/files/attach/images/379199/570/652/image_20.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/570/652/image_thumb_9.png" width="440" height="339" editor_component="image_link" /></a> </li>    <li>In my case, the access to please_modify_this.com causes the error. Ater changing this to http://www.google.com . It shows the green bar now.      <br /><a href="/files/attach/images/379199/570/652/image_22.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/570/652/image_thumb_10.png" width="536" height="145" editor_component="image_link" /></a> </li>    <li>You can add the break point in the test case. Then select Debug As ==&gt; JUnit Test.      <br /><a href="/files/attach/images/379199/570/652/image_24.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/570/652/image_thumb_11.png" width="445" height="118" editor_component="image_link" /></a> </li>    <li>Then you can debug the test case using the generic Eclipse debugging feature.      <br /><a href="/files/attach/images/379199/570/652/image_28.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/570/652/image_thumb_13.png" width="684" height="285" editor_component="image_link" /></a> </li>    <li>When you think the test case writing is almost completed, you may want to see the result in the repeated run situation. You can provide the @Repeat annotation on the test case class for this need. Then run as JUnit test again.      <br /><a href="/files/attach/images/379199/570/652/image_32.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/570/652/image_thumb_15.png" width="437" height="129" editor_component="image_link" /></a> </li>    <li>Then you can see that test case is executed multiple times you specified. Please note that it’s 100 repetition by single thread. (not multi thread or multi process)<br /><a href="/files/attach/images/379199/570/652/image_34.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/570/652/image_thumb_16.png" width="297" height="193" editor_component="image_link" /></a> </li>    <li>If you think the test case is ready, commit it into subversion selecting Team ==&gt; Commit. Finally run this test in nGrinder.</li> </ol>]]></description>
                        <pubDate>Tue, 07 May 2013 06:30:25 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>groovy</category>
                        <category>script guide</category>
                                </item>
        										        <item>
            <title>Install Groovy IDE</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=install-groovy-ide</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=install-groovy-ide</guid>
                                    <description><![CDATA[<blockquote class="q4"><p>When you create Groovy Maven project, you can use IDE to write and debug test cases. Groovy maven project use maven’s pom.xml to structure src folders and specify dependencies. Therefore if your IDE supports Groovy and Maven project, you can use it. For who don’t have IDE yet. This explains how to install Eclipse based Groovy Maven IDE.</p>

</blockquote><ol>
<li>Download and unzip the lastest “Eclipse IDE for Java Developers” which fits to your OS.</li>    <ul>     <li><a href="http://www.eclipse.org/downloads/packages/eclipse-ide-java-developers/junosr2">http://www.eclipse.org/downloads/packages/eclipse-ide-java-developers/junosr2</a></li>      <li>The above version already includes Maven Eclipse plugin but Groovy and Subversion. You need to&nbsp;separately&nbsp;install&nbsp;them.&nbsp;</li>
<li>Firstly, run the downloaded eclipse.</li>   </ul>    <li>Install Groovy</li>    <ol>     <li>Go to “Help” ==&gt; “Eclipse Market Place”</li>      <li>Type "groovy" in the search field. Then click the install button in Groovy Eclipse for Juno. (Aha! It's my name Juno :-) Kidding)<br /><a href="/files/attach/images/379199/127/651/image_10.png"><img style="margin: 0px; border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="/files/attach/images/379199/127/651/image_thumb_4.png" width="525" height="131" editor_component="image_link" /></a></li>      <li>Then install all.       <br /><a href="/files/attach/images/379199/127/651/image_12.png"><img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="/files/attach/images/379199/127/651/image_thumb_5.png" width="527" height="66" editor_component="image_link" /></a></li>      <li>Then click “Next”s and “Finish”s and restart Eclipse until the installation is completed.</li> <!--EndFragment--></ol>    <li>Install Subversive&nbsp;</li>    <ol>     <li>Go to “Help” ==&gt; “Eclipse Market Place”</li>      <li>Type "subversive" in the search field. Then click install below.       <br /><a href="/files/attach/images/379199/127/651/image_6.png"><img style="margin: 0px; border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="/files/attach/images/379199/127/651/image_thumb_2.png" width="525" height="131" editor_component="image_link" /></a></li>      <li>Select Subversive SVN JDK Ignore Extensions and Team Provider. Then select “Next” buttons until the installation is started.        <br /><a href="/files/attach/images/379199/127/651/image_8.png"><img style="margin: 0px; border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="/files/attach/images/379199/127/651/image_thumb_3.png" width="624" height="139" editor_component="image_link" /></a></li>      <li>Restart Eclipse and and select SVN Kit 1.7.8. Subversion repo provided by nGrinder is compatible with above SVN Kit 1.7.8.       <br />Then click “Next”s and “Finish”s and restart Eclipse until the installation is completed.        <br /><a href="/files/attach/images/379199/127/651/image_4.png"><img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="/files/attach/images/379199/127/651/image_thumb_1.png" width="543" height="88" editor_component="image_link" /></a></li>      <li>Now it’s time to connect Maven and Subversion by installing m2e subversive connector. Click File menu ==&gt; New ==&gt; Checkout Maven Projects from SCM.       <br /><a href="/files/attach/images/379199/127/651/image_14.png"><img style="margin: 0px; border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="/files/attach/images/379199/127/651/image_thumb_6.png" width="470" height="220" editor_component="image_link" /></a></li>      <li>Then click m2e Marketplace in the next dialog.       <br /><a href="/files/attach/images/379199/127/651/image_16.png"><img style="margin: 0px; border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="/files/attach/images/379199/127/651/image_thumb_7.png" width="530" height="374" editor_component="image_link" /></a></li>      <li>Check the m2e subversive and click Finish button.       <br /><a href="/files/attach/images/379199/127/651/image_18.png"><img style="margin: 0px; border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline; background-image: none;" title="image" border="0" alt="image" src="/files/attach/images/379199/127/651/image_thumb_8.png" width="533" height="83" editor_component="image_link" /></a>        <br />Then click “Next”s and “Finish”s and restart Eclipse until the installation is completed.</li>
<li>Groovy JUnit Running requires the special JVM argument for every test run. It can be very annoying. If you plan to use this Eclipse instance only for nGrinder Test Case, it might be a good choice to provide the default JVM options for every JVM execution in this Eclipse.&nbsp;<br />Go To Window ==&gt; Preference ==&gt; Java ==&gt; Installed JRE. Then click Edit on the default JRE.<br /><img src="http://www.cubrid.org/files/attach/images/379199/127/651/pic3.PNG" alt="pic3.PNG" width="567" height="399" editor_component="image_link" />
<br />Finally you can provide the default VM arguments in the above field. The VM arguments you should provide here varies depending on the user configuration. Please check [Import Groovy Maven Project in IDE] to know which VM arguments you should provide.</li>   </ol> </ol>  <p>Now your IDE is ready to run and debug your nGrinder groovy test cases. Go to &nbsp;[Import Groovy Maven Project in IDE]&nbsp;</p>]]></description>
                        <pubDate>Mon, 06 May 2013 00:47:00 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>groovy</category>
                        <category>user-guide</category>
                                </item>
        										        <item>
            <title>Groovy Maven Structure</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=groovy-maven-structure</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=groovy-maven-structure</guid>
                                    <description><![CDATA[<blockquote class="q4"><p>When you run the groovy maven project, it might take time to run the test at the first time. It's because maven project requires to download the related libraries from maven repo. Please be patient. :-).</p>

</blockquote><p>If you choose to use Groovy Script when you create a script, it works&nbsp;similar&nbsp;to Jython script except the JUnit styled test cases. However if you want not only to use Groovy but also to execute JUnit runner in your IDE or easily configure dependencies, you can choose to make Groovy Maven Project first.</p>  <p><a href="/files/attach/images/379199/955/651/image_2.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/955/651/image_thumb.png" width="351" height="248" editor_component="image_link" /></a></p>  <p>If you create Groovy Maven Project, you will have the following directories&nbsp;containing&nbsp;three files under the&nbsp;specified&nbsp;project folder.</p>  <p><a href="/files/attach/images/379199/955/651/image_4.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/955/651/image_thumb_1.png" width="269" height="87" editor_component="image_link" /></a></p>  <table cellspacing="0" cellpadding="4" width="595" border="0"><tbody>     <tr>       <td valign="top" width="250">Location</td>        <td valign="top" width="343">Description</td>     </tr>      <tr>       <td valign="top" width="250">${name}/pom.xml</td>        <td valign="top" width="343">Maven project file.          <br />You can add the library dependencies in this file.</td>     </tr>      <tr>       <td valign="top" width="250">${name}/src/main/java/Test1.groovy</td>        <td valign="top" width="343">Default groovy script file</td>     </tr>      <tr>       <td valign="top" width="250">${name}/src/main/java/resources1.txt</td>        <td valign="top" width="343">Default resource file</td>     </tr>      <tr>       <td valign="top" width="250">${name}/lib</td>        <td valign="top" width="343">Not automatically generated. but this folder can be used to distribute private libraries if available.</td>     </tr>   </tbody></table>  <p>You can import this project into you IDE using SVN checkout. You may need to check the below links.</p>  <ul>   <li>[Install Groovy IDE] </li>    <li>[Import Groovy Maven Project in IDE] </li> </ul>  <p>In pom.xml, You can specify the additional library dependencies.</p>  <pre class="brush: xml;">&lt;project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"&gt;
    &lt;modelVersion&gt;4.0.0&lt;/modelVersion&gt;
    &lt;groupId&gt;ngrinder&lt;/groupId&gt;
    &lt;artifactId&gt;${name}&lt;/artifactId&gt;
    &lt;version&gt;0.0.1&lt;/version&gt;

    &lt;properties&gt;
        &lt;jdk-version&gt;1.6&lt;/jdk-version&gt;
        &lt;source-encoding&gt;UTF-8&lt;/source-encoding&gt;
    &lt;/properties&gt;

    &lt;repositories&gt;
        &lt;repository&gt;
            &lt;id&gt;nhnopensource.maver.repo&lt;/id&gt;
            &lt;url&gt;https://github.com/nhnopensource/nhnopensource.maven.repo/raw/master/releases&lt;/url&gt;
        &lt;/repository&gt;
    &lt;/repositories&gt;

    &lt;dependencies&gt;
        &lt;!-- Following dependency is mandatory --&gt;
        &lt;dependency&gt;
            &lt;groupId&gt;org.ngrinder&lt;/groupId&gt;
            &lt;artifactId&gt;ngrinder-groovy&lt;/artifactId&gt;
            &lt;version&gt;3.2&lt;/version&gt;
            &lt;scope&gt;provided&lt;/scope&gt;
        &lt;/dependency&gt;

        &lt;!-- Add the dependencies --&gt;
        &lt;!--  &lt;dependency&gt;
            &lt;groupId&gt;commons-io&lt;/groupId&gt;
            &lt;artifactId&gt;commons-io&lt;/artifactId&gt;
            &lt;version&gt;2.0.1&lt;/version&gt;
        &lt;/dependency&gt;
         --&gt;
        &lt;!-- Put your private library like this --&gt;
        &lt;!--  
        &lt;dependency&gt;
            &lt;groupId&gt;your_lib&lt;/groupId&gt;
            &lt;artifactId&gt;your_lib&lt;/artifactId&gt;
            &lt;version&gt;your_lib_version&lt;/version&gt;
            &lt;scope&gt;system&lt;/scope&gt;
            &lt;systemPath&gt;${project.basedir}/lib/hello.jar&lt;/systemPath&gt;
        &lt;/dependency&gt;
        --&gt;
    &lt;/dependencies&gt;

    &lt;build&gt;
        &lt;plugins&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
                &lt;artifactId&gt;maven-compiler-plugin&lt;/artifactId&gt;
                &lt;configuration&gt;
                    &lt;source&gt;${jdk-verion}&lt;/source&gt;
                    &lt;target&gt;${jdk-version}&lt;/target&gt;
                    &lt;encoding&gt;${source-encoding}&lt;/encoding&gt;
                &lt;/configuration&gt;
            &lt;/plugin&gt;
            &lt;plugin&gt;
                &lt;groupId&gt;org.apache.maven.plugins&lt;/groupId&gt;
                &lt;artifactId&gt;maven-eclipse-plugin&lt;/artifactId&gt;
                &lt;version&gt;2.9&lt;/version&gt;
                &lt;configuration&gt;
                    &lt;additionalProjectnatures&gt;
                        &lt;projectnature&gt;
                            org.eclipse.jdt.groovy.core.groovyNature
                        &lt;/projectnature&gt;
                        &lt;projectnature&gt;
                            org.eclipse.m2e.core.maven2Nature
                        &lt;/projectnature&gt;
                    &lt;/additionalProjectnatures&gt;
                &lt;/configuration&gt;
            &lt;/plugin&gt;
        &lt;/plugins&gt;
    &lt;/build&gt;
&lt;/project&gt;</pre>

<p>If you like to add the private libraries which do not exist in the public maven repository, you can put them in the lib folder directly and specify the systemPath option like the above sample. lib folder will be automatically detected and copied into agents as well when the controller prepares the script distribution. 
  <br />When a script is selected in the performance test configuration page, the controller automatically detects whether the script is under the folder ${name}/src/main/java and there is pom.xml in the base folder. If the controller detects it, the controller will copy the files in the ${name}/src/main/resources and ${name}/src/main/java folder recursively into controller’s distribution preparation folder before distributing them to agents. The below figure illustrates how each folder in svn are copied to the distribution preparation folder.</p>
<blockquote class="q4">
<pre>- from svn foler + pom.xml
                 + src/main/java/Test1.groovy
                                /package_names/the_other_groovyscripts
                 + src/main/resources/resources1.txt
                                     /subfolder_names/the_other_resources
                 + lib (private libraris)


- to dist folder + Test1.groovy 
                 + resources1.txt 
                 + package_names/the_other_groovy_scripts 
                 + subfolder_names/the_other_resources 
                 + lib (copied from maven dependencies and files in lib folder existing subversion)</pre>
</blockquote>
<p>In generic Jython script and Groovy script, the resources are loaded using command "open(“./resources/resource1.txt”)" or "new File("./resources/resource1.txt"). However this won’t work in Groovy Maven project. We had to replace this path based resource discovery into the classpath based resource discovery to make Groovy JUnit test workable in IDE as well,&nbsp;<br />All resources in ${project_name}/src/main/resources/.. are copied into the same folder where the test script is copied but keeping the sub directory hierachy. You can load the resources using code below.</p>

<pre class="brush: groovy;">import org.codehaus.groovy.reflection.ReflectionUtils;
....


class YourTest {
    String text;

    @BeforeThread
    public void beforeThread() {
       // In groovy, InputStream contains text field.
       text = loadResourceFromClassPath("/resource1.txt").text;
    }

    @Test
    public void doTest() {
       ....
    }

    // This is groovy way to load resource from classpath
    public loadResourceFromClassPath(String resourcePath) {
        return ReflectionUtils.getCallingClass(0).getResourceAsStream(resourcePath);
    }
}</pre>]]></description>
                        <pubDate>Mon, 06 May 2013 18:49:19 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>groovy</category>
                        <category>script guide</category>
                                </item>
        										        <item>
            <title>Groovy Script</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=groovy-script</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=groovy-script</guid>
                                    <description><![CDATA[<p>nGrinder 3.2 supports Groovy as a another scripting language. It’s not a just replacement of Jython but also new test script development model. When you decide to write scripts with groovy in maven structure, you can reuse the exiting full development experiences from JUnit and Eclipse development&nbsp;environments.</p>  <ul>   <li>[Groovy Script Structure]</li>    <li>[Groovy Maven Structure]</li>    <li>[Install Groovy IDE]</li> <!--EndFragment-->    <li>[Import Groovy Maven Project in IDE]</li>
</ul>Groovy is not only&nbsp;convenient&nbsp;to write but also efficient to execute. Our benchmark result shows that the Groovy script which does same job as Jython script can have 2 times more virtual user count(especially thread count) per agent.<ul> </ul>]]></description>
                        <pubDate>Sun, 05 May 2013 20:26:38 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>groovy</category>
                        <category>script guide</category>
                                </item>
        										        <item>
            <title>Recorder Quick Start</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=recorder-quick-start</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=recorder-quick-start</guid>
                                    <description><![CDATA[<p>nGrinder Recorder contains <a href="http://grinder.sourceforge.net/g3/tcpproxy.html" target="_blank">TCPProxy</a>&nbsp;internally which the Grinder has. In addition, nGrinder Recorder contains the embedded browser. A user can record the HTTP/HTTPS messages on the embedded browser. When a user run nGrinder Recorder, the following initial instruction page is shown. This page describes which port is used for the proxy and how to connect the external browser to the given proxy. In the following screen, it tells us the proxy is initiated in 10288 port.</p>  <p><a href="/files/attach/images/379199/437/636/image_2.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/437/636/image_thumb.png" width="599" height="397" editor_component="image_link" /></a></p>  <p>You can start recording by clicking Start Recording button on the right panel. Then, navigate the site you want to visit in the browser panel.</p>  <p><a href="/files/attach/images/379199/437/636/image_4.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/437/636/image_thumb_1.png" width="591" height="392" editor_component="image_link" /></a></p>  <p>On the right panel, www.google.com / www.google.co.kr are shown, These are hosts to which the browser connected. Basically connecting to www.google.com is forwarded to www.google.co.kr&nbsp; in Korea . So it shows two connections. Just Ignore www.google.com by unchecking www.google.com host now. </p>  <p><a href="/files/attach/images/379199/437/636/image_6.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/437/636/image_thumb_2.png" width="206" height="113" editor_component="image_link" /></a></p>  <p>From now on, the messages sent to www.google.com will not be recorded. Then type the text you want to search in the browser.</p>  <p><a href="/files/attach/images/379199/437/636/image_8.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/437/636/image_thumb_3.png" width="446" height="113" editor_component="image_link" /></a></p>  <p>Google will automatically switches the main page into the search page due to its instant search feature.</p>  <p><a href="/files/attach/images/379199/437/636/image_12.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/437/636/image_thumb_5.png" width="210" height="177" editor_component="image_link" /></a></p>  <p>While doing this, you may notice that the count of recorder messages to www.google.co.kr is increased and new hosts ssl.gstatic.com and t1.gstatic.com show up. These two hosts may have some static resources like javascript, images. Just uncheck these hosts.</p>  <p><a href="/files/attach/images/379199/437/636/image_14.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/437/636/image_thumb_6.png" width="219" height="157" editor_component="image_link" /></a></p>  <p>Then click Stop Recording..</p>  <p><a href="/files/attach/images/379199/437/636/image_16.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/437/636/image_thumb_7.png" width="487" height="323" editor_component="image_link" /></a></p>  <p>Then you can see the generated script only contains the connection to www.google.co.kr.</p>  <p><a href="/files/attach/images/379199/437/636/image_20.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/437/636/image_thumb_9.png" width="492" height="369" editor_component="image_link" /></a></p>  <p>There in the main __call__ function which nGrinder threads will run eventually. It calls three different pages. (page1 / page2 / page3). All HTTP calls are organized by page methods which are generated per the user click events on the web page. There are too much calls in this recording more than 600 lines. We can shorten these by ignoring some static resources retrieved from www.google.co.kr. Uncheck followings in the right panel.</p>  <p><a href="/files/attach/images/379199/437/636/image_22.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; margin: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/437/636/image_thumb_10.png" width="200" height="126" editor_component="image_link" /></a></p>  <p>Then click Start Recording and Stop Recording again. Then you will see little bit shorten script. Then you can shorten unnecessary part more by editing sript directly.</p>  <p><a href="/files/attach/images/379199/437/636/image_26.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/437/636/image_thumb_12.png" width="505" height="463" editor_component="image_link" /></a></p>  <p>In this case, while typing “ngrinder” in the search field, n, ng, ngr, ngri, ngrin…. queries were sent to the server. If you need to record all of these, just leave it. However in my case it is useless, I deleted all except "ngrinder" query. Then copy and paste the generated script into Script Editor in nGrinder controller and run validation check.</p>  <p><a href="/files/attach/images/379199/437/636/image_28.png"><img title="image" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px" border="0" alt="image" src="/files/attach/images/379199/437/636/image_thumb_13.png" width="519" height="422" editor_component="image_link" /></a></p>  <p>Is it complex? nGrinder Recorder is a helper application not perfect one. <img class="wlEmoticon wlEmoticon-smile" style="border-top-style: none; border-left-style: none; border-bottom-style: none; border-right-style: none" alt="Smile" src="/files/attach/images/379199/437/636/wlEmoticon-smile_2.png" editor_component="image_link" /></p>]]></description>
                        <pubDate>Mon, 15 Apr 2013 22:44:14 -0800</pubDate>
                        <category>ngrinder</category>
                        <category>recorder</category>
                                </item>
        										        <item>
            <title>Help nGrinder</title>
            <dc:creator>junoyoon</dc:creator>
            <link>http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=help-ngrinder</link>
            <guid isPermaLink="true">http://www.cubrid.org/?mid=wiki_ngrinder&amp;entry=help-ngrinder</guid>
                                    <description><![CDATA[<p>We do our best to make nGrinder more stable and flexible. However sometimes there are some points we can not touch. We need some help from nGrinder users. If you like to help us, you can contribute the followings.</p>

<p></p>

<ul>
<li>i18n. We're supporting English, Korean, Chinese currently. If you like to provide your own language translation. Please fork our nGrinder project and do pull request with translation. Check the English message file here.&nbsp;https://github.com/nhnopensource/ngrinder/blob/master/ngrinder-controller/src/main/resources/messages_en.properties<br />Because we are not natvie English speaker, there are a lot of typo mistakes and not smooth expression. If you find some, please let us know.</li>
<li>OS compatibility. When we release, we test nGrinder on Windows and CentOS mostly. However there are many OS we didn't test much. For example Ubuntu, OS X, Fedora, etc... If you expect that nGrinder runs on your OS well, please participate the our BETA testing. We'll give you the BETA version to you and we'll make it works on your OS. Please contact junoyoon at gmail.com</li>
<li>The Grinder plugins : The underlying engine, The Grinder supports plugins so that statistics on tests using the other protocol can be collected. If you like to have your own plugin and make it as a default nGrinder plugin as well. Please share it to us.</li>
</ul>
<p></p>]]></description>
                        <pubDate>Wed, 06 Feb 2013 04:46:31 -0800</pubDate>
                        <category>ngrinder</category>
                                </item>
            </channel>
</rss>
