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.game.ItemManager;
|
||||||
import net.runelite.client.menus.MenuManager;
|
import net.runelite.client.menus.MenuManager;
|
||||||
import net.runelite.client.plugins.PluginManager;
|
import net.runelite.client.plugins.PluginManager;
|
||||||
import net.runelite.client.rs.ClientUpdateCheckMode;
|
|
||||||
import net.runelite.client.rs.ClientLoader;
|
import net.runelite.client.rs.ClientLoader;
|
||||||
|
import net.runelite.client.rs.ClientUpdateCheckMode;
|
||||||
import net.runelite.client.task.Scheduler;
|
import net.runelite.client.task.Scheduler;
|
||||||
import net.runelite.client.util.DeferredEventBus;
|
import net.runelite.client.util.DeferredEventBus;
|
||||||
|
import net.runelite.client.util.ExecutorServiceExceptionLogger;
|
||||||
import net.runelite.client.util.QueryRunner;
|
import net.runelite.client.util.QueryRunner;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import net.runelite.http.api.RuneLiteAPI;
|
import net.runelite.http.api.RuneLiteAPI;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class RuneLiteModule extends AbstractModule
|
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("updateCheckMode")).to(updateCheckMode);
|
||||||
bindConstant().annotatedWith(Names.named("developerMode")).to(developerMode);
|
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(OkHttpClient.class).toInstance(RuneLiteAPI.CLIENT);
|
||||||
bind(QueryRunner.class);
|
bind(QueryRunner.class);
|
||||||
bind(MenuManager.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.ClientToolbar;
|
||||||
import net.runelite.client.ui.NavigationButton;
|
import net.runelite.client.ui.NavigationButton;
|
||||||
import net.runelite.client.util.ImageUtil;
|
import net.runelite.client.util.ImageUtil;
|
||||||
import net.runelite.client.util.RunnableExceptionLogger;
|
|
||||||
|
|
||||||
@PluginDescriptor(
|
@PluginDescriptor(
|
||||||
name = "Account",
|
name = "Account",
|
||||||
@@ -108,7 +107,7 @@ public class AccountPlugin extends Plugin
|
|||||||
|
|
||||||
private void loginClick()
|
private void loginClick()
|
||||||
{
|
{
|
||||||
executor.execute(RunnableExceptionLogger.wrap(sessionManager::login));
|
executor.execute(sessionManager::login);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void logoutClick()
|
private void logoutClick()
|
||||||
|
|||||||
@@ -49,7 +49,6 @@ import net.runelite.client.game.ItemManager;
|
|||||||
import net.runelite.client.ui.ColorScheme;
|
import net.runelite.client.ui.ColorScheme;
|
||||||
import net.runelite.client.ui.components.IconTextField;
|
import net.runelite.client.ui.components.IconTextField;
|
||||||
import net.runelite.client.ui.components.PluginErrorPanel;
|
import net.runelite.client.ui.components.PluginErrorPanel;
|
||||||
import net.runelite.client.util.RunnableExceptionLogger;
|
|
||||||
import net.runelite.http.api.item.ItemPrice;
|
import net.runelite.http.api.item.ItemPrice;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,7 +103,7 @@ class GrandExchangeSearchPanel extends JPanel
|
|||||||
searchBar.setPreferredSize(new Dimension(100, 30));
|
searchBar.setPreferredSize(new Dimension(100, 30));
|
||||||
searchBar.setBackground(ColorScheme.MEDIUM_GRAY_COLOR);
|
searchBar.setBackground(ColorScheme.MEDIUM_GRAY_COLOR);
|
||||||
searchBar.setHoverBackgroundColor(ColorScheme.MEDIUM_GRAY_COLOR.brighter());
|
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.setLayout(new GridBagLayout());
|
||||||
searchItemsPanel.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
searchItemsPanel.setBackground(ColorScheme.DARK_GRAY_COLOR);
|
||||||
@@ -148,7 +147,7 @@ class GrandExchangeSearchPanel extends JPanel
|
|||||||
void priceLookup(String item)
|
void priceLookup(String item)
|
||||||
{
|
{
|
||||||
searchBar.setText(item);
|
searchBar.setText(item);
|
||||||
executor.execute(RunnableExceptionLogger.wrap(() -> priceLookup(true)));
|
executor.execute(() -> priceLookup(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void priceLookup(boolean exactMatch)
|
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.MaterialTab;
|
||||||
import net.runelite.client.ui.components.materialtabs.MaterialTabGroup;
|
import net.runelite.client.ui.components.materialtabs.MaterialTabGroup;
|
||||||
import net.runelite.client.util.ImageUtil;
|
import net.runelite.client.util.ImageUtil;
|
||||||
import net.runelite.client.util.RunnableExceptionLogger;
|
|
||||||
import net.runelite.client.util.StackFormatter;
|
import net.runelite.client.util.StackFormatter;
|
||||||
import net.runelite.http.api.hiscore.HiscoreClient;
|
import net.runelite.http.api.hiscore.HiscoreClient;
|
||||||
import net.runelite.http.api.hiscore.HiscoreEndpoint;
|
import net.runelite.http.api.hiscore.HiscoreEndpoint;
|
||||||
@@ -169,7 +168,7 @@ public class HiscorePanel extends PluginPanel
|
|||||||
searchBar.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
searchBar.setBackground(ColorScheme.DARKER_GRAY_COLOR);
|
||||||
searchBar.setHoverBackgroundColor(ColorScheme.DARK_GRAY_HOVER_COLOR);
|
searchBar.setHoverBackgroundColor(ColorScheme.DARK_GRAY_HOVER_COLOR);
|
||||||
searchBar.setMinimumSize(new Dimension(0, 30));
|
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()
|
searchBar.addMouseListener(new MouseAdapter()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ import net.runelite.client.ui.FontManager;
|
|||||||
import net.runelite.client.ui.PluginPanel;
|
import net.runelite.client.ui.PluginPanel;
|
||||||
import net.runelite.client.util.ImageUtil;
|
import net.runelite.client.util.ImageUtil;
|
||||||
import net.runelite.client.util.LinkBrowser;
|
import net.runelite.client.util.LinkBrowser;
|
||||||
import net.runelite.client.util.RunnableExceptionLogger;
|
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class InfoPanel extends PluginPanel
|
public class InfoPanel extends PluginPanel
|
||||||
@@ -139,7 +138,7 @@ public class InfoPanel extends PluginPanel
|
|||||||
{
|
{
|
||||||
if (e.getURL().toString().equals(RUNELITE_LOGIN))
|
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;
|
package net.runelite.client.util;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
public class RunnableExceptionLogger implements Runnable
|
public class RunnableExceptionLogger implements Runnable
|
||||||
{
|
{
|
||||||
private final Runnable runnable;
|
private final Runnable runnable;
|
||||||
|
|
||||||
private RunnableExceptionLogger(Runnable runnable)
|
|
||||||
{
|
|
||||||
this.runnable = runnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run()
|
public void run()
|
||||||
{
|
{
|
||||||
@@ -46,6 +43,7 @@ public class RunnableExceptionLogger implements Runnable
|
|||||||
catch (Throwable ex)
|
catch (Throwable ex)
|
||||||
{
|
{
|
||||||
log.warn("Uncaught exception in runnable {}", runnable, ex);
|
log.warn("Uncaught exception in runnable {}", runnable, ex);
|
||||||
|
throw ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user