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