Quick question regarding how to build a visual on a specific condition of a java counter in Grafana please.
Currently, I have a small piece of java code, straightforward.
private String question(MeterRegistry meterRegistry) {
if (someCondition()) {
Counter.builder("theCounter").tags("GOOD", "GOOD").register(meterRegistry).increment();
return "good";
} else {
LOGGER.warn("it is failing, we should increment failure");
Counter.builder("theCounter").tags("FAIL", "FAIL").register(meterRegistry).increment();
return "fail";
}
}
As you can see, it is very simple, just a "if a condition is met, increment the GOOD counter, if not, increment the FAIL counter"
I am interested in building a dashboard for the failures only.
When I query my /prometheus endpoint I successfully see:
myCounter_total{FAIL="FAIL",} 7.0
myCounter_total{GOOD="GOOD",} 3.0
Hence, I started using this query.
myCounter_total{_ws_="workspace",_ns_="namespace",_source_="source}
Unfortunately, this query is giving me the visual for everything, the GOOD and the FAIL. In my example, I see all 10 counters, while I just want to see the 7 failures.
I tried putting
myCounter_total{FAIL="FAIL",_ws_="workspace",_ns_="namespace",_source_="source}
{{FAIL}}
But no luck.
May I ask what did I miss please?
Create only one counter for this case and give it a label named status, for example. Now, depending on whether the good or the fail condition occurs, increment your counter with a string "GOOD" or "FAIL" as a value for the status label, for example like in this pseudo code:
Counter myCounter =
Counter.build().name("myCounter").help("This is my counter").labelNames("status").register();
if (someCondition()) {
myCounter.labels("GOOD").increment();
} else {
myCounter.labels("FAIL").increment();
}
Now you should be able see a query output like this:
myCounter_total{status="FAIL"} 7.0
myCounter_total{status="GOOD"} 3.0
For visualization purposes, if you'd like to see two graphs, one for good and one for bad cases, you could use something like below. This one query querying myCounter_total reveals its data and the Legend takes care of separating values/graphs with different status label values.
Query: myCounter_total
Legend: {{status}}
Related
I have a section of code that does a running count of payments to see if rent has been paid for a property, code is as follows:
BigDecimal remainingAmount = MathUtilities.roundBigDecimal(new BigDecimal(amountDue.getAmount().doubleValue()));
for(RentPayment payment : this.rentPayments) {
remainingAmount = remainingAmount.subtract(payment.getAmountPaid().getAmount());
}
return remainingAmount;
So here, all that needs to happen is remaining amount needs to be returned so we know how much rent has been paid for a particular invoice. When I run this in the debugger, it does 235.66 - 235.66, with the logical result of 0:
remainingAmount.subtract(payment.getAmountPaid().getAmount());
However, when running this code normally, the result, no matter how many payments of 235.66, is always 235.66, event though I'm explicitly setting remainingAmount. Is there something I'm missing? Every question I've looked at seems to suggest I'm doing this correctly.
Edit: Just to show I'm not crazy or missing something obvious:
And:
The issue was because a watch I had used to validate the result of the operation was left in and it was overriding what my code was doing, this was a simple user error, closing out this question.
I saw the following code in this commit for MongoDB's Java Connection driver, and it appears at first to be a joke of some sort. What does the following code do?
if (!((_ok) ? true : (Math.random() > 0.1))) {
return res;
}
(EDIT: the code has been updated since posting this question)
After inspecting the history of that line, my main conclusion is that there has been some incompetent programming at work.
That line is gratuitously convoluted. The general form
a? true : b
for boolean a, b is equivalent to the simple
a || b
The surrounding negation and excessive parentheses convolute things further. Keeping in mind De Morgan's laws it is a trivial observation that this piece of code amounts to
if (!_ok && Math.random() <= 0.1)
return res;
The commit that originally introduced this logic had
if (_ok == true) {
_logger.log( Level.WARNING , "Server seen down: " + _addr, e );
} else if (Math.random() < 0.1) {
_logger.log( Level.WARNING , "Server seen down: " + _addr );
}
—another example of incompetent coding, but notice the reversed logic: here the event is logged if either _ok or in 10% of other cases, whereas the code in 2. returns 10% of the times and logs 90% of the times. So the later commit ruined not only clarity, but correctness itself.
I think in the code you have posted we can actually see how the author intended to transform the original if-then somehow literally into its negation required for the early return condition. But then he messed up and inserted an effective "double negative" by reversing the inequality sign.
Coding style issues aside, stochastic logging is quite a dubious practice all by itself, especially since the log entry does not document its own peculiar behavior. The intention is, obviously, reducing restatements of the same fact: that the server is currently down. The appropriate solution is to log only changes of the server state, and not each its observation, let alone a random selection of 10% such observations. Yes, that takes just a little bit more effort, so let's see some.
I can only hope that all this evidence of incompetence, accumulated from inspecting just three lines of code, does not speak fairly of the project as a whole, and that this piece of work will be cleaned up ASAP.
https://github.com/mongodb/mongo-java-driver/commit/d51b3648a8e1bf1a7b7886b7ceb343064c9e2225#commitcomment-3315694
11 hours ago by gareth-rees:
Presumably the idea is to log only about 1/10 of the server failures (and so avoid massively spamming the log), without incurring the cost of maintaining a counter or timer. (But surely maintaining a timer would be affordable?)
Add a class member initialized to negative 1:
private int logit = -1;
In the try block, make the test:
if( !ok && (logit = (logit + 1 ) % 10) == 0 ) { //log error
This always logs the first error, then every tenth subsequent error. Logical operators "short-circuit", so logit only gets incremented on an actual error.
If you want the first and tenth of all errors, regardless of the connection, make logit class static instead of a a member.
As had been noted this should be thread safe:
private synchronized int getLogit() {
return (logit = (logit + 1 ) % 10);
}
In the try block, make the test:
if( !ok && getLogit() == 0 ) { //log error
Note: I don't think throwing out 90% of the errors is a good idea.
I have seen this kind of thing before.
There was a piece of code that could answer certain 'questions' that came from another 'black box' piece of code. In the case it could not answer them, it would forward them to another piece of 'black box' code that was really slow.
So sometimes previously unseen new 'questions' would show up, and they would show up in a batch, like 100 of them in a row.
The programmer was happy with how the program was working, but he wanted some way of maybe improving the software in the future, if possible new questions were discovered.
So, the solution was to log unknown questions, but as it turned out, there were 1000's of different ones. The logs got too big, and there was no benefit of speeding these up, since they had no obvious answers. But every once in a while, a batch of questions would show up that could be answered.
Since the logs were getting too big, and the logging was getting in the way of logging the real important things he got to this solution:
Only log a random 5%, this will clean up the logs, whilst in the long run still showing what questions/answers could be added.
So, if an unknown event occurred, in a random amount of these cases, it would be logged.
I think this is similar to what you are seeing here.
I did not like this way of working, so I removed this piece of code, and just logged these
messages to a different file, so they were all present, but not clobbering the general logfile.
What is the difference between the cursor.count() and cursor.size() methods of MongoDB's DBCursor?
From the Javadoc of the MongoDB Java Driver, it says :
DBCursor.count(): Counts the number of objects matching the query. This
does not take limit/skip into consideration.
DBCursor.size(): Counts the number of objects matching the query. This
does take limit/skip into consideration.
More than an answer I'd like to point out an issue that our team faced "mixing" this two.
We had something like this:
DBCursor cursor = collection.find(query).limit(batchSize);
logger.info("{} items found.", cursor.count());
while (cursor.hasNext()) {
...
}
It turned out that after calling the cursor.count() method, the limit was ignored (plase take a look at this other question) , we intended to know how many items were returned by the query so we should have called the cursor.size() method instead, since calling the count one did have an undesired collateral effect.
I hope this could be helpful to anyone else since it was not that easy to find the source of the issue we were facing.
When I first read the documentation on the difference between cursor.count and cursor.size, I was similarly stumped b/c I didn't understand what it meant to not consider skip or limit. I found this article to be helpful read more here. I think the following example illustrates the differences
// by default cursor.count ignores limit or skip. note that 100 records were returned despite the limit being 5
> db.restaurants.find( { "cuisine": "Bakery", "address.zipcode": "10462" } ).limit(5).count();
100
// if you want to consider limits and skips, then add an optional parameter specifying so
> db.restaurants.find( { "cuisine": "Bakery", "address.zipcode": "10462" } ).limit(5).count(true);
5
// cursor.size on the other hand abides by limits and skips
> db.restaurants.find( { "cuisine": "Bakery", "address.zipcode": "10462" } ).limit(5).size();
5
I'm writing some Java code using MongoDB with Java API and I'm unsure of some part of the Javadoc.
In a multi-thread context I use DBCollection.html#update(com.mongodb.DBObject, com.mongodb.DBObject) to update a unique document, but I saw that two threads could try to write concurrently. In this context, I observed that only one write was done, as Mongodb seems to use optimistic write lock, but I wanted to find out programmatically in which thread the write was the one who wrote, and which one was not. As a "no update" behavior was silent (I mean no exception or something), I searched into the API some way to answer my issue and after some tests found out this method: WriteResult#getN()
public int getN()
Gets the "n" field
Returns:
The description is, hum... not really exhaustive. My tests showed that the thread that win the write has a getN() that return 1, and the other 0.
So my question is: Could someone confirm this ?
From the GetLastError() documentation
The return value from the command is an object with various fields. The common fields are listed below; there may also be other fields.
ok - true indicates the getLastError command completed successfully. This does NOT indicate there wasn't a last error.
err - if non-null, indicates an error occurred. Value is a textual description of the error.
code - if set, indicates the error code which occurred. connectionId - the id of the connection
lastOp - the op-id from the last operation
For updates:
n - if an update was done, this is the number of documents updated.
So in this context, 'get "n" field' means get n which is the number of documents updated. Without "multi" being set to true it can only be either 0 or 1.
So I have worked through the Money example in Kent Beck's book Test Driven Development by Example and have been able to get the code to work up until the last test that he writes:
#Test
public void testPlusSameCurrencyReturnsMoney(){
Expression sum = Money.dollar(1).plus(Money.dollar(1));
assertTrue(sum instanceof Money);
}
and here is the function that this calls
public Expression plus(Expression addend) {
return new Sum(this, addend);
}
When I run this, it gives java.lang.AssertionError, so my question is why is it giving this error and how do I fix it?
Lunivore already answered the question with how to solve the problem, but I think you should re-read the paragraph just before and after the block of code (and test), if you want to understand more on what Beck was trying to convey.
The last sentence reads "Here is the code we would have to modify to make it work:". That block of code was first entered on page 75 (with test case). Nothing was changed in end effect on page 79. It was just an indication of what we could change, if we wanted to keep this test.
"There is no obvious, clean way to check the currency of the argument if and only if it is Money. The experiment fails, we delete the test, and away we go".
He also stated that this test is ugly and concluded on the following page "Tried a brief experiment, then discarded it when it didn't work out".
I wrote this just in case you were thinking all of the examples just work and should be kept.
You're checking that the sum variable is a Money, but returning a Sum in the plus method.
So, unless Sum is a subclass of Money, that assertion will always fail.
To make it pass, you might want to do something like:
public Expression plus(Expression addend) {
return new Money(...<whatever>...);
}
Of course, Money would then have to be an Expression too.
Or you might want to evaluate the sum to get the money out of it. Or maybe even do sum instanceof Sum instead. It depends on what behavior you're actually trying to achieve.
By the way, beware the instanceof operator.