如何以及在何处将日志文件存储在 Spring 部署在 CF 或 Heroku 中的引导应用程序中?

How and Where to Store Log Files in Spring Boot App deployed in CF or Heroku?

我创建了一个 JHipster webapp(SpringBoot & Angular Js) 并将其部署在 Pivotal CF 和 Heroku 上。

我将日志文件保存在 src/main/webapp/logs/ 目录下,该目录在本地主机中工作正常,但在 Pivotal CF 和 Heroku 中部署时出现以下错误消息

Sorry, an error has occurred.

Status: Not Found (Not Found)

Message: No message available

问题:

  1. 我可以查看日志文件列表并在本地主机上下载或查看日志文件的内容,但是当部署在 CF 或 Heroku 中时,我只能看到日志文件名列表,但无法访问日志文件。 由于我能够看到文件名列表,这意味着 CF/Heroku 目录中存在日志文件。那么为什么我无法访问它们?

  2. 我可以在 Heroku 或 Pivotal CF 应用程序中保存日志文件吗space?

  3. 我知道我不应该像上面那样保存日志文件,只是想知道为什么这在 CF/Heroku?

    [=56= 中不起作用]
  4. 当我的应用程序部署在 Heroku 或 CF 上时,存储日志文件的最佳、简单和便宜的方法是什么? AWS S3 存储?

这是我的 project repo.

这是我在 Heroku

中的应用 link

Login with below credentials:

UserName : user Password : user

Navigate to Administration -> Logs

Please do not change the Password. Thanks!

下面是我的代码片段:

Returns src/main/webapp/logs/ 目录中的日志文件名列表。

@RequestMapping(value = "/logs/files",
        method = RequestMethod.GET,
        produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public List<String> getLogFileNames() throws IOException {

    Resource resource = resourceLoader.getResource("file:src/main/webapp/logs");
    System.out.println("resource : "+ resource);
    File file = resource.getFile();
    File[] listFiles = file.listFiles();
    List<String> fileNames = new ArrayList<>();
    List<File> list = Arrays.asList(listFiles);
    for (File f : list) {
        System.out.println(f.getName());
        fileNames.add(f.getName());
    }           

    return fileNames;
}

logback-spring.xml 配置:

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>src/main/webapp/logs/logFile.%d{yyyy-MM-dd}.log</fileNamePattern>
        <maxHistory>90</maxHistory>
    </rollingPolicy>
    <encoder>
        <charset>utf-8</charset>
        <Pattern>%d %-5level [%thread] %logger{0}: %msg%n</Pattern>
    </encoder>
</appender>

log.service.js:

angular.module('blogaggrApp')
.factory('LogsFileNameService', function ($resource) {
    return $resource('api/logs/files', {}, {
        'getLogFileNames': { method: 'GET', isArray: true}
    });
});

logs.html :

<form class="form-inline">
  <div class="form-group">
    <div class="dropdown">
      <button class="btn btn-success btn-md dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
        Click to Open Log Files
        <span class="caret"></span>
      </button>
      <ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
        <li ng-repeat="(key, value) in logFileNames" value="{{value}}" style="width:100%;">
            <a ng-href="/logs/{{value}}" target="_blank"><strong>{{value}}</strong> </a>
        </li>
      </ul>
    </div>
  </div>
</form>

在 Cloud Foundry 环境中,应用程序实例在容器中运行。 PCF 中的容器是一个 Garden 单元格。单元格具有的存储称为 "Ephemeral Storage"。这意味着,只要容器还活着,应用程序就有存储空间。 https://dzone.com/articles/the-12-factor-app-a-java-developers-perspective

如果应用程序实例死亡,Cloud Foundry 大脑将销毁容器。这包括临时存储。当一个新的应用程序实例启动时,它的容器将拥有全新的存储空间,同样是短暂的。

这就是为什么在 Cloud Foundry 中,您的应用程序不能在运行时依赖本地文件系统。

请查看“12 Factor App”文档 (https://dzone.com/articles/the-12-factor-app-a-java-developers-perspective)。它将在开发云原生应用程序时派上用场。