Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

手把手教你如何串接 Log 到各種網路服務

logback 是目前 logging framework 蠻紅的一套,這場 talk 會先分享各家 logger framework 之間的關係。再來介紹 logback 的架構,以了解如何串接各種網路服務。

最後用 logback-redmine-appender 及 logback-sms-appender 實際展示使用者送出 log 之後,如何在 Redmine 即時建立新 issue 及如何在簡訊內客製 log 內容。

手把手教你如何串接 Log 到各種網路服務

  1. 1. 手把手教你如何串接 log 到 各種網路服務 Kewang
  2. 2. Who I am ● 王慕羣 ● Java / Node.js / AngularJS ● HBase / SQL-like ● Git / DevOps kewang @ GitHub kewang.information @ Facebook kewangtw @ Linkedin kewang @ SlideShare cpckewang @ Gmail HadoopCon '14, '15 MOPCON '14
  3. 3. What Mitake is 三竹資訊 ● Qmi:企業內部即時通訊軟體 ● 全國最大的企業簡訊平台 ● 市佔近 100% 的行動下單 ● 市佔近 70% 的行動銀行 ● 企業內部應用、產壽險、金融相關政府機關 ● 其他:兌彩券、台灣匯率、三竹小股王、行動股市 ... 等
  4. 4. 4 Agenda
  5. 5. 5 Agenda ● 各 logger framework 簡單介紹
  6. 6. 6 Agenda ● 各 logger framework 簡單介紹 ● logback 內部架構
  7. 7. 7 Agenda ● 各 logger framework 簡單介紹 ● logback 內部架構 ● 如何用 logback 串接網路服務
  8. 8. 8 各 logger framework 簡單介紹 interface & implementation
  9. 9. 9 logger framework
  10. 10. 10 logger framework ● slf4j
  11. 11. 11 logger framework ● slf4j ● jcl
  12. 12. 12 logger framework ● slf4j ● jcl ● jul
  13. 13. 13 logger framework ● slf4j ● jcl ● jul ● Log4j 1
  14. 14. 14 logger framework ● slf4j ● jcl ● jul ● Log4j 1 ● Log4j 2
  15. 15. 15 logger framework ● slf4j ● jcl ● jul ● Log4j 1 ● Log4j 2 ● Logback
  16. 16. 16
  17. 17. 17 logger 分類 - Interface
  18. 18. 18 logger 分類 - Interface ● slf4j - Simple Logging Facade for Java – 利用 Facade Pattern 提供一些 logging API ,可以轉換 各種不同的 logger implementation
  19. 19. 19 logger 分類 - Interface ● slf4j - Simple Logging Facade for Java – 利用 Facade Pattern 提供一些 logging API ,可以轉換 各種不同的 logger implementation ● jcl - Jakarta Commons Logging – Apache 開發出與 slf4j 類似功用的 library
  20. 20. 20 logger 分類 - Implementation
  21. 21. 21 logger 分類 - Implementation ● Logback - 今日主角
  22. 22. 22 logger 分類 - Implementation ● Logback - 今日主角 ● jul - java.util.logging – Java 1.4 之後的內建 logger API
  23. 23. 23 logger 分類 - Implementation ● Logback - 今日主角 ● jul - java.util.logging – Java 1.4 之後的內建 logger API ● Log4j 1 - logging library for Java – EOL @ 2015/8/5
  24. 24. 24 logger 分類 - Implementation ● Logback - 今日主角 ● jul - java.util.logging – Java 1.4 之後的內建 logger API ● Log4j 1 - logging library for Java – EOL @ 2015/8/5 ● Log4j 2 - Interface + Implementation
  25. 25. 25
  26. 26. 26 logback 內部架構
  27. 27. 27 Architecture
  28. 28. 28 Architecture ● Logger – effective level – basic selection rule
  29. 29. 29 Architecture ● Logger – effective level – basic selection rule ● Appender – output destination – i.e. console, files, remote socket servers, DB, JMS, and remote UNIX Syslog daemons
  30. 30. 30 Architecture ● Logger – effective level – basic selection rule ● Appender – output destination – i.e. console, files, remote socket servers, DB, JMS, and remote UNIX Syslog daemons ● Layout – formatting the event to string
  31. 31. 31 Architecture - flow ● Get the filter chain decision ● Apply the basic selection rule ● Create a LoggingEvent object ● Invoking appenders ● Formatting the output ● Sending out the LoggingEvent
  32. 32. 32 Architecture - sequence diagram
  33. 33. 33 Architecture - sequence diagram
  34. 34. 34 如何用 logback 串接網路服務
  35. 35. 35 logback.xml - 給使用者看的
  36. 36. 36 logback.xml - 給使用者看的 <appender name="REDMINE" class="example.MyOwnAppender"> <url>http://example.com</url> <apiKey>abcdef1234567890</apiKey> <projectId>5566</projectId> <title>Logback Redmine Appender</title> <onlyError>true</onlyError> <encoder class="c.q.l.c.e.PatternLayoutEncoder"> <pattern>${PATTERN}</pattern> <charset>${CHARSET}</charset> </encoder> </appender>
  37. 37. 37 logback.xml - 注意事項
  38. 38. 38 logback.xml - 注意事項 ● camelCase
  39. 39. 39 logback.xml - 注意事項 ● camelCase ● follow the setter/getter JavaBeans conventions
  40. 40. 40 logback.xml - 注意事項 ● camelCase ● follow the setter/getter JavaBeans conventions ● only tag, no attribute
  41. 41. 41 logback.xml - 注意事項 ● camelCase ● follow the setter/getter JavaBeans conventions ● only tag, no attribute ● Joran
  42. 42. 42 Template - 給開發者看的 MyOwnAppender extends AppenderBase<ILoggingEvent> { @Override protected void append(ILoggingEvent event) { } } write log
  43. 43. 43 Template - 給開發者看的 MyOwnAppender extends AppenderBase<ILoggingEvent> { @Override public void start() { super.start(); } @Override protected void append(ILoggingEvent event) { } } initialization
  44. 44. 44 start() - initialization
  45. 45. 45 start() - initialization super.start();
  46. 46. 46 start() - initialization if (!checkProperties()) { addError("Some message"); return; } super.start();
  47. 47. 47 start() - initialization if (!checkProperties()) { addError("Some message"); return; } encoder.init(System.out); super.start();
  48. 48. 48 start() - initialization if (!checkProperties()) { addError("Some message"); return; } encoder.init(System.out); layout = encoder.getLayout(); super.start();
  49. 49. 49 start() - initialization if (!checkProperties()) { addError("Some message"); return; } encoder.init(System.out); layout = encoder.getLayout(); initialProperties(); super.start();
  50. 50. 50 append(ILoggingEvent) - write log
  51. 51. 51 append(ILoggingEvent) - write log String log = decorateLog(event);
  52. 52. 52 append(ILoggingEvent) - write log String log = decorateLog(event); writeLogToSomewhere(log);
  53. 53. 53 StackTraces 2016-10-03 22:00:09.174 [main] ERROR com.hello.Test - Caught: java.lang.RuntimeException: Oops at com.hello.AppTest.testSms(AppTest.java:13)
  54. 54. 54 ILoggingEvent 2016-10-03 22:00:09.174 [main] ERROR com.hello.Test - Caught:
  55. 55. 55 ILoggingEvent 2016-10-03 22:00:09.174 [main] ERROR com.hello.Test - Caught: event.getTimestamp()
  56. 56. 56 ILoggingEvent 2016-10-03 22:00:09.174 [main] ERROR com.hello.Test - Caught: event.getTimestamp() event.getThreadName()
  57. 57. 57 ILoggingEvent 2016-10-03 22:00:09.174 [main] ERROR com.hello.Test - Caught: event.getTimestamp() event.getThreadName() event.getLevel()
  58. 58. 58 ILoggingEvent 2016-10-03 22:00:09.174 [main] ERROR com.hello.Test - Caught: event.getTimestamp() event.getThreadName() event.getLevel() event.getLoggerName()
  59. 59. 59 ILoggingEvent 2016-10-03 22:00:09.174 [main] ERROR com.hello.Test - Caught: event.getTimestamp() event.getThreadName() event.getLevel() event.getLoggerName() event.getMessage()
  60. 60. 60 ILoggingEvent 2016-10-03 22:00:09.174 [main] ERROR com.hello.Test - Caught: event.getTimestamp() event.getThreadName() event.getLevel() event.getLoggerName() event.getMessage() %d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg
  61. 61. 61 IThrowableProxy 2016-10-03 22:00:09.174 [main] ERROR com.hello.Test - Caught: java.lang.RuntimeException: Oops event.getThrowableProxy()
  62. 62. 62 IThrowableProxy 2016-10-03 22:00:09.174 [main] ERROR com.hello.Test - Caught: java.lang.RuntimeException: Oops proxy.getClassName() event.getThrowableProxy()
  63. 63. 63 IThrowableProxy 2016-10-03 22:00:09.174 [main] ERROR com.hello.Test - Caught: java.lang.RuntimeException: Oops proxy.getClassName() proxy.getMessage() event.getThrowableProxy()
  64. 64. 64 StackTraceElement 2016-10-03 22:00:09.174 [main] ERROR com.hello.Test - Caught: java.lang.RuntimeException: Oops at com.hello.AppTest.testSms(AppTest.java:13) proxy .getStackTraceElementProxyArray()[n] .getStackTraceElement()
  65. 65. 65 StackTraceElement 2016-10-03 22:00:09.174 [main] ERROR com.hello.Test - Caught: java.lang.RuntimeException: Oops at com.hello.AppTest.testSms(AppTest.java:13) elem.getClassName() proxy .getStackTraceElementProxyArray()[n] .getStackTraceElement()
  66. 66. 66 StackTraceElement 2016-10-03 22:00:09.174 [main] ERROR com.hello.Test - Caught: java.lang.RuntimeException: Oops at com.hello.AppTest.testSms(AppTest.java:13) elem.getClassName() elem.getMethodName() proxy .getStackTraceElementProxyArray()[n] .getStackTraceElement()
  67. 67. 67 StackTraceElement 2016-10-03 22:00:09.174 [main] ERROR com.hello.Test - Caught: java.lang.RuntimeException: Oops at com.hello.AppTest.testSms(AppTest.java:13) elem.getClassName() elem.getMethodName() elem.getFileName() proxy .getStackTraceElementProxyArray()[n] .getStackTraceElement()
  68. 68. 68 StackTraceElement 2016-10-03 22:00:09.174 [main] ERROR com.hello.Test - Caught: java.lang.RuntimeException: Oops at com.hello.AppTest.testSms(AppTest.java:13) elem.getClassName() elem.getMethodName() elem.getFileName() elem.getLineNumber() proxy .getStackTraceElementProxyArray()[n] .getStackTraceElement()
  69. 69. 69 StackTraceElement 2016-10-03 22:00:09.174 [main] ERROR com.hello.Test - Caught: java.lang.RuntimeException: Oops at com.hello.AppTest.testSms(AppTest.java:13) elem.toString() proxy .getStackTraceElementProxyArray()[n] .getStackTraceElement()
  70. 70. 70 Appenders @ kewang
  71. 71. 71 Appenders @ kewang ● logback-redmine-appender ● logback-sms-appender
  72. 72. 72 Appenders @ kewang ● logback-redmine-appender – merge the same StackTraces @ one issue ● logback-sms-appender
  73. 73. 73 Appenders @ kewang ● logback-redmine-appender – merge the same StackTraces @ one issue – link StackTraces with git repo ● logback-sms-appender
  74. 74. 74 Appenders @ kewang ● logback-redmine-appender – merge the same StackTraces @ one issue – link StackTraces with git repo – nested tag ● logback-sms-appender
  75. 75. 75 Appenders @ kewang ● logback-redmine-appender – merge the same StackTraces @ one issue – link StackTraces with git repo – nested tag ● logback-sms-appender – custom output
  76. 76. 76 Appenders @ kewang ● logback-redmine-appender – merge the same StackTraces @ one issue – link StackTraces with git repo – nested tag ● logback-sms-appender – custom output – only append ERROR level
  77. 77. 77 Live DEMO
  78. 78. 78 One more thing
  79. 79. 79 Logpushhttp://logpush.io
  80. 80. 80 Live DEMO
  81. 81. 81 Features
  82. 82. 82 Features ● one AP,multiple environments
  83. 83. 83 Features ● one AP,multiple environments ● one environment, multiple subscriptions
  84. 84. 84 Features ● one AP,multiple environments ● one environment, multiple subscriptions ● RESTful API
  85. 85. 85 Features ● one AP,multiple environments ● one environment, multiple subscriptions ● RESTful API ● ...... etc.
  86. 86. 86 logback-logpush-appender <dependency> <groupId>io.logpush</groupId> <artifactId>logback-logpush-appender</artifactId> <version>0.1.0</version> </dependency> pom.xml
  87. 87. 87 logback-logpush-appender <appender name="LOGPUSH" class="i.l.l.a.LogpushAppender"> <token>THIS_IS_LOGPUSH_TOKEN</token> <onlyError>true</onlyError> <encoder class="c.q.l.c.e.PatternLayoutEncoder"> <pattern>${PATTERN}</pattern> <charset>${CHARSET}</charset> </encoder> </appender> logback.xml
  88. 88. 88 Definition ● AP ● Logpush Server ● Firebase Cloud Messaging ● Mobile device
  89. 89. 89 Log flow Firebase Cloud MessagingLogpush Server Mobile deviceAP
  90. 90. 90 Log flow - send log to Logpush Firebase Cloud MessagingLogpush Server Mobile deviceAP send log via appender
  91. 91. 91 Log flow - send msg to FCM Firebase Cloud MessagingLogpush Server Mobile deviceAP send send log via appender
  92. 92. 92 Log flow - send log to subscription Firebase Cloud MessagingLogpush Server Mobile deviceAP send receivesend log via appender
  93. 93. 93 Log flow - other features Firebase Cloud MessagingLogpush Server Mobile deviceAP send receivesend log via appender RESTful API
  94. 94. 94
  95. 95. 95 早期版本,請小力鞭
  96. 96. 96 早期版本,請小力鞭
  97. 97. 97 References ● http://logpush.io ● Logback ● jdk-logging log4j logback、 、 日志介绍及原理 ● slf4j jcl jul log4j1 log4j2 logback、 、 、 、 、 大总结 ● Log4j Log4j 2 Logback SFL4J JUL JCL、 、 、 、 、 的比 较
  98. 98. 98
  99. 99. 99

×