I am struggling a little bit to understand how to implement a Hystrix Metrics Publisher plugin.
Having read the documentation, it is still not clear how things are supposed to work together.
My goal is to write a plugin that will collect every metrics published by hystrix and write these metrics to a file on disk.
This file will later be collected and processed by an external tool giving us a good historical basis of the circuit’s behavior and problems.
The system where hystrix is running is a normal spring application. This said, I am also somewhat new on the java platform (although I am comfortable with the java language).
I thought that a first step towards understanding how the plugin could be implemented would be looking at the already implemented publishers. With this in mind, I looked at some of the implementations of hystrix-contrib directory.
I have chosen hystrix-codahale-metrics-publisher and hystrix-servo-metrics-publisher.
Both of them have a main class (servo is HystrixServoMetricsPublisher) which seems to register for receiving all possible kinds of metrics and some classes to deal with each kind of metric.
By looking at what I will call the main class, I see that, for example, there is a method called getMetricsPublisherForCommand that must return an implementation of the interface HystrixMetricsPublisherCommand.
Now questions start:
Question 1 I am assuming that once a plugin is registered every execution of every command on the context where the plugin is registered, and by the word command we can understand every execution of the execute() method of every class which inherits from HistrixCommand on that context, will generate a call to the getMetricsPublisherForCommand() method of my plugin. Is it true?
If so, there are a lot of low level implementations in hystrix such as thread pools and other, Should my getMetricsPublisherForCommand() implementation be thread-safe or I am guaranteed to receive calls in a sequential order? On what thread will my getMetricsPublisherForCommand() be executed?
Question 2 By looking at the documentation I am still not sure about what exactly the implementation of HystrixMetricsPublisherCommand to be returned by getMetricsPublisherForCommand() has to do. This is due to the fact that the HystrixMetricsPublisherCommand interface only specifies a method called initialize (). if it specified a method called, say, publish() I would conclude that the hystrix engine would call my custom getMetricsPublisherForCommand() method to get a metrics publisher on which it would call a publish() method to perform the custom publishing. But the initialize () method seens to be called only once when this given object is returned and I have found no other method the engine would call afterwards.
Also, by reading the documentation, I am under the impression that the implementation of HystrixMetricsPublisherCommand returned by getMetricsPublisherForCommand() will be somehow a singleton which completely breaks my understanding about how the thing is supposed to work.
The documentation say this:
The initialize() method will be called once-and-only-once to indicate when this instance can register with external services, start publishing metrics etc.
If you look at the servopublisher however you will notice that, unless I am completely and absolutely confused, the publishing stuff is performed right from the constructor. Now, if initialize() will be called to make some setup, how can I code my logic from the constructor where, unless the object is a singleton, it will be executed before any method including initialize () will have a chance to be called? In the other hand ,,, if this is a singleton, how can it run its constructor for every hystrix command?
May be I have missed something, I don't know ... but I need to understand conceptually what is going on here in order to implement my logic the right way. Thanks for your patience and I hope I have made myself clear enough in this long question.
First, recommend staying within the one (concise) question format.
Second, recommend using an existing implementation such as the default CodaHale (formerly DropWizard) implementation (which publishes to Graphite repository for Grafana consumption for example) to get it working.
HystrixPlugins.reset();
final WebApplicationContext springContext =
WebApplicationContextUtils.getWebApplicationContext(sce.getServletContext());
HystrixPlugins plugins = HystrixPlugins.getInstance();
plugins.registerCommandExecutionHook(...);
// Good idea to use properties to enable/disable metrics generally...
// Using Spring type example...
if (hystrixMetricsEnabled.get()) {
plugins.registerMetricsPublisher(new HystrixCodaHaleMetricsPublisher(
getRegistry(springContext, sce.getServletContext())));
...
Otherwise the Hystrix documentation and full source of classes involved are publicly available:
https://github.com/Netflix/Hystrix/wiki/Plugins#metricspublisher
Related
Say I'm using a library (Java) which defines / registers metrics in Prometheus. I'm wondering how I might be able to unregister/redefine/customize these metrics which have already been defined/registered by said library? Specifically, if I had a Histogram with certain buckets that were already registered, how could I update the same Histogram with different buckets?
For example, if my-java-library defines a Histogram with name my_histogram, I was thinking I might be able to use the unregister method on CollectorRegistry like so:
in my-java-library:
{
...
this.myHistogram = Histogram.build()
.name("my_histogram")
.register();
...
}
public Histogram getMyHistogram() {
return this.myHistogram;
}
in my-repo that uses my-java-library:
import my-java-library; // ignore the poor naming convention :^)
...
{
...
Histogram myHistogram = myJavaLibrary.getMyHistogram();
CollectorRegistry.defaultRegistry.unregister(myHistogram);
...
}
The above example seems to be problematic for a few reasons:
The unregister method is apparently only supposed to be used in rare cases for unit tests and not (apparently) for the above purpose ([1], [2], [3])
It seems the client_java repo for Prometheus is registering background, inaccessible metrics behind the scenes which, since these Collector instances aren't accessible (at least not to my knowledge), cannot be unregistered using the aforementioned model. This means even if I tried and succeeded at unregistering my_histogram, I will still run into a runtime exception (IllegalArgumentException) since these behind-the-scene metrics are being caught by the assertNoDuplicateNames method.
I'm at a bit of a loss. I will probably create an issue in the client_java repo as well but wanted to see if anyone on SO has run into and solved this problem for themselves.
I guess the problem is that my-java-library will use the this.myHistogram instance. So unregistering this.myHistogram does not help because the library will just continue using the unregistered this.myHistogram instance, but you would never see these metrics as the histogram is no longer registered.
What you could try is to replace this.myHistogram with your own instance. If the library has a setter myJavaLibrary.setMyHistogram(Histogram) that should work, if it doesn't you will likely need to use reflection to replace the this.myHistogram instance in the library.
This is not directly related to unregistering the original myHistogram instance. You can just register your own instance with a different name and keep the original instance registered. You can use CollectorRegistry.defaultRegistry.unregister(myHistogram) for unregistering the original instance, but this is just for cleaning up and should not affect functionality, because after setting this.myHistogram the library will not be able to access the original instance and the original instance will never be used.
Does that help?
I want to do something which seems really straightforward: just pass a lot of logging commands (maybe all, but particularly WARN and ERROR levels) through a method in a simple utility class. I want to do this in particular so that during testing I can suppress the actual output to logging by mocking the method which does this call.
But I can't find out how, with ch.qos.logback.classic.Logger, to call a single method with the Level as a parameter ... obviously I could use a switch command based on this value, but in some logging frameworks there's a method or two which lets you pass the logging Level as a parameter. Seems a bit "primitive" not to provide this.
The method might look a bit like this:
Logger.log( Level level, String msg )
Later
Having now looked up the "XY problem" I understand the scepticism about this question. Dynamic logging is considered bad, at least in Java (possibly less so in Python)... now I know and understand that the preferred route is to configure the logging configuration appropriately for testing.
One minor point, though, if I may: although I haven't implemented this yet with this particular project, I generally find "just" tracing the stacktrace back to the beginning of the particular Thread insufficient, and this is what logback does (with Exceptions passed at WARN or ERROR levels). I plan to implement a system for recording "snapshots" of Threads when they run new Threads... which can then be listed (right back to the start of the app's first Thread) if an error occurs. This is, if you like, another justification for using something to "handle" outgoing log calls. I suppose that if I want to implement something like this I will instead have to try to extend some elements of logback in some way.
I have a class that users will inherit from and implement two methods: navigateForwards() and navigateBackwards() (it's a wizard-like web application).
The user may want to add interceptors to these methods.
Another class (let's say it's part of a framework) will find the appropriate subclass, select() it and call the navigate(String) method which will call either navigateForwards() or navigateBackwards(). At that point interceptors won't work anymore since it's an unproxied method call. I could add interceptors to the navigate() method, but that's not the method subclasses are interested in overriding.
Is there an easy way to tell CDI to intercept a method that otherwise wouldn't be intercepted?
I came up with a couple of general approaches to solve this but none of them seems very promising:
Somehow get the proxy object that called me. That would require some sort of self-injection that replicates the select() call made in the "framework" class.
Get the list of interceptors for the method from CDI and call them manually. Somehow.
Use DeltaSpike's EnableInterceptorsProxyFactory http://deltaspike.apache.org/documentation/proxy.html to wrap this. That could be slow and/or uncover other limitations.
There may be another option with CDI extensions, but I'm not sure what an extension is capable of.
I've already tried turning everything upside-down and using decorators instead of a base class in the hopes that a call to the delegate object would get intercepted but it didn't, at least not in JBoss EAP 6.x (most likely 6.4, but it could be an earlier version when I tested).
The simplest solution I found (which for some obscure reason hadn't occurred to me before) is making navigate() static and passing the object explicitly (e.g. as self).
Looking from the outside the class gets a bit weird since it looks like it could have a regular non-static method but has a static one. OTOH it does the job and is easy to understand. I needed the current proxy object so I passed it in. It's trivial and it keeps interceptor behavior.
There are just a few calls that have to be changed in my project, but other projects will have different needs so it isn't a general solution unfortunately. That's why I am not accepting my own answer.
I am a bit confused as to why someone would use #PreAuthorize("denyAll") for a method. As per the spring security documentation, it always evaluates to false.
If we are not going to allow access to a particular method, what is the point of keeping such a method. Why not comment it out? Or is it that it can still be accessed from within the same class?
I am trying to understand under what scenario such a requirement would arise.
One small clarification that I found in general for deny all was
#DenyAll annotation can be used to restrict business interface access from anyone, logged in or not. The method is still invokable from within the bean class itself.
So the jist is it can be used for a method which is public for some reason or have been exposed (perhaps it implements an interface) but should never be called directly from outside. However they can be called from inside(within the class).
here is the link
One real example that I can give you is (which is quite related with my work). We have 2 business unit with same code base. Now in one unit there is a feature where some mobile reseller can directly call a service which cancels the voucher directly to the operator end but in the other unit we needed to block this due to some business rule. Since we use the same interface in both system so in one system we blocked its usage using denyall
Hope this gives you a clear idea.
I decorate my service classes in this way which requires the individual inner service methods to override the denying class level PreAuth annotation. This ensures that each method in the class will be appropriately secured w/a fallback to denyAll.
I know this is old but I stumbled on it looking for the syntax for #PreAuthorize('denyAll') and thought I'd throw my 2cents in.
I have the following requirement: before each method, I need to perform some set-ups, and, after each method, I need to perform some clean-ups. For example, after each method is executed, I need to dump logs in SQL Server.
How can I create custom annotations for this type of repetitive tasks?
Please note that, due to certain design considerations, I cannot accommodate JUnit in my application.
It sounds like you are trying to recreate spring aspects, see this:
http://docs.spring.io/spring/docs/2.0.x/reference/aop.html
However, you may feel like adding a dependency on spring is too large an undertaking, you could consider just depending on aspectj:
http://www.eclipse.org/aspectj/
As a last alternative, you could make your class implement an interface, and then write a "wrapper" implementation of that interface, that merely wraps another implementation and does before/after logic. That is by far the simplest way to do this, and I do that all the time.
One last alternative is to use a duck typed proxy:
http://docs.oracle.com/javase/6/docs/api/java/lang/reflect/Proxy.html
However, I don't recommend doing that.
On a side note, I have never heard of a project that can't accomodate junit or some kind of testing framework. If you are not planning to write unit tests, you're going to have an exponentially tough time writing large applications.