Merge pull request #5704 from deathbeam/add-logging-for-executor
Add executor service logger that logs exceptions
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user