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