Using Baggage with openTelemetry (Java) automaton tools - open-telemetry

Please consult adding some extra information to trace (span's) when using openTelemetry javaagent for instrumentation.
Can I use the Baggage API for this?
https://www.javadoc.io/static/io.opentelemetry/opentelemetry-api/1.0.0/io/opentelemetry/api/baggage/package-summary.html
https://www.javadoc.io/static/io.opentelemetry/opentelemetry-api/1.0.0/io/opentelemetry/api/baggage/Baggage.html
Are there any other better ways?
Could anyone share their experience please?

Please consult adding some extra information to trace (span's)
You are probably looking to use span operations for enriching the span data. There are number of operations you could perform on span such as adding attributes, adding events, and recording exception etc. Please look at the specification for full list of ops https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#span-operations. Small snippet to demonstrate to operations.
...
...
Tracer tracer = openTelemetrySdk.getTracer("TracerExample");
Span span = tracer.spanBuilder("mySpanName").startSpan();
span.setAttribute("user.id", "ENS1001");
span.setAttribute("cart.items.count", 10);
...
...
Attributes eventAttributes = Attributes.of(stringKey("someKey"), "someCustomValue");
span.addEvent("Completed", eventAttributes)
span.end();
...
Javadoc reference for span https://www.javadoc.io/doc/io.opentelemetry/opentelemetry-api-trace/latest/io/opentelemetry/api/trace/Span.html.

Related

Loading protocol buffer in ruby or java similar to node

I have a .proto file that contains my schema and service definition. I'm looking for a method in ruby/java that is similar to how Node loads and parses it (code below). Looking at the grpc ruby gem, I don't see anything that can replicate how Node does it.
Digging around I see this (https://github.com/grpc/grpc/issues/6708) which states that dynamically loading .proto files is only available in node. Hopefully, someone can provide me with an alternative.
Use case: Loading .proto files dynamically as provided in the client but I can only use either ruby or java to do it.
let grpc = require("grpc");
let loader = require("#grpc/proto-loader");
let packageDefinition = loader.loadSync(file.file, {});
let parsed = grpc.loadPackageDefinition(packageDefinition);
I've been giving this a try for the past few month and it seems like Node is the only way to read a protobuf file on runtime. Hopefully this helps anyone in the future that needs it.

Customize spring-boot jaeger auto-configuration

I'm working on a POC and was able to integrate 2 microservices with JaegerUI.
Request to an endpoint in serviceA calls an endpoint in serviceB and returns a response.
I have used below dependencies:
spring.boot.version : 2.1.4.RELEASE
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-spring-jaeger-web-starter</artifactId>
<version>3.1.1</version>
<groupId>io.opentracing.contrib</groupId>
<artifactId>opentracing-spring-cloud-starter</artifactId>
<version>0.4.0</version>
Spring autoconfiguration takes care of everything so just added the required properties:
opentracing.jaeger.http-sender.url
opentracing.jaeger.service-name
opentracing.jaeger.enabled
opentracing.spring.cloud.async.enabled
I want to achieve the below:
I want to add application logs to the span so that they are visible in JaegerUI.
I want to add some fields to span tags so that it's easy to search in JaegerUI.
Also, I want the spanId and traceId to the application log.
Is it possible to search in JaegerUI based on spanId/traceId? If yes, how?
Based on the answer in below SO question:
How to enrich Jaeger opentracing data with the application logs (produced by slf4j) for Spring Boot?
opentracing-spring-cloud-starter dependency should automatically take care of sending app logs to span in JaegerUI.
I have a log statement like below in serviceA:
logger.info("sending request to serviceB.");
But above log is not getting captured in corresponding span and not visible in JaegerUI.
Any suggestions on how to achieve the above scenarios are appreciated!
I was studying Opentracing and Jeager and I've used this tutorial to get familiar with the basic possibilities:
https://github.com/yurishkuro/opentracing-tutorial/tree/master/java
If you take a look in the case 1 (Hello World), it explains how to "Annotate the Trace with Tags and Logs".
That would answer your questions 1, 2 and 3, as with that you can add all the info that you would like within spans and logs.
Here is a snippet from the repository (but I'd recommend checking there, as it has a more detailed explanation):
Span span = tracer.buildSpan("say-hello").start();
span.setTag("hello-to", helloTo);
In this case helloTo is a variable containing a name, to whom the app will say hello. It would create a span tag called hello-to with the value that is coming from the execution.
Below we have an example for the logs case, where the whole helloStr message is added to the logs:
// this goes inside the sayHello method
String helloStr = String.format("Hello, %s!", helloTo);
span.log(ImmutableMap.of("event", "string-format", "value", helloStr));
System.out.println(helloStr);
span.log(ImmutableMap.of("event", "println"));
Regarding the last question, that would be easier, you can use the Jaeger UI to search for the trace you would like, there is a field for that on the top left corner:
There you go.
I want to add application logs to the span so that they are visible in JaegerUI.
Span span = tracer.buildSpan("my-span-name").start();
span.setTag("my-tag-name", "my-tag-value");
There are various overloaded methods as follows
Span setTag(String key, String value);
Span setTag(String key, boolean value);
Span setTag(String key, Number value);
I want to add some fields to span tags so that it's easy to search in JaegerUI.
Jaeger API provides log method to log multiple fields that needs to be added to a map, the method signature is as follows,
Span log(Map<String, ?> fields);
eg:
span.log(
ImmutableMap.Builder<String, Object>()
.put("event", "soft error")
.put("type", "cache timeout")
.put("waited.millis", 1500)
.build()
);
Also, I want the spanId and traceId to the application log.
spanId and traceId are stored in JaegerSpanContext class, which can be obtained from context() method of Span class.
JaegerSpanContext spanContext = (JaegerSpanContext)sprintSpan.context();
long spanId = spanContext.getSpanId();
long traceId = spanContext.getTraceId();
Is it possible to search in JaegerUI based on spanId/traceId? If yes, how?
There is a search box in the navigation bar of Jaeger UI where you can search traces by trace ID.

Can we control Jmeter's components through Beanshell? I want to disable all assertions through one flag. how can I do it?

Can we control Jmeter's components through Beanshell? I want to disable all assertions through one flag. How can I do it?
If any other solution than beanShell then let me know.
The easiest way is running your JMeter test using Taurus tool as a wrapper, it naturally supports JMeter tests, moreover it provides some nice extensions.
Particular in your case you can use Modifications for Existing Scripts functionality which allows enabling or disabling Test Elements
---
scenarios:
modification_example:
script: /your/jmeter/testplan.jmx
modifications:
disable: # Names of the tree elements to disable
- Response Assertion
- Duration Assertion
I see two ways in addition to previous answers:
1) Wrap assertions into If controllers, then - yes, set a flag var & check at the If block.
2) Run JMeter programmatically through JMeter API - here you'd have programmatic access to each and every element in the TestPlan.
Although that way is documented quite poorly while the API model is far from being clear itself.
UPD: some clues for the way of doing the latter
1) Here's the main reference: http://jmeter.apache.org/api/index.html
2) Instantiate engine and load properties:
StandardJMeterEngine jmeter = new StandardJMeterEngine();
JMeterUtils.loadJMeterProperties("/path/to/jmeter.properties");
3) Instantiate SaveService and load your plan (yes, save service is what resposible for that)
SaveService.loadProperties();
File yourplan = new File("/path/to/yourplan.jmx");
HashTree planTree = SaveService.loadTree(yourplan);
4) Here's the point where you can access & work your plan elements, going through the HashTree, retrieving test elements in sub-hashtrees (for elements, see the reference mentioned in p.1) & changing them and/or the test structure (cast to TestElement must be good enough for enabling/disabling).
5) As you got done with it, the rest is straightforward:
jmeter.configure(planTree);
jmeter.run();
That should be pretty much it.
From my knowledge, you can not disable all Assertions in the Test Plan by using BeanShell
The work around is as follows:
Create a variable as processAssertions in User Defined Variable config element.
Keep All Assertions inside If Controllers.
Add condition as ${processAssertions}==true, so Assertions will be evaluated ONLY when you set the processAssertions value to true. Set any value other than true, to make JMeter to ignore Assertions.
Using Bean Shell Assertion:
Pre-condition: create processAssertions (Set to TRUE) in User Defined Variables
import org.apache.jmeter.assertions.ResponseAssertion;
log.info("hello");
try{
ResponseAssertion obj = new ResponseAssertion();
if(${processAssertions}==TRUE) { // value accessed from UDV
log.info("inside if");
obj.Enabled=false;
SampleResult.setSuccessful(true); // set sample result to PASS, set to false to mark it failure.
}
} catch(Exception e) {
}
If Controller - with assertions:
If Controller - without assertions:
References:
https://www.blazemeter.com/blog/how-use-jmeter-assertions-3-easy-steps
http://jmeter.apache.org/usermanual/component_reference.html#assertions

Can I use Serilog.Extra.Web's HttpRequestNumber or HttpRequestId as the SerilogMetrics timed-operation identifier?

I'm using SerilogMetrics's BeginTimedOperation() in a Web API, and it would be really great to be able to use the HttpRequestNumber or HttpRequestId properties (from the respective Serilog.Extra.Web enrichers) as the identifier, making it super easy to correlate timing-related log entries with others across a request.
Something like:
using (logger.BeginTimedOperation("doing some work", HttpRequestNumberEnricher.CurrentRequestNumber))
{ ... }
Short of poking around in HttpContext.Current for the magically- (i.e. non-public) named properties, is this achievable? Thanks!
If you begin a timed operation during a web request, the operation's events will already be tagged with the HttpRequestId.
You'll see it when logging to a structured log server like Seq, but if you're writing it out to a text file or trace then the property won't be included in the output message by default. To show it in there use something like:
.WriteTo.File(...,
outputTemplate: "{Timestamp} [{Level}] ({HttpRequestId}) {Message} ...")
The logging methods use a default template you can draw on for inspiration, and there's some info spread around the wiki though there's no definitive reference.

Spring HATEOAS / MockMvc / JsonPath best practices

I'm writing unit tests for Spring HATEOAS backend using MockMvc and JsonPath.
To test the links contained in a response I'm doing something like:
#Test
public void testListEmpty() throws Exception {
mockMvc.perform(get("/rest/customers"))
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.links", hasSize(1))) // make sure links only contains self link
.andExpect(jsonPath("$.links[?(#.rel=='self')]", hasSize(1))) // make sure the self link exists 1 time
.andExpect(jsonPath("$.links[?(#.rel=='self')].href", contains("http://localhost/rest/customers{?page,size,sort}"))) // test self link is correct
.andExpect(jsonPath("$.links[?(#.rel=='self')][0].href", is("http://localhost/rest/customers{?page,size,sort}"))) // alternative to test self link is correct
.andExpect(jsonPath("$.content", hasSize(0))); // make sure no content elements exists
}
However I wonder if there are some best practices I should use to make it easier for myself like:
Testing link contains http://localhost does not feel right. Can I use some Spring MovkMvc helper to determine the host?
With JsonPath it's difficult to test if an array contains an element where 2 attributes have certain value.
Like that the array should contain a self link with a certain value.
Is there a better way to test that then above
This will also come into play when testing validation errors for fields with error messages.
I've see technique like below in some blog posts:
.andExpect(jsonPath("$.fieldErrors[*].path", containsInAnyOrder("title", "description")))
.andExpect(jsonPath("$.fieldErrors[*].message", containsInAnyOrder(
"The maximum length of the description is 500 characters.",
"The maximum length of the title is 100 characters.")));
But this does not guarantee at all that title has the specific error message.
It could also be that the title has incorrectly the "The maximum length of the description is 500 characters." but the test will succeed.
You may use Traverson (included in Spring HATEOAS) to traverse the links in tests.
If you are using Spring Boot, I'd consider using #WebIntegrationTest("server.port=0") rather than MockMvc, as in some cases I experienced behaviours slightly different from the actual application.
You may find some example in a post of mine: Implementing HAL hypermedia REST API using Spring HATEOAS.
Also look at the tests in the sample project.
One approach that addresses the http://localhost concern without sacrificing the need to test two attribute constraints on an array element is to use the org.hamcrest.CoreMatchers.hasItem(org.hamcrest.Matcher nestedMatcher) matcher. The test you showed above now becomes:
.andExpect(jsonPath("$.links[?(#.rel=='self')].href", hasItem(endsWith("/rest/customers{?page,size,sort}"))))
.andExpect(jsonPath("$.links[?(#.rel=='self')][0].href", hasItem(endsWith("/rest/customers{?page,size,sort}"))))

Resources