问题描述

在使用Azure Spring Cloud服务时,如果要收集应用程序的日志。有控制台输出(实时流日志),也可以配置Log Analytics服务。

日志流式处理

可以通过以下命令在 Azure CLI 中使用日志流式处理。

az spring-cloud app logs -n hellospring -s yourspringcloudname -g <resource group name> --lines 100 -f

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

【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?的更多相关文章

  1. C# windows服务:如何获取服务程序所在的文件夹

    AppDomain.CurrentDomain.BaseDirectory 就这么一句话

  2. react native android 上传文件,Nodejs服务端获取上传的文件

    React Native端 使用react-native-image-picker 做出选择图片的操作,选择完成后,直接将图片Post至服务器,保存在服务器的某个地方(保存图片的路径需要公开显示),并 ...

  3. 从Spring迁移到Spring Boot

    文章目录 添加Spring Boot starters 添加应用程序入口 Import Configuration和Components 迁移应用程序资源 迁移应用程序属性文件 迁移Spring We ...

  4. spring boot / cloud (十四) 微服务间远程服务调用的认证和鉴权的思考和设计,以及restFul风格的url匹配拦截方法

    spring boot / cloud (十四) 微服务间远程服务调用的认证和鉴权的思考和设计,以及restFul风格的url匹配拦截方法 前言 本篇接着<spring boot / cloud ...

  5. 笔记:Spring Cloud Feign 声明式服务调用

    在实际开发中,对于服务依赖的调用可能不止一处,往往一个接口会被多处调用,所以我们通常会针对各个微服务自行封装一些客户端类来包装这些依赖服务的调用,Spring Cloud Feign 在此基础上做了进 ...

  6. spring boot / cloud (二十) 相同服务,发布不同版本,支撑并行的业务需求

    spring boot / cloud (二十) 相同服务,发布不同版本,支撑并行的业务需求 有半年多没有更新了,按照常规剧本,应该会说项目很忙,工作很忙,没空更新,吧啦吧啦,相关的话吧, 但是细想想 ...

  7. Spring Cloud 入门教程 - Eureka服务注册与发现

    简介 在微服务中,服务注册与发现对管理各个微服务子系统起着关键作用.随着系统水平扩展的越来越多,系统拆分为微服务的数量也会相应增加,那么管理和获取这些微服务的URL就会变得十分棘手,如果我们每新加一个 ...

  8. 《Spring Cloud与Docker微服务架构实战》配套代码

    不才写了本使用Spring Cloud玩转微服务架构的书,书名是<Spring Cloud与Docker微服务架构实战> - 周立,已于2017-01-12交稿.不少朋友想先看看源码,现将 ...

  9. 一起来学Spring Cloud | 第二章:服务注册和发现组件 (Eureka)

    本篇文章,很浅显的一步步讲解如何搭建一个能运行的springcloud项目(带所有操作截图).相信!看完本篇之后,你会觉得springcloud搭建如此简单~~~~ 一. Eureka简介: 1.1  ...

随机推荐

  1. ffmpeg使用总结

    2021-07-21 初稿 截图 ffmpeg -i <video> -ss <time> -vframes 1 <output_pic> 设置视频封面 ffmpe ...

  2. Opentelemetry SDK的简单用法

    Opentelemetry SDK的简单用法 概述 Opentelemetry trace的简单架构图如下,客户端和服务端都需要启动一个traceProvider,主要用于将trace数据传输到reg ...

  3. POI导出复杂Excel,合并单元格(1)

    /** * 导出复杂excel 合并单元格 (HSSFWorkbook) */ @GetMapping("/testHSSFWorkbook.do") public void te ...

  4. Python 中生成器的原理

    生成器的使用 在 Python 中,如果一个函数定义的内部使用了 yield 关键字,那么在执行函数的时候返回的是一个生成器,而不是常规函数的返回值. 我们先来看一个常规函数的定义,下面的函数 f() ...

  5. Spring-03

    1. AOP相关概念 1.1 AOP概念&作用 AOP(Aspect Oriented Programming)是一种思想,面向切面编程 作用:在不修改源码的前提下,在程序运行过程中对方法进行 ...

  6. 从编译器对指令集的要求看API设计原则

    摘要:最近看<计算机体系结构:量化研究方法(第五版)>,发现指令集设计中的一些原则,对API设计也同样适用,给大家分享一下. 本文中的所有内容来自工作和学习过程中的心得整理,如需转载请注明 ...

  7. Hadoop - MapReduce 过程

    Hadoop - MapReduce 一.MapReduce设计理念 map--->映射 reduce--->归纳 mapreduce必须构建在hdfs之上的一种大数据离线计算框架 在线: ...

  8. PySide6/PyQt开发xml编辑器(1)

    QTreeWidget折叠子项(折叠当前项的所有子项) 本文仅供本人知识总结使用,所以内容会比较浅显,不喜勿喷. 目录 QTreeWidget折叠子项(折叠当前项的所有子项) 目录 一.仅折叠子项 二 ...

  9. 算法竞赛进阶指南 0x43 线段树

    目录 线段树简介 线段树的简单代码实现 建树代码 修改操作 查询操作 线段树的查询操作的时间复杂度分析: AcWing245. 你能回答这些问题吗 思路 代码[时间复杂度:\(O( \space(N+ ...

  10. Running Median_via牛客网

    题目 链接:https://ac.nowcoder.com/acm/contest/28886/1002 来源:牛客网 时间限制:C/C++ 5秒,其他语言10秒 空间限制:C/C++ 65536K, ...