better logging

This commit is contained in:
Andy Pack 2022-11-23 23:39:58 +00:00
parent d73ec449cf
commit a3b1a67b5b
Signed by: sarsoo
GPG Key ID: A55BA3536A5E0ED7
12 changed files with 154 additions and 49 deletions

View File

@ -8,6 +8,7 @@
import UIKit import UIKit
import SwiftyJSON import SwiftyJSON
import OSLog
@UIApplicationMain @UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate { class AppDelegate: UIResponder, UIApplicationDelegate {
@ -34,3 +35,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
} }
extension Logger {
private static var subsystem = Bundle.main.bundleIdentifier!
/// Logs the view cycles like viewDidLoad.
static let net = Logger(subsystem: subsystem, category: "net")
static let parse = Logger(subsystem: subsystem, category: "parse")
static let sys = Logger(subsystem: subsystem, category: "sys")
}

View File

@ -10,6 +10,7 @@ import Foundation
import Alamofire import Alamofire
import SwiftyJSON import SwiftyJSON
import KeychainAccess import KeychainAccess
import OSLog
class LiveUser: ObservableObject { class LiveUser: ObservableObject {
@ -54,6 +55,8 @@ class LiveUser: ObservableObject {
func logout() { func logout() {
let keychain = Keychain(service: "xyz.sarsoo.music.login") let keychain = Keychain(service: "xyz.sarsoo.music.login")
Logger.sys.info("logging user out")
do { do {
try keychain.remove("username") try keychain.remove("username")
try keychain.remove("jwt") try keychain.remove("jwt")
@ -68,8 +71,10 @@ class LiveUser: ObservableObject {
self.loggedIn = false self.loggedIn = false
Logger.sys.debug("successfully logged user out")
} catch let error { } catch let error {
debugPrint("Could not clear keychain, \(error)") Logger.sys.error("could not clear keychain, \(error)")
} }
} }
@ -83,17 +88,21 @@ class LiveUser: ObservableObject {
func refresh_user(onSuccess: (() -> Void)? = nil, onFailure: (() -> Void)? = nil) { func refresh_user(onSuccess: (() -> Void)? = nil, onFailure: (() -> Void)? = nil) {
self.isRefreshingUser = true self.isRefreshingUser = true
Logger.sys.info("refreshing user")
let api = UserApi.getUser let api = UserApi.getUser
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
if self.check_network_response(response: response) { if self.check_network_response(response: response) {
guard let data = response.data else { guard let data = response.data else {
fatalError("error getting user") Logger.net.error("error getting user")
return
} }
guard let json = try? JSON(data: data) else { guard let json = try? JSON(data: data) else {
fatalError("error parsing user") Logger.parse.error("error parsing user")
return
} }
// update state // update state
@ -102,12 +111,14 @@ class LiveUser: ObservableObject {
self.isRefreshingUser = false self.isRefreshingUser = false
if let success = onSuccess { if let success = onSuccess {
Logger.sys.debug("successfully refreshed user")
success() success()
} }
} else { } else {
if let failure = onFailure { if let failure = onFailure {
Logger.net.error("failed to refresh user")
failure() failure()
} }
} }
@ -117,17 +128,21 @@ class LiveUser: ObservableObject {
func refresh_playlists(onSuccess: (() -> Void)? = nil, onFailure: (() -> Void)? = nil) { func refresh_playlists(onSuccess: (() -> Void)? = nil, onFailure: (() -> Void)? = nil) {
self.isRefreshingPlaylists = true self.isRefreshingPlaylists = true
Logger.sys.info("refreshing playlists")
let api = PlaylistApi.getPlaylists let api = PlaylistApi.getPlaylists
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
if self.check_network_response(response: response) { if self.check_network_response(response: response) {
guard let data = response.data else { guard let data = response.data else {
fatalError("error getting playlists") Logger.net.error("error getting playlists from net request")
return
} }
guard let json = try? JSON(data: data) else { guard let json = try? JSON(data: data) else {
fatalError("error parsing reponse") Logger.parse.error("error parsing playlists reponse")
return
} }
let playlists = json["playlists"].arrayValue let playlists = json["playlists"].arrayValue
@ -138,6 +153,7 @@ class LiveUser: ObservableObject {
self.isRefreshingPlaylists = false self.isRefreshingPlaylists = false
if let success = onSuccess { if let success = onSuccess {
Logger.sys.debug("successfully refreshed playlists")
success() success()
} }
@ -145,12 +161,13 @@ class LiveUser: ObservableObject {
do { do {
UserDefaults.standard.set(String(data: try encoder.encode(playlists), encoding: .utf8), forKey: "playlists") UserDefaults.standard.set(String(data: try encoder.encode(playlists), encoding: .utf8), forKey: "playlists")
} catch { } catch {
print("error encoding playlists: \(error)") Logger.parse.error("error encoding playlists: \(error)")
} }
} else { } else {
if let failure = onFailure { if let failure = onFailure {
Logger.net.error("failed to refresh playlists")
failure() failure()
} }
} }
@ -159,6 +176,8 @@ class LiveUser: ObservableObject {
func refresh_tags(onSuccess: (() -> Void)? = nil, onFailure: (() -> Void)? = nil) { func refresh_tags(onSuccess: (() -> Void)? = nil, onFailure: (() -> Void)? = nil) {
self.isRefreshingTags = true self.isRefreshingTags = true
Logger.sys.info("refreshing tags")
let api = TagApi.getTags let api = TagApi.getTags
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
@ -166,11 +185,13 @@ class LiveUser: ObservableObject {
if self.check_network_response(response: response) { if self.check_network_response(response: response) {
guard let data = response.data else { guard let data = response.data else {
fatalError("error getting tags") Logger.net.error("error getting tags")
return
} }
guard let json = try? JSON(data: data) else { guard let json = try? JSON(data: data) else {
fatalError("error parsing reponse") Logger.parse.error("error parsing tags response")
return
} }
let tags = json["tags"].arrayValue let tags = json["tags"].arrayValue
@ -181,6 +202,7 @@ class LiveUser: ObservableObject {
self.isRefreshingTags = false self.isRefreshingTags = false
if let success = onSuccess { if let success = onSuccess {
Logger.sys.debug("successfully refreshed tags")
success() success()
} }
@ -188,12 +210,13 @@ class LiveUser: ObservableObject {
do { do {
UserDefaults.standard.set(String(data: try encoder.encode(tags), encoding: .utf8), forKey: "tags") UserDefaults.standard.set(String(data: try encoder.encode(tags), encoding: .utf8), forKey: "tags")
} catch { } catch {
print("error encoding tags: \(error)") Logger.parse.error("error encoding tags: \(error)")
} }
} else { } else {
if let failure = onFailure { if let failure = onFailure {
Logger.net.error("failed to refresh tags")
failure() failure()
} }
} }
@ -205,21 +228,28 @@ class LiveUser: ObservableObject {
if let statusCode = response.response?.statusCode { if let statusCode = response.response?.statusCode {
switch statusCode { switch statusCode {
case 401: // token has expired case 401: // token has expired
Logger.sys.info("token expired, logging user out")
self.logout() self.logout()
return false return false
case 400..<500: case 400..<500:
Logger.net.error("client fault \(statusCode)")
return false return false
case 500..<600: case 500..<600:
Logger.net.warning("server fault \(statusCode)")
return false return false
case _: // 200 -> Success case _: // 200 -> Success
return true return true
} }
} }
Logger.net.error("live user failed to access status code to check")
return false return false
} }
func load_user_defaults() -> LiveUser { func load_user_defaults() -> LiveUser {
Logger.sys.debug("loading user defaults")
let defaults = UserDefaults.standard let defaults = UserDefaults.standard
let decoder = JSONDecoder() let decoder = JSONDecoder()
@ -230,17 +260,19 @@ class LiveUser: ObservableObject {
do { do {
if let _strPlaylists = _strPlaylists { if let _strPlaylists = _strPlaylists {
if _strPlaylists.count > 0 { if _strPlaylists.count > 0 {
Logger.sys.debug("reading \(_strPlaylists.count) playlists")
self.playlists = (try decoder.decode([Playlist].self, from: _strPlaylists.data(using: .utf8)!)).sorted(by: { $0.name.lowercased() < $1.name.lowercased() }) self.playlists = (try decoder.decode([Playlist].self, from: _strPlaylists.data(using: .utf8)!)).sorted(by: { $0.name.lowercased() < $1.name.lowercased() })
} }
} }
if let _strTags = _strTags { if let _strTags = _strTags {
if _strTags.count > 0 { if _strTags.count > 0 {
Logger.sys.debug("reading \(_strTags.count) tags")
self.tags = (try decoder.decode([Tag].self, from: _strTags.data(using: .utf8)!)).sorted(by: { $0.name.lowercased() < $1.name.lowercased() }) self.tags = (try decoder.decode([Tag].self, from: _strTags.data(using: .utf8)!)).sorted(by: { $0.name.lowercased() < $1.name.lowercased() })
} }
} }
} catch { } catch {
print("error decoding: \(error)") Logger.parse.error("error parsing user defaults: \(error)")
} }
return self return self

View File

@ -9,6 +9,7 @@
import Foundation import Foundation
import UIKit import UIKit
import SwiftyJSON import SwiftyJSON
import OSLog
class Playlist: Identifiable, Equatable, Codable, ObservableObject { class Playlist: Identifiable, Equatable, Codable, ObservableObject {
@ -121,7 +122,7 @@ class Playlist: Identifiable, Equatable, Codable, ObservableObject {
case 200, 201: case 200, 201:
break break
case _: case _:
debugPrint("error: \(self.name), \(updates)") Logger.net.error("error: \(self.name), \(updates)")
} }
} }
//TODO: do better error checking //TODO: do better error checking
@ -261,7 +262,7 @@ class Playlist: Identifiable, Equatable, Codable, ObservableObject {
username = try container.decode(String.self, forKey: .username) username = try container.decode(String.self, forKey: .username)
}catch { }catch {
username = "NO USER" username = "NO USER"
debugPrint("failed to parse username") Logger.parse.warning("failed to parse username")
} }
type = try container.decode(String.self, forKey: .type) type = try container.decode(String.self, forKey: .type)
@ -269,13 +270,11 @@ class Playlist: Identifiable, Equatable, Codable, ObservableObject {
do{ do{
description_overwrite = try container.decode(String.self, forKey: .description_overwrite) description_overwrite = try container.decode(String.self, forKey: .description_overwrite)
}catch { }catch {
// debugPrint("no description overwrite")
} }
do{ do{
description_suffix = try container.decode(String.self, forKey: .description_suffix) description_suffix = try container.decode(String.self, forKey: .description_suffix)
}catch { }catch {
// debugPrint("no description suffix")
} }
last_updated = try container.decode(String.self, forKey: .last_updated) last_updated = try container.decode(String.self, forKey: .last_updated)
@ -296,7 +295,6 @@ class Playlist: Identifiable, Equatable, Codable, ObservableObject {
include_library_tracks = try container.decode(Bool.self, forKey: .include_library_tracks) include_library_tracks = try container.decode(Bool.self, forKey: .include_library_tracks)
}catch { }catch {
include_library_tracks = false include_library_tracks = false
// debugPrint("failed to parse include_library_tracks")
} }
parts = try container.decode([String].self, forKey: .parts) parts = try container.decode([String].self, forKey: .parts)
@ -307,42 +305,36 @@ class Playlist: Identifiable, Equatable, Codable, ObservableObject {
sort = try container.decode(String.self, forKey: .sort) sort = try container.decode(String.self, forKey: .sort)
}catch { }catch {
sort = "release_date" sort = "release_date"
// debugPrint("failed to parse sort value")
} }
do { do {
add_last_month = try container.decode(Bool.self, forKey: .add_last_month) add_last_month = try container.decode(Bool.self, forKey: .add_last_month)
}catch { }catch {
add_last_month = false add_last_month = false
// debugPrint("failed to parse add last month")
} }
do { do {
add_this_month = try container.decode(Bool.self, forKey: .add_this_month) add_this_month = try container.decode(Bool.self, forKey: .add_this_month)
}catch { }catch {
add_this_month = false add_this_month = false
// debugPrint("failed to parse add this month")
} }
do { do {
day_boundary = try container.decode(Int.self, forKey: .day_boundary) day_boundary = try container.decode(Int.self, forKey: .day_boundary)
}catch { }catch {
day_boundary = 21 day_boundary = 21
// debugPrint("failed to parse day boundary")
} }
do{ do{
chart_range = try LastFmRange(rawValue: container.decode(String.self, forKey: .chart_range)) ?? LastFmRange.month chart_range = try LastFmRange(rawValue: container.decode(String.self, forKey: .chart_range)) ?? LastFmRange.month
}catch { }catch {
chart_range = .halfyear chart_range = .halfyear
// debugPrint("failed to parse chart_range")
} }
do{ do{
chart_limit = try container.decode(Int.self, forKey: .chart_limit) chart_limit = try container.decode(Int.self, forKey: .chart_limit)
}catch { }catch {
chart_limit = 50 chart_limit = 50
// debugPrint("failed to parse chart_limit")
} }
} }

View File

@ -8,6 +8,7 @@
import UIKit import UIKit
import SwiftyJSON import SwiftyJSON
import OSLog
enum UserType: String, Decodable { enum UserType: String, Decodable {
case user = "user" case user = "user"
@ -69,7 +70,7 @@ class User: Identifiable, Decodable {
case 200, 201: case 200, 201:
break break
case _: case _:
debugPrint("error: \(updates)") Logger.net.error("error while updating user: \(updates)")
} }
} }
//TODO: do better error checking //TODO: do better error checking

View File

@ -9,6 +9,7 @@
import Foundation import Foundation
import Alamofire import Alamofire
import SwiftyJSON import SwiftyJSON
import OSLog
let txTypeHeaders = ["default", "recents", "fmchart"] let txTypeHeaders = ["default", "recents", "fmchart"]
@ -145,7 +146,7 @@ extension PlaylistApi: ApiRequest {
let playlist = try decoder.decode(Playlist.self, from: playlist) let playlist = try decoder.decode(Playlist.self, from: playlist)
return playlist return playlist
} catch { } catch {
print(error) Logger.parse.error("error parsing playlist from json: \(error)")
} }
return nil return nil
} }
@ -160,7 +161,7 @@ extension PlaylistApi: ApiRequest {
let playlist = try decoder.decode(Playlist.self, from: data) let playlist = try decoder.decode(Playlist.self, from: data)
return playlist return playlist
} catch { } catch {
print(error) Logger.parse.error("error parsing playlist from json: \(error)")
} }
} }
return nil return nil

View File

@ -9,6 +9,7 @@
import Foundation import Foundation
import Alamofire import Alamofire
import SwiftyJSON import SwiftyJSON
import OSLog
public enum TagApi { public enum TagApi {
case getTags case getTags
@ -110,7 +111,7 @@ extension TagApi: ApiRequest {
let _tag = try decoder.decode(Tag.self, from: data) let _tag = try decoder.decode(Tag.self, from: data)
return _tag return _tag
} catch { } catch {
print(error) Logger.parse.error("error parsing tag from json: \(error)")
} }
} }
return nil return nil

View File

@ -9,6 +9,7 @@
import Foundation import Foundation
import Alamofire import Alamofire
import SwiftyJSON import SwiftyJSON
import OSLog
public enum UserApi { public enum UserApi {
case getUser case getUser
@ -76,7 +77,7 @@ extension UserApi: ApiRequest {
let user = try decoder.decode(User.self, from: user) let user = try decoder.decode(User.self, from: user)
return user return user
} catch { } catch {
print(error) Logger.parse.error("error parsing user from json: \(error)")
} }
return nil return nil
} }
@ -91,7 +92,7 @@ extension UserApi: ApiRequest {
let user = try decoder.decode(User.self, from: data) let user = try decoder.decode(User.self, from: data)
return user return user
} catch { } catch {
print(error) Logger.parse.error("error parsing user from json: \(error)")
} }
} }
return nil return nil

View File

@ -8,6 +8,7 @@
import SwiftUI import SwiftUI
import SwiftyJSON import SwiftyJSON
import OSLog
struct UsersList: View { struct UsersList: View {
@ -48,11 +49,13 @@ struct UsersList: View {
if self.liveUser.check_network_response(response: response) { if self.liveUser.check_network_response(response: response) {
guard let data = response.data else { guard let data = response.data else {
fatalError("error getting users") Logger.net.error("failed to get users")
return
} }
guard let json = try? JSON(data: data) else { guard let json = try? JSON(data: data) else {
fatalError("error parsing user") Logger.parse.error("failed to get users")
return
} }
// update state // update state
@ -62,7 +65,7 @@ struct UsersList: View {
}) })
} else { } else {
Logger.net.error("failed to get users from view")
} }
} }
} }

View File

@ -10,6 +10,7 @@ import SwiftUI
import ToastUI import ToastUI
import KeychainAccess import KeychainAccess
import SwiftyJSON import SwiftyJSON
import OSLog
enum ScreenMode { enum ScreenMode {
case None case None
@ -83,27 +84,34 @@ struct LoginScreen: View {
keychain["username"] = username keychain["username"] = username
Logger.sys.debug("making login request")
let api = AuthApi.token(username: username, password: password, expiry: 604800) let api = AuthApi.token(username: username, password: password, expiry: 604800)
RequestBuilder.buildRequest(apiRequest: api) RequestBuilder.buildRequest(apiRequest: api)
.validate() .validate()
.responseJSON { response in .responseJSON { response in
switch response.response?.statusCode { let code = response.response?.statusCode ?? -1
switch code {
case 200, 201: case 200, 201:
guard let data = response.data else { guard let data = response.data else {
fatalError("error getting token") Logger.net.error("failed to get API token from request")
return
} }
guard let json = try? JSON(data: data) else { guard let json = try? JSON(data: data) else {
fatalError("error parsing reponse") Logger.parse.error("failed to parse API token")
return
} }
let token = json["token"].stringValue let token = json["token"].stringValue
keychain["jwt"] = token keychain["jwt"] = token
self.liveUser.loggedIn = true self.liveUser.loggedIn = true
Logger.net.info("login succeeded (\(code))")
case _: case _:
keychain["username"] = nil keychain["username"] = nil
@ -111,6 +119,14 @@ struct LoginScreen: View {
toastText = "Login Failed" toastText = "Login Failed"
showingToast = true showingToast = true
if let data = response.data {
Logger.net.info("login failed (\(code)): \(data)")
return
}
else {
Logger.net.info("login failed (\(code))")
}
} }
} }
}) { }) {
@ -127,28 +143,38 @@ struct LoginScreen: View {
keychain["username"] = username keychain["username"] = username
Logger.sys.debug("making register request")
let api = AuthApi.register(username: username, password: password, password2: password2) let api = AuthApi.register(username: username, password: password, password2: password2)
RequestBuilder.buildRequest(apiRequest: api) RequestBuilder.buildRequest(apiRequest: api)
.validate() .validate()
.responseJSON { response in .responseJSON { response in
switch response.response?.statusCode { let registerCode = response.response?.statusCode ?? -1
switch registerCode {
case 200, 201: case 200, 201:
Logger.net.debug("register request succeeded, logging in")
let token_api = AuthApi.token(username: username, password: password, expiry: 604800) let token_api = AuthApi.token(username: username, password: password, expiry: 604800)
RequestBuilder.buildRequest(apiRequest: token_api) RequestBuilder.buildRequest(apiRequest: token_api)
.validate() .validate()
.responseJSON { response in .responseJSON { response in
switch response.response?.statusCode { let loginCode = response.response?.statusCode ?? -1
switch loginCode {
case 200, 201: case 200, 201:
guard let data = response.data else { guard let data = response.data else {
fatalError("error getting token") Logger.net.error("failed to get API token for register from login request")
return
} }
guard let json = try? JSON(data: data) else { guard let json = try? JSON(data: data) else {
fatalError("error parsing reponse") Logger.parse.error("failed to parse API token for register from login request")
return
} }
let token = json["token"].stringValue let token = json["token"].stringValue
@ -163,14 +189,21 @@ struct LoginScreen: View {
toastText = "Token Generation Failed" toastText = "Token Generation Failed"
showingToast = true showingToast = true
Logger.net.error("failed to login post-registration (\(loginCode)")
} }
} }
// TODO: add handling for 400, password dont match case 400:
// TODO: add handling for 409, conflict Logger.net.info("register failed, passwords didn't match (400)")
case 409:
Logger.net.info("register failed, username already exists (409)")
case _: case _:
Logger.net.info("register request failed (\(registerCode)")
keychain["username"] = nil keychain["username"] = nil
keychain["jwt"] = nil keychain["jwt"] = nil

View File

@ -10,6 +10,7 @@ import SwiftUI
import ToastUI import ToastUI
import SwiftyJSON import SwiftyJSON
import SwiftUICharts import SwiftUICharts
import OSLog
struct PlaylistView: View { struct PlaylistView: View {
@ -239,6 +240,9 @@ struct PlaylistView: View {
} }
func runPlaylist() { func runPlaylist() {
Logger.net.debug("running playlist from view: \(self.playlist.name)")
let api = PlaylistApi.runPlaylist(name: playlist.name) let api = PlaylistApi.runPlaylist(name: playlist.name)
RequestBuilder.buildRequest(apiRequest: api) RequestBuilder.buildRequest(apiRequest: api)
.validate() .validate()
@ -250,16 +254,23 @@ struct PlaylistView: View {
toastSuccess = true toastSuccess = true
showingToast = true showingToast = true
Logger.net.debug("playlist run queued from view: \(self.playlist.name)")
} else { } else {
toastText = "Run Request Failed" toastText = "Run Request Failed"
toastSuccess = false toastSuccess = false
showingToast = true showingToast = true
Logger.net.debug("playlist run request failed from view: \(self.playlist.name)")
} }
} }
} }
func refreshStats() { func refreshStats() {
Logger.net.debug("refreshing playlist stats from view: \(self.playlist.name)")
let api = PlaylistApi.refreshStats(name: playlist.name) let api = PlaylistApi.refreshStats(name: playlist.name)
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
@ -269,43 +280,56 @@ struct PlaylistView: View {
toastSuccess = true toastSuccess = true
showingToast = true showingToast = true
Logger.net.debug("stat refresh queued from view: \(self.playlist.name)")
} else { } else {
toastText = "Stat Refresh Failed" toastText = "Stat Refresh Failed"
toastSuccess = false toastSuccess = false
showingToast = true showingToast = true
Logger.net.debug("stat refresh request failed from view: \(self.playlist.name)")
} }
} }
} }
func openPlaylist() { func openPlaylist() {
Logger.sys.debug("attempting to open \(self.playlist.link)")
if let url = URL(string: self.playlist.link) { if let url = URL(string: self.playlist.link) {
UIApplication.shared.open(url) UIApplication.shared.open(url)
} }
} }
func updatePlaylist(updates: JSON) { func updatePlaylist(updates: JSON) {
Logger.net.debug("updating playlist from view: \(self.playlist.name)")
let api = PlaylistApi.updatePlaylist(name: playlist.name, updates: updates) let api = PlaylistApi.updatePlaylist(name: playlist.name, updates: updates)
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
if self.liveUser.check_network_response(response: response) { if self.liveUser.check_network_response(response: response) {
debugPrint("success") Logger.net.debug("updated playlist from view")
} else { } else {
debugPrint("error") Logger.net.error("failed to update playlist from view")
} }
} }
//TODO: do better error checking
} }
func refreshPlaylist() { func refreshPlaylist() {
Logger.net.debug("Refreshing playlist: \(self.playlist.name)")
let api = PlaylistApi.getPlaylist(name: self.playlist.name) let api = PlaylistApi.getPlaylist(name: self.playlist.name)
RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in RequestBuilder.buildRequest(apiRequest: api).responseJSON{ response in
if self.liveUser.check_network_response(response: response) { if self.liveUser.check_network_response(response: response) {
guard let data = response.data else { guard let data = response.data else {
fatalError("error getting playlist") Logger.net.error("failed to get playlist from net request")
return
} }
self.playlist = PlaylistApi.fromJSON(playlist: data)! self.playlist = PlaylistApi.fromJSON(playlist: data)!
@ -314,7 +338,11 @@ struct PlaylistView: View {
toastSuccess = true toastSuccess = true
showingToast = true showingToast = true
Logger.net.debug("Successfully refreshed playlist: \(self.playlist.name)")
} else { } else {
Logger.net.error("request failed for get playlist")
toastText = "Refresh Failed" toastText = "Refresh Failed"
toastSuccess = false toastSuccess = false

View File

@ -8,6 +8,7 @@
import SwiftUI import SwiftUI
import ToastUI import ToastUI
import OSLog
struct Name: Identifiable, Hashable { struct Name: Identifiable, Hashable {
var id = UUID() var id = UUID()
@ -74,7 +75,7 @@ struct SpotInputList: View {
showingToast = true showingToast = true
} }
else { else {
print("Failed to add playlist: \(response.response?.statusCode ?? 0)") Logger.net.error("Failed to add playlist: \(response.response?.statusCode ?? 0)")
toastText = "Failed to add playlist" toastText = "Failed to add playlist"
toastSuccess = false toastSuccess = false
showingToast = true showingToast = true

View File

@ -9,6 +9,7 @@
import SwiftUI import SwiftUI
import SwiftyJSON import SwiftyJSON
import SwiftUICharts import SwiftUICharts
import OSLog
struct TagView: View { struct TagView: View {
@ -149,11 +150,13 @@ struct TagView: View {
if self.liveUser.check_network_response(response: response) { if self.liveUser.check_network_response(response: response) {
guard let data = response.data else { guard let data = response.data else {
fatalError("error getting tag") Logger.net.error("failed to get tag from net request")
return
} }
guard let json = try? JSON(data: data) else { guard let json = try? JSON(data: data) else {
fatalError("error parsing reponse") Logger.net.error("failed to parse tag")
return
} }
let _tag = TagApi.fromJSON(tag: json["tag"]) let _tag = TagApi.fromJSON(tag: json["tag"])
if let tag = _tag { if let tag = _tag {
@ -161,7 +164,7 @@ struct TagView: View {
} }
} else { } else {
Logger.net.error("request failed for refresh tag")
} }
self.isRefreshing = false self.isRefreshing = false