-
Notifications
You must be signed in to change notification settings - Fork 147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Microprofile Health #25186
base: master
Are you sure you want to change the base?
Add Microprofile Health #25186
Changes from all commits
dd7c5e4
a1c4b38
0490f26
7be24a9
3b9cc17
1ec8dd8
f0b52b8
b2842fe
cfab442
84b51ef
6f5fbdf
c21a583
1df0d36
7d13b7d
2d80b6d
88fcd1e
75ad0f6
ef217b5
2b2e6e8
9bea997
4f2fc1e
87035d1
35bb755
96528c9
c8ceff3
c1355d9
f80f757
67e74ef
f629daa
f3052c6
eb5af30
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
Manifest-Version: 1.0 | ||
Bundle-Description: MicroProfile Health :: API | ||
Bundle-License: Apache License, Version 2.0 | ||
Bundle-SymbolicName: org.eclipse.microprofile.health | ||
Bnd-LastModified: 1664892780713 | ||
Bundle-ManifestVersion: 2 | ||
Bundle-DocURL: https://microprofile.io/project/eclipse/microprofile-he | ||
alth/microprofile-health-api | ||
Bundle-Vendor: Eclipse Foundation | ||
Import-Package: jakarta.enterprise.util;version="[3.0,5)",jakarta.inje | ||
ct;version="[2.0,4)",org.eclipse.microprofile.health;version="[3.0,5) | ||
",org.eclipse.microprofile.health.spi;version="[1.1,2)" | ||
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))" | ||
Tool: Bnd-5.2.0.202010142003 | ||
Export-Package: org.eclipse.microprofile.health;version="3.0";uses:="j | ||
akarta.enterprise.util,jakarta.inject,org.eclipse.microprofile.health | ||
.spi",org.eclipse.microprofile.health.spi;version="1.1";uses:="org.ec | ||
lipse.microprofile.health" | ||
Bundle-Name: MicroProfile Health Check Bundle | ||
Bundle-Version: 4.0.1 | ||
Bundle-SCM: url="https://github.com/eclipse/microprofile-health/microp | ||
rofile-health-api",connection="scm:git:https://github.com/eclipse/mic | ||
roprofile-health.git/microprofile-health-api",developer-connection="s | ||
cm:git:[email protected]:eclipse/microprofile-health.git/microprofile-he | ||
alth-api",tag="4.0.1" | ||
Build-Jdk-Spec: 1.8 | ||
Created-By: 1.8.0_292 (AdoptOpenJDK) | ||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,89 @@ | ||||||||||||||||||||||||||||||
<?xml version="1.0" encoding="UTF-8"?> | ||||||||||||||||||||||||||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||||||||||||||||||||||||||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||||||||||||||||||||||||||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||||||||||||||||||||||||||||||
<modelVersion>4.0.0</modelVersion> | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
<parent> | ||||||||||||||||||||||||||||||
<groupId>org.glassfish.main.microprofile</groupId> | ||||||||||||||||||||||||||||||
<artifactId>microprofile-parent</artifactId> | ||||||||||||||||||||||||||||||
<version>7.0.21-SNAPSHOT</version> | ||||||||||||||||||||||||||||||
</parent> | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
<artifactId>health-glassfish</artifactId> | ||||||||||||||||||||||||||||||
<packaging>glassfish-jar</packaging> | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
<properties> | ||||||||||||||||||||||||||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||||||||||||||||||||||||||||||
<maven.compiler.release>17</maven.compiler.release> | ||||||||||||||||||||||||||||||
</properties> | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
<dependencies> | ||||||||||||||||||||||||||||||
<dependency> | ||||||||||||||||||||||||||||||
<groupId>org.glassfish.main.microprofile</groupId> | ||||||||||||||||||||||||||||||
<artifactId>microprofile-health</artifactId> | ||||||||||||||||||||||||||||||
<version>${project.version}</version> | ||||||||||||||||||||||||||||||
<scope>provided</scope> | ||||||||||||||||||||||||||||||
</dependency> | ||||||||||||||||||||||||||||||
<dependency> | ||||||||||||||||||||||||||||||
<groupId>jakarta.json.bind</groupId> | ||||||||||||||||||||||||||||||
<artifactId>jakarta.json.bind-api</artifactId> | ||||||||||||||||||||||||||||||
<scope>provided</scope> | ||||||||||||||||||||||||||||||
</dependency> | ||||||||||||||||||||||||||||||
<dependency> | ||||||||||||||||||||||||||||||
<groupId>jakarta.enterprise</groupId> | ||||||||||||||||||||||||||||||
<artifactId>jakarta.enterprise.cdi-api</artifactId> | ||||||||||||||||||||||||||||||
<scope>provided</scope> | ||||||||||||||||||||||||||||||
</dependency> | ||||||||||||||||||||||||||||||
</dependencies> | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
<build> | ||||||||||||||||||||||||||||||
<plugins> | ||||||||||||||||||||||||||||||
<plugin> | ||||||||||||||||||||||||||||||
<artifactId>maven-compiler-plugin</artifactId> | ||||||||||||||||||||||||||||||
<configuration> | ||||||||||||||||||||||||||||||
<release>17</release> | ||||||||||||||||||||||||||||||
</configuration> | ||||||||||||||||||||||||||||||
</plugin> | ||||||||||||||||||||||||||||||
<plugin> | ||||||||||||||||||||||||||||||
<groupId>org.apache.felix</groupId> | ||||||||||||||||||||||||||||||
<artifactId>maven-bundle-plugin</artifactId> | ||||||||||||||||||||||||||||||
<configuration> | ||||||||||||||||||||||||||||||
<supportedProjectTypes> | ||||||||||||||||||||||||||||||
<supportedProjectType>glassfish-jar</supportedProjectType> | ||||||||||||||||||||||||||||||
</supportedProjectTypes> | ||||||||||||||||||||||||||||||
<instructions> | ||||||||||||||||||||||||||||||
<!-- A list of packages that are exposed to classes outside the bundle --> | ||||||||||||||||||||||||||||||
<Export-Package> | ||||||||||||||||||||||||||||||
org.glassfish.microprofile.impl; | ||||||||||||||||||||||||||||||
</Export-Package> | ||||||||||||||||||||||||||||||
<Import-Package> | ||||||||||||||||||||||||||||||
jakarta.enterprise.context.spi; | ||||||||||||||||||||||||||||||
jakarta.enterprise.event; | ||||||||||||||||||||||||||||||
jakarta.enterprise.inject; | ||||||||||||||||||||||||||||||
jakarta.enterprise.inject.spi; | ||||||||||||||||||||||||||||||
jakarta.json.bind; | ||||||||||||||||||||||||||||||
jakarta.servlet; | ||||||||||||||||||||||||||||||
jakarta.servlet.http; | ||||||||||||||||||||||||||||||
org.eclipse.microprofile.health; | ||||||||||||||||||||||||||||||
org.glassfish.internal.api; | ||||||||||||||||||||||||||||||
org.glassfish.microprofile.health; | ||||||||||||||||||||||||||||||
org.glassfish.hk2.api; | ||||||||||||||||||||||||||||||
org.glassfish.hk2.utilities; | ||||||||||||||||||||||||||||||
</Import-Package> | ||||||||||||||||||||||||||||||
Comment on lines
+60
to
+73
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||||||||||||||||||||||||||
</instructions> | ||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||||||||||||||||||||||||||
</configuration> | ||||||||||||||||||||||||||||||
<executions> | ||||||||||||||||||||||||||||||
<execution> | ||||||||||||||||||||||||||||||
<id>osgi-bundle</id> | ||||||||||||||||||||||||||||||
<phase>package</phase> | ||||||||||||||||||||||||||||||
<goals> | ||||||||||||||||||||||||||||||
<goal>bundle</goal> | ||||||||||||||||||||||||||||||
</goals> | ||||||||||||||||||||||||||||||
</execution> | ||||||||||||||||||||||||||||||
</executions> | ||||||||||||||||||||||||||||||
</plugin> | ||||||||||||||||||||||||||||||
</plugins> | ||||||||||||||||||||||||||||||
</build> | ||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||
</project> |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,75 @@ | ||||||
/* | ||||||
* Copyright (c) 2024 Contributors to Eclipse Foundation. | ||||||
* | ||||||
* This program and the accompanying materials are made available under the | ||||||
* terms of the Eclipse Public License v. 2.0, which is available at | ||||||
* http://www.eclipse.org/legal/epl-2.0. | ||||||
* | ||||||
* This Source Code may also be made available under the following Secondary | ||||||
* Licenses when the conditions for such availability set forth in the | ||||||
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License, | ||||||
* version 2 with the GNU Classpath Exception, which is available at | ||||||
* https://www.gnu.org/software/classpath/license.html. | ||||||
* | ||||||
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 | ||||||
*/ | ||||||
package org.glassfish.microprofile.impl; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would rename this package. It doesn't even mention "health". For example:
Suggested change
If the package name is not "impl", then it can even be removed from |
||||||
|
||||||
import jakarta.enterprise.context.spi.CreationalContext; | ||||||
import jakarta.enterprise.event.Observes; | ||||||
import jakarta.enterprise.inject.spi.AfterDeploymentValidation; | ||||||
import jakarta.enterprise.inject.spi.Annotated; | ||||||
import jakarta.enterprise.inject.spi.Bean; | ||||||
import jakarta.enterprise.inject.spi.BeanManager; | ||||||
import jakarta.enterprise.inject.spi.Extension; | ||||||
import jakarta.enterprise.inject.spi.ProcessBean; | ||||||
|
||||||
import java.util.Collections; | ||||||
import java.util.Set; | ||||||
import java.util.concurrent.ConcurrentHashMap; | ||||||
|
||||||
import org.eclipse.microprofile.health.HealthCheck; | ||||||
import org.eclipse.microprofile.health.Liveness; | ||||||
import org.eclipse.microprofile.health.Readiness; | ||||||
import org.eclipse.microprofile.health.Startup; | ||||||
import org.glassfish.hk2.api.ServiceLocator; | ||||||
import org.glassfish.hk2.utilities.ServiceLocatorUtilities; | ||||||
import org.glassfish.internal.api.Globals; | ||||||
import org.glassfish.microprofile.health.HealthReporter; | ||||||
|
||||||
|
||||||
public class CollectHealthChecksExtension implements Extension { | ||||||
|
||||||
private final HealthReporter service; | ||||||
private final Set<Bean<HealthCheck>> healthChecks = Collections.newSetFromMap(new ConcurrentHashMap<>()); | ||||||
|
||||||
public CollectHealthChecksExtension() { | ||||||
ServiceLocator defaultBaseServiceLocator = Globals.getDefaultBaseServiceLocator(); | ||||||
HealthReporter healthReporterService = defaultBaseServiceLocator.getService(HealthReporter.class); | ||||||
if (healthReporterService == null) { | ||||||
ServiceLocatorUtilities.addClasses(defaultBaseServiceLocator, true, HealthReporter.class); | ||||||
healthReporterService = defaultBaseServiceLocator.getService(HealthReporter.class); | ||||||
} | ||||||
service = healthReporterService; | ||||||
} | ||||||
public <T> void processBeans(@Observes ProcessBean<T> beans) { | ||||||
Annotated annotated = beans.getAnnotated(); | ||||||
if (annotated.isAnnotationPresent(Liveness.class) || | ||||||
annotated.isAnnotationPresent(Readiness.class) || | ||||||
annotated.isAnnotationPresent(Startup.class)) { | ||||||
if (beans.getBean().getTypes().contains(HealthCheck.class)) { | ||||||
healthChecks.add((Bean<HealthCheck>) beans.getBean()); | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
public void afterDeploymentValidation(@Observes AfterDeploymentValidation adv, BeanManager beanManager) { | ||||||
healthChecks.forEach(bean -> { | ||||||
CreationalContext<HealthCheck> creationalContext = beanManager.createCreationalContext(bean); | ||||||
service.addHealthCheck("", bean.create(creationalContext)); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should bind the health checks to application name, which has to be unique. When undeployed, The problem with the current approach is that when 2 applications are deployed, they deploy all health checks under the same context name. When one of the applications is undeployed, it would remove health checks also from other applications. We need to add and remove health checks for a single application under a unique context. |
||||||
}); | ||||||
} | ||||||
|
||||||
|
||||||
|
||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package org.glassfish.microprofile.impl; | ||
|
||
|
||
import org.glassfish.api.StartupRunLevel; | ||
import org.glassfish.api.event.EventListener; | ||
import org.glassfish.hk2.runlevel.RunLevel; | ||
import org.glassfish.internal.api.Globals; | ||
import org.glassfish.internal.data.ApplicationInfo; | ||
import org.glassfish.internal.deployment.Deployment; | ||
import org.glassfish.microprofile.health.HealthReporter; | ||
import org.jvnet.hk2.annotations.Service; | ||
|
||
@Service(name = "healthcheck-service") | ||
@RunLevel(StartupRunLevel.VAL) | ||
public class HealthService implements EventListener { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's required to register the event listener, otherwise the event method won't be called:
|
||
|
||
|
||
@Override | ||
public void event(Event<?> event) { | ||
|
||
HealthReporter service = Globals.getDefaultHabitat().getService(HealthReporter.class); | ||
|
||
if (event.is(Deployment.APPLICATION_UNLOADED) && event.hook() instanceof ApplicationInfo appInfo) { | ||
service.removeAllHealthChecksFrom(appInfo.getName()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The healthchecks are registered with "" context root but here we want to remove them by |
||
} | ||
|
||
if (event.is(Deployment.APPLICATION_STARTED) && event.hook() instanceof ApplicationInfo appInfo) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Either remove this block, or use it to find out the application name to be used in the CDI extension for the application context name |
||
|
||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
* Copyright (c) 2024 Contributors to Eclipse Foundation. | ||
* | ||
* This program and the accompanying materials are made available under the | ||
* terms of the Eclipse Public License v. 2.0, which is available at | ||
* http://www.eclipse.org/legal/epl-2.0. | ||
* | ||
* This Source Code may also be made available under the following Secondary | ||
* Licenses when the conditions for such availability set forth in the | ||
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License, | ||
* version 2 with the GNU Classpath Exception, which is available at | ||
* https://www.gnu.org/software/classpath/license.html. | ||
* | ||
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 | ||
*/ | ||
package org.glassfish.microprofile.impl; | ||
|
||
import jakarta.json.bind.Jsonb; | ||
import jakarta.json.bind.JsonbBuilder; | ||
import jakarta.servlet.http.HttpServlet; | ||
import jakarta.servlet.http.HttpServletRequest; | ||
import jakarta.servlet.http.HttpServletResponse; | ||
|
||
import java.io.IOException; | ||
import java.util.List; | ||
import java.util.logging.Level; | ||
import java.util.logging.Logger; | ||
|
||
import org.eclipse.microprofile.health.HealthCheckResponse; | ||
import org.glassfish.internal.api.Globals; | ||
import org.glassfish.microprofile.health.HealthReport; | ||
import org.glassfish.microprofile.health.HealthReporter; | ||
|
||
public class HealthServlet extends HttpServlet { | ||
|
||
private static final Logger LOGGER = Logger.getLogger(HealthServlet.class.getName()); | ||
|
||
@Override | ||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { | ||
HealthReport healthReport; | ||
try { | ||
healthReport = Globals.getDefaultHabitat().getService(HealthReporter.class) | ||
.getReport(getReportKind(req.getRequestURI())); | ||
|
||
int httpStatus = switch (healthReport.status()) { | ||
case UP -> HttpServletResponse.SC_OK; | ||
case DOWN -> HttpServletResponse.SC_SERVICE_UNAVAILABLE; | ||
}; | ||
resp.setStatus(httpStatus); | ||
} catch (Exception e) { | ||
LOGGER.log(Level.SEVERE, "Unable to fetch health check status", e); | ||
healthReport = new HealthReport(HealthCheckResponse.Status.DOWN, List.of()); | ||
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); | ||
} | ||
|
||
Jsonb jsonb = JsonbBuilder.create(); | ||
String json = jsonb.toJson(healthReport); | ||
resp.setCharacterEncoding("UTF-8"); | ||
resp.setContentType("application/json"); | ||
resp.getWriter().println(json); | ||
OndroMih marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
private static HealthReporter.ReportKind getReportKind(String path) { | ||
if (path.endsWith("health/live")) { | ||
return HealthReporter.ReportKind.LIVE; | ||
} else if (path.endsWith("health/ready")) { | ||
return HealthReporter.ReportKind.READY; | ||
} else if (path.endsWith("health/started")) { | ||
return HealthReporter.ReportKind.STARTED; | ||
} else { | ||
return HealthReporter.ReportKind.ALL; | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove
maven.compiler.release
setting, it's ignored.