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