44
55import os. log
66import UIKit
7+ import Foundation
8+
9+ class StdoutRedirector {
10+ private var originalStdout : Int32 = - 1
11+ private var originalStderr : Int32 = - 1
12+ private var stdoutPipe : [ Int32 ] = [ - 1 , - 1 ]
13+ private var stderrPipe : [ Int32 ] = [ - 1 , - 1 ]
14+ private var stdoutReadSource : DispatchSourceRead ?
15+ private var stderrReadSource : DispatchSourceRead ?
16+
17+ func start( ) {
18+ originalStdout = dup ( STDOUT_FILENO)
19+ originalStderr = dup ( STDERR_FILENO)
20+
21+ guard Darwin . pipe ( & stdoutPipe) == 0 ,
22+ Darwin . pipe ( & stderrPipe) == 0 else {
23+ Logger . error ( " Failed to create stdout/stderr pipes " )
24+ return
25+ }
26+
27+ dup2 ( stdoutPipe [ 1 ] , STDOUT_FILENO)
28+ dup2 ( stderrPipe [ 1 ] , STDERR_FILENO)
29+ close ( stdoutPipe [ 1 ] )
30+ close ( stderrPipe [ 1 ] )
31+
32+ stdoutReadSource = createReader (
33+ readPipe: stdoutPipe [ 0 ] ,
34+ writeToOriginal: originalStdout,
35+ label: " stdout "
36+ )
37+
38+ stderrReadSource = createReader (
39+ readPipe: stderrPipe [ 0 ] ,
40+ writeToOriginal: originalStderr,
41+ label: " stderr "
42+ )
43+ }
44+
45+ private func createReader(
46+ readPipe: Int32 ,
47+ writeToOriginal: Int32 ,
48+ label: String
49+ ) -> DispatchSourceRead {
50+ let source = DispatchSource . makeReadSource (
51+ fileDescriptor: readPipe,
52+ queue: . global( qos: . utility)
53+ )
54+
55+ source. setEventHandler {
56+ let bufferSize = 4096
57+ var buffer = [ UInt8] ( repeating: 0 , count: bufferSize)
58+ let bytesRead = read ( readPipe, & buffer, bufferSize)
59+
60+ if bytesRead > 0 {
61+ let output = String (
62+ bytes: buffer [ 0 ..< bytesRead] ,
63+ encoding: . utf8
64+ ) ?? " "
65+
66+ let trimmed = output. trimmingCharacters ( in: . newlines)
67+ if !trimmed. isEmpty {
68+ // we're sending stderr to oslog, so we need to avoid recursive calls
69+ if trimmed. hasPrefix ( " OSLOG- " ) {
70+ // make sure the system can parse the oslogs
71+ write ( writeToOriginal, & buffer, bytesRead)
72+ } else {
73+ Logger . info ( " [ \( label) ] \( trimmed) " )
74+ }
75+ }
76+ }
77+ }
78+
79+ source. setCancelHandler {
80+ close ( readPipe)
81+ }
82+
83+ source. resume ( )
84+ return source
85+ }
86+ }
787
888/// Wrapper class for os_log function
989public class Logger {
@@ -21,7 +101,7 @@ public class Logger {
21101 }
22102 }
23103
24- static func log( _ items: Any ... , category: String , type: OSLogType ) {
104+ static func log( _ items: [ Any ] , category: String , type: OSLogType ) {
25105 if Logger . enabled {
26106 var message = " "
27107 let last = items. count - 1
@@ -31,6 +111,7 @@ public class Logger {
31111 message += " "
32112 }
33113 }
114+
34115 let log = OSLog ( subsystem: Bundle . main. bundleIdentifier ?? " - " , category: category)
35116 os_log ( " %{public}@ " , log: log, type: type, String ( message. prefix ( 4068 ) ) )
36117 }
0 commit comments