問題描述
在使用Azure Spring Cloud服務時,如果要收集應用程式的日志。有控制台輸出(實時流日志),也可以配置Log Analytics服務。
日志流式處理
可以通過以下指令在 Azure CLI 中使用日志流式處理。
az spring-cloud app logs -n hellospring -s yourspringcloudname -g <resource group name> --lines 100 -f
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLwATNzAjMzcDOx0CN4MTNzITN1EjMwkDMyIDMy0iMwgzNyEjMvwVOwIjMwIzLcJDM4cjMxIzLcd2bsJ2Lc12bj5ycn9Gbi52YuIjMwIzZtl2Lc9CX6MHc0RHaiojIsJye.png)
Log Analytics
在Azure Spring Cloud門戶頁面,轉到“服務 | 概述”頁,然後在“監視”部分中選擇“日志” 。 選擇 Azure Spring Cloud 的一個示例查詢上的“運作”。
但是,如果應用中需要自行把日志寫入到日志檔案中,那麼如果應用部署到Azure Spring Cloud 上後,如何來檢視并擷取到應用程式自身專門用于記錄日志的檔案呢?
問題解答
Azure Spring Cloud 與 App Service有較大的差別。App Service可以通過Kudu工具通路應用的檔案系統,就可以在Home目錄下直接看見應用程式生成的日志檔案并下載下傳。
而Spring Cloud服務,需要通過檔案挂載(Mount)的方式,把一個存儲賬号(Storage Account)挂載到Spring Cloud的App上。
挂載Storage Account以及在代碼中配置挂載後的日志路徑步驟:
第一步:為Azure Spring Cloud服務添加一個Storage
- Storage name:為自定義名稱,根據自己情況設定,如 springstorage01
- Account name:為存儲賬号(Storage Account)的名稱,需要從Azure Storage Account的頁面中擷取
- Account Key:從Azure Storage Account的Access Key頁面中擷取。注意:此處隻需要填寫Access Key就可以,不需要完整的Conneciton String
第二步:為Spring Cloud App添加挂載
在Spring Cloud頁面,點選“Apps”列舉出所有的App。選中需要配置日志檔案路徑的應用。然後選擇“Configuration” --> "Persistent Storage"
- Storage Name:為第一步中自定義的Storage Name。
- Share Name:為在Azure Storage Account的檔案共享中所建立的一個共享檔案夾。可以自定義檔案夾名稱。
- Mount Path: 所挂載Spring Cloud App所運作執行個體上的檔案路徑。這一步的内容也是将在應用為日志檔案所配置的存放路徑。非常關鍵!如使用 /app/logs
第三步:在Java Spring應用中重新配置日志生成路徑
修改應用中的日志儲存路徑。如本執行個體中使用的 logback-spring.xml 。 修改檔案輸出路徑為: <file>/app/logs/test.log</file>
重新生成Jar檔案并再次釋出。
第四步: 在存儲賬号中檢查應用日志
在Azure門戶中,進入Storage Account中,檢視Spring Cloud App的運作日志。如下:
附錄:Spring Cloud應用示例代碼
POM.XML 依賴封包件
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.11</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>hellospring</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>hellospring</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2021.0.3</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>net.logstash.logback</groupId>
<artifactId>logstash-logback-encoder</artifactId>
<version>6.5</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.properties 配置檔案
spring.cloud.config.enabled=false
logback-spring.xml配置檔案
<configuration>
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp>
<fieldName>timestamp</fieldName>
<timeZone>UTC</timeZone>
</timestamp>
<loggerName>
<fieldName>logger</fieldName>
</loggerName>
<logLevel>
<fieldName>level</fieldName>
</logLevel>
<threadName>
<fieldName>thread</fieldName>
</threadName>
<nestedField>
<fieldName>mdc</fieldName>
<providers>
<mdc />
</providers>
</nestedField>
<stackTrace>
<fieldName>stackTrace</fieldName>
<!-- maxLength - limit the length of the stack trace -->
<throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter">
<maxDepthPerThrowable>200</maxDepthPerThrowable>
<maxLength>14000</maxLength>
<rootCauseFirst>true</rootCauseFirst>
</throwableConverter>
</stackTrace>
<message />
<throwableClassName>
<fieldName>exceptionClass</fieldName>
</throwableClassName>
</providers>
</encoder>
</appender>
<appender name="files" class="ch.qos.logback.core.FileAppender">
<file>/app/logs/test.log</file>
<append>true</append>
<encoder class="net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder">
<providers>
<timestamp>
<fieldName>timestamp</fieldName>
<timeZone>UTC</timeZone>
</timestamp>
<loggerName>
<fieldName>logger</fieldName>
</loggerName>
<logLevel>
<fieldName>level</fieldName>
</logLevel>
<threadName>
<fieldName>thread</fieldName>
</threadName>
<nestedField>
<fieldName>mdc</fieldName>
<providers>
<mdc />
</providers>
</nestedField>
<stackTrace>
<fieldName>stackTrace</fieldName>
<!-- maxLength - limit the length of the stack trace -->
<throwableConverter class="net.logstash.logback.stacktrace.ShortenedThrowableConverter">
<maxDepthPerThrowable>200</maxDepthPerThrowable>
<maxLength>14000</maxLength>
<rootCauseFirst>true</rootCauseFirst>
</throwableConverter>
</stackTrace>
<message />
<throwableClassName>
<fieldName>exceptionClass</fieldName>
</throwableClassName>
</providers>
</encoder>
</appender>
<root level="info">
<appender-ref ref="stdout" />
<appender-ref ref="files" />
</root>
</configuration>
HelloController.java 代碼
package com.example.hellospring;
import org.springframework.web.bind.annotation.RestController;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestMapping;
@RestController
public class HelloController {
org.slf4j.Logger logger = LoggerFactory.getLogger(getClass());
@RequestMapping("/")
public String index() {
logger.info("Loging into Storage Folder.... request from index page.... test by lb @09-02");
return "Greetings from Azure Spring Cloud!";
}
}
HellospringApplication.java 代碼
package com.example.hellospring;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HellospringApplication {
public static void main(String[] args) {
SpringApplication.run(HellospringApplication.class, args);
}
}
參考資料
快速入門:在 Azure Spring Cloud 中部署你的第一個應用程式:https://docs.azure.cn/zh-cn/spring-cloud/quickstart?tabs=Azure-CLI#build-and-deploy-the-app
日志: https://docs.azure.cn/zh-cn/spring-cloud/quickstart-logs-metrics-tracing?tabs=Azure-CLI
當在複雜的環境中面臨問題,格物之道需:濁而靜之徐清,安以動之徐生。 雲中,恰是如此!