PCF に springboot アプリケーションをデプロイしました。環境変数に基づいてメッセージをログに記録したいのですが、アプリケーションを再起動せずに実行時のログ レベルの変更が機能するようにするにはどうすればよいですか?
12 に答える
これは@Michael Simonsの回答の拡張です。このメソッドを使用すると、それを行うための UI が得られます。
この方法は少し長くなりますが、より多くのことを解決します。Spring Boot Admin Serverというツールを使用します。
まず、いくつかの依存関係を含める必要があります
<!--Dependency for registering your app as a Spring Boot Admin Server--> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-server</artifactId> <version>1.3.3</version> </dependency> <!--Provide a nice looking ui--> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-server-ui</artifactId> <version>1.3.3</version> </dependency> <!--Dependency for registering your app as a Spring Boot Admin Client--> <dependency> <groupId>de.codecentric</groupId> <artifactId>spring-boot-admin-starter-client</artifactId> <version>1.3.0</version> </dependency> <dependency> <groupId>org.jolokia</groupId> <artifactId>jolokia-core</artifactId> </dependency>
アノテーションを使用して、アプリを Spring Boot 管理サーバーにできるようにします
@EnableAdminServer
。@SpringBootApplication @EnableAdminServer public class Application { public static void main(String[] args) { // ... your code as before ... } }
以下を
application.properties
追加します。まだアプリであるSpring Boot管理サーバーにアプリを登録します
spring.boot.admin.url=http://localhost:8031
Spring Boot 管理サーバーにクライアントの場所を指示する
// For versions 2.*.* spring.boot.admin.client.url=http://localhost:8031 // For versions 1.*.* spring.boot.admin.client.service-url=http://localhost:8031 spring.boot.admin.client.management-url=http://localhost:8031 spring.boot.admin.client.health-url=http://localhost:8031/health
logback.xml
次の行を追加するだけ<jmxConfigurator/>
です。これにより、JMX を介したログバックの構成が可能になります。詳細はこちら
...そして出来上がりです。実行時に任意のロガーのデバッグ レベルを変更できるようになりました。
私。Spring Boot 管理サーバーの URL にアクセスするだけです。この場合はこちら ( http:/localhost:8031
)。
ii. 登録されているアプリケーション(クライアント)の一覧がホームページに表示されます。
iii. Details
登録済みのクライアントをクリックすると、別のページに移動します。
iv。Logging
アプリケーションに登録されているすべてのロガーを一覧表示するタブをクリックします。
v. ログ レベルを変更すると、実行時にログ レベルが変更されます。ここにあなたが期待するもののスニペットがあります
Spring Boot 1.5.x 以降、ロガー エンドポイントを使用して、目的のログ レベルを POST できます。
デフォルトのロギング プロバイダーは logback です。実行時にログ レベルを変更できるようにシステムをセットアップするには、次の手順を実行する必要があります。
最初に、 Spring のデフォルト コンフィギュレーターを含むsrc/main/resources
という名前のカスタム ログバック構成を作成し、logback-spring.xml
JMX 経由でログバック構成を公開するディレクティブを追加します。
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
<jmxConfigurator />
</configuration>
ここで、Jolokia JMX-over-HTTP ブリッジへの依存関係を追加します: org.jolokia:jolokia-core
.
/jolokia
これで、Spring Boot アプリケーションでエンドポイントをヒットできるはずです。プロトコルはここに文書化されています。それはきれいではありません。まずGET
、ブラウザから直接アクセスできる例をいくつか示します。
ROOT ロガーレベルを表示:
/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/getLoggerLevel/ROOT
ROOT ロガー レベルをデバッグに変更します。
/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/setLoggerLevel/ROOT/debug
spring-boot-actuator はエンドポイントを認識しており、クラスパスに spring-security がある場合は認証が必要になるように/jolokia
マークされています。sensitive=true
コントローラーで次のコードを使用し、API を呼び出してログ レベルを変更できます。
@PostMapping("/changeloglevel")
public void changeloglevel(@RequestParam String loglevel)
{
LoggerContext loggerContext = (LoggerContext)LoggerFactory.getILoggerFactory();
loggerContext.getLogger("package where springboot main class resides").setLevel(Level.toLevel(loglevel));
}
ログレベルは ERROR、INFO、WARN などです。
jspを作成し、それを直接使用することができます
https://gist.github.com/iamkristian/943918/043ac51bd80321a0873d93277979c8a9a20a9a48#file-log4jadmin-jsp
<%@ page language="java" contentType="text/html;charset=UTF-8" %>
<%@ page import="org.apache.log4j.Level" %>
<%@ page import="org.apache.log4j.LogManager" %>
<%@ page import="org.apache.log4j.Logger" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Enumeration" %>
<%@ page import="java.util.Set" %>
<%@ page import="java.util.Arrays" %>
<% long beginPageLoadTime = System.currentTimeMillis();%>
<html>
<head>
<title>Log4J Administration</title>
<style type="text/css">
<!--
#content {
margin: 0px;
padding: 0px;
text-align: center;
background-color: #ccc;
border: 1px solid #000;
width: 100%;
}
body {
position: relative;
margin: 10px;
padding: 0px;
color: #333;
}
h1 {
margin-top: 20px;
font: 1.5em Verdana, Arial, Helvetica sans-serif;
}
h2 {
margin-top: 10px;
font: 0.75em Verdana, Arial, Helvetica sans-serif;
text-align: left;
}
a, a:link, a:visited, a:active {
color: red;
text-decoration: none;
text-transform: uppercase;
}
table {
width: 100%;
background-color: #000;
padding: 3px;
border: 0px;
}
th {
font-size: 0.75em;
background-color: #ccc;
color: #000;
padding-left: 5px;
text-align: center;
border: 1px solid #ccc;
white-space: nowrap;
}
td {
font-size: 0.75em;
background-color: #fff;
white-space: nowrap;
}
td.center {
font-size: 0.75em;
background-color: #fff;
text-align: center;
white-space: nowrap;
}
.filterForm {
font-size: 0.9em;
background-color: #000;
color: #fff;
padding-left: 5px;
text-align: left;
border: 1px solid #000;
white-space: nowrap;
}
.filterText {
font-size: 0.75em;
background-color: #fff;
color: #000;
text-align: left;
border: 1px solid #ccc;
white-space: nowrap;
}
.filterButton {
font-size: 0.75em;
background-color: #000;
color: #fff;
padding-left: 5px;
padding-right: 5px;
text-align: center;
border: 1px solid #ccc;
width: 100px;
white-space: nowrap;
}
-->
</style>
</head>
<body onLoad="javascript:document.logFilterForm.logNameFilter.focus();">
<%
String containsFilter = "Contains";
String beginsWithFilter = "Begins With";
String[] logLevels = {"debug", "info", "warn", "error", "fatal", "off"};
String targetOperation = (String) request.getParameter("operation");
String targetLogger = (String) request.getParameter("logger");
String targetLogLevel = (String) request.getParameter("newLogLevel");
String logNameFilter = (String) request.getParameter("logNameFilter");
String logNameFilterType = (String) request.getParameter("logNameFilterType");
%>
<div id="content">
<h1>Log4J Administration</h1>
<div class="filterForm">
<form action="log4jAdmin.jsp" name="logFilterForm">Filter Loggers:
<input name="logNameFilter" type="text" size="50" value="<%=(logNameFilter == null ? "":logNameFilter)%>"
class="filterText"/>
<input name="logNameFilterType" type="submit" value="<%=beginsWithFilter%>" class="filterButton"/>
<input name="logNameFilterType" type="submit" value="<%=containsFilter%>" class="filterButton"/>
<input name="logNameClear" type="button" value="Clear" class="filterButton"
onmousedown='javascript:document.logFilterForm.logNameFilter.value="";'/>
<input name="logNameReset" type="reset" value="Reset" class="filterButton"/>
<param name="operation" value="changeLogLevel"/>
</form>
</div>
<table cellspacing="1">
<tr>
<th width="25%">Logger</th>
<th width="25%">Parent Logger</th>
<th width="15%">Effective Level</th>
<th width="35%">Change Log Level To</th>
</tr>
<%
Enumeration loggers = LogManager.getCurrentLoggers();
HashMap loggersMap = new HashMap(128);
Logger rootLogger = LogManager.getRootLogger();
if (!loggersMap.containsKey(rootLogger.getName())) {
loggersMap.put(rootLogger.getName(), rootLogger);
}
while (loggers.hasMoreElements()) {
Logger logger = (Logger) loggers.nextElement();
if (logNameFilter == null || logNameFilter.trim().length() == 0) {
loggersMap.put(logger.getName(), logger);
} else if (containsFilter.equals(logNameFilterType)) {
if (logger.getName().toUpperCase().indexOf(logNameFilter.toUpperCase()) >= 0) {
loggersMap.put(logger.getName(), logger);
}
} else {
// Either was no filter in IF, contains filter in ELSE IF, or begins with in ELSE
if (logger.getName().startsWith(logNameFilter)) {
loggersMap.put(logger.getName(), logger);
}
}
}
Set loggerKeys = loggersMap.keySet();
String[] keys = new String[loggerKeys.size()];
keys = (String[]) loggerKeys.toArray(keys);
Arrays.sort(keys, String.CASE_INSENSITIVE_ORDER);
for (int i = 0; i < keys.length; i++) {
Logger logger = (Logger) loggersMap.get(keys[i]);
// MUST CHANGE THE LOG LEVEL ON LOGGER BEFORE GENERATING THE LINKS AND THE
// CURRENT LOG LEVEL OR DISABLED LINK WON'T MATCH THE NEWLY CHANGED VALUES
if ("changeLogLevel".equals(targetOperation) && targetLogger.equals(logger.getName())) {
Logger selectedLogger = (Logger) loggersMap.get(targetLogger);
selectedLogger.setLevel(Level.toLevel(targetLogLevel));
}
String loggerName = null;
String loggerEffectiveLevel = null;
String loggerParent = null;
if (logger != null) {
loggerName = logger.getName();
loggerEffectiveLevel = String.valueOf(logger.getEffectiveLevel());
loggerParent = (logger.getParent() == null ? null : logger.getParent().getName());
}
%>
<tr>
<td><%=loggerName%>
</td>
<td><%=loggerParent%>
</td>
<td><%=loggerEffectiveLevel%>
</td>
<td class="center">
<%
for (int cnt = 0; cnt < logLevels.length; cnt++) {
String url = "log4jAdmin.jsp?operation=changeLogLevel&logger=" + loggerName + "&newLogLevel=" + logLevels[cnt] + "&logNameFilter=" + (logNameFilter != null ? logNameFilter : "") + "&logNameFilterType=" + (logNameFilterType != null ? logNameFilterType : "");
if (logger.getLevel() == Level.toLevel(logLevels[cnt]) || logger.getEffectiveLevel() == Level.toLevel(logLevels[cnt])) {
%>
[<%=logLevels[cnt].toUpperCase()%>]
<%
} else {
%>
<a href='<%=url%>'>[<%=logLevels[cnt]%>]</a>
<%
}
}
%>
</td>
</tr>
<%
}
%>
</table>
<h2>
Revision: 1.0<br/>
Page Load Time (Millis): <%=(System.currentTimeMillis() - beginPageLoadTime)%>
</h2>
</div>
</body>
</html>