---
agentTools:
  projectIndex: https://operations.readme.io/llms.txt
---

# Logging

Internal log property available to `Operation` subclasses

`Operation` has a log property which can be used to observe scheduling and execution. It support some standard logging features such as a dedicated serial queue, and levels of severity with a threshold.

For example

[block:code]
{
  "codes": [
    {
      "code": "class LogExample: Operation {\n   \n    override func execute() {\n        log.info(\"Hello World!\")\n        finish()\n    }\n}",
      "language": "swift",
      "name": "log example"
    }
  ]
}
[/block]

There are five levels of severity: `.Verbose`, `.Notice`, `.Info`, `.Warning` and `.Fatal`.

[block:code]
{
  "codes": [
    {
      "code": "// Internally the framework uses .Verbose to describe state transitions so, it can be very chatty.\nlog.verbose(\"Really chatty, handy for caveman debugging!\")\n\nlog.notice(\"Public service announcements etc\")\nlog.info(\"Print out info\")\n\n// Internally the framework will log warnings when an operation finishes with an error.\nlog.warning(\"Received a recoverable error.\")\nlog.fatal(\"Something is seriously broken\")",
      "language": "swift",
      "name": "internal operation logs"
    }
  ]
}
[/block]

[block:api-header]
{
  "type": "basic",
  "title": "Default severity threshold"
}
[/block]

The default severity threshold is set on the `LogManager` and is `.Warning`. This means that by default, only `.Warning` and `.Fatal` logs are displayed. This can be adjusted, say in your `AppDelegate`'s `didFinishLaunchingWithOptions` method

[block:code]
{
  "codes": [
    {
      "code": "func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {\n\n    LogManager.severity = .Notice\n    return true\n}",
      "language": "swift",
      "name": "setting default log severity"
    }
  ]
}
[/block]

During development of your app, `.Notice` can be a good setting, as it will provide quite a rich debug setting, yet avoid too much noise from the the framework itself.

If you are encountering scheduling issues, switching to `.Verbose` will give lots more output about an `Operation`'s state, such as when it is pending, evaluating conditions, starting or finishing.

[block:api-header]
{
  "type": "basic",
  "title": "Default enabled"
}
[/block]

Logging can be disabled entirely too:

[block:code]
{
  "codes": [
    {
      "code": "LogManager.enabled = false",
      "language": "swift",
      "name": "disabled logging"
    }
  ]
}
[/block]

[block:api-header]
{
  "type": "basic",
  "title": "Individual overrides"
}
[/block]

Each `Operation` subclass creates a `Logger` using defaults from the `LogManager`. This means that changes to the `LogManager` after an `Operation` has been initialized will not be respected.

However, this does mean that each logger can override the global behavior. This can be especially useful to debug an individual operation at a lower threshold than all the other operations.

[block:code]
{
  "codes": [
    {
      "code": "class LogExample: Operation {\n   \n   override init() {\n       super.init()\n       name = \"Log Example\"\n       log.severity = .Verbose\n   }\n   \n    override func execute() {\n        log.verbose(\"Hello World!\")\n        finish()\n    }\n}",
      "language": "swift",
      "name": "override log severity"
    }
  ]
}
[/block]