Code Monkey home page Code Monkey logo

justlog's Introduction

JustLog Banner

Warning: This library is not supported by Just Eat Takeaway anymore and therefore considered deprecated. The repository has been archived.

JustLog

Build Status Version License Platform

JustLog takes logging on iOS to the next level. It supports console, file and remote Logstash logging via TCP socket with no effort. Support for logz.io available.

Overview

At Just Eat, logging and monitoring are fundamental parts of our job as engineers. Whether you are a back-end engineer or a front-end one, you'll often find yourself in the situation where understanding how your software behaves in production is important, if not critical. The ELK stack for real-time logging has gained great adoption over recent years, mainly in the back-end world where multiple microservices often interact with each other.

In the mobile world, the common approach to investigating issues is gathering logs from devices or trying to reproduce the issue by following a sequence of reported steps. Mobile developers are mostly familiar with tools such as Google Analytics or Fabric.io but they are tracking systems, not fully fledged logging solutions.

We believe tracking is different in nature from logging and that mobile apps should take advantage of ELK too in order to take their monitoring and analysis to another level. Remote logging the right set of information could provide valuable information that would be difficult to gather otherwise, unveil unexpected behaviours and bugs, and even if the data was properly anonymized, identify the sequences of actions of singular users.

JustLog takes logging on iOS to the next level. It supports console, file and remote Logstash logging via TCP socket out of the box. You can also setup JustLog to use logz.io with no effort. JustLog relies on SwiftyBeaver, exposes a simple swifty API but it also plays just fine with Objective-C.

JustLog sets the focus on remote logging, but fully covers the basic needs of local console and file logging.

Installation

CocoaPods

Add the following to your podfile:

pod "JustLog"

You can find the latest version on cocoapods.org

Swift Package Manager

Copy the URL for this repo, and add the package in your project settings.

Usage

Import it into your files like so:

// swift
import JustLog

// Objective-C
@import JustLog;

This logging system strongly relies on SwiftyBeaver. We decided to adopt SwiftyBeaver due to the following reasons:

  • good and extensible design
  • ability to upload logs to the cloud
  • macOS app to analyze logs

A log can be of one of 5 different types, to be used according to the specific need. A reasonable adopted convention on mobile could be the following:

  • 📣 verbose: Use to trace the code, trying to find one part of a function specifically, sort of debugging with extensive information.
  • 📝 debug: Information that is helpful to developers to diagnose an issue.
  • ℹ️ info: Generally useful information to log (service start/stop, configuration assumptions, etc). Info to always have available but usually don't care about under normal circumstances. Out-of-the-box config level.
  • ⚠️ warning: Anything that can potentially cause application oddities but an automatic recovery is possible (such as retrying an operation, missing data, etc.)
  • ☠️ error: Any error which is fatal to the operation, but not the service or application (can't open a required file, missing data, etc.). These errors will force user intervention. These are usually reserved for failed API calls, missing services, etc.

When using JustLog, the only object to interact with is the shared instance of the Logger class, which supports 3 destinations:

  • sync writing to Console (custom destination)
  • sync writing to File (custom destination)
  • async sending logs to Logstash (usually part of an ELK stack)

Following is a code sample to configure and setup the Logger. It should be done at app startup time, in the applicationDidFinishLaunchingWithOptions method in the AppDelegate.

let logger = Logger.shared

// file destination
logger.logFilename = "justeat-demo.log"

// logstash destination
logger.logstashHost = "my.logstash.endpoint.com"
logger.logstashPort = 3515
logger.logstashTimeout = 5
logger.logLogstashSocketActivity = true

// default info
logger.defaultUserInfo = ["app": "my iOS App",
                          "environment": "production",
                          "tenant": "UK",
                          "sessionID": someSessionID]
logger.setup()

The defaultUserInfo dictionary contains a set of basic information to add to every log.

The Logger class exposes 5 functions for the different types of logs. The only required parameter is the message, optional error and userInfo can be provided. Here are some examples of sending logs to JustLog:

Logger.shared.verbose("not so important")
Logger.shared.debug("something to debug")
Logger.shared.info("a nice information", userInfo: ["some key": "some extra info"])
Logger.shared.warning("oh no, that won’t be good", userInfo: ["some key": "some extra info"])
Logger.shared.error("ouch, an error did occur!", error: someError, userInfo: ["some key": "some extra info"])

It plays nicely with Objective-C too:

[Logger.shared debug_objc:@"some message"];
[Logger.shared info_objc:@"some message" userInfo:someUserInfo];
[Logger.shared error_objc:@"some message" error:someError];
[Logger.shared error_objc:@"some message" error:someError userInfo:someUserInfo];

Please note that metadata such as filename and line number are unavailable in Objective-C.

The message is the only required argument for each log type, while userInfo and error are optional. The Logger unifies the information from message, error, error.userInfo, userInfo, defaultUserInfo and call-site info/metadata in a single dictionary with the following schema form of type [String : Any] (we call this 'aggregated form'). E.g. in JSON representation:

{
  "message": "the log message",
  "user_info": {
    "app": "my iOS App",
    "environment": "production",
    "custom_key": "some custom value",
    ...
  },
  "errors": [
  {
    "error_domain" : "com.domain",
    "error_code" : "1234",
    "NSLocalizedDescription": ...,
    "NSLocalizedFailureReasonError": ...,
    ...
  },
  {
    "errorDomain" : "com.domain.inner",
    "errorCode" : "5678",
    "NSLocalizedDescription": ...,
    "NSLocalizedFailureReasonError": ...,
    ...
  }],  
  "metadata": {
    "file": ...,
    "function": ...,
    "line": ...,
    ...
  }
}

All destinations (console, file, logstash) are enabled by default but they can be disabled at configuration time like so:

logger.enableConsoleLogging = false
logger.enableFileLogging = false
logger.enableLogstashLogging = false

The above 5 logs are treated and showed differently on the each destination:

Console

The console prints only the message.

Console

File

On file we store all the log info in the 'aggregated form'.

2016-12-24 12:31:02.734  📣 VERBOSE: {"metadata":{"file":"ViewController.swift","app_version":"1.0 (1)","version":"10.1","function":"verbose()","device":"x86_64","line":"15"},"user_info":{"environment":"production","app":"my iOS App","log_type":"verbose","tenant":"UK"},"message":"not so important"}
2016-12-24 12:31:36.777  📝 DEBUG: {"metadata":{"file":"ViewController.swift","app_version":"1.0 (1)","version":"10.1","function":"debug()","device":"x86_64","line":"19"},"user_info":{"environment":"production","app":"my iOS App","log_type":"debug","tenant":"UK"},"message":"something to debug"}
2016-12-24 12:31:37.368  ℹ️ INFO: {"metadata":{"file":"ViewController.swift","app_version":"1.0 (1)","version":"10.1","function":"info()","device":"x86_64","line":"23"},"user_info":{"environment":"production","app":"my iOS App","log_type":"info","tenant":"UK","some key":"some extra info"},"message":"a nice information"}
2016-12-24 12:31:37.884  ⚠️ WARNING: {"metadata":{"file":"ViewController.swift","app_version":"1.0 (1)","version":"10.1","function":"warning()","device":"x86_64","line":"27"},"user_info":{"environment":"production","app":"my iOS App","log_type":"warning","tenant":"UK","some key":"some extra info"},"message":"oh no, that won’t be good"}
2016-12-24 12:31:38.475  ☠️ ERROR: {"metadata":{"file":"ViewController.swift","app_version":"1.0 (1)","version":"10.1","function":"error()","device":"x86_64","line":"47"},"user_info":{"environment":"production","log_type":"error","some key":"some extra info","app":"my iOS App","tenant":"UK","NSLocalizedFailureReason":"error value"},"errors":[{"error_code":1234,"error_domain":"com.just-eat.test","NSLocalizedDescription":"description","NSLocalizedRecoverySuggestion":"recovery suggestion"}],"message":"ouch, an error did occur!"}

Logstash

Before sending a log to Logstash, the 'aggregated form' is flattened to a simpler `[String : Any] dictionary, easily understood by Logstash and handy to be displayed on Kibana. E.g. in JSON representation:

{
  "message": "ouch, an error did occur!",

  "environment": "production",
  "log_type": "error",
  "version": "10.1",
  "app": "iOS UK app",
  "tenant": "UK",
  "app_version": "1.0 (1)",
  "device": "x86_64",

  "file": "ViewController.swift",
  "function": "error()",
  "line": "47",
  "errors": [{
    "error_domain": "com.just-eat.test",
    "error_code": "1234",
    "NSLocalizedDescription": "description",
    "NSLocalizedFailureReason": "error value"
  }]
}

Which would be shown in Kibana as follows:

Kibana

A note on Logstash destination

The logstash destination is configured via properties exposed by the Logger. E.g.:

let logger = Logger.shared
logger.logstashHost = "my.logstash.endpoint.com"
logger.logstashPort = 3515
logger.logstashTimeout = 5
logger.logLogstashSocketActivity = true

When the logLogstashSocketActivity is set to true, socket activity is printed to the console:

Socket Activity

This destination is the only asynchronous destination that comes with JustLog. This means that logs to Logstash are batched and sent at some point in future when the timer fires. The logstashTimeout property can be set to the number of seconds for the dispatch. In some cases, it might be important to dispatch the logs immediately after an event occurs like so:

Logger.shared.forceSend()

or, more generally, in the applicationDidEnterBackground and applicationWillTerminate methods in the AppDelegate like so:

func applicationDidEnterBackground(_ application: UIApplication) {
  forceSendLogs(application)
}

func applicationWillTerminate(_ application: UIApplication) {
  forceSendLogs(application)
}

private func forceSendLogs(_ application: UIApplication) {

  var identifier = UIBackgroundTaskIdentifier(rawValue: 0)

  identifier = application.beginBackgroundTask(expirationHandler: {
    application.endBackgroundTask(identifier)
    identifier = UIBackgroundTaskIdentifier.invalid
  })

  Logger.shared.forceSend { completionHandler in
    application.endBackgroundTask(identifier)
    identifier = UIBackgroundTaskIdentifier.invalid
  }
}

Sending logs to logz.io

JustLog supports sending logs to logz.io.

At the time of writing, logz.io uses the following host and port (please refer to the official documentation):

logger.logstashHost = "listener.logz.io"
logger.logstashPort = 5052

When configuring the Logger (before calling setup()), simply set the token like so:

logger.logzioToken = <logzio_token>

Custom

From 3.2.0 onward JustLog supports a custom destination that can be defined by you. To implement a custom logger, all you need to do is provide a type that conforms to the CustomDestinationSender protocol to the new overloaded setupWithCustomLogSender() method.

Don't forget to set the enableCustomLogging property to true before calling setupWithCustomLogSender.

class MyCustomDestinationSender: CustomDestinationSender {
    func log(_ string: String) {
        // send the log somewhere
    }
}

let customSender = MyCustomDestinationSender()
let logger = Logger.shared
logger.enableCustomLogging = true
logger.setupWithCustomLogSender(customSender)

Log Sanitization

JustLog supports the implementation of a sanitize method that can be set within the client. This method accepts two placeholder variables:

  • Message: This variable concerns the log message that you wish to sanitize.
  • Log Type: This variable concerns the log level applied to the given log message.
public var sanitize: (_ message: String, _ minimumLogType: LogType) -> String = { message, minimumLogType in

    return message
}

This closure method is set up and called within Logger.Swift. If this method not expanded upon within the client it will simply return the original message, as expected. An example of how we have adopted this sanitize method can be seen within AppDelegate.swift in which we redact certain values based upon an input list. Clicking on 'Sanitized Log Message' in the example app will provide an example of the santizer method in action.

Conclusion

JustLog aims to be an easy-to-use working solution with minimal setup. It covers the most basic logging needs (console and file logging) via the great foundations given by SwiftBeaver, but also provides an advanced remote logging solution for Logstash (which is usually paired with Elasticsearch and Kibana in an ELK stack). JustLog integrates with logz.io, one of the most widely used ELK SaaS, placing itself as the only solution in the market (at the time of writing) to leverage such stack on iOS.

We hope this library will ease the process of setting up the logging for your team and help you find solutions to the issues you didn't know you had.

  • Just Eat iOS team

justlog's People

Contributors

aj9 avatar albertodebortoli avatar alkiviadispapadakis-je avatar antoniostrijdom avatar danlages avatar dchakarov avatar denys-meloshyn avatar diemer avatar dmcrodrigues avatar federicocappelli avatar federicocappelli-je avatar fguchelaar avatar gigisommo avatar ilazakis avatar isavynskyi avatar junaidyounus-je avatar kayoslab avatar maciejtrybilo avatar markj avatar molynerd avatar natanrolnik avatar nirlachman-monday avatar oliverpearmain-je avatar oronbz avatar piotr-adamczak-mobica avatar richardrauser-je avatar stevenwarren-je avatar wolfale avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

justlog's Issues

Issue when building a static library

Hello,

When trying to package a static library with JustLog as a dependency in podspec, raises the following error

The Swift pod "JustLog" depends upon "CocoaAsyncSocket", which do not define modules. To opt into those targets generating module maps (which is necessary to import them from Swift when building as static libraries), you may set "use_modular_headers!" globally in your Podfile, or specify ":modular_headers => true" for particular dependencies.

At the moment you have to specify s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } flag in your podspec to get rid of this issue (see here : CocoaPods/CocoaPods#7683 )

Could you please add this flag into your podspec?

Implement CocoaAsyncSocket 7.6.1

I'd like to use this for my project, but this pod depends on CocoaAsyncSocket 7.5.0 and I'm already depending on 7.6.1.

I'd love to help out if possible, but it doesn't appear that the files are complete. There appears to be no way to open this project. That could just be my inexperience with developing pods. Let me know.

Not able to see log on Kibana even after seeing `🔌 <AsyncSocket>, did write`

Hi,
Firstly thanks for this utility repository. i am facing issues to search log in Kibana.

I am using the following code, it's just an integration attempt to check everything is working fine.

The code base i am using:

struct LogDestinationLogStash: LogDestinationType {
    let logger = Logger.shared

    init(appID: String, enviroment: LogStashEnv) {
        // logstash destination
        logger.logstashHost = "https://my.aws.found.io"
        logger.logstashPort = 1111
        logger.logstashTimeout = 5
        logger.logLogstashSocketActivity = true

        // default info
        logger.defaultUserInfo = ["app": appID,
                                  "environment": enviroment.rawValue,
                                  "tenant": "UK",
                                  "sessionID": "someSessionID"]
        logger.setup()
    }
    func appendText(_ text: String) {
        Logger.shared.info(text, userInfo: ["some key": "some extra info"])
    }
}

The observation:

When executing Logger.shared.info(text, userInfo: ["some key": "some extra info"]), i can see some logs on my Xcode console.

2020-03-25 18:43:58.003  ℹ️ INFO: Home Screen: getHomeData Table view reloaded
2020-03-25 18:43:58.554  ℹ️ INFO: LoaderPermissionFlow screen removed from navigation controller
// and so on then
🔌 <AsyncSocket>, did write
🔌 <AsyncSocket>, did write
// SOME MORE log with `did write`
🔌 <AsyncSocket>, did write
🔌 <AsyncSocket>, did write
🔌 <AsyncSocket>, disconnected!
🔌 <AsyncSocket>, connected!
🔌 <AsyncSocket>, did secure
🔌 <AsyncSocket>, did write
🔌 <AsyncSocket>, disconnected!

The Issue

Based on this log i am assuming that logs written from my code was successfully uploaded to LogStash, but while searching i am not able to see them. But i can see logs coming from my account due to hitting some end points.

My Questions

  1. Do i missing any thing here?
  2. Is there any log on my console (or enabling DEBUG mode) will help me to have some log to be ensure that log is uploaded to ELK stack component LogStash?

Edit

When I change my host name to some wrong value, i get the following error

🔌 <AsyncSocket>, Could not startTLS: The operation couldn’t be completed. (JustLog.AsyncSocketManager.AsyncSocketError error 0.)
2020-03-25 19:12:47.581  ℹ️ INFO: Home Screen: getHomeData Table view reloaded
🔌 <AsyncSocket>, Could not connect: Attempting to connect while connected or accepting connections. Disconnect first.
🔌 <AsyncSocket>, Could not startTLS: The operation couldn’t be completed. (JustLog.AsyncSocketManager.AsyncSocketError error 0.)
🔌 <AsyncSocket>, Could not connect: Attempting to connect while connected or accepting connections. Disconnect first.
🔌 <AsyncSocket>, Could not startTLS: The operation couldn’t be completed. (JustLog.AsyncSocketManager.AsyncSocketError error 0.)
🔌 <AsyncSocket>, Could not connect: Attempting to connect while connected or accepting connections. Disconnect first.
🔌 <AsyncSocket>, Could not startTLS: The operation couldn’t be completed. (JustLog.AsyncSocketManager.AsyncSocketError error 0.)
🔌 <AsyncSocket>, disconnected with error: nodename nor servname provided, or not known
Error Domain=kCFStreamErrorDomainNetDB Code=8 "nodename nor servname provided, or not known" UserInfo={NSLocalizedDescription=nodename nor servname provided, or not known}

Minimum deployment target to iOS 8.0

Hi,
is there anything that could prevent us from lowering the deployment target to iOS 8.0 ? It seems that both libs(SwiftyBeaver,CocoaAsyncSocket) support iOS 8.0.

SPM: explicitly declare them as resources or exclude from the target

Added JustLog as a SPM dependency

let package = Package(
....
    dependencies: [
        .package(url: "https://github.com/justeat/JustLog", .upToNextMajor(from: "3.4.0")),

Trying to resolve packages graph with Xcode 12.5. Got the following warning:

found 1 file(s) which are unhandled; explicitly declare them as resources or exclude from the target

/SourcePackages/checkouts/JustLog/JustLog/Supporting Files/Info.plist

Carthage build error using release 3.0.0

Problem:
When trying to include JustLog version 3.0.0 I get the following error:

.../Carthage/Checkouts/JustLog/JustLog/Classes/Logger.swift:101:35: error: 'scheduledTimer(withTimeInterval:repeats:block:)' is only available on iOS 10.0 or newer
            dispatchTimer = Timer.scheduledTimer(withTimeInterval: dispatchInterval, repeats: true) { [weak self] timer in
                                  ^
...

Solution:
increase the iOS Deployment target in project.pbxproj to 10.0 (from 8.0)

[Crash] Over committing from RepeatingTimer

Hey there,
We noticed there's a somewhat repeating crash on JustLog that looks like this:

Crashed: com.apple.root.default-qos.overcommit
EXC_BAD_ACCESS KERN_INVALID_ADDRESS 0x0000000000000000

image

Over-comitting basically means the queue can't handle the amount of scheduled pieces of work simultaneously with the provided quality of service. I believe this is related to the fact you're using makeTimerSource and using the default queue instead of possibly creating your own queue with a different quality of service, but haven't had a chance to properly investigate.

Are you aware of this crash? Couldn't find any other reports on it. Thanks!

Set logStash log level

Hi,
Is there anyway to set the log level threshold that will be uploaded to logStash?
for instance, I want to see verbose logs in my console but I do not want them uploaded to logstash. Let's say I want to upload only debug and up.
Is there a possible solution to this?

Fatal Exception: NSInvalidArgumentException -[__NSCFNumber count] Logger.log(_:_:error:userInfo:_:_:_:)

Hi,

Please let me know how to fix the following issue in your lib.
Thanks

Fatal Exception: NSInvalidArgumentException
-[__NSCFNumber count]: unrecognized selector sent to instance 0x8000000000000000
Logger.log(::error:userInfo:::_:)
keyboard_arrow_down

Fatal Exception: NSInvalidArgumentException
0 CoreFoundation 0x1a4112754 __exceptionPreprocess
1 libobjc.A.dylib 0x1b8bd97a8 objc_exception_throw
2 CoreFoundation 0x1a4015c3c -[NSOrderedSet initWithSet:copyItems:]
3 CoreFoundation 0x1a41152ac forwarding
4 CoreFoundation 0x1a41175b0 CF_forwarding_prep_0
5 MyApp. 0x100b40efc Logger.log(
::error:userInfo::::) ()
6 MyApp. 0x100b412a0 Logger.verbose(:error:userInfo::::)
7 MyApp. 0x100b40484 Logger.verbose(:error:userInfo::::)

Add Sematext / Elasticsearch as log output destination

Elasticsearch has a simple HTTP REST API for ingesting data.
Sematext exposes the Elasticsearch API, so by adding support for Elasticsearch output/destination we'd automatically get support for sending logs to Sematext, too. 2 birds...

Being able to send logs to Sematext or Elasticsearch would be welcomed by a lot of people.

@albertodebortoli-je WDYT?

No support for Objective-C Projects?

Since this is using SwiftyBeaver, this can't be used in Objective-C projects? Not sure why README shows that it does support Obj-C projects then.

macOS Support

Hey,

Was hoping to use this project for logging in some macOS products but I see the pod spec doesn't specify osx support. Aside from the UIDevice extension is there anything else that'd stop it working on macOS projects?

If not I'm happy to do a PR for macOS support.

Sean.

Question on Offline Logging and re-upload when internet connection is available

Hello,

Does justLog supports saving logs to a file or a database and then uploading the logs to Elasticsearch or even a custom server when internet connection is available and based on some conditions for example :

  • perdiodic timer

  • when the size of the logs reach a certain size ?

After checking the code base of the library, i conclude that this is not provided, if i am not mistaken can i add this functionality to the Library myself ?

Thank you for your replies !

Loglevel?

I can't figure out if it's possible to configure a minimum loglevel to send?
I want to disable debug/info-logs when going to production.

`error` parameter with non-JSONable `userInfo`

When passing an NSError parameter to the logging method, the error's userInfo property is merged into the userInfo parameter and converted to JSON. However, some standard NSErrors contain userInfo which are not valid JSON objects. For example, NSURLErrorDomain errors usually contain NSErrorFailingURLKey which is of type NSURL. Moreover, some of these are trapped inside underlying errors beneath NSUnderlyingErrorKey which is hard to track.

The resulting outcome is that the whole log message is discarded, and the only thing printed to the console is The data couldn’t be read because it isn’t in the correct format., making it almost impossible to track the source of the error.

My proposal is to update the merging process of the userInfos in the logger to take the description of objects which aren't Encodable, and if they don't conform to CustomStringConvertible, then discard them.

minLevel set

Hi, I wanted to set minLevel for console logging but the vars are private

    private let internalLogger = SwiftyBeaver.self
    private var console: ConsoleDestination!

Do you have another way to set it or should I send a PR with a functionality to enable minLevel changes?

use case: I only wanted to see logs on warning and error, ignoring all the others.

crash when logstashHost isn't set

during setup(), this will crash

logstash = LogstashDestination(host: logstashHost, port: logstashPort, timeout: logstashTimeout, logActivity: logLogstashSocketActivity)

because logstashHost is of type String!.

easy way to solve would be to just give a default of "" like the other logstash vars.

Multiple Logger instances

Hi,
Is it possible to have multiple Logger instances, like:
I want to see two log files.

  • One with all the logging
  • One with only the critical ones so they are easily visible without the need for a Logfile analysis tool

In my AppDelegate, I created:

let genericLogger = JustLog.Logger.shared
let criticalLogger = JustLog.Logger()

And then I configured them both
And then I called setup() on both

Would that be possible?
(I tried and got a crash)

Or would there be another solution to get 2 logfiles ... or 2 instances of the Logger?

Thanks!
Wouter

How can I get the actual rest results with XCUITest in the Log file

I need to use the following example :

2016-12-24 12:31:02.734  📣 VERBOSE: {"metadata":{"file":"ViewController.swift","app_version":"1.0 (1)","version":"10.1","function":"verbose()","device":"x86_64","line":"15"},"user_info":{"environment":"production","app":"my iOS App","log_type":"verbose","tenant":"UK"},"message":"not so important"}
2016-12-24 12:31:36.777  📝 DEBUG: {"metadata":{"file":"ViewController.swift","app_version":"1.0 (1)","version":"10.1","function":"debug()","device":"x86_64","line":"19"},"user_info":{"environment":"production","app":"my iOS App","log_type":"debug","tenant":"UK"},"message":"something to debug"}
2016-12-24 12:31:37.368  ℹ️ INFO: {"metadata":{"file":"ViewController.swift","app_version":"1.0 (1)","version":"10.1","function":"info()","device":"x86_64","line":"23"},"user_info":{"environment":"production","app":"my iOS App","log_type":"info","tenant":"UK","some key":"some extra info"},"message":"a nice information"}
2016-12-24 12:31:37.884  ⚠️ WARNING: {"metadata":{"file":"ViewController.swift","app_version":"1.0 (1)","version":"10.1","function":"warning()","device":"x86_64","line":"27"},"user_info":{"environment":"production","app":"my iOS App","log_type":"warning","tenant":"UK","some key":"some extra info"},"message":"oh no, that won’t be good"}
2016-12-24 12:31:38.475  ☠️ ERROR: {"metadata":{"file":"ViewController.swift","app_version":"1.0 (1)","version":"10.1","function":"error()","device":"x86_64","line":"47"},"user_info":{"environment":"production","log_type":"error","some key":"some extra info","app":"my iOS App","tenant":"UK","NSLocalizedFailureReason":"error value"},"errors":[{"error_code":1234,"error_domain":"com.just-eat.test","NSLocalizedDescription":"description","NSLocalizedRecoverySuggestion":"recovery suggestion"}],"message":"ouch, an error did occur!"}
Logstash

but with a real example from the XCTest and log in the log file or send it to the JSON file for LogStash

Crashing on writeLogs()

I got some crashes happend on my hockey crash report:

Thread 13 Crashed:
0   JustLog                              0x00000001015128b8 generic specialization <[Swift.Int : [Swift.String : protocol<>]] with [Swift.Int : [Swift.String : protocol<>]] : Swift.Collection in Swift> of Swift._copyCollectionToContiguousArray <A where A: Swift.Collection> (A) -> Swift.ContiguousArray<A.Iterator.Element> (LogstashDestination.swift:0)
1   JustLog                              0x0000000101513b48 function signature specialization <Arg[0] = Owned To Guaranteed> of JustLog.LogstashDestination.(writeLogs () -> ()).(closure #1) (LogstashDestination.swift:0)
2   JustLog                              0x000000010151179c JustLog.LogstashDestination.(writeLogs () -> ()).(closure #1) (LogstashDestination.swift:0)
3   Foundation                           0x0000000186dd4374 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 12

Any idea why this happened?

Logging while app is in the background

Hi, I have an app that runs a background refresh task.As part of that task I am logging the event.

The issue comes when the device is locked, regardless of wether the app is minimised or not. When the background task is triggered i get the following error:

*** Terminating app due to uncaught exception 'NSFileHandleOperationException', reason: '*** -[NSConcreteFileHandle writeData:]: Operation not permitted'

This is the code that triggers the logger:

func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { self.isLaunchingFromBackground = true DispatchQueue.global(qos: .default).async { self.logger.verbose("Background Fetch Initiated", userInfo: ["SSID": Globals.shared.getWiFiSsid()!, "Is First Run": Globals.shared.isFirstRun, "Reachable": Globals.shared.isReachable, "User Is Valid": AppUser.shared.isValid(), "User emailAddress": AppUser.shared.emailAddress, "IsLaunchingFromBackground": self.isLaunchingFromBackground ]) } Answers.logCustomEvent(withName: "Background Fetch Initiated")

It was not initially wrapped with the DispatchQueue, I was trying that as a way round the issue.
I have attached a screenshot to the app capabilities.

Screenshot 2019-09-20 at 13 50 36
I have tried to wrap in a do / try handler but the logger does not throw any exceptions so it can't be caught.

Thanks
Chris

Carthage support

Hi, would you guys be open to supporting Carthage? I could volunteer to implement this :D

Is this still maintained? Looking for collaborators?

Hi Guys,
I've started using JustLog and it kind of fit my needs so many thanks on the great work you've done here. I didn't find any other Logz.io solution for iOS other than implementing it myself.

But I've noticed you're not very active on PRs and issues. Do you need any help with maintaining this library? Should I fork it and maintain it on my own?

There are a few things I'd like to improve and fix in this library.
Please let me know the best way to continue with this.

Thanks,
Oron

Store some of the logs on the file and send the others to the server

Hello,

I wanted to ask about the ability to store some of the logs on the file and the others on the server. For example, all the messages of type Info I'd like to store on the file. However, when serious error occurs, I'd like to send the message of type Error to the server. How do I implement this?

Additionally, how do you send entire log file to the server (logz.io or Parse)?

Thank you very much!

Carthage Error: Task failed with exit code 65

Getting this error when trying to run the Carthage update command.

Command:
carthage update JustLog --use-xcframeworks

Error:
Task failed with exit code 65

More specific error from logs:
Build input file cannot be found: '/Users/parag/Work/Backup/ios2Backup/Carthage/Checkouts/JustLog/JustLog/Classes/AsyncSocketManager.swift' (in target 'JustLog' from project 'JustLog')

It'd be great if you can help to resolve this. Thank you.

Objective-C interface reports wrong metadata

The objective-C interface reports the wrong line number, file name, and function - this happens due to the macros being referenced within the *_objc method bodies, rather than as a default parameter.

(Unfortunately, it is not currently possible to create an Obj-C implementation to wrap the swift version due to the lack of Obj-C bridging for StaticString).

What is JustLog default character encoding?

Hello,

I want to ask what is JustLog default character encoding? I have received the error from my Logstash server. Can I set the JustLog default to UTF-8?

logstash log:
Received an event that has a different character encoding than you configured. {:text=>"\u0016\u0003\u0001\u0000\xB5\u0001\u0000\u0000\xB1\u0003\u0003[\xBE\xD3N\xE0&\x9C(wQ.\u0010&jH\u0014\xE3\"4ct\xA4\xCB)\xD6\xDB\xE4\x8C\u0004\x90ߥ\u0000\u0000,\u0000\xFF\xC0,\xC0+\xC0$\xC0#\xC0", :expected_charset=>"UTF-8"}
[2018-10-11T04:36:30,425][WARN ][logstash.codecs.line ] Received an event that has a different character encoding than you configured. {:text=>"\xC0\t\xC0\b\xC00\xC0/\xC0(\xC0'\xC0\u0014\xC0\u0013\xC0\u0012\u0000\x9D\u0000\x9C\u0000=\u0000<\u00005\u0000/\u0000", :expected_charset=>"UTF-8"}

My conf file in conf.d:
input {
tcp {
port => 5000

ssl_enable => false
}

}
...

Thanks

Code=28 "No space left on device"

Hi everyone,

Found an issue
🔌 <LogstashDestination>, 1998045481163 did error: The operation couldn’t be completed. No space left on device
Error Domain=NSPOSIXErrorDomain Code=28 "No space left on device" UserInfo={_kCFStreamErrorCodeKey=28, _kCFStreamErrorDomainKey=1}

Xcode 13.1, iOS 15.1

How to reproduce:
After sending approximately 500 request with logs, next requests do not sending.

Why:
As I can see in "LogstashDestinationSocket" we create task "streamTask(withHostName: self.host, port: self.port)" , then write data in task, then resume it. But, this task will not never cancel in future, and itwill live for all time of living URLSession, or for all time of living app. When will be created about 500 task, we will have an error.
Count of created tasks we can check by "session.getAllTasks". All tasks will have status "running"

To fix it I think we can add "task.cancel()" in "dispatchGroup.notify".

dispatchGroup.notify(queue: queue) {
    task.cancel()
    complete(sendStatus)
}

or

dispatchGroup.notify(queue: queue) {
    task.closeWrite()
    task.closeRead()
    complete(sendStatus)
}

Proposal: Smaller API

We are currently using JustLog in our project, but we find the current API area quite extensive:

public protocol Logging {

    public func verbose(_ message: String, error: NSError?, userInfo: [String : Any]?, _ file: StaticString, _ function: StaticString, _ line: UInt)

    public func debug(_ message: String, error: NSError?, userInfo: [String : Any]?, _ file: StaticString, _ function: StaticString, _ line: UInt)

    public func info(_ message: String, error: NSError?, userInfo: [String : Any]?, _ file: StaticString, _ function: StaticString, _ line: UInt)

    public func warning(_ message: String, error: NSError?, userInfo: [String : Any]?, _ file: StaticString, _ function: StaticString, _ line: UInt)

    public func error(_ message: String, error: NSError?, userInfo: [String : Any]?, _ file: StaticString, _ function: StaticString, _ line: UInt)
}

To make it easier for us, we created a wrapper around the Logging protocol like so:

extension BabylonLogging {
    func log(_ level: LogLevel,
              _ message: String,
              error: Error?,
              userInfo: [String : Any]?,
              _ file: StaticString,
              _ function: StaticString,
              _ line: UInt)
}

Where the key bit is the LogLevel:

public enum LogLevel {
    case verbose
    case debug
    case info
    case warning
    case error
}

This is just a minor thing, but do you think it would make sense to have the same in JustLog? I am happy to make a PR.

no ssl

How do we manage SSL? Neither documentation covers nor could I have found a way to set the certificate.

Is JustLog available or validated on macOS?

Hello folks.

I'm looking for a good solution for exporting logs to an ELK stack (I'm currently using Elastic cloud), but I sometimes need to support macOS in my apps. I'm about to attempt a validation to see if JustLog is suitable, but I thought I'd ask whether you folks have any insights that might be helpful.

Thanks in advance.

[Question] How to setup on react-native

Hello,

I'm developing a react-native app and I want to use this to send iOS logs to logz.io. I don't see any reason it won't work but I can't seem to make it work.

I tried to setup it like this

  // iOS Native logging
  Logger.shared.enableConsoleLogging = true;
  Logger.shared.enableFileLogging = true;
  Logger.shared.enableLogstashLogging = true;

  // logstash destination
  Logger.shared.logstashHost = @"listener.logz.io";
  Logger.shared.logstashPort = 5052;
  Logger.shared.logzioToken = @"<my-logz-token>";

  [Logger.shared setup];
  
  [Logger.shared debug_objc:@"Hi there"];

The logs appears correctly in xcode, but I receive nothing on logz.io.

Screenshot 2021-06-24 at 14 25 32

I don't really know obj-c so my guess is that the setup I did is wrong. Is there some setup documentation for obj-c like the one you did for swift in the README ?

Carthage

Do you intend to give the possibility to install your framework with Carthage ? thks

Doc mistake?

In doc I see:
Please note that metadata such as filename and line number are unavailable in Objective-C.
But may be in Swift it is unavailable?
On Objective-C you can do it with:
NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__,...
https://stackoverflow.com/a/969291/602249

Xcode 11 build error using Carthage

Hi,

After installing Xcode 11, when running carthage update I get the following error when building the tvOS scheme:

** ARCHIVE SUCCEEDED **

/usr/bin/xcrun xcodebuild -project /Users/dario/Documents/editedPath/Carthage/Checkouts/JustLog/JustLog.xcodeproj -scheme JustLog-tvos -configuration Release -derivedDataPath /Users/dario/Library/Caches/org.carthage.CarthageKit/DerivedData/11.0_11A420a/JustLog/3.0.0 -sdk appletvsimulator -destination platform=tvOS\ Simulator,id=CC888E18-9DDF-4057-A755-B047BED08DBC -destination-timeout 3 ONLY_ACTIVE_ARCH=NO CODE_SIGNING_REQUIRED=NO CODE_SIGN_IDENTITY= CARTHAGE=YES build (launched in /Users/dario/Documents/editedPath/Carthage/Checkouts/JustLog)User defaults from command line:
    IDEDerivedDataPathOverride = /Users/dario/Library/Caches/org.carthage.CarthageKit/DerivedData/11.0_11A420a/JustLog/3.0.0

Build settings from command line:
    CARTHAGE = YES
    CODE_SIGN_IDENTITY =
    CODE_SIGNING_REQUIRED = NO
    ONLY_ACTIVE_ARCH = NO
    SDKROOT = appletvsimulator13.0

xcodebuild: error: Unable to find a destination matching the provided destination specifier:
		{ platform:tvOS Simulator, id:CC888E18-9DDF-4057-A755-B047BED08DBC }

	Ineligible destinations for the "JustLog-tvos" scheme:
		{ platform:tvOS, id:dvtdevice-DVTiOSDevicePlaceholder-appletvos:placeholder, name:Generic tvOS Device }
		{ platform:tvOS Simulator, id:dvtdevice-DVTiOSDeviceSimulatorPlaceholder-appletvsimulator:placeholder, name:Generic tvOS Simulator Device }

this is the content of the Cartfile

github "justeat/JustLog" ~> 3.0.0

I can avoid it by building only for the iOS platform, but if it is an easy fix I would like to be able to solve the issue for the tvOS platform.

Logstash ssl error

Logging through logstash is unreliable - works for some time and not for the rest. The library shows these errors in the console:

Error in postLogs: Optional(Error Domain=kCFStreamErrorDomainSSL Code=-9806 "(null)" UserInfo={NSLocalizedRecoverySuggestion=Error code definition can be found in Apple's SecureTransport.h})
🔌 <AsyncSocket>, Could not connect: Attempting to connect while connected or accepting connections. Disconnect first.
🔌 <AsyncSocket>, Could not startTLS: The operation couldn't be completed. (JustLog.AsyncSocketManager.AsyncSocketError error 0.)
Error in postLogs: Optional(Error Domain=NSPOSIXErrorDomain Code=0 "Undefined error: 0" UserInfo={NSLocalizedDescription=Undefined error: 0, NSLocalizedFailureReason=Error in connect() function})

Restarting logstash seems to fix the issue, which suggests there's something wrong with the logstash config (shown below). Any suggestions on what could be wrong? I'm on logstash 5.1.1

    tcp {
        port => "19540"
        tags => ["input_ios_sdk"]
        ssl_enable => true
        ssl_cert => "/path/to/domain.com.crt"
        ssl_key => "/path/to/wild.domain.com.key"
        ssl_verify => false
    }

Thanks for the good work on the library!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.