Periodic java logging - java.util.logging

Can i flush all the logs based on time interval using configuration file. Searched a lot. Didn't find any. Short cut is using Timer ourselves and flush all loggers. But wanted to know whether configuraiton file allows it.

The configuration file options are explained in the LogManager documentation. At this time, the only way to do this is via the configuration file is to use the 'config' option to install your custom code to flush all loggers and perform the timer management. If you need to access to the JVM lifecycle, you can create a custom handler that ignores all log records but listens to constructor and close method calls.
public class FlushAllHandler extends Handler {
private final ScheduledExecutorService ses;
private final Future<?> task;
public FlushAllHandler() {
//TODO: Look these up from the LogManager.
super.setLevel(Level.OFF); //Ignore all published records.
ses = Executors.newScheduledThreadPool(1);
long delay = 1L;
TimeUnit unit = TimeUnit.HOURS;
task = ses.scheduleWithFixedDelay(new Task(), delay, delay, unit);
}
#Override
public void publish(LogRecord record) {
//Allow a trigger filter to kick off a flush.
if (isLoggable(record)) {
ses.execute(new Task());
}
}
#Override
public void flush() {
}
#Override
public void close() throws SecurityException {
super.setLevel(Level.OFF);
task.cancel(false);
ses.shutdown();
try {
ses.awaitTermination(30, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt();
}
ses.shutdownNow();
}
private static class Task implements Runnable {
Task() {
}
#Override
public void run() {
final ArrayList<Handler> handlers = new ArrayList<>();
final LogManager manager = LogManager.getLogManager();
synchronized (manager) { //avoid ConcurrentModificationException
final Enumeration<String> e = manager.getLoggerNames();
while (e.hasMoreElements()) {
final Logger l = manager.getLogger(e.nextElement());
if (l != null) {
Collections.addAll(handlers, l.getHandlers());
}
}
}
//Don't hold LogManager lock while flushing handlers.
for (Handler h : handlers) {
h.flush();
}
}
}
}

Related

android, how to unit test BroadcastReceiver which uses doAsync()

on android app, using Broadcastreceiver to handle the notification click.
public class NotificationReceiver extends BroadcastReceiver {
public void onReceive(final Context context, final Intent intent) {
final PendingResult asyncResult = goAsync();
ExecutorService executor = Executors.newSingleThreadExecutor();
asycTask(executor, new Runnable() {
#Override
public void run() {
handleAction(context, intent); //a length process
asyncResult.finish(); //<=== unit test throws exception, asyncResult is null
}
});
}
#VisibleForTesting
void asycTask(ExecutorService executor, final Runnable task) {
try {
executor.execute(task);
} catch (Throwable ex) {}
}
}
in the unit test
#Test
public void test_{
NotificationReceiver receiver = new NotificationReceiver();
final CountDownLatch latch = new CountDownLatch(1);
receiver.onReceive(application, intent);
latch.await(10, TimeUnit.SECONDS);
// verify
// ... ...
}
but it throws an exception because the asyncResult is null.
How to test when it uses doAsync()?
fond a way, there must be better one tho.
BroadcastReceiver.PendingResult pendingResultMock =
mock(BroadcastReceiver.PendingResult.class);
NotificationReceiver receiverSpy = spy(new NotificationReceiver());
doReturn(pendingResultMock).when(receiverSpy).goAsync();

how to propagate the ServiceRequestContext to my customized thread pool

I have a scenario, which process armeria request, and dispatch some event to guava's EventBus. the problem is I loss the context while process the event in the EventBus handler.
I want to know is there any way to let the event processor access ServiceRequestContext.
class EventListener {
#Subscribe
public void process(SomeCustomizedClass event) {
final ServiceRequestContext context = ServiceRequestContext.currentOrNull();
log.info("process ServiceRequestContext context={}", context);
}
}
register the event handler.
EventBus eventBus = new AsyncEventBus(ThreadPoolTaskExecutor());
eventBus.register(new EventListener());
here is my Armeria service
#Slf4j
public class NameAuthRestApi {
final NameAuthService nameAuthService;
#Post("/auth")
#ProducesJson
public Mono<RealNameAuthResp> auth(RealNameAuthReq req) {
return nameAuthService.auth(NameAuthConverter.CONVERTER.toDto(req))
.handle((result, sink) -> {
if (result.isSuccess()) {
// I post an event here, but the event process couldn't access the ServiceRequestContext
// that's would be the problem.
eventBus.post(new SomeCustomizedClass(result));
final RealNameAuthResp realNameAuthResp = new RealNameAuthResp();
realNameAuthResp.setTradeNo(result.getTradeNo());
realNameAuthResp.setSuccess(true);
sink.next(realNameAuthResp);
sink.complete();
} else {
sink.error(new SystemException(ErrorCode.API_ERROR, result.errors()));
}
});
}
}
You need to do:
public Mono<RealNameAuthResp> auth(ServiceRequestContxt ctx, RealNameAuthReq req) {
// Executed by an EventLoop 1.
// This thread has the ctx in its thread local.
return nameAuthService.auth(NameAuthConverter.CONVERTER.toDto(req))
.handle((result, sink) -> {
// Executed by another EventLoop 2.
// But this doens't.
try (SafeCloseable ignord = ctx.push()) {
if (result.isSuccess()) {
...
} else {
...
}
}
});
}
The problem is that the handle method is executed by another thread that does not have the ctx in its thread local. So, you should manually set the ctx.
You can achieve the same effect using xAsync method with the ctx.eventLoop():
public Mono<RealNameAuthResp> auth(ServiceRequestContxt ctx, RealNameAuthReq req) {
return nameAuthService.auth(NameAuthConverter.CONVERTER.toDto(req))
.handleAsync((result, sink) -> {
if (result.isSuccess()) {
...
} else {
...
}
}, ctx.eventLoop());
}
We have two ways to solve this:
First, use the executor which has the ctx:
ctx.eventLoop().submit(new Task(new Event("eone")));
// If it's blocking task, then we must use ctx.blockingTaskExecutor().
Or, propagate the ctx manually:
#Slf4j
public static class Task implements Runnable {
private final Event event;
private final ServiceRequestContext ctx;
Task(Event event) {
this.event = event;
ctx = ServiceRequestContext.current();
}
#Override
public void run() {
try (SafeCloseable ignored = ctx.push()) {
...
}
}
}
#minwoox, to simplify, my code would be looks like this
public class NameAuthRestApi {
JobExecutor executor = new JobExecutor();
#Post("/code")
public HttpResponse authCode(ServiceRequestContext ctx) {
try (SafeCloseable ignore = ctx.push()) {
executor.submit(new Task(new Event("eone")));
}
return HttpResponse.of("OK");
}
#Getter
#AllArgsConstructor
public static class Event {
private String name;
}
#RequiredArgsConstructor
#Slf4j
public static class Task implements Runnable {
final Event event;
#Override
public void run() {
// couldn't access ServiceRequestContext here
ServiceRequestContext ctx = ServiceRequestContext.currentOrNull();
log.info("ctx={}, event={}", ctx, event);
}
}
public static class JobExecutor {
ExecutorService executorService = Executors.newFixedThreadPool(2);
public void submit(Task task) {
executorService.submit(task);
}
}
}

Manual pause and resume functionality in AWS SWF java framework

Does SWF natively supports manual pause and resume workflow functionality in java framework? If not is there any way to achieve to achieve that semantics?
Edit: I implemented following example, seems to be working with initial testing. Is there anything which can break with this. My workflow is going to be long running (~3-5 hours) with same activity being multiple times with different params.
import com.amazonaws.services.simpleworkflow.flow.annotations.Asynchronous;
import com.amazonaws.services.simpleworkflow.flow.core.Promise;
import com.amazonaws.services.simpleworkflow.flow.core.Settable;
public class GreeterWorkflowImpl implements GreeterWorkflow {
private GreeterActivitiesClient operations = new GreeterActivitiesClientImpl();
Settable<Void> paused = new Settable<>();
public void greet() {
Promise<String> fs = getGreeting(0, operations.getName());
print(fs);
}
#Asynchronous
private Promise<String> getGreeting(int count, Promise<String> name)
{
if (count > 10)
return name;
return getGreeting(count, name, paused);
}
#Asynchronous
private Promise<String> getGreeting(int count, Promise<String> name, Settable<Void> paused) {
Promise<String> returnString = operations.getGreeting(name.get());
return getGreeting(count + 1, returnString);
}
#Asynchronous
private void print(Promise<String> finalString)
{
System.out.println("Final String is " + finalString.get());
}
// #Signal method
#Override
public void pause() {
paused = new Settable<>();
}
// #Signal method
#Override
public void resume() {
paused.set(null);
}
}
In case you get multiple signals for resume, you will be setting the paused settable again (which is already ready) so you might end up with unhandled IllegalStateException

Akka "Best Effort Retry" with RxJava

I am curious about using RxJava to implement best effort retry in Akka, without Persistent Actors. The idea is to use Rx's retry method to keep asking until a response is received from the destination actor.
Other examples of this is hard to find. Are there any Akka gurus out there that could verify this implementation, or point me to a better solution?
Example:
public class RxWithAkka {
private final Logger LOGGER = LoggerFactory.getLogger(getClass());
public static final Timeout TIMEOUT = Timeout.apply(10, TimeUnit.MILLISECONDS);
private final ActorRef actor;
private final ActorSystem actorSystem;
public RxWithAkka(ActorSystem actorSystem) {
this.actorSystem = actorSystem;
this.actor = actorSystem.actorOf(Props.create(MyActor.class));
}
public Observable<Object> ping() {
return createObservable()
.doOnError(t -> LOGGER.warn(t.getMessage()))
.retry();
}
Observable<Object> createObservable() {
return Observable.create(subscriber -> {
LOGGER.info("Send ping");
Patterns.ask(actor, "ping", TIMEOUT)
.onComplete(new OnComplete<Object>() {
#Override
public void onComplete(Throwable failure, Object success) throws Throwable {
if (success != null) {
subscriber.onNext(success);
subscriber.onCompleted();
} else {
subscriber.onError(failure);
}
}
}, actorSystem.dispatcher());
});
}
}
Example actor to demonstrate message not received and timeout:
public class MyActor extends UntypedActor {
private int counter = 0;
#Override
public void onReceive(Object message) throws Exception {
switch (counter++) {
case 0:
// ignore message
break;
case 1:
// timeout
Thread.sleep(200);
break;
default:
getSender().tell("pong", getSelf());
}
}
}
}
Test:
public class RxWithAkkaTest {
#Test
public void testIt() throws Exception {
ActorSystem system = ActorSystem.create("system");
RxWithAkka example = new RxWithAkka(system);
String res = (String) example.ping().toBlocking().first();
assertThat(res).isEqualTo("pong");
}
}
In RxJava, you can use the timeout operator in conjunction with retry.

Restarting a cancelled scheduler in akka

I am just starting with Akka and have created a test application. In it I create a bunch of actors who create a scheduler to generate a heartbeat event. Upon another type of event, I cancel the scheduler with heartbeat.cancel();, but I'd like to restart it when another event occurs. If I recreate the scheduler I see that the memory consumption increases continuously.
The question then would be either how do I resume the scheduler or how do I dispose the scheduler properly.
This is the code for that Actor
public class Device extends UntypedActor {
enum CommunicationStatus{
OK,
FAIL,
UNKNOWN
}
private static class Heartbeat {
}
public final String deviceId;
private CommunicationStatus commStatus;
private Cancellable heartBeatScheduler;
public Device(String Id)
{
deviceId = Id;
commStatus = CommunicationStatus.UNKNOWN;
}
#Override
public void preStart() {
getContext().system().eventStream().subscribe(getSelf(), DeviceCommunicationStatusUpdated.class);
startHeartbeat();
}
#Override
public void postStop() {
stopHeartBeat();
}
private void startHeartbeat() {
LoggingAdapter log = Logging.getLogger(getContext().system(), this);
log.info("Starting heartbeat");
heartBeatScheduler = getContext().system().scheduler().
schedule(Duration.Zero(),
Duration.create(1, TimeUnit.SECONDS),
getContext().self(),
new Heartbeat(),
getContext().system().dispatcher(),
ActorRef.noSender());
}
private void stopHeartBeat() {
if(!heartBeatScheduler.isCancelled()) {
LoggingAdapter log = Logging.getLogger(getContext().system(), this);
log.info("Stopping heartbeat");
heartBeatScheduler.cancel();
}
}
public String getDeviceId() {
return deviceId;
}
public CommunicationStatus getCommunicationStatus(){
return commStatus;
}
#Override
public void onReceive(Object message) throws Exception {
LoggingAdapter log = Logging.getLogger(getContext().system(), this);
if(message instanceof Heartbeat){
log.info("Pum, pum");
}
else if (message instanceof DeviceCommunicationStatusUpdated){
DeviceCommunicationStatusUpdated event = (DeviceCommunicationStatusUpdated) message;
if(event.deviceId == this.deviceId){
log.info("Received communication status update. '{}' is now {}", deviceId, event.state);
this.commStatus =
event.state == DeviceCommunicationStatusUpdated.State.OK ?
CommunicationStatus.OK : CommunicationStatus.FAIL;
if(commStatus == CommunicationStatus.OK && heartBeatScheduler.isCancelled()){
startHeartbeat();
}
else {
stopHeartBeat();
}
}
}
else unhandled(message);
}
}
Finally there is no leak, it's just that I'm new to Java and was impatient with the garbage collection. In any case, I would like to know about the resetting / restarting of a scheduler.