GoogleCloudDestination.swift 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. //
  2. // GoogleCloudDestination.swift
  3. // SwiftyBeaver
  4. //
  5. // Copyright © 2017 Sebastian Kreutzberger. All rights reserved.
  6. //
  7. import Foundation
  8. public final class GoogleCloudDestination: BaseDestination {
  9. private let serviceName: String
  10. public init(serviceName: String) {
  11. self.serviceName = serviceName
  12. super.init()
  13. }
  14. override public var asynchronously: Bool {
  15. get {
  16. return false
  17. }
  18. set {
  19. return
  20. }
  21. }
  22. override public func send(_ level: SwiftyBeaver.Level, msg: String, thread: String,
  23. file: String, function: String, line: Int, context: Any? = nil) -> String? {
  24. let reportLocation: [String: Any] = ["filePath": file, "lineNumber": line, "functionName": function]
  25. var gcpContext: [String: Any] = ["reportLocation": reportLocation]
  26. if let context = context as? [String: Any] {
  27. if let httpRequestContext = context["httpRequest"] as? [String: Any] {
  28. gcpContext["httpRequest"] = httpRequestContext
  29. }
  30. if let user = context["user"] as? String {
  31. gcpContext["user"] = user
  32. }
  33. }
  34. let gcpJSON: [String: Any] = [
  35. "serviceContext": [
  36. "service": serviceName
  37. ],
  38. "message": msg,
  39. "severity": level.severity,
  40. "context": gcpContext
  41. ]
  42. let finalLogString: String
  43. do {
  44. finalLogString = try jsonString(obj: gcpJSON)
  45. } catch {
  46. let uncrashableLogString = "{\"context\":{\"reportLocation\":{\"filePath\": \"\(file)\"" +
  47. ",\"functionName\":\"\(function)\"" +
  48. ",\"lineNumber\":\(line)},\"severity\"" +
  49. ":\"CRITICAL\",\"message\":\"Error encoding " +
  50. "JSON log entry. You may be losing log messages!\"}"
  51. finalLogString = uncrashableLogString.description
  52. }
  53. print(finalLogString)
  54. return finalLogString
  55. }
  56. private func jsonString(obj: Dictionary<String, Any>) throws -> String {
  57. let json = try JSONSerialization.data(withJSONObject: obj, options: [])
  58. guard let string = String(data: json, encoding: .utf8) else {
  59. throw GCPError.serialization
  60. }
  61. return string
  62. }
  63. }
  64. ///
  65. /// https://cloud.google.com/logging/docs/reference/v2/rest/v2/LogEntry#LogSeverity
  66. extension SwiftyBeaver.Level {
  67. /// Verbose is reported as Debug to GCP.
  68. /// Recommend you don't bother using it.
  69. var severity: String {
  70. switch self {
  71. // There is only one level below "Debug": "Default", which becomes "Any" and is considered as a potential error as well
  72. case .verbose: return "DEBUG"
  73. case .debug: return "DEBUG"
  74. case .info: return "INFO"
  75. case .warning: return "WARNING"
  76. case .error: return "ERROR"
  77. }
  78. }
  79. }
  80. private enum GCPError: Error {
  81. case serialization
  82. }