11import Foundation
22import Logging
33
4+ #if os(iOS)
5+ import UIKit
6+ #elseif os(macOS)
7+ import AppKit
8+ #endif
9+
410public struct SupabaseLogConfig {
511 let supabaseURL : String
612 let supabaseAnonKey : String
@@ -59,23 +65,40 @@ public struct SupabaseLogHandler: LogHandler {
5965
6066final class SupabaseLogManager {
6167
62- let queue = DispatchQueue ( label: " co.binaryscraping.supabase-log-manager " , qos: . background)
63- var payloads : [ [ String : Any ] ] = [ ]
68+ let cache : LogsCache
6469 let config : SupabaseLogConfig
6570
6671 init ( config: SupabaseLogConfig ) {
6772 self . config = config
73+ self . cache = LogsCache . shared
74+
75+ #if os(macOS)
76+ NotificationCenter . default. addObserver (
77+ self , selector: #selector( appWillTerminate) , name: NSApplication . willTerminateNotification,
78+ object: nil )
79+ #elseif os(iOS)
80+ DispatchQueue . main. asyncAfter ( deadline: . now( ) + 0.5 ) {
81+ // We need to use a delay with these type of notifications because they fire on app load which causes a double load of the cache from disk
82+ NotificationCenter . default. addObserver (
83+ self , selector: #selector( self . didEnterForeground) ,
84+ name: UIApplication . willEnterForegroundNotification, object: nil )
85+ NotificationCenter . default. addObserver (
86+ self , selector: #selector( self . didEnterBackground) ,
87+ name: UIApplication . didEnterBackgroundNotification, object: nil )
88+ }
89+ #endif
6890 }
6991
7092 func log( _ payload: [ String : Any ] ) {
71- queue. async {
72- self . payloads. append ( payload)
73- }
93+ Task { await cache. push ( payload) }
7494 }
7595
76- func uploadLogs( ) {
77- queue. async {
78- let data = try ! JSONSerialization . data ( withJSONObject: self . payloads)
96+ private func checkForLogsAndSend( ) {
97+ Task {
98+ let logs = await cache. pop ( )
99+ if logs. isEmpty { return }
100+
101+ let data = try ! JSONSerialization . data ( withJSONObject: logs)
79102 guard
80103 let url = URL ( string: self . config. supabaseURL) ? . appendingPathComponent ( self . config. table)
81104 else {
@@ -86,14 +109,35 @@ final class SupabaseLogManager {
86109 request. httpMethod = " POST "
87110 request. httpBody = data
88111
89- URLSession . shared. dataTask ( with: request) { data, response, error in
90- if let error = error {
91- print ( error)
92- return
93- }
112+ do {
113+ let ( _, response) = try await URLSession . shared. data ( for: request)
114+ if let httpResponse = response as? HTTPURLResponse {
115+ if 200 ..< 300 ~= httpResponse. statusCode {
116+ return
117+ }
94118
95- self . payloads = [ ]
96- } . resume ( )
119+ await cache. push ( logs)
120+ }
121+ } catch {
122+ await cache. push ( logs)
123+ }
97124 }
98125 }
99126}
127+
128+ extension SupabaseLogManager {
129+ @objc func appWillTerminate( ) {
130+ Task { await cache. backupCache ( ) }
131+ }
132+
133+ #if os(iOS)
134+ @objc func didEnterForeground( ) {
135+ }
136+
137+ @objc func didEnterBackground( ) {
138+ Task {
139+ await cache. backupCache ( )
140+ }
141+ }
142+ #endif
143+ }
0 commit comments