11import { DeviceLogProviderBase } from "./device-log-provider-base" ;
22import { DEVICE_LOG_EVENT_NAME } from "../constants" ;
3- import { LoggerConfigData } from "../../constants" ;
43import { injector } from "../yok" ;
54
5+ import * as chalk from "chalk" ;
6+ import { LoggerConfigData } from "../../constants" ;
7+ import { IOptions } from "../../declarations" ;
8+
69export class DeviceLogProvider extends DeviceLogProviderBase {
710 constructor (
811 protected $logFilter : Mobile . ILogFilter ,
912 protected $logger : ILogger ,
10- protected $logSourceMapService : Mobile . ILogSourceMapService
13+ protected $logSourceMapService : Mobile . ILogSourceMapService ,
14+ protected $options : IOptions
1115 ) {
1216 super ( $logFilter , $logger , $logSourceMapService ) ;
1317 }
@@ -17,6 +21,7 @@ export class DeviceLogProvider extends DeviceLogProviderBase {
1721 platform : string ,
1822 deviceIdentifier : string
1923 ) : void {
24+ // console.log(lineText)
2025 const loggingOptions = this . getDeviceLogOptionsForDevice ( deviceIdentifier ) ;
2126 let data = this . $logFilter . filterData ( platform , lineText , loggingOptions ) ;
2227 data = this . $logSourceMapService . replaceWithOriginalFileLocations (
@@ -25,7 +30,7 @@ export class DeviceLogProvider extends DeviceLogProviderBase {
2530 loggingOptions
2631 ) ;
2732 if ( data ) {
28- this . logDataCore ( data ) ;
33+ this . logDataCore ( data , deviceIdentifier ) ;
2934 this . emit ( DEVICE_LOG_EVENT_NAME , lineText , deviceIdentifier , platform ) ;
3035 }
3136 }
@@ -34,8 +39,130 @@ export class DeviceLogProvider extends DeviceLogProviderBase {
3439 this . $logFilter . loggingLevel = logLevel . toUpperCase ( ) ;
3540 }
3641
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+ }
39166 }
40167}
41168injector . register ( "deviceLogProvider" , DeviceLogProvider ) ;
0 commit comments