add feed refresh engine metrics

This commit is contained in:
Athou
2023-05-26 15:20:17 +02:00
parent 0626e5cd7a
commit f10cfd7ad0
2 changed files with 27 additions and 6 deletions

View File

@@ -1,6 +1,7 @@
import { Accordion, Tabs } from "@mantine/core" import { Accordion, Box, Tabs } from "@mantine/core"
import { client } from "app/client" import { client } from "app/client"
import { Loader } from "components/Loader" import { Loader } from "components/Loader"
import { Gauge } from "components/metrics/Gauge"
import { Meter } from "components/metrics/Meter" import { Meter } from "components/metrics/Meter"
import { MetricAccordionItem } from "components/metrics/MetricAccordionItem" import { MetricAccordionItem } from "components/metrics/MetricAccordionItem"
import { Timer } from "components/metrics/Timer" import { Timer } from "components/metrics/Timer"
@@ -15,11 +16,17 @@ const shownMeters: { [key: string]: string } = {
"com.commafeed.backend.feed.FeedRefreshUpdater.entryCacheMiss": "Entry cache miss rate", "com.commafeed.backend.feed.FeedRefreshUpdater.entryCacheMiss": "Entry cache miss rate",
} }
const shownGauges: { [key: string]: string } = {
"com.commafeed.backend.feed.FeedRefreshEngine.queue.size": "Queue size",
"com.commafeed.backend.feed.FeedRefreshEngine.worker.active": "Feed Worker active",
"com.commafeed.backend.feed.FeedRefreshEngine.updater.active": "Feed Updater active",
}
export function MetricsPage() { export function MetricsPage() {
const query = useAsync(() => client.admin.getMetrics(), []) const query = useAsync(() => client.admin.getMetrics(), [])
if (!query.result) return <Loader /> if (!query.result) return <Loader />
const { meters, timers } = query.result.data const { meters, gauges, timers } = query.result.data
return ( return (
<Tabs defaultValue="stats"> <Tabs defaultValue="stats">
<Tabs.List> <Tabs.List>
@@ -39,6 +46,15 @@ export function MetricsPage() {
</MetricAccordionItem> </MetricAccordionItem>
))} ))}
</Accordion> </Accordion>
<Box pt="xs">
{Object.keys(shownGauges).map(g => (
<Box key={g}>
<span>{shownGauges[g]}&nbsp;</span>
<Gauge gauge={gauges[g]} />
</Box>
))}
</Box>
</Tabs.Panel> </Tabs.Panel>
<Tabs.Panel value="timers" pt="xs"> <Tabs.Panel value="timers" pt="xs">

View File

@@ -18,6 +18,7 @@ import javax.inject.Singleton;
import org.apache.commons.lang3.time.DateUtils; import org.apache.commons.lang3.time.DateUtils;
import org.hibernate.SessionFactory; import org.hibernate.SessionFactory;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.Meter; import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry; import com.codahale.metrics.MetricRegistry;
import com.commafeed.CommaFeedConfiguration; import com.commafeed.CommaFeedConfiguration;
@@ -45,8 +46,8 @@ public class FeedRefreshEngine implements Managed {
private final ExecutorService feedProcessingLoopExecutor; private final ExecutorService feedProcessingLoopExecutor;
private final ExecutorService refillLoopExecutor; private final ExecutorService refillLoopExecutor;
private final ExecutorService refillExecutor; private final ExecutorService refillExecutor;
private final ExecutorService workerExecutor; private final ThreadPoolExecutor workerExecutor;
private final ExecutorService databaseUpdaterExecutor; private final ThreadPoolExecutor databaseUpdaterExecutor;
@Inject @Inject
public FeedRefreshEngine(SessionFactory sessionFactory, FeedDAO feedDAO, FeedRefreshWorker worker, FeedRefreshUpdater updater, public FeedRefreshEngine(SessionFactory sessionFactory, FeedDAO feedDAO, FeedRefreshWorker worker, FeedRefreshUpdater updater,
@@ -65,6 +66,10 @@ public class FeedRefreshEngine implements Managed {
this.refillExecutor = newDiscardingSingleThreadExecutorService(); this.refillExecutor = newDiscardingSingleThreadExecutorService();
this.workerExecutor = newBlockingExecutorService(config.getApplicationSettings().getBackgroundThreads()); this.workerExecutor = newBlockingExecutorService(config.getApplicationSettings().getBackgroundThreads());
this.databaseUpdaterExecutor = newBlockingExecutorService(config.getApplicationSettings().getDatabaseUpdateThreads()); this.databaseUpdaterExecutor = newBlockingExecutorService(config.getApplicationSettings().getDatabaseUpdateThreads());
metrics.register(MetricRegistry.name(getClass(), "queue", "size"), (Gauge<Integer>) queue::size);
metrics.register(MetricRegistry.name(getClass(), "worker", "active"), (Gauge<Integer>) workerExecutor::getActiveCount);
metrics.register(MetricRegistry.name(getClass(), "updater", "active"), (Gauge<Integer>) databaseUpdaterExecutor::getActiveCount);
} }
@Override @Override
@@ -185,7 +190,7 @@ public class FeedRefreshEngine implements Managed {
/** /**
* returns an ExecutorService with a single thread that discards tasks if a task is already running * returns an ExecutorService with a single thread that discards tasks if a task is already running
*/ */
private ExecutorService newDiscardingSingleThreadExecutorService() { private ThreadPoolExecutor newDiscardingSingleThreadExecutorService() {
ThreadPoolExecutor pool = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue<>()); ThreadPoolExecutor pool = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue<>());
pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy()); pool.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
return pool; return pool;
@@ -194,7 +199,7 @@ public class FeedRefreshEngine implements Managed {
/** /**
* returns an ExecutorService that blocks submissions until a thread is available * returns an ExecutorService that blocks submissions until a thread is available
*/ */
private ExecutorService newBlockingExecutorService(int threads) { private ThreadPoolExecutor newBlockingExecutorService(int threads) {
ThreadPoolExecutor pool = new ThreadPoolExecutor(threads, threads, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue<>()); ThreadPoolExecutor pool = new ThreadPoolExecutor(threads, threads, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue<>());
pool.setRejectedExecutionHandler((r, e) -> { pool.setRejectedExecutionHandler((r, e) -> {
if (e.isShutdown()) { if (e.isShutdown()) {