1
1
import { DeviceLogProviderBase } from "./device-log-provider-base" ;
2
2
import { DEVICE_LOG_EVENT_NAME } from "../constants" ;
3
- import { LoggerConfigData } from "../../constants" ;
4
3
import { injector } from "../yok" ;
5
4
5
+ import * as chalk from "chalk" ;
6
+ import { LoggerConfigData } from "../../constants" ;
7
+ import { IOptions } from "../../declarations" ;
8
+
6
9
export class DeviceLogProvider extends DeviceLogProviderBase {
7
10
constructor (
8
11
protected $logFilter : Mobile . ILogFilter ,
9
12
protected $logger : ILogger ,
10
- protected $logSourceMapService : Mobile . ILogSourceMapService
13
+ protected $logSourceMapService : Mobile . ILogSourceMapService ,
14
+ protected $options : IOptions
11
15
) {
12
16
super ( $logFilter , $logger , $logSourceMapService ) ;
13
17
}
@@ -17,6 +21,7 @@ export class DeviceLogProvider extends DeviceLogProviderBase {
17
21
platform : string ,
18
22
deviceIdentifier : string
19
23
) : void {
24
+ // console.log(lineText)
20
25
const loggingOptions = this . getDeviceLogOptionsForDevice ( deviceIdentifier ) ;
21
26
let data = this . $logFilter . filterData ( platform , lineText , loggingOptions ) ;
22
27
data = this . $logSourceMapService . replaceWithOriginalFileLocations (
@@ -25,7 +30,7 @@ export class DeviceLogProvider extends DeviceLogProviderBase {
25
30
loggingOptions
26
31
) ;
27
32
if ( data ) {
28
- this . logDataCore ( data ) ;
33
+ this . logDataCore ( data , deviceIdentifier ) ;
29
34
this . emit ( DEVICE_LOG_EVENT_NAME , lineText , deviceIdentifier , platform ) ;
30
35
}
31
36
}
@@ -34,8 +39,130 @@ export class DeviceLogProvider extends DeviceLogProviderBase {
34
39
this . $logFilter . loggingLevel = logLevel . toUpperCase ( ) ;
35
40
}
36
41
37
- private logDataCore ( data : string ) : void {
38
- this . $logger . info ( data , { [ LoggerConfigData . skipNewLine ] : true } ) ;
42
+ private consoleLogLevelRegex : RegExp = / ^ C O N S O L E ( L O G | I N F O | W A R N | E R R O R | T R A C E | I N F O ( .+ ) ) : \s / ;
43
+ private consoleLevelColor : Record < string , ( line : string ) => string > = {
44
+ log : ( line ) => line ,
45
+ info : chalk . cyanBright ,
46
+ warn : chalk . yellowBright ,
47
+ error : chalk . redBright ,
48
+ trace : chalk . grey ,
49
+ time : chalk . greenBright ,
50
+ } ;
51
+
52
+ private deviceColorMap = new Map < string , typeof chalk . BackgroundColor > ( ) ;
53
+
54
+ private colorPool : typeof chalk . BackgroundColor [ ] = [
55
+ "bgGray" ,
56
+ "bgMagentaBright" ,
57
+ "bgBlueBright" ,
58
+ "bgWhiteBright" ,
59
+ "bgCyanBright" ,
60
+ "bgYellowBright" ,
61
+ "bgGreenBright" ,
62
+ ] ;
63
+ private colorPoolIndex = 0 ;
64
+
65
+ private getDeviceColor ( deviceIdentifier : string ) {
66
+ if ( this . deviceColorMap . has ( deviceIdentifier ) ) {
67
+ return this . deviceColorMap . get ( deviceIdentifier ) ;
68
+ }
69
+
70
+ const color = this . colorPool [ this . colorPoolIndex ] ;
71
+ // wrap around if we have no more colors in the pool
72
+ this . colorPoolIndex =
73
+ this . colorPoolIndex === this . colorPool . length - 1
74
+ ? 0
75
+ : this . colorPoolIndex + 1 ;
76
+
77
+ this . deviceColorMap . set ( deviceIdentifier , color ) ;
78
+
79
+ return color ;
80
+ }
81
+
82
+ private logDataCore ( data : string , deviceIdentifier : string ) : void {
83
+ // todo: use config to set logger - --env.classicLogs is temporary!
84
+ if ( "classicLogs" in this . $options . env ) {
85
+ // legacy logging
86
+ this . $logger . info ( data , { [ LoggerConfigData . skipNewLine ] : true } ) ;
87
+ return ;
88
+ }
89
+
90
+ // todo: extract into an injectable printer/logger service
91
+ let shouldPrepend = false ;
92
+ let splitIndexes : number [ ] = [ ] ;
93
+ const lines = data
94
+ . split ( / \n ( C O N S O L E ) / )
95
+ . map ( ( line , index , lines ) => {
96
+ if ( line === "CONSOLE" ) {
97
+ shouldPrepend = true ;
98
+
99
+ if ( lines [ index - 1 ] ) {
100
+ splitIndexes . push ( index - 1 ) ;
101
+ }
102
+
103
+ return null ;
104
+ }
105
+
106
+ if ( shouldPrepend ) {
107
+ shouldPrepend = false ;
108
+ return `CONSOLE${ line } ` ;
109
+ }
110
+
111
+ const suffix = line . endsWith ( "\n" ) ? "" : "\n" ;
112
+ return line + suffix ;
113
+ } )
114
+ . map ( ( line , index ) => {
115
+ if ( splitIndexes . includes ( index ) ) {
116
+ return line + "\n" ;
117
+ }
118
+ return line ;
119
+ } )
120
+ . filter ( ( line ) => {
121
+ return line !== null ;
122
+ } ) ;
123
+
124
+ if ( ! lines . length && data . length ) {
125
+ lines . push ( data ) ;
126
+ }
127
+
128
+ for ( const line of lines ) {
129
+ let [ match , level , timeLabel ] =
130
+ this . consoleLogLevelRegex . exec ( line ) ?? [ ] ;
131
+
132
+ if ( timeLabel ) {
133
+ level = "time" ;
134
+ timeLabel = timeLabel . replace ( "INFO " , "" ) . trim ( ) + ": " ;
135
+ } else {
136
+ level = level ?. toLowerCase ( ) ?? "log" ;
137
+ }
138
+
139
+ const toLog = [ timeLabel ?? "" , match ? line . replace ( match , "" ) : line ]
140
+ . join ( "" )
141
+ . trim ( ) ;
142
+
143
+ toLog . split ( "\n" ) . forEach ( ( actualLine ) => {
144
+ this . printLine (
145
+ chalk [ this . getDeviceColor ( deviceIdentifier ) ] ( " " ) ,
146
+ this . consoleLevelColor [ level ] ( actualLine )
147
+ ) ;
148
+ } ) ;
149
+ }
150
+ }
151
+
152
+ private printLine ( prefix : string , ...parts : string [ ] ) {
153
+ const maxWidth = process . stdout . columns - 2 ;
154
+ const fullLine = parts . join ( " " ) ;
155
+
156
+ // console.log(prefix, fullLine);
157
+ // return;
158
+ if ( fullLine . length < maxWidth ) {
159
+ console . log ( prefix , fullLine ) ;
160
+ } else {
161
+ for ( let i = 0 ; i < fullLine . length ; i += maxWidth ) {
162
+ const part = fullLine . substring ( i , i + maxWidth ) ;
163
+ console . log ( prefix , part ) ;
164
+ }
165
+ }
39
166
}
40
167
}
41
168
injector . register ( "deviceLogProvider" , DeviceLogProvider ) ;
0 commit comments