How can Spring Boot Admin send custom notifications for actuator metric change? - spring-boot-admin

Spring Boot Admin provides notification feature only for status up or down of the application. I want to send email notification for some metric change in actuator endpoint. could you please guide me how can I configure this?
Simple notification for UP/DOWN of the application
#Configuration
public class NotifierConfiguration {
#Autowired
private Notifier notifier;
#Primary
#Bean(initMethod = "start", destroyMethod = "stop")
public RemindingNotifier remindingNotifier() {
RemindingNotifier notifier = new RemindingNotifier(notifier, repository);
notifier.setReminderPeriod(Duration.ofMinutes(10));
notifier.setCheckReminderInverval(Duration.ofSeconds(10));
return notifier;
}
}
This is for the UP?DOWN of the application. I want to configure in some metric of the actuator endpoint

I don't think there's an easy way to do that at the moment.
Notifications are sent by classes implementing the Notifier interface. These classes are consuming a Flux of InstanceEvent to produce these notifications. These events are triggered when there are changes on an instance info/status actuator endpoint, when an instance is registered/unregistered, etc. To create notifications for actuator metrics, you should therefore create a custom InstanceEvent (say InstanceMetricsChangedEvent) each time there's some changes on an instance metrics actuator endpoint. Maybe you can have a look at how InstanceInfoChangedEvent are triggered and see if it's possible to do something similar with your InstanceMetricsChangedEvent. Have a look at : InfoUpdater and InfoUpdateTrigger.

Related

Can NestFactory.create in Nestjs subscribe to topics on kafka?

The documentation suggests using NestFactory.createMicroservice to create a transport subscribing app.
I currently have a REST based microservice that contains domain logic and connection to the database. I'd like to subscribe on that microservice to Kafka messages. Is it possible to do this in a scope of this single microservice? I can't see that in the docs.
It makes me wonder if the pattern should be: I should create an extra microservice with NestFactory.createMicroservice that will connect to Kafka and then will distribute message to my REST API... over REST? This would mean that the rest api would have all possible "actions" happen over rest, but the intermittent microservice will be triggering it upon Kafka's message.
If that was true, does that mean that as my application scales, I might end up with one Kafka subscribing microservice per one rest microservice? Or will there be one subscribing microservice that will trigger multiple REST APIs? Or perhaps... it depends on the use case?
It is possible to connect both approaches in nest - microservice and normal app. The documentation doesn't mention it, but FAQ explains how to make a Hybrid application.
The GRPC example shows it in action
import { NestFactory } from '#nestjs/core';
import { MicroserviceOptions } from '#nestjs/microservices';
import { AppModule } from './app.module';
import { grpcClientOptions } from './grpc-client.options';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.connectMicroservice<MicroserviceOptions>(grpcClientOptions);
await app.startAllMicroservicesAsync();
await app.listen(3001);
console.log(`Application is running on: ${await app.getUrl()}`);
}
bootstrap();
This way you can have rest api with kafka/rabbit/grpc connected

Expose REST controller only during testing by using "test profile"

For better testability of our application I'm adding a REST controller which allows setting certain states, e.g. http://localhost:8090/test-api/customer would allow creating a new customer in the application's database for further tests.
The class would basically look like this:
#RequestScoped
#Path("/test-api/customer")
public class TestController {
#POST
public void createCustomer() {}
}
Now I'd like this controller to be available only for testing, i.e. the production system should not expose this endpoint. Is there something like a "testing profile" or "testing annotation" like a Spring Boot profile I can add to this class to hide it from the production system?

I want to expose my existing controller as a Restful service

I have an application where I'm registering a user so user will enter his data on JSP page and the data will be save into DB, the flow will be JSP->dispatcher->controller->Service->Dao.
Now in MemberController which is delegating the request to the Service, has a method register() which will take the MemberDto as a parameter now and return the Successfull msg to the success.jsp page. Sometihng like user registered successfully.
public String Register(MemberDto memberDto)
Now I want to expose this same method as RestFul service using Jersey for partners and also use this same method within my application as a normal MVC flow. How can I acheive this
So u want to use Jersey so import the jersey library to support JAX-RS.
#Path("/classlevelpath")
public class MyController {
#POST
#Produces(MediaType.APPLICATION-XML)
#Path("/register")
public String Register(MemberDto memberDto) {
}
}
Be careful JAX-RS (Jersey is an implementaion) and Spring REST annotations are different.
Annotate your rest class with #RestController. The best practice is to create another controller. By you can see this answer if you want to transform your existing controller: https://stackoverflow.com/questions/33062509/returning-view-from-spring-mvc-restcontroller

Autofac OWIN web api - load dependency based on request

How I can load a service dependency based on the route parameter?
My requirement is different, but I'll try to use a simple example.
A user can select the shipping provider (UPS, Fedex...) and the information is as part of the request model or route. Based on the route, I need to load the service class.
How it can be done in Autofac OWIN? Help on this will be appreciated
When you use the Autofac's OWIN integration, each request creates a new lifetime scope in which the current IOwinContext is registered, as you can see here.
You could then delegate the creation of your service to a factory that would take a dependency on IOwinContext.
public class MyServiceFactory
{
private readonly IOwinContext _context;
public MyServiceFactory(IOwinContext context)
{
_context = context;
}
public IService Create()
{
// inspect the context and determine which service you need
// you could return, dependending on, let's say, the URL
// - UpsService()
// - FedexService()
}
}
One thing you'll need to make sure is that you register your factory as InstancePerLifetimeScope since the IOwinContext will be different for each request.
Do you need to work at the OWIN layer, though? It will make things harder, and possibly a bit hacky, since OWIN is really just the HTTP layer, so there's no such thing as route data.
If you use ASP.NET Web API, you could base the factory on the current HttpRequestMessage if you use the RegisterHttpRequestMessage extension method.
You can then access route data through request.GetRequestContext().RouteData. Note that GetRequestContext is an extension method in the System.Net.Http namespace.
If you use ASP.NET MVC, you can register the AutofacWebTypesModule in the container, itself registering quite a few types in the container.
One of those is HttpRequestContext which has a RouteData property, so you can inject this one in the factory and apply your logic.

Architecture for stateful MVVM application with self contained client-server code and IoC container

I have an application which has multiple screens and talks to a WCF web service. I am using SimpleInjector for my favourite IoC container, and Caliburn Micro for MMVM with WPF.
I have a separate class implementation of ITransportClient that controls the connection to the web service and sends and receives messages.
The application has the following states:
Start up and initialisation of the application.
Display the login form.
Login form performs connection to chat server with ITransportClient.Login(username, password).
If login successful show a new MainWindow view, if failed prompt user for credentials again.
When logged in, MainWindow controls messages sent and received to the WCF service.
When connection is lost with the server (notified by ITransportClientCallback.OnTransportDisconnected), or when the user clicks logout, the Login form is displayed again.
With the technology I have available and this being my first MVVM project I have the following architectural and design questions:
What design pattern should I use to control showing a separate log in screen, then the main screen when connected, and revert back to the login screen when the connection has been lost?
Who should control the connection state of the chat application and where would this code sit? Would this state sit in the bootstrapper class?
Could I have the ITransportClient registered as a persistence instance scope, and have multiple forms control when required by injecting in to the ViewModel that required it (i.e. both the login form and the main window form)?
The ITransportClient interface is below:
public interface ITransportClientCallback
{
string OnReceivedMessage();
void OnTransportDisconnected();
}
// transport interface that client calls
public interface ITransportClient
{
bool SendLogin(string username, string password);
void SendLogout();
void SendMessage();
void RegisterCallback(ITransportClientCallback applicationHostCallback);
}
Along with the Caliburn.Micro bootstrapper code using SimpleInjector:
public class SimpleInjectorBootstrapper : Caliburn.Micro.Bootstrapper
{
private Container container;
protected override void Configure()
{
this.container = new Container();
this.container.Register<IWindowManager, WindowManager>();
this.container.Register<IEventAggregator, EventAggregator>();
this.container.Register<IAppViewModel, AppViewModel>();
this.container.RegisterSingle<ITransportClient, Transport.WCF.TransportClient>();
}
protected override object GetInstance(Type serviceType, string key)
{
return this.container.GetInstance(serviceType);
}
protected override IEnumerable<object> GetAllInstances(Type serviceType)
{
return this.container.GetAllInstances(serviceType);
}
protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
{
base.OnStartup(sender, e);
var appViewModel = this.container.GetInstance<IAppViewModel>();
var windowManager = this.container.GetInstance<IWindowManager>();
windowManager.ShowWindow(appViewModel);
}
}
What design pattern should I use to control showing a separate log in
screen, then the main screen when connected, and revert back to the
login screen when the connection has been lost?
In alot of cases, MVVM project is accompanied with a "mediator" or "messenger". All View Models can interact between each other through this mechanism by subscribing and publishing messages. All VMs would subscribe to "UserLoggedOutMessage" and do the necessary response (i.e. change its visual state to readonly, or not show anything at all). A separate bootstrapper can also "redirect" the user to the login screen.
Who should control the connection state of the chat application and
where would this code sit? Would this state sit in the bootstrapper
class?
One approach is to have an abstraction for the state of the app - this is equivalent to the HTTPContext.Current variable in asp.net. You could have a Session object which has a CurrentState read-only property with corresponding Login(), Logout(), SendMessage() methods which acts as a state machine. All View Model would then subscribe to the events as soon as the state of the app changes - again through the Mediator. The Session object can be a static variable on the bootstrapper, or a singleton injected to all VMs via the IoC.
Could I have the ITransportClient registered as a persistence instance
scope, and have multiple forms control when required by injecting in
to the ViewModel that required it (i.e. both the login form and the
main window form)?
that's definitely the idea. in most MVVM project, you would want to have a single instance of the dependencies injected to the VMs. This allow for more efficient memory use and also allow a clean object oriented model (as opposed to a procedural immutable transaction scripts).
Having said that, if this was an attempt to check for the "application state" I would change the level of the abstraction to something higher e.g. IApplicationStateMachine or IUserSession. This way if you want to ever support multiple user in one application instance, you could in theory have multiple instances of the IUserSession objects.