StackdriverLogging

4.0.0

Swift (apple/swift-log) LogHandler for logging JSON to GCP Stackdriver
brainfinance/StackdriverLogging

What's New

4.0.0

2024-04-24T14:13:57Z

Modernize the implementation overall.

Changes

  • Make the setup of EventLoopGroup unnecessary and switch the worker queue to NIOThreadPool.
  • Use swift-system for file I/O.
  • Remove StackdriverLogHandler.Factory, as there is no need for setup due to the default singleton NIOThreadPool.
    Those who want customization can use their own NIOThreadPool.
    Delete old test support files for Linux and additionally implement tests.

Many thanks @sidepelican 👍

StackdriverLogging

A SwiftLog LogHandler that logs GCP Stackdriver formatted JSON.

For more information on Stackdriver structured logging, see: https://cloud.google.com/logging/docs/structured-logging and LogEntry

Dependencies

This Stackdriver LogHandler depends on SwiftNIO which is used to create and save your new log entries in a non-blocking fashion.

How to install

Swift Package Manager

.package(url: "https://github.com/Brainfinance/StackdriverLogging.git", from: "4.0.0"),

In your target's dependencies add "StackdriverLogging" e.g. like this:

.target(name: "App", dependencies: ["StackdriverLogging"]),

Vapor 4

Here's a bootstrapping example for a standard Vapor 4 application.

import App
import Vapor

var env = try Environment.detect()
try LoggingSystem.bootstrap(from: &env) { (logLevel) -> (String) -> LogHandler in
    return { label -> LogHandler in
        var logger = StackdriverLogHandler(destination: .stdout)
        logger.logLevel = logLevel
        return logger
    }
}
let app = Application(env)
defer { app.shutdown() }
try configure(app)
try app.run()

Logging JSON values using Logger.MetadataValue

To log metadata values as JSON, simply log all JSON values other than String as a Logger.MetadataValue.stringConvertible and, instead of the usual conversion of your value to a String in the log entry, it will keep the original JSON type of your values whenever possible.

For example:

var logger = Logger(label: "Stackdriver")
logger[metadataKey: "jsonpayload-example-object"] = [
    "json-null": .stringConvertible(NSNull()),
    "json-bool": .stringConvertible(true),
    "json-integer": .stringConvertible(1),
    "json-float": .stringConvertible(1.5),
    "json-string": .string("Example"),
    "stackdriver-timestamp": .stringConvertible(Date()),
    "json-array-of-numbers": [.stringConvertible(1), .stringConvertible(5.8)],
    "json-object": [
        "key": "value"
    ]
]
logger.info("test")

Will log the non pretty-printed representation of:

{  
   "sourceLocation":{  
      "function":"boot(_:)",
      "file":"\/Sources\/App\/boot.swift",
      "line":25
   },
   "jsonpayload-example-object":{  
      "json-bool":true,
      "json-float":1.5,
      "json-string":"Example",
      "json-object":{  
         "key":"value"
      },
      "json-null":null,
      "json-integer":1,
      "json-array-of-numbers":[  
         1,
         5.8
      ],
      "stackdriver-timestamp":"2019-07-15T21:21:02.451Z"
   },
   "message":"test",
   "severity":"INFO"
}

Logging from a managed platform

If your app is running inside a managed environment such as Google Cloud Run or a container based Compute Engine, logging to stdout should get you up and running automatically.

Stackdriver logging agent + fluentd config

If you prefer logging to a file, you can use a file destination StackdriverLogHandler.Destination.file in combination with the Stackdriver logging agent https://cloud.google.com/logging/docs/agent/installation and a matching json format google-fluentd config (/etc/google-fluentd/config.d/example.conf) to automatically send your JSON logs to Stackdriver for you.

Here's an example google-fluentd conf file that monitors a json based logfile and send new log entries to Stackdriver:

<source>
    @type tail
    # Format 'JSON' indicates the log is structured (JSON).
    format json
    # The path of the log file.
    path /var/log/example.log
    # The path of the position file that records where in the log file
    # we have processed already. This is useful when the agent
    # restarts.
    pos_file /var/lib/google-fluentd/pos/example-log.pos
    read_from_head true
    # The log tag for this log input.
    tag exampletag
</source>

Description

  • Swift Tools 5.8.0
View More Packages from this Author

Dependencies

Last updated: Mon Nov 04 2024 02:00:38 GMT-1000 (Hawaii-Aleutian Standard Time)