Merge pull request #5704 from deathbeam/add-logging-for-executor

Add executor service logger that logs exceptions
This commit is contained in:
Tomas Slusny
2018-10-09 08:07:03 +02:00
committed by GitHub
8 changed files with 229 additions and 18 deletions

View File

@@ -46,15 +46,16 @@ import net.runelite.client.config.RuneLiteConfig;
import net.runelite.client.game.ItemManager;
import net.runelite.client.menus.MenuManager;
import net.runelite.client.plugins.PluginManager;
import net.runelite.client.rs.ClientUpdateCheckMode;
import net.runelite.client.rs.ClientLoader;
import net.runelite.client.rs.ClientUpdateCheckMode;
import net.runelite.client.task.Scheduler;
import net.runelite.client.util.DeferredEventBus;
import net.runelite.client.util.ExecutorServiceExceptionLogger;
import net.runelite.client.util.QueryRunner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.runelite.http.api.RuneLiteAPI;
import okhttp3.OkHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Slf4j
public class RuneLiteModule extends AbstractModule
@@ -73,7 +74,7 @@ public class RuneLiteModule extends AbstractModule
{
bindConstant().annotatedWith(Names.named("updateCheckMode")).to(updateCheckMode);
bindConstant().annotatedWith(Names.named("developerMode")).to(developerMode);
bind(ScheduledExecutorService.class).toInstance(Executors.newSingleThreadScheduledExecutor());
bind(ScheduledExecutorService.class).toInstance(new ExecutorServiceExceptionLogger(Executors.newSingleThreadScheduledExecutor()));
bind(OkHttpClient.class).toInstance(RuneLiteAPI.CLIENT);
bind(QueryRunner.class);
bind(MenuManager.class);

View File

@@ -39,7 +39,6 @@ import net.runelite.client.plugins.PluginDescriptor;
import net.runelite.client.ui.ClientToolbar;
import net.runelite.client.ui.NavigationButton;
import net.runelite.client.util.ImageUtil;
import net.runelite.client.util.RunnableExceptionLogger;
@PluginDescriptor(
name = "Account",
@@ -108,7 +107,7 @@ public class AccountPlugin extends Plugin
private void loginClick()
{
executor.execute(RunnableExceptionLogger.wrap(sessionManager::login));
executor.execute(sessionManager::login);
}
private void logoutClick()

View File

@@ -49,7 +49,6 @@ import net.runelite.client.game.ItemManager;
import net.runelite.client.ui.ColorScheme;
import net.runelite.client.ui.components.IconTextField;
import net.runelite.client.ui.components.PluginErrorPanel;
import net.runelite.client.util.RunnableExceptionLogger;
import net.runelite.http.api.item.ItemPrice;
/**
@@ -104,7 +103,7 @@ class GrandExchangeSearchPanel extends JPanel
searchBar.setPreferredSize(new Dimension(100, 30));
searchBar.setBackground(ColorScheme.MEDIUM_GRAY_COLOR);
searchBar.setHoverBackgroundColor(ColorScheme.MEDIUM_GRAY_COLOR.brighter());
searchBar.addActionListener(e -> executor.execute(RunnableExceptionLogger.wrap(() -> priceLookup(false))));
searchBar.addActionListener(e -> executor.execute(() -> priceLookup(false)));
searchItemsPanel.setLayout(new GridBagLayout());
searchItemsPanel.setBackground(ColorScheme.DARK_GRAY_COLOR);
@@ -148,7 +147,7 @@ class GrandExchangeSearchPanel extends JPanel
void priceLookup(String item)
{
searchBar.setText(item);
executor.execute(RunnableExceptionLogger.wrap(() -> priceLookup(true)));
executor.execute(() -> priceLookup(true));
}
private void priceLookup(boolean exactMatch)

View File

@@ -57,7 +57,6 @@ import net.runelite.client.ui.components.IconTextField;
import net.runelite.client.ui.components.materialtabs.MaterialTab;
import net.runelite.client.ui.components.materialtabs.MaterialTabGroup;
import net.runelite.client.util.ImageUtil;
import net.runelite.client.util.RunnableExceptionLogger;
import net.runelite.client.util.StackFormatter;
import net.runelite.http.api.hiscore.HiscoreClient;
import net.runelite.http.api.hiscore.HiscoreEndpoint;
@@ -169,7 +168,7 @@ public class HiscorePanel extends PluginPanel
searchBar.setBackground(ColorScheme.DARKER_GRAY_COLOR);
searchBar.setHoverBackgroundColor(ColorScheme.DARK_GRAY_HOVER_COLOR);
searchBar.setMinimumSize(new Dimension(0, 30));
searchBar.addActionListener(e -> executor.execute(RunnableExceptionLogger.wrap(this::lookup)));
searchBar.addActionListener(e -> executor.execute(this::lookup));
searchBar.addMouseListener(new MouseAdapter()
{
@Override

View File

@@ -55,7 +55,6 @@ import net.runelite.client.ui.FontManager;
import net.runelite.client.ui.PluginPanel;
import net.runelite.client.util.ImageUtil;
import net.runelite.client.util.LinkBrowser;
import net.runelite.client.util.RunnableExceptionLogger;
@Singleton
public class InfoPanel extends PluginPanel
@@ -139,7 +138,7 @@ public class InfoPanel extends PluginPanel
{
if (e.getURL().toString().equals(RUNELITE_LOGIN))
{
executor.execute(RunnableExceptionLogger.wrap(sessionManager::login));
executor.execute(sessionManager::login);
}
}
});

View File

@@ -0,0 +1,55 @@
/*
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.util;
import java.util.concurrent.Callable;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RequiredArgsConstructor
public class CallableExceptionLogger<V> implements Callable<V>
{
private final Callable<V> callable;
@Override
public V call() throws Exception
{
try
{
return callable.call();
}
catch (Throwable ex)
{
log.warn("Uncaught exception in callable {}", callable, ex);
throw ex;
}
}
public static <V> CallableExceptionLogger<V> wrap(Callable<V> callable)
{
return new CallableExceptionLogger<>(callable);
}
}

View File

@@ -0,0 +1,161 @@
/*
* Copyright (c) 2018, Tomas Slusny <slusnucky@gmail.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.runelite.client.util;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
/**
* Wrapper for ${@link ScheduledExecutorService} that will log all uncaught exceptions as warning to console
*/
@Slf4j
@RequiredArgsConstructor
public class ExecutorServiceExceptionLogger implements ScheduledExecutorService
{
private final ScheduledExecutorService service;
private static Runnable monitor(final Runnable command)
{
return RunnableExceptionLogger.wrap(command);
}
private static <V> Callable<V> monitor(final Callable<V> command)
{
return CallableExceptionLogger.wrap(command);
}
@Override
public <T> Future<T> submit(Callable<T> task)
{
return service.submit(monitor(task));
}
@Override
public <T> Future<T> submit(Runnable task, T result)
{
return service.submit(monitor(task), result);
}
@Override
public Future<?> submit(Runnable task)
{
return service.submit(monitor(task));
}
@Override
public void execute(Runnable command)
{
service.execute(monitor(command));
}
// Everything below is direct proxy to provided executor service
@Override
public void shutdown()
{
service.shutdown();
}
@Override
public List<Runnable> shutdownNow()
{
return service.shutdownNow();
}
@Override
public boolean isShutdown()
{
return service.isShutdown();
}
@Override
public boolean isTerminated()
{
return service.isTerminated();
}
@Override
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException
{
return service.awaitTermination(timeout, unit);
}
@Override
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException
{
return service.invokeAll(tasks);
}
@Override
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException
{
return service.invokeAll(tasks, timeout, unit);
}
@Override
public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException
{
return service.invokeAny(tasks);
}
@Override
public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
{
return service.invokeAny(tasks, timeout, unit);
}
@Override
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit)
{
return service.schedule(command, delay, unit);
}
@Override
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit)
{
return service.schedule(callable, delay, unit);
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
{
return service.scheduleAtFixedRate(command, initialDelay, period, unit);
}
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit)
{
return service.scheduleWithFixedDelay(command, initialDelay, delay, unit);
}
}

View File

@@ -24,18 +24,15 @@
*/
package net.runelite.client.util;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RequiredArgsConstructor
public class RunnableExceptionLogger implements Runnable
{
private final Runnable runnable;
private RunnableExceptionLogger(Runnable runnable)
{
this.runnable = runnable;
}
@Override
public void run()
{
@@ -46,6 +43,7 @@ public class RunnableExceptionLogger implements Runnable
catch (Throwable ex)
{
log.warn("Uncaught exception in runnable {}", runnable, ex);
throw ex;
}
}