Skip to content
19 changes: 19 additions & 0 deletions Sources/DataConnect.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import Foundation
import FirebaseAppCheck
import FirebaseAuth
import FirebaseCore
import OSLog

let kFIRPrivateLogDisabledArgument = "-FIRPrivateLogDisabled"

@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
public class DataConnect {
Expand All @@ -36,6 +39,10 @@ public class DataConnect {
public static let port = 9399
}

class ArgumentFlag {
static var enablePrivacyLogging = true
}

// MARK: Static Creation

/// Returns an instance of DataConnect matching the parameters.
Expand Down Expand Up @@ -106,6 +113,18 @@ public class DataConnect {
callerSDKType: self.callerSDKType
)
operationsManager = OperationsManager(grpcClient: grpcClient)

LoadArgument()
}

private func LoadArgument() {
let arguments = ProcessInfo.processInfo.arguments
if arguments.contains(kFIRPrivateLogDisabledArgument) {
ArgumentFlag.enablePrivacyLogging = false
DataConnectLogger.debug("DataConnect privacy logging disabled.")
} else {
DataConnectLogger.debug("DataConnect privacy logging enabled.")
}
}

// MARK: Operations
Expand Down
7 changes: 3 additions & 4 deletions Sources/Internal/CodableTimestamp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,9 @@ extension CodableTimestamp {
.firstMatch(in: timestampString, range: NSRange(location: 0,
length: timestampString.count)) !=
nil else {
FirebaseLogger.dataConnect
.error(
"Timestamp string format doesn't support."
)
DataConnectLogger.error(
"Timestamp string \(timestampString, privacy: .private) format doesn't support."
)
throw DataConnectError.invalidTimestampFormat
}

Expand Down
54 changes: 0 additions & 54 deletions Sources/Internal/FirebaseLogger/FirebaseLogger.swift

This file was deleted.

162 changes: 51 additions & 111 deletions Sources/Internal/GrpcClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ import FirebaseAppCheck
import FirebaseAuth
import FirebaseCore
import GRPC
import Logging
import NIOCore
import NIOHPACK
import NIOPosix
import OSLog
import SwiftProtobuf

@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
Expand Down Expand Up @@ -50,9 +50,6 @@ actor GrpcClient: CustomStringConvertible {

private let callerSDKType: CallerSDKType

// Remove debug flag when logging privacy is properly handled.
private let debugEnable = false

enum RequestHeaders {
static let googRequestParamsHeader = "x-goog-request-params"
static let authorizationHeader = "x-firebase-auth-token"
Expand All @@ -65,11 +62,8 @@ actor GrpcClient: CustomStringConvertible {

private lazy var client: FirebaseDataConnectAsyncClient? = {
do {
if debugEnable == true {
FirebaseLogger.dataConnect.debug("\(self.description) initialization starts.")
} else {
FirebaseLogger.dataConnect.debug("GrpcClient initialization starts.")
}
DataConnectLogger
.debug("GrpcClient\(self.description, privacy: .private) initialization starts.")
let group = PlatformSupport.makeEventLoopGroup(loopCount: threadPoolSize)
let channel = try GRPCChannelPool.with(
target: .host(serverSettings.host, port: serverSettings.port),
Expand All @@ -78,18 +72,11 @@ actor GrpcClient: CustomStringConvertible {
.plaintext,
eventLoopGroup: group
)
if debugEnable == true {
FirebaseLogger.dataConnect.debug("\(self.description) has been created.")
} else {
FirebaseLogger.dataConnect.debug("GrpcClient has been created.")
}
DataConnectLogger.debug("GrpcClient\(self.description, privacy: .private) has been created.")
return FirebaseDataConnectAsyncClient(channel: channel)
} catch {
if debugEnable == true {
FirebaseLogger.dataConnect.error("Error:\(error) when creating \(self.description).")
} else {
FirebaseLogger.dataConnect.debug("Error:\(error) when creating GrpcClient.")
}
DataConnectLogger
.debug("Error:\(error) when creating GrpcClient\(self.description, privacy: .private).")
return nil
}
}()
Expand Down Expand Up @@ -130,8 +117,7 @@ actor GrpcClient: CustomStringConvertible {
googRequestHeaderValue = "location=\(self.connectorConfig.location)&frontend=data"

description = """
GrpcClient: \
projectId=\(projectId) \
: projectId=\(projectId) \
connector=\(connectorConfig.connector) \
host=\(serverSettings.host) \
port=\(serverSettings.port) \
Expand All @@ -145,8 +131,7 @@ actor GrpcClient: CustomStringConvertible {
.Type)
async throws -> OperationResult<ResultType> {
guard let client else {
FirebaseLogger.dataConnect
.error("When calling executeQuery(), grpc client has not been configured.")
DataConnectLogger.error("When calling executeQuery(), grpc client has not been configured.")
throw DataConnectError.grpcNotConfigured
}

Expand All @@ -155,49 +140,28 @@ actor GrpcClient: CustomStringConvertible {
connectorName: connectorName,
request: request
)
let requestString = try ": " + grpcRequest.jsonString()

do {
if debugEnable == true {
try FirebaseLogger.dataConnect
.debug("executeQuery() sends grpc request: \(grpcRequest.jsonString()).")
} else {
try FirebaseLogger.dataConnect
.debug("executeQuery() sends grpc request.")
}
DataConnectLogger
.debug("executeQuery() sends grpc request\(requestString, privacy: .private).")
let results = try await client.executeQuery(grpcRequest, callOptions: createCallOptions())
if debugEnable == true {
try FirebaseLogger.dataConnect
.debug("executeQuery() receives response: \(results.jsonString()).")
} else {
try FirebaseLogger.dataConnect
.debug("executeQuery() receives response.")
}
let resultsString = try ": " + results.jsonString()
DataConnectLogger
.debug("executeQuery() receives response\(resultsString, privacy: .private).")
// Not doing error decoding here
if let decodedResults = try codec.decode(result: results.data, asType: resultType) {
return OperationResult(data: decodedResults)
} else {
// In future, set this as error in OperationResult
if debugEnable == true {
try FirebaseLogger.dataConnect
.error("executeQuery() response: \(results.jsonString()) decode failed.")
} else {
try FirebaseLogger.dataConnect
.error("executeQuery() response decode failed.")
}
DataConnectLogger
.debug("executeQuery() response\(resultsString, privacy: .private) decode failed.")
throw DataConnectError.decodeFailed
}
} catch {
if debugEnable == true {
try FirebaseLogger.dataConnect
.error(
"executeQuery() with request: \(grpcRequest.jsonString()) grpc call FAILED with \(error)."
)
} else {
try FirebaseLogger.dataConnect
.error(
"executeQuery() grpc call FAILED with \(error)."
)
}
DataConnectLogger.error(
"executeQuery()\(requestString, privacy: .private) grpc call FAILED with \(error)."
)
throw error
}
}
Expand All @@ -208,7 +172,7 @@ actor GrpcClient: CustomStringConvertible {
.Type)
async throws -> OperationResult<ResultType> {
guard let client else {
FirebaseLogger.dataConnect
DataConnectLogger
.error("When calling executeMutation(), grpc client has not been configured.")
throw DataConnectError.grpcNotConfigured
}
Expand All @@ -219,46 +183,26 @@ actor GrpcClient: CustomStringConvertible {
request: request
)

let requestString = try ": " + grpcRequest.jsonString()

do {
if debugEnable == true {
try FirebaseLogger.dataConnect
.debug("executeMutation() sends grpc request: \(grpcRequest.jsonString()).")
} else {
try FirebaseLogger.dataConnect
.debug("executeMutation() sends grpc request.")
}
DataConnectLogger
.debug("executeMutation() sends grpc request \(requestString, privacy: .private).")
let results = try await client.executeMutation(grpcRequest, callOptions: createCallOptions())
if debugEnable == true {
try FirebaseLogger.dataConnect
.debug("executeMutation() receives response: \(results.jsonString()).")
} else {
try FirebaseLogger.dataConnect
.debug("executeMutation() receives response.")
}
let resultsString = try ": " + results.jsonString()
DataConnectLogger
.debug("executeMutation() receives response\(resultsString, privacy: .private).")
if let decodedResults = try codec.decode(result: results.data, asType: resultType) {
return OperationResult(data: decodedResults)
} else {
if debugEnable == true {
try FirebaseLogger.dataConnect
.error("executeMutation() response: \(results.jsonString()) decode failed.")
} else {
try FirebaseLogger.dataConnect
.error("executeMutation() response decode failed.")
}
DataConnectLogger
.debug("executeMutation() response\(resultsString, privacy: .private) decode failed.")
throw DataConnectError.decodeFailed
}
} catch {
if debugEnable == true {
try FirebaseLogger.dataConnect
.error(
"executeMutation() with request: \(grpcRequest.jsonString()) grpc call FAILED with \(error)."
)
} else {
try FirebaseLogger.dataConnect
.error(
"executeMutation() grpc call FAILED with \(error)."
)
}
DataConnectLogger.error(
"executeMutation()\(requestString, privacy: .private) grpc call FAILED with \(error)."
)
throw error
}
}
Expand All @@ -274,44 +218,40 @@ actor GrpcClient: CustomStringConvertible {
do {
if let token = try await auth.currentUser?.getIDToken() {
headers.add(name: RequestHeaders.authorizationHeader, value: "\(token)")
if debugEnable == true {
FirebaseLogger.dataConnect
.debug("Auth token added: \(token)")
} else {
FirebaseLogger.dataConnect
.debug("Auth token added.")
}
DataConnectLogger.debug("Auth token added")
} else {
FirebaseLogger.dataConnect.debug("No auth token available. Not adding auth header.")
DataConnectLogger.debug("No auth token available. Not adding auth header.")
}
} catch {
FirebaseLogger.dataConnect
DataConnectLogger
.debug("Cannot get auth token successfully due to: \(error). Not adding auth header.")
}

// Add AppCheck token if available
do {
if let token = try await appCheck?.token(forcingRefresh: false) {
headers.add(name: RequestHeaders.appCheckHeader, value: token.token)
if debugEnable == true {
FirebaseLogger.dataConnect
.debug("App Check token added: \(token.token)")
} else {
FirebaseLogger.dataConnect
.debug("App Check token added.")
}
DataConnectLogger.debug("App Check token added")
} else {
FirebaseLogger.dataConnect
.debug("App Check token unavailable. Not adding App Check header.")
DataConnectLogger.debug("App Check token unavailable. Not adding App Check header.")
}
} catch {
FirebaseLogger.dataConnect
.debug(
"Cannot get App Check token successfully due to: \(error). Not adding App Check header."
)
DataConnectLogger.debug(
"Cannot get App Check token successfully due to: \(error). Not adding App Check header."
)
}

var options = CallOptions(customMetadata: headers)

// Enable GRPC tracing
if DataConnectLogger.logLevel.rawValue <= FirebaseLoggerLevel.info.rawValue,
DataConnect.ArgumentFlag.enablePrivacyLogging == false {
var logger = Logger(label: "com.google.firebase.dataconnect.grpc")
logger.logLevel = .trace
options.logger = logger
options.requestIDProvider = .autogenerated
}

let options = CallOptions(customMetadata: headers)
return options
}
}
Loading
Loading