1 module androidlogger; 2 3 import std.experimental.logger; 4 5 6 class AndroidLogger : FileLogger { 7 import std.stdio; 8 import std.string; 9 import std.concurrency; 10 import std.process; 11 import colored; 12 alias fg = StringWithForeground!(AnsiColor); 13 string[LogLevel] logLevel2String; 14 fg[LogLevel] logLevel2Fg; 15 bool withColors; 16 17 this(bool withColors=true) @system { 18 super(stdout, LogLevel.all); 19 this.withColors = withColors; 20 initLogLevel2String(); 21 } 22 23 static string tid2string(Tid id) @trusted { 24 import std.conv : text; 25 return text(id).replace("Tid(", "").replace(")", ""); 26 } 27 28 override void writeLogMsg(ref LogEntry payload) { 29 with (payload) { 30 // android logoutput looks lokes this: 31 // 06-06 12:14:46.355 372 18641 D audio_hw_primary: disable_audio_route: reset and update 32 // DATE TIME PID TID LEVEL TAG Message 33 auto h = timestamp.fracSecs.split!("msecs"); 34 auto idx = msg.indexOf(':'); 35 string tag = ""; // "%s.%d".format(file, line), 36 string text = ""; 37 if (idx == -1) { 38 tag = "stdout"; 39 text = msg; 40 } else { 41 tag = msg[0..idx]; 42 text = msg[idx+1..$]; 43 } 44 this.file.lockingTextWriter().put(colorize("%02d-%02d %02d:%02d:%02d.%03d %d %s %s %s: %s\n".format( 45 timestamp.month, // DATE 46 timestamp.day, 47 timestamp.hour, // TIME 48 timestamp.minute, 49 timestamp.second, 50 h.msecs, 51 std.process.thisProcessID, // PID 52 tid2string(threadId), // TID 53 logLevel2String[logLevel], 54 tag, 55 text), logLevel).toString); 56 57 } 58 } 59 private void initLogLevel2String() { 60 logLevel2String[LogLevel.trace] = "T"; 61 logLevel2String[LogLevel.info] = "I"; 62 logLevel2String[LogLevel.warning] = "W"; 63 logLevel2String[LogLevel.error] = "E"; 64 logLevel2String[LogLevel.critical] = "C"; 65 logLevel2String[LogLevel.fatal] = "F"; 66 } 67 68 private auto colorize(string s, LogLevel logLevel) { 69 if (!withColors) { 70 return s.defaultColor.onDefaultColor; 71 } 72 73 switch (logLevel) { 74 case LogLevel.trace: return s.black.onDefaultColor; 75 case LogLevel.info: return s.defaultColor.onDefaultColor; 76 case LogLevel.warning: return s.green.onDefaultColor; 77 case LogLevel.error: return s.yellow.onDefaultColor; 78 case LogLevel.critical: return s.black.onRed; 79 case LogLevel.fatal: return s.yellow.onRed; 80 default: assert(0); 81 } 82 } 83 }