How to forward Platform.sh logs to Logz.io

Goal

To forward Platform.sh logs to Logz.io.

Assumptions

Problems

Forwarding Platform.sh to a third-party indexer such as Logz.io is useful, especially when integrating log monitoring across other projects, including those that are not hosted on Platform.sh.

Logz.io recommends Filebeat to create configuration, auth and forwarding files when shipping logs. Since projects on Platform.sh are read-only from deployment onwards, we will have to create mount point in the file system, ideally directories that will only ever contain files and never code.

The source for this How-to can be found in the platformsh-examples/logzio repository. It ships logs using the Flask Template as its application, but the steps below could very easily be followed for any other project.

More information about Platform.sh logs can be found in the public documentation.

Steps

1. Platform.sh configuration

Since the following example is adapted from an existing template project, it already contains the three required files needed to deploy on Platform.sh:

  • .platform/routes.yaml: which defines how requests are handled.
  • .platform/services.yaml: configures services (e.g. databases).
  • .platform.app.yaml: defines the build and deploy process for the application.

We will only need to modify .platform.app.yaml in two places from the existing template to ship logs to Logz.io.

First, since Filebeat requires some write-access to the file system to index and ship logs, create three mounts that allow it to do so:

mounts:
    'filebeat/data':
        source: local
        source_path: filebeat/data
    'filebeat/logs':
        source: local
        source_path: filebeat/logs
    'filebeat/registry':
        source: local
        source_path: filebeat/registry

Next, modify the build hook to install Filebeat during build by calling a script we will write in the following step.

hooks:
    build: |
      pipenv install --system --deploy
      chmod +x install_filebeat.sh
      ./install_filebeat.sh

Then add a deploy hook that actually calls Filebeat. It will detect differences since the last ship, and ship those new logs to Logz.io.

hooks:
    build: |
      pipenv install --system --deploy
      chmod +x install_filebeat.sh
      ./install_filebeat.sh
    deploy:
      ./filebeat/filebeat run --once

You can view the final full .platform.app.yaml configuration here.

2. Install Filebeat

The deploy hook calls the install_filebeat.sh script which needs to contain the following:

#!/usr/bin/env bash

# Install Filebeat.
FILEBEAT_VERSION=7.4.0
curl -L -O https://artifacts.elastic.co/downloads/beats/filebeat/filebeat-$FILEBEAT_VERSION-linux-x86_64.tar.gz
mkdir filebeat && tar xzvf filebeat-$FILEBEAT_VERSION-linux-x86_64.tar.gz -C filebeat --strip-components 1
rm filebeat-$FILEBEAT_VERSION-linux-x86_64.tar.gz

# Download the certificate.
wget https://raw.githubusercontent.com/logzio/public-certificates/master/COMODORSADomainValidationSecureServerCA.crt
mkdir -p filebeat/pki/tls/certs
mv COMODORSADomainValidationSecureServerCA.crt filebeat/pki/tls/certs/

# Run some tests.
./filebeat/filebeat test config
./filebeat/filebeat test output

It downloads Filebeat and validates the download. Finally, it runs two tests that will be visible in the console during the build process.

3. Configure Filebeat

The final addition that needs to be made is the inclusion of a configuration file that is used by Filebeat so it knows where to send your logs: filebeat.yml. This file should reside in your project route and contain the following:

############################# Filebeat #####################################

filebeat.inputs:

- type: log
  paths:
    - /var/log/*.log
  fields:
    logzio_codec: plain
    token: ${LOGZIO_TOKEN}
    type: platformsh_build
  fields_under_root: true
  encoding: utf-8
  ignore_older: 3h

#For version 7 and higher
filebeat.registry.path: /app/filebeat/registry

#The following processors are to ensure compatibility with version 7
processors:
- rename:
    fields:
     - from: "agent"
       to: "beat_agent"
    ignore_missing: true
- rename:
    fields:
     - from: "log.file.path"
       to: "source"
    ignore_missing: true

############################# Output ##########################################

output:
  logstash:
    hosts: ["listener.logz.io:5015"]
    ssl:
      certificate_authorities: ['/app/filebeat/pki/tls/certs/COMODORSADomainValidationSecureServerCA.crt']

There is a configuration wizard in the Logz.io dashboard that will make this file for you when you specify Platform.sh’s log directory - /var/log/*.log.

The only modification that needs to be made from the generated file is the filebeat.inputs array. The fields.token attribute is the identifier token for your Logz.io account, and is necessary in order to receive logs in your dashboard. You can access this token from your account settings.

Since this file will be a part of your commit history, it’s inadvisable to actually commit that token. Instead, the LOGZIO_TOKEN environment variable is used, and you will define it in the next step.

4. Push to Platform.sh

Use the Platform.sh CLI to create a new project:

platform project:create

and set the project as a remote for the local repository:

platform project:set-remote <project ID>

Define the project-wide environment variable LOGZIO_TOKEN:

platform variable:create --level project --name LOGZ_TOKEN --value <your token>

Commit the changes and push to the Platform.sh remote:

$ git push platform master

Commit the changes and push to the Platform.sh remote:

$ git push platform <environment name>

Filebeat will be installed during the build hook and configured to Logz.io during the deploy hook.

Each time Filebeat is run at the end of each deployment, it will detect changes to the log files within /var/log and ship those differences to Logz.io.

Conclusion

Platform.sh is set up to provide a read-only file system for application containers so that consistent builds and deployments are ensured. Utilizing writable mounts however provides a simple way of setting up Filebeat to ship Platform.sh logs to Logz.io.

I want to ask about following to code fragments:

and

The second one comes from config.sh, part of deploy hook, so runs in read-only. Files are suppose to be copied over to filebeat dir (a.k.a /app/filebeat), but since that directory is not registered as mount (/app/.filebeat is) deployment fails.

@jakub You’re right - there was some copypasta in there for sure.

The post is now updated and cleaned up with some fresh eyes. Feel free to check out the example source here. Hope it helps!