A logging backend for swift-log that sends logging messages to Logstash (eg. the ELK stack)

Overview

LoggingELK

Swift5.4+ release codecov jazzy Build and Test license

LoggingELK is a logging backend library for Apple's swift-log

The LoggingELK library provides a logging backend for Apple's apple/swift-log package (which basically just defines a logging API). The log entries are properly formatted, cached, and then uploaded via HTTP/HTTPS to elastic/logstash, which allows for further processing in its pipeline. The logs can then be stored in elastic/elasticsearch and visualized in elastic/kibana.

Features

  • Written completly in Swift
  • Supports both Darwin (macOS) and Linux platforms
  • Uploads the log data automatically to Logstash (eg. the ELK stack)
  • Caches the created log entries and sends them via HTTP either periodically or when exceeding a certain configurable memory threshold to Logstash
  • Converts the logging metadata to a JSON representation, which allows querying after those values (eg. filter after a specific parameter in Kibana)
  • Logs itself via a background activity logger (including protection against a possible infinite recursion)

Setup

LoggingELK requires Xcode 12 or a Swift 5.4 toolchain with the Swift Package Manager.

Swift Package Manager

Add swift-log and the swift-log-elk package as a dependency to your Package.swift file.

dependencies: [
    .package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"),
    .package(url: "https://github.com/Apodini/swift-log-elk.git", from: "0.1.0")
]

Add Logging (from swift-log) and LoggingELK (from swift-log-elk) to your target's dependencies.

targets: [
    .target(
        name: "ExampleWebService",
        dependencies: [
            .product(name: "Logging", package: "swift-log"),
            .product(name: "LoggingELK", package: "swift-log-elk")
        ]
    )
]

Setup Logging

Import both Logging and LoggingELK modules:

import Logging
import LoggingELK

Setup the LogstashLogHandler with the appropriate configuration and register the to be used logging backend once (!) during the lifetime of the application:

// Setup of LogstashLogHandler
LogstashLogHandler.setup(hostname: "0.0.0.0", port: 31311)

// Register LogstashLogHandler in the LoggingSystem
LoggingSystem.bootstrap(LogstashLogHandler.init)

Important: Setup the LogstashLogHandler before registering it in the LoggingSystem!

Furthermore, it's possible to register multiple logging backends. An option would be to send the logs to Logstash as well as print them to console:

// Setup of LogstashLogHandler
LogstashLogHandler.setup(hostname: "0.0.0.0", port: 31311)

// Register LogHandlers in the LoggingSystem
LoggingSystem.bootstrap { label in
    MultiplexLogHandler(
        [
            LogstashLogHandler(label: label),
            StreamLogHandler.standardOutput(label: label)
        ]
    ) 
}

The LogstashLogHandler can also be configured beyond the standard configuration values. Below you can see an example of the maximum possible configuration options. The developer can eg. specify if HTTPS (so TLS encryption) should be used, the to be used EventLoopGroup for handeling the HTTP requests, a Logger that logs background activity of the LogstashLogHandler or network connectivity, and a certain uploadInterval, so in what time intervals the log data should be uploaded to Logstash. Furthermore, the size of the buffer that caches the log data can be configured as well as the maximum total size of all the log buffers (since temporary buffers are created during uploading).

Important: The maximumTotalLogStorageSize MUST be at least twice as large as the logStorageSize (this is also validated during instanciation of the LogstashLogHandler). The reason for this are the temporary buffers that are allocated during uploading of the log data, so that a simultaneous logging call doesn't block (except for the duration it takes to copy the logs to the temporary buffer which is very fast).

Why at least twice as large? The process of allocating temporary buffers could possibly be repeated, if the log storage runs full during uploading of "old" log data. A possible scenario is an environment, where the network conncection to Logstash is really slow and therefore the uploading takes long. This process could repeat itself over and over again until the maximumTotalLogStorageSize is reached. Then, a new logging call blocks until enought memory space is available again, achieved through a partial completed uploading of log data, resulting in freed temporary buffers. In practice, approaching the maximumTotalLogStorageSize should basically never happen, except in very resource restricted environments.

// Setup of LogstashLogHandler
LogstashLogHandler.setup(
    hostname: "0.0.0.0",
    port: 31311,
    useHTTPS: false,
    eventLoopGroup: eventLoopGroup,
    backgroundActivityLogger: logger,
    uploadInterval: TimeAmount.seconds(5),
    logStorageSize: 500_000,
    maximumTotalLogStorageSize: 4_000_000
)

// Register LogstashLogHandler in the LoggingSystem
LoggingSystem.bootstrap(LogstashLogHandler.init)

Now that the setup of the LogstashLogHandler is completed, you can use SwiftLog as usual (also with metadata etc.).

import Logging

let logger = Logger(label: "com.example.WebService")

logger.info("This is a test!")

Setup Logstash (ELK stack)

To actually use the LogstashLogHandler, there's obviously one last step left: Set up a elastic/logstash instance where the logs are sent to. The probably most easy setup of a local Logstash instance is to use docker/elk, which provides the entire Elastic stack (ELK) powered by Docker and Docker-compose. The ELK stack allows us to collect, analyze and present the log data and much much more. Please follow the instructions in the README.me of the repository to setup and configure the ELK stack correctly.

Then, we need to configure the Logstash pipeline to accept HTTP input on a certain host and port. This can be done in the Logstash pipeline configuration file. Just adapt the input section of the file like this to allow logs to be uploaded locally on port 31311:

input {
    http {
        host => "0.0.0.0"
        port => 31311
    }
}

Furthermore, to use the timestamp created by the LogstashLogHandler (not the timestamp when the data is actually sent to Logstash), adapt the filter section of the Logstash pipeline configuration file like shown below. The second option eliminates the headers of the HTTP request from the LogstashLogHandler to Logstash, since those headers would also have been saved to the log entry (which are definitly not relevant to us).

filter {
    date {
        match => [ "timestamp", "ISO8601" ]
        locale => "en_US"       # POSIX
        target => "@timestamp"
    }

    mutate {
        remove_field => ["headers"]
    }
}

Now that the entire setup process is finished, create some log data that is then automatically sent to Logstash (eg. see section above).

Since we use the entire ELK stack, not just Logstash, we can use elastic/kibana to instantly visualize the uploaded log data. Access the Kibana web interface (on the respective port) and navigate to Analytics/Discover. Your created log messages (including metadata) should now be displayed here:

image

Congrats, you sent your first logs via swift-log and swift-log-elk to elastic/logstash, saved them in elastic/elasticsearch and visualized them with elastic/kibana! πŸŽ‰

Usage

For details on how to use the Logging features of apple/swift-log exactly, please check out the documentation of swift-log.

Documentation

Take a look at our API reference for a full documentation of the package.

Contributing

Contributions to this project are welcome. Please make sure to read the contribution guidelines first.

License

This project is licensed under the MIT License. See License for more information.

You might also like...
Customizable Console UI overlay with debug log on top of your iOS App
Customizable Console UI overlay with debug log on top of your iOS App

AEConsole Customizable Console UI overlay with debug log on top of your iOS App AEConsole is built on top of AELog, so you should probably see that fi

🍯 Awesome log aggregator for iOS
🍯 Awesome log aggregator for iOS

🍯 Awesome log aggregator for iOS

Gedatsu provide readable format about AutoLayout error console log
Gedatsu provide readable format about AutoLayout error console log

Gedatsu Gedatsu provide readable format about AutoLayout error console log Abstract At runtime Gedatsu hooks console log and formats it to human reada

Puree is a log collector which provides some features like below
Puree is a log collector which provides some features like below

Puree Description Puree is a log collector which provides some features like below Filtering: Enable to interrupt process before sending log. You can

Log every incoming notification to view them again later, also includes attachments and advanced settings to configure

VΔ“ Natively integrated notification logger Installation Add this repository to your package manager

Automate box any value! Print log without any format control symbol! Change debug habit thoroughly!

LxDBAnything Automate box any value! Print log without any format control symbol! Change debug habit thoroughly! Installation You only need drag LxD

A log should tell a story, not drown the reader in irrelevance.

StoryTeller A log should tell a story, not drown the reader in irrelevance Story Teller is an advanced logging framework that takes an entirely differ

Simply, Logify provides instant colorful logs to improve log tracking and bug tracing
Simply, Logify provides instant colorful logs to improve log tracking and bug tracing

Logify Simply, Logify provides instant colorful logs to improve log tracking and bug tracing. Why I need to use Logify? As discussed before in a lot o

100 Days of SwiftUI log

100DaysOfSwiftUI 100 Days of SwiftUI log Table of Contents Day 1: variables, constants, strings, and numbers Day 1 Variables store values and can be c

Comments
  • Update dependencies to latest versions

    Update dependencies to latest versions

    Name of the PR

    Update dependencies to latest versions

    :recycle: Current situation

    Dependencies have really outdated version, especially async-http-client

    :bulb: Proposed solution

    Update Package.swift to use latest available version of dependencies

    Problem that is solved

    Potentially a lot of problems related to http requests and dependency hierarchy

    Testing

    Not changed

    Reviewer Nudging

    Not much to review.

    opened by olegbraginontarget 0
  • Add the @avaialble directive to restrict the code being able to execute only under iOS 13 and above and add Authorization support.

    Add the @avaialble directive to restrict the code being able to execute only under iOS 13 and above and add Authorization support.

    Name of the PR

    Enhance restriction of supported iOS version 13 and above in code. And allow proving the http requests with authorisation header.

    :recycle: Current situation

    The package lacks the @avaialble directive and doesn't built under Xcode 14 and authorisation support

    :bulb: Proposed solution

    Added the @available(iOS 13, *) for the whole LogstashLogHandler struct.
    Added Authorizable protocol and a default structure implementing it, so that http request for uploading the logs can use authorisation.

    Testing

    Test for @avaialble directive were not changed, since it was only a compile time issue. Test for Authorisation support are not added, since it requires more work, because current tests are not emulating the upload process itself. Tests for that are coming soon.

    Reviewer Nudging

    From the beginning.

    opened by olegbraginontarget 0
  • [Bug]: Build failed with error

    [Bug]: Build failed with error "withoutEscapingSlashes' is only available in iOS 13.0 or newer"

    Description

    I tried to build the project with Xcode 14 and latest swift toolchain (default, only one installed, swift 5.7). The build failed with error from subject. I used a project generated from Create New Project Xcode feature. Added a package dependency only for swift-log-elk package.

    Reproduction

    Generate a sample project and add a package dependency to swift-log-elk package and build the project.

    Expected behavior

    Project should build fine.

    Additional context

    No response

    Code of Conduct

    • [X] I agree to follow this project's Code of Conduct and Contributing Guidelines
    bug 
    opened by olegbraginontarget 0
Releases(0.2.2)
Owner
Apodini: Enabling Web Service Evolution - A TUM reserach project lead by Paul Schmiedmayer
null
Log messages to text files and share them by email or other way.

LogToFiles How to log messages to text files and share them by email or share center. 1 - Add the Log.swift file to your App 2 - Just log the messages

Miguel Chaves 0 Jan 9, 2022
Sentry logging backend for SwiftLog

SwiftLogSentry A Sentry logging backend for SwiftLog, it works by creating and adding a Breadcrumb for log events. Features Supports metadata by inser

Eric Lewis 3 Nov 22, 2022
Twitter Logging Service is a robust and performant logging framework for iOS clients

Twitter Logging Service Background Twitter created a framework for logging in order to fulfill the following requirements: fast (no blocking the main

Twitter 290 Nov 15, 2022
Tap to swap out words with emojis. Inspired by Messages.app on iOS 10.

EmojiTextView Tap to swap out words with emojis. Works with any UITextView. Heavily inspired by Messages.app on iOS 10. Created by Arkadiusz Holko (@a

Arek Holko 339 Dec 24, 2022
A Swift-based API for reading from & writing to the Apple System Log (more commonly known somewhat inaccurately as "the console")

CleanroomASL Notice: CleanroomASL is no longer supported The Apple System Log facility has been deprecated by Apple. As a result, we've deprecated Cle

Gilt Tech 62 Jan 29, 2022
A custom logger implementation and Task Local helper for swift-log

LGNLog A custom logger implementation and TaskLocal helper for Swift-Log. Why and how This package provides two and a half things (and a small bonus):

17:11 Games 0 Oct 26, 2021
Simple Design for Swift bridge with Javascript. Also can get javascript console.log.

SDBridgeOC is here. If your h5 partner confused about how to deal with iOS and Android. This Demo maybe help. YouTube video is here. bilibili Video is

null 20 Dec 28, 2022
πŸ“±πŸ’¬πŸš¦ TinyConsole is a micro-console that can help you log and display information inside an iOS application, where having a connection to a development computer is not possible.

TinyConsole TinyConsole is a tiny log console to display information while using your iOS app and written in Swift. Usage Wrap your Main ViewControlle

Devran Cosmo Uenal 2k Jan 3, 2023
Gedatsu provide readable format about AutoLayout error console log

Gedatsu Gedatsu provide readable format about AutoLayout error console log Abstract At runtime Gedatsu hooks console log and formats it to human reada

bannzai 520 Jan 6, 2023