JMeter - how to log the full request for a failed response? - jmeter

i'm using JMeter command line to stress test our website api. Now, here's a sample result i'm getting back:
Creating summariser <summary>
Created the tree successfully using street_advisor.jmx
Starting the test # Sat Oct 03 15:22:59 PDT 2009 (1254608579848)
Waiting for possible shutdown message on port 4445
summary + 1 in 0.0s = 37.0/s Avg: 27 Min: 27 Max: 27 Err: 1 (100.00%)
<snip a few more lines>
<then i break it>
So i'm getting an error.
Currently, all errors are going to a file. When i check that file, it's saying it's a 404. Er.. ok. Is there anyway i can see exactly what the request JMeter tried?
here's a snippet of my config file...
<ResultCollector guiclass="SimpleDataWriter" testclass="ResultCollector" testname="Error Writer" enabled="true">
<boolProp name="ResultCollector.error_logging">true</boolProp>
<objProp>
<name>saveConfig</name>
<value class="SampleSaveConfiguration">
<time>true</time>
<latency>true</latency>
<timestamp>false</timestamp>
<success>true</success>
<label>true</label>
<code>true</code>
<message>true</message>
<threadName>false</threadName>
<dataType>true</dataType>
<encoding>false</encoding>
<assertions>true</assertions>
<subresults>true</subresults>
<responseData>false</responseData>
<samplerData>false</samplerData>
<xml>true</xml>
<fieldNames>false</fieldNames>
<responseHeaders>true</responseHeaders>
<requestHeaders>true</requestHeaders>
<responseDataOnError>false</responseDataOnError>
<saveAssertionResultsFailureMessage>false</saveAssertionResultsFailureMessage>
<assertionsResultsToSave>0</assertionsResultsToSave>
<bytes>true</bytes>
</value>
</objProp>
<stringProp name="filename">./error.jtl</stringProp>
</ResultCollector>
Now, before someone says 'Check the webserver log files', I know I can do this and yep, I've found the 404 .. but i'm hoping to see if it's possible without accessing them .. especially if they are on another server and/or I can't get access to them.
Please help!

The View Results Tree component shows a tree of all sample responses, allowing you to view both the request and response for any sample.
When load testing (Always in NON GUI mode), fill in "Filename" field and select to only save Responses in Error:
As you can see above we clicked on Configure to select all fields except CSV ones.
You can also save the entire response to a file using Save Responses to a file:

I found this thread searching for a solution to log the response only when a sampler fails, so the accepted solution is not good for me. I have occasional sample failures at a very high load involving hundreds of thousands of samples, so a tree listener is completely impractical for me (it will reach several gigabytes in size), so here is what I came up with (which should be good for the OP's scenario as well):
Add a [JSR223 Assertion][1] (should come after all the other assertions) and put the below code in it:
if (Boolean.valueOf(vars.get("DEBUG"))) {
for (a: SampleResult.getAssertionResults()) {
if (a.isError() || a.isFailure()) {
log.error(Thread.currentThread().getName()+": "+SampleLabel+": Assertion failed for response: " + new String((byte[]) ResponseData));
}
}
}
This will cause the entire response getting logged to the jmeter log file which is fine in my case, as I know that the responses are really small, but for large responses, more intelligent processing could be done.

There is a 'Save responses to a file' listener, which can save to file only when error occurs.

This is how I log the full request (request URL + request body) for failed requests.
Add a Listener inside the Thread Group
try{
var message = "";
var currentUrl = sampler.getUrl();
message += ". URL = " +currentUrl;
var requestBody = sampler.getArguments().getArgument(0).getValue();
message += " --data " + sampler.getArguments();
if(!sampleResult.isSuccessful()){
log.error(message);
}
}catch(err){
//do nothing. this could be a debug sampler. no need to log the error
}
For every Sampler inside the Thread Group, the Listener will execute this code after the Sampler.

Related

Send logs to datadog with custom formatter shows only the first log of multiple ones

I am trying to send logs to DD (datadog) in such a way that the logs are being received as json and therefore shown properly in the portal through attributes.
My logger is a simple Logger.new(STDOUT, level: Logger::INFO).
If I stick to its standard output, it will in the form
I, [2022-07-30T22:43:35.216846 #1] INFO -- my-app: {"user":"1234"}
which is not really parsable by DD since not a proper JSON. In this case however all the logs appear at least on the DD portal.
Now.. I am trying to format the logs in a JSON manner in this way:
def self.logger
#logger ||= Logger.new(STDOUT, level: Logger::INFO)
#logger.progname = 'my-app'
#logger.formatter = proc do |severity, datetime, progname, msg|
{timestamp: datetime.to_s, progname: progname, severity: severity, correlation: Datadog::Tracing.log_correlation, message: msg}.to_json
end
#logger
end
This is my logger and thanks to this logs are seen properly in DD and parsed correctly because formatted in my app in a proper JSON.
The problem with this approach though seems to be that the logs are sent in 1 full block. Meaning that only the very first log is being visible. Let's say that I want to log this:
my_hash = {"message" => '1', "prop" => '1234'}.to_json
logger.info(my_hash)
my_hash = {"message" => '2', "prop" => '12345'}.to_json
logger.info(my_hash)
only the first log will be shown correctly on the DD portal. Parsed correctly with its message and prop attributes, but nothing about the second log.
Here is the thing, if I see the output of my app locally in the console I see this:
{"timestamp":"2022-07-31 01:15:39 +0200","progname":"my-app","severity":"INFO","correlation":"dd.service=my-app dd.trace_id=2976451780376429536 dd.span_id=0","message":"{"message":"1","prop":"1234"}"}{"timestamp":"2022-07-31 01:15:39 +0200","progname":"my-app","severity":"INFO","correlation":"dd.service=my-app dd.trace_id=2976451780376429536 dd.span_id=0","message":"{"message":"2","prop":"12345"}"}127.0.0.1 - - [31/Jul/2022:01:15:39 +0200] "GET /controller/test_controller HTTP/1.1" 200 - 0.0024
so the 2nd log gets actually outputted! But DD somehow sees only the first log..
(I know there is even a 3rd one shown in this message.. but that's just Sinatra automatic behavior for every http call reaching the api). What do you guys think is the problem?

Mulesoft EC2 *describeInstances* with *filter* option

I'm having problems using the EC2 connector with filters for DescribeInstances. Specifically, I'm trying to find all instances that have the tag "classId" set.
I've also tried to find all instances that have the classId tag with specific string, e.g. "123".
Below are the XMLs of the describeInstance for both scenarios.
tag-key ------
<ec2:describe-instances doc:name="Describe instances" doc:id="ca64b7d4-99bb-4045-bbb4-16c0c27b1df5" config-ref="Amazon_EC2_Configuration">
<ec2:filters>
<ec2:filter name="tag-key" values="#[['classId']]">
</ec2:filter>
</ec2:filters>
</ec2:describe-instances>
tag:classId:----
<ec2:describe-instances doc:name="Describe instances" doc:id="ca64b7d4-99bb-4045-bbb4-16c0c27b1df5" config-ref="Amazon_EC2_Configuration">
<ec2:filters>
<ec2:filter name="tag:classId">
<ec2:values >
<ec2:value value="#['123']" />
</ec2:values>
</ec2:filter>
</ec2:filters>
</ec2:describe-instances>
Each time I receive an error like the following (for tag:classId):
ERROR 2021-03-29 08:32:49,693 [[MuleRuntime].uber.04: [ec2-play].ec2-playFlow.BLOCKING #1092a5bc] [processor: ; event: df5e2df0-908a-11eb-94b5-38f9d38da5c3] org.mule.runtime.core.internal.exception.OnErrorPropagateHandler: 
********************************************************************************
Message        : The filter 'null' is invalid (Service: AmazonEC2; Status Code: 400; Error Code: InvalidParameterValue; Request ID: 33e3bbfb-99ea-4382-932f-647662810c92; Proxy: null)
Element        : ec2-playFlow/processors/0 # ec2-play:ec2-play.xml:33 (Describe instances)
Element DSL      : <ec2:describe-instances doc:name="Describe instances" doc:id="ca64b7d4-99bb-4045-bbb4-16c0c27b1df5" config-ref="Amazon_EC2_Configuration">
<ec2:filters>
<ec2:filter name="tag:classId">
<ec2:values>
<ec2:value value="#['123']"></ec2:value>
</ec2:values>
</ec2:filter>
</ec2:filters>
</ec2:describe-instances>
Error type      : EC2:INVALID_PARAMETER_VALUE
FlowStack       : at ec2-playFlow(ec2-playFlow/processors/0 # ec2-play:ec2-play.xml:33 (Describe instances))
 (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)
********************************************************************************
NOTE: The code works without a filter, returning all instances. But, that isn't what I want or need. The more filtering I can do the faster the response.
Does anyone have samples of the filter option working? Can you tell me what I'm doing wrong?
Thanks!
This surely is a bug. I tried the same and it was not working for me as well. I enabled debug logging and found that the connector is not sending the filter.1.Name=tag:classId as a query parameter in the request. Here is the debug log that I found. (Notice there is no filter.1.Name=tag:classId in the query string)
DEBUG 2021-04-02 21:55:17,198 [[MuleRuntime].uber.03: [test-aws-connector].test-aws-connectorFlow.BLOCKING #2dff3afe] [processor: ; event: 91a34891-93d0-11eb-af49-606dc73d31d1] org.apache.http.wire: http-outgoing-0 >> "Action=DescribeInstances&Version=2016-11-15&Filter.1.Value.1=123"
However, I tried to use the Expression or Bean Reference option and set the expression directly as [{name: 'tag:classId', values:['123']}] like this:
and it worked correctly. Here is the same debug log after this change
DEBUG 2021-04-02 21:59:17,198 [[MuleRuntime].uber.03: [test-aws-connector].test-aws-connectorFlow.BLOCKING #2dff3afe] [processor: ; event: 91a34891-93d0-11eb-af49-606dc73d31d1] org.apache.http.wire: http-outgoing-0 >> "Action=DescribeInstances&Version=2016-11-15&Filter.1.Name=tag%3AclassId&Filter.1.Value.1=123"
Also, I want to point out very weird behaviour, this does not work if you try to format [{name: 'tag:classId',values: ['123']}] across multiple lines in the expression and will give an error during deployment.

Getting Content is not allowed in prolog when running in Java

I am facing Content is not allowed in prolog exception when I run my xxx.jmx file from Java (Jmeter 5.0).
I tested the jmx in the GUI mode and everything works fine and in the Java I am just following the standard way to call the jmx file and execute it.
The jmx just have some normal stuff. Sending HTTP request and validate the expected and received XML (I am using this snipped to validate):
import org.apache.commons.io.FileUtils
expect = FileUtils.readFileToString(new File('some_path'))
XmlParser parser = new XmlParser()
expectedXML = new XmlSlurper().parseText(expect)
actualXML = new XmlSlurper().parseText(prev.getResponseDataAsString())
if (expectedXML != actualXML) {
AssertionResult.setFailure(true)
AssertionResult.setFailureMessage('Mismatch between expected and actual XML \n'+ prev.getResponseDataAsString())
and the stack trace:
2018/10/24 15:18:03,386 12675 [ERROR ] [Thread Group 1-1] (JSR223Assertion.java:52) – Problem in JSR223 script: Validate resposne
javax.script.ScriptException: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:320)
at org.codehaus.groovy.jsr223.GroovyCompiledScript.eval(GroovyCompiledScript.java:72)
at javax.script.CompiledScript.eval(CompiledScript.java:92)
at org.apache.jmeter.util.JSR223TestElement.processFileOrScript(JSR223TestElement.java:221)
at org.apache.jmeter.assertions.JSR223Assertion.getResult(JSR223Assertion.java:49)
at org.apache.jmeter.threads.JMeterThread.processAssertion(JMeterThread.java:901)
at org.apache.jmeter.threads.JMeterThread.checkAssertions(JMeterThread.java:892)
at org.apache.jmeter.threads.JMeterThread.executeSamplePackage(JMeterThread.java:565)
at org.apache.jmeter.threads.JMeterThread.processSampler(JMeterThread.java:486)
at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:253)
at java.lang.Thread.run(Thread.java:745)
Caused by: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1; Content is not allowed in prolog.
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at groovy.util.XmlSlurper.parse(XmlSlurper.java:207)
at groovy.util.XmlSlurper.parse(XmlSlurper.java:260)
at groovy.util.XmlSlurper.parseText(XmlSlurper.java:286)
at groovy.util.XmlSlurper$parseText.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125)
at Script1.run(Script1.groovy:9)
at org.codehaus.groovy.jsr223.GroovyScriptEngineImpl.eval(GroovyScriptEngineImpl.java:317)
... 10 more
UPDATE 1:
The problem of using Response Assertion is it cannot ignore the space or tab. So if the format is not exactly the same when I use equal will always fail. Any ideas how to ignore these things by using Response Assertion?
UPDATE 2:
I found out that the issue is not related to the BOM. Is becasue if I run the jmx from my Java application:
prev.getResponseDataAsString()
above function always return:
${__FileToString(${inputFilePath},,)}
but not the actual response. This function is come from the body data of the HTTP Request sampler!!!!!! If I give the acutal body there then I am able to run the jmx...... Any idea how to deal with this dynamic body data?
It might be the case your "expected" XML file contains BOM and it causes your code failure.
BOM is basically 3 first bytes so you can remove them using code like:
def expect = FileUtils.readFileToString(new File('some_path')).getBytes().flatten()
1.upto(3) {
expect.remove(0)
}
XmlParser parser = new XmlParser()
def expectedXML = parser.parseText(new String(expect.toArray(new Byte[0])))
The rest of your code should work fine.
Check out The Groovy Templates Cheat Sheet for JMeter article to learn more Groovy tips and tricks.
Also be informed that in majority of cases it's easier to use Response Assertion or when it comes to XML - XPath Assertion, Java code will work faster than Groovy in any case.

Gateway and aggregator - CorrelationStrategy error

I have to access an external service using spring integration. The process is (1) I had to pass an id to get basic information (2) using basic info from step 1, I need to access to more services and merge the information into a singlr object.
integration-graph:
input: Channel1 outputs to : Channel1Out
I have recipient list router that puts message to the 2 channels Channel2 and Channel3.
Channel2 and Channel3's output channels use a xml xpath-transformer
and output to Channel 4
<int:aggregator id="aggregatorChannel"
correlation-strategy-expression="headers['jms_messageId']"
release-strategy-expression="size() == 2" method="mergeVO"
input-channel="channel4" output-channel="dest-channel">
<bean class="n.b.lbr.eai.vo.PojoAggregator"></bean>
</int:aggregator>
This is giving error.
java.lang.IllegalStateException: Null correlation not allowed. Maybe the CorrelationStrategy is failing?
at org.springframework.util.Assert.state(Assert.java:70) ~[spring-core-4.3.8.RELEASE.jar:4.3.8.RELEASE]
at org.springframework.integration.aggregator.AbstractCorrelatingMessageHandler.handleMessageInternal(AbstractCorrelatingMessageHandler.java:385) ~[spring-integration-core-4.3.9.RELEASE.jar:4.3.9.RELEASE]
I did see some posts on this topic, but I do not understand how to solve the below error
{
"timestamp": 1533137160301,
"status": 500,
"error": "Internal Server Error",
"exception": "java.lang.IllegalStateException",
"message": "Null correlation not allowed. Maybe the CorrelationStrategy is failing?",
"path": "/w/b/search/11223"
}
please suggest, if this is a design issue or how to solve this problem
EDIT1:
Is the below valid scatter gather?
<bean id="messageStore" class="org.springframework.integration.store.SimpleMessageStore"/>
<int:scatter-gather id="scatterGather2" input-channel="drBInputChannel" gather-channel="gatherChannel" gather-timeout="5000">
<int:scatterer id="myScatterer" apply-sequence="true">
<int:recipient channel="bserviceInputChannel"/>
<int:recipient channel="aserviceInputChannel"/>
</int:scatterer>
<int:gatherer id="myGatherer"
**??**
message-store="messageStore"
correlation-strategy=**??**
release-strategy-expression="size() == 2"
>
<bean class="nd.wbr.eai.vo.PojoAggregator"></bean>
</int:gatherer>
</int:scatter-gather>
I need help to convert to xml and use in the above
#Bean
public MessageHandler gatherer() {
return new AggregatingMessageHandler(
***new ExpressionEvaluatingMessageGroupProcessor("^[payload gt 5] ?:-1D"),***
new SimpleMessageStore(),
***new HeaderAttributeCorrelationStrategy(
IntegrationMessageHeaderAccessor.CORRELATION_ID),***
new ExpressionEvaluatingReleaseStrategy("size() == 2"));
}
The "java.lang.IllegalStateException: Null correlation not allowed. Maybe the CorrelationStrategy is failing?" exception means that your correlation-strategy-expression="headers['jms_messageId']" doesn't produce anything meaningful. To be precise there is just no jms_messageId header in the message.
Not sure why you did such a choice for the correlation key, but there is definitely not going to be such a headers when you perform HTTP request. You may emulate it though, but it might be better to choose some other correlation strategy.
On the other hand, looking to your original task description, I would say that you need to take a look into the Scatter-Gather pattern and stop to worry about correlation key altogether!

logstash-logger and filtering events

I'm using logstash-logger in a Ruby app. It's great. However, I seem to have a problem that my debug messages are being forwarded, and no setting seems to turn that off. It's increasing my logging requirements by 3 to 5 fold, both increasing the costs and slowing down the app.
Is there a way to filter log messages to eliminate this noise?
I have set in the config.logger_level to :info, but debug messages are still being forwarded.
Any suggestions?
P.s. My config below, is still sending debug messages and info messages.
#logstash_logger = ::LogStashLogger.new(
type: :multi_delegator,
outputs: [
{ type: :stdout },
{ type: :udp, host: logging_host, port: logging_port }
])
#logstash_logger.level = ::Logger::WARN

Resources