Skip to content

Commit

Permalink
feat((quartz)): implement quartz endpoint for spring boot acutator
Browse files Browse the repository at this point in the history
Added acutator endpoints and autoconfiguration for the module.
 - Add end point for managing
jobs/trigger

fix #2
  • Loading branch information
sathyabodh committed Aug 8, 2019
1 parent 600ea04 commit ebaf195
Show file tree
Hide file tree
Showing 31 changed files with 1,469 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .settings/org.eclipse.m2e.core.prefs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
activeProfiles=
eclipse.preferences.version=1
resolveWorkspaceProjects=true
version=1
113 changes: 113 additions & 0 deletions src/main/asciidoc/endpoints/quartz.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
[[quartz]]
= Quartz

Quartz actuator provides end points for managing jobs and triggers

[[quartz-jobs]]
== Quartz Job (`quartz-jobs`)
The `quartz-jobs` endpoint provides access to application's quartz jobs

[[list-job]]
=== Retrieving jobs
To retrieve jobs, make `GET` request to `/actuator/quartz-jobs` as shown in the following curl-based example:

include::{snippets}/quartz-jobs/list/curl-request.adoc[]

The resulting response is similar to the following:

include::{snippets}/quartz-jobs/list/http-response.adoc[]

[[list-job-query-parameter]]
==== Query parameter
Jobs listing can be further filtered using `group` and `name` query parameter.The following table shows the supported query parameters:

[cols="2,4"]
include::{snippets}/quartz-jobs/list/request-parameters.adoc[]

[[list-job-response-structure]]
==== Response Structure
The response contains the details of the jobs managed by quartz.The following table describes
the structure of the response:

[cols="3,1,3"]
include::{snippets}/quartz-jobs/list/response-fields.adoc[]

[[job-detail]]
=== Retrieving Job details
To retrieve job details with trigger information, make GET request to `/actuator/quartz-jobs/{group}/{name}` as shown in the following curl-based example:

include::{snippets}/quartz-jobs/named/jobdetails/curl-request.adoc[]

[[job-detail-response-structure]]
==== Response Structure
The response contains details about the job and its associated triggers. The following table describes the structure of the response:

[cols="3,1,3"]
include::{snippets}/quartz-jobs/named/jobdetails/response-fields.adoc[]

[[pause-job]]
=== Pause Job
To pause particular job, make a `POST` request to `/actuator/quartz-jobs/{group}/{name}/pause` as shown in the following curl-based example:

include::{snippets}/quartz-jobs/named/job/pause/curl-request.adoc[]


[[resume-job]]
=== Resume Job
To resume particular job, make a `POST` request to `/actuator/quartz-jobs/{group}/{name}/resume` as shown in the following curl-based example:

include::{snippets}/quartz-jobs/named/job/resume/curl-request.adoc[]

[[pause-jobgroup]]
=== Pause Job group
To pause particular job group, make `POST` request to `/actuator/quartz-jobs/{group}` as shown in the following curl-based example:

include::{snippets}/quartz-jobs/named/jobgroup/pause/curl-request.adoc[]

[[resume-jobgroup]]
=== Resume Job group
To resume particular job group, make `POST` request to `/actuator/quartz-jobs/{group}` as shown in the following curl-based example:

include::{snippets}/quartz-jobs/named/jobgroup/resume/curl-request.adoc[]

[[quartz-triggers]]
== Quartz Triggers (`quartz-triggers`)
The `quartz-triggers` endpoint provides access to application's quartz triggers

[[list-triggers]]
=== Retrieving Triggers
To retrieve triggers, make `GET` request to `/actuator/quartz-triggers` as shown in the following curl-based example:

include::{snippets}/quartz-jobs/list/curl-request.adoc[]

The resulting response is similar to the following:

include::{snippets}/quartz-triggers/list/http-response.adoc[]

[[list-trigger-query-parameter]]
==== Query parameter
Triggers listing can be further filtered using `group` and `name` query parameter.The following table shows the supported query parameters:

[cols="2,4"]
include::{snippets}/quartz-triggers/list/request-parameters.adoc[]

[[list-trigger-response-structure]]
==== Response Structure
The response contains the details of the triggers managed by quartz.The following table describes
the structure of the response:

[cols="3,1,3"]
include::{snippets}/quartz-triggers/list/response-fields.adoc[]

[[pause-trigger]]
=== Pause Trigger
To pause particular trigger, make a `POST` request to `/actuator/quartz-triggers/{group}/{name}/pause` as shown in the following curl-based example:

include::{snippets}/quartz-triggers/named/trigger/pause/curl-request.adoc[]


[[resume-trigger]]
=== Resume Trigger
To resume particular trigger, make a `POST` request to `/actuator/quartz-triggers/{group}/{name}/resume` as shown in the following curl-based example:

include::{snippets}/quartz-triggers/named/trigger/resume/curl-request.adoc[]
25 changes: 25 additions & 0 deletions src/main/asciidoc/endpoints/quartz.adoc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[[quartz]] = Quartz

Quartz actuator provides end points for managing jobs and triggers

[[quartz-jobs]] == Quartz Job (`quartz-jobs`)

The `quartz-jobs` endpoint provides access to application's quartz jobs

[[pause-job]] === Pause Job To pause particular job, make a `POST`
request to `/actuator/quartz-jobs/{group}/{name}/pause` as shown in the
following curl-based example:

include::{snippets}/quartz-jobs/named/job/pause/curl-request.adoc[]

[[resume-job]] === Resume Job To resume particular job, make a `POST`
request to `/actuator/quartz-jobs/{group}/{name}/resume` as shown in the
following curl-based example:

include::{snippets}/quartz-jobs/named/job/resume/curl-request.adoc[]

[[pause-jobgroup]] === Pause Job group To pause particular job group,
make `POST` request to `/actuator/quartz-jobs/{group}` as shown in the
following curl-based example:

include::{snippets}/quartz-jobs/named/jobgroup/pause/curl-request.adoc[]
48 changes: 48 additions & 0 deletions src/main/asciidoc/endpoints/quartz.adoc.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<article>
<articleinfo>
<title></title>
</articleinfo>
<para>
[[quartz]] = Quartz
</para>
<para>
Quartz actuator provides end points for managing jobs and triggers
</para>
<para>
[[quartz-jobs]] == Quartz Job (<literal>quartz-jobs</literal>)
</para>
<para>
The <literal>quartz-jobs</literal> endpoint provides access to
application's quartz jobs
</para>
<para>
[[pause-job]] === Pause Job To pause particular job, make a
<literal>POST</literal> request to
<literal>/actuator/quartz-jobs/{group}/{name}/pause</literal> as shown
in the following curl-based example:
</para>
<para>
include::{snippets}/quartz-jobs/named/job/pause/curl-request.adoc[]
</para>
<para>
[[resume-job]] === Resume Job To resume particular job, make a
<literal>POST</literal> request to
<literal>/actuator/quartz-jobs/{group}/{name}/resume</literal> as
shown in the following curl-based example:
</para>
<para>
include::{snippets}/quartz-jobs/named/job/resume/curl-request.adoc[]
</para>
<para>
[[pause-jobgroup]] === Pause Job group To pause particular job group,
make <literal>POST</literal> request to
<literal>/actuator/quartz-jobs/{group}</literal> as shown in the
following curl-based example:
</para>
<para>
include::{snippets}/quartz-jobs/named/jobgroup/pause/curl-request.adoc[]
</para>
</article>
10 changes: 10 additions & 0 deletions src/main/asciidoc/index.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
:doctype: book
:toc: left
:toclevels: 4
:source-highlighter: prettify
:numbered:
:icons: font
:hide-uri-scheme:
:docinfo: shared,private

include::endpoints/quartz.adoc[leveloffset=+1]
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.sathyabodh.actuator.autoconfigure.cache;

import java.util.Map;

import org.sathyabodh.actuator.cache.CachesEndPoint;
import org.sathyabodh.actuator.cache.CachesEndPointWebExtension;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConditionalOnClass(CacheManager.class)
@AutoConfigureAfter(CacheAutoConfiguration.class)
public class CachesEndPointAutoConfiguration {

@Bean
@ConditionalOnMissingBean
@ConditionalOnEnabledEndpoint
public CachesEndPoint cachesEndPoint(Map<String, CacheManager> cacheManagers){
return new CachesEndPoint(cacheManagers);
}

@Bean
@ConditionalOnBean(CachesEndPoint.class)
public CachesEndPointWebExtension cachesEndPointWebExtension(CachesEndPoint cachesEndPoint){
return new CachesEndPointWebExtension(cachesEndPoint);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.sathyabodh.actuator.autoconfigure.quartz;

import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.sathyabodh.actuator.quartz.QuartzTriggerEndPoint;
import org.sathyabodh.actuator.quartz.QuartzTriggerEndPointWebExtension;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConditionalOnClass({Scheduler.class, SchedulerFactory.class})
@AutoConfigureAfter(QuartzAutoConfiguration.class)
public class QuartzTriggerEndPointAutoConfiguration {

@Bean
@ConditionalOnMissingBean
@ConditionalOnEnabledEndpoint
public QuartzTriggerEndPoint quartzTriggerEndPoint(Scheduler scheduler){
return new QuartzTriggerEndPoint(scheduler);
}

@Bean
@ConditionalOnBean(QuartzTriggerEndPoint.class)
public QuartzTriggerEndPointWebExtension quartzTriggerEndPointWebExtension(QuartzTriggerEndPoint quartzTriggerEndPoint){
return new QuartzTriggerEndPointWebExtension(quartzTriggerEndPoint);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.sathyabodh.actuator.autoconfigure.quartz;

import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.sathyabodh.actuator.quartz.QuartzJobEndPoint;
import org.sathyabodh.actuator.quartz.QuartzJobEndPointWebExtension;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConditionalOnClass({ Scheduler.class, SchedulerFactory.class })
@AutoConfigureAfter(QuartzAutoConfiguration.class)
public class QurtzJobEndPointAutoConfiguration {

@Bean
@ConditionalOnMissingBean
@ConditionalOnEnabledEndpoint
public QuartzJobEndPoint quartzJobEndPoint(Scheduler scheduler) {
return new QuartzJobEndPoint(scheduler);
}

@Bean
@ConditionalOnBean(QuartzJobEndPoint.class)
public QuartzJobEndPointWebExtension quartzJobEndPointWebExtension(QuartzJobEndPoint quartzJobEndPoint) {
return new QuartzJobEndPointWebExtension(quartzJobEndPoint);
}

}
77 changes: 77 additions & 0 deletions src/main/java/org/sathyabodh/actuator/cache/CachesEndPoint.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package org.sathyabodh.actuator.cache;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.sathyabodh.actuator.cache.exception.NonUniqueCacheException;
import org.sathyabodh.actuator.cache.model.CacheDetailModel;
import org.sathyabodh.actuator.cache.model.CacheEntryModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.actuate.endpoint.annotation.DeleteOperation;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
import org.springframework.boot.actuate.endpoint.annotation.Selector;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.lang.Nullable;

@Endpoint(id="caches")
public class CachesEndPoint {

private static Logger log = LoggerFactory.getLogger(CachesEndPoint.class);
private Map<String, CacheManager> cacheManagers ;

public CachesEndPoint(Map<String, CacheManager> cacheManagers) {
this.cacheManagers = cacheManagers;
}

@ReadOperation
public CacheDetailModel caches(){
final CacheDetailModel detailModel = new CacheDetailModel();
cacheManagers.entrySet().forEach(entry->detailModel.get(entry.getKey()).add(entry.getValue()));
return detailModel;
}

@ReadOperation
public CacheEntryModel cache(@Selector String name, @Nullable String cacheManager){
return findUniqueCache(name, cacheManager);
}

@DeleteOperation
public boolean evictCaches(@Selector String name, @Nullable String cacheManager){
CacheEntryModel cache = findUniqueCache(name, cacheManager);
return cache == null ? false:clearCache(cache);
}

private boolean clearCache(CacheEntryModel cacheEntryModel){
CacheManager cacheManager = cacheManagers.get(cacheEntryModel.getCacheManager());
if(cacheManager == null){
return false;
}
Cache cache = cacheManager.getCache(cacheEntryModel.getName());
if(cache == null){
return false;
}

log.info("Clearning cache:[{}]", cache.getName());
cache.clear();
log.info("Cleared cache:[{}]", cache.getName());
return true;
}

private CacheEntryModel findUniqueCache(String name, String cacheManager){
List<CacheEntryModel> caches = cacheManagers.entrySet().stream().filter(it-> cacheManager == null || cacheManager.equals(it.getKey()))
.map(entry->entry.getValue().getCache(name) == null ? null : new CacheEntryModel(entry.getKey(), entry.getValue().getCache(name)))
.filter(entry->entry != null).collect(Collectors.toList());
if(caches.size() > 1){
throw new NonUniqueCacheException(
String.format("Non unique cache name:%s. "
+ "Please use cacheManager name to uniquely identify", name));
}
return caches.isEmpty() ? null : caches.get(0);
}


}
Loading

0 comments on commit ebaf195

Please sign in to comment.