2016年8月10日 星期三

How to Use Java to Make an HTTPS Connection without Authentication

注意事項:
    1. TrustModifier 使用上需確認 HTTPS Protocol 是否為 TLS
    2. 本文供參考及學習使用

Catalog

Abstract

過去小編曾撰寫過不同語言的 HTTPS 連線,必須 PASS 掉 HTTPS 中 X509 和 HostName 的狀況並不算少數,這時以 Python 來講只需要增加一個布林值即可,但在 Java 中卻需要實作兩個類別,為了能更簡單的有效的進行程式開發及測試,小編撰寫了一個 TrustModifier,此類別中僅有一個外部可以呼叫的方法,通過此方法可以快速 PASS 掉 X509 及 HostName 驗證

關於 HTTPS 的小知識

在撰寫爬蟲或串接第三方 API 時,不可避免的在某些情況下必須用到 HTTPS 協定,這時如果對方伺服器所提供的是合法的接口,那在實作上只需要直接用 HTTPS 方式去連接即可。但事實並非總是如此,在測試中或使用到內部網路時,會因為伺服器不被信任而造成程式中斷,就小編所知這時我們的選擇,有以下兩種:
  1. 將對方伺服器中的憑證加入信任名單,並設法欺騙己方的伺服器,認為對方的 HostName 是正確的
  2. 在連線過程中無條件 Pass 第一種的兩種檢查
P.S 無論哪一種在傳輸時都仍然有加密,只是目前所要連線的伺服器並未通過驗證可能不安全

TrustModifier.java

import javax.net.ssl.*;
import java.net.URLConnection;
import java.security.cert.*;

/**
 * Created by Cookie on 16/8/9.
 */
public class TrustModifier {
    private static final HostnameVerifier VERIFIER = new AllowHostnameVerifier();
    private static final TrustManager[] MANAGER = new TrustManager[]{new AllowManager()};
    private static final TrustModifier MODIFIER = new TrustModifier("TLS");

    private final SSLSocketFactory factory;

    private TrustModifier(String protocol) {
        try {
            SSLContext ctx = SSLContext.getInstance(protocol);
            ctx.init(null, MANAGER, null);
            factory = ctx.getSocketFactory();
        } catch (Exception e) {
            throw new RuntimeException("Create Trust Modifier Failed.", e);
        }
    }

    private HttpsURLConnection modify(HttpsURLConnection conn) {
        conn.setSSLSocketFactory(factory);
        conn.setHostnameVerifier(VERIFIER);
        return conn;
    }

    /** Call this method and it will modify connection with trust settings. */
    public static URLConnection trust(URLConnection conn) {
        return (conn instanceof HttpsURLConnection)?
                MODIFIER.modify((HttpsURLConnection) conn) : conn;
    }

    private static final class AllowHostnameVerifier implements HostnameVerifier {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }

    private static final class AllowManager implements X509TrustManager {
        public void checkClientTrusted(X509Certificate[] arg0, String arg1) {}
        public void checkServerTrusted(X509Certificate[] arg0, String arg1) {}
        public X509Certificate[] getAcceptedIssuers() { return null; }
    }
}

SampleMain.java

import java.io.*;
import java.net.*;

/**
 * Created by Cookie on 16/8/9.
 */
public class SampleMain {

    public static void main(String[] args) throws IOException {
        URLConnection conn = new URL("https://74.125.203.94/").openConnection();

        /** Modify connection */
        TrustModifier.trust(conn);

        String inputLine;
        try(InputStreamReader stream = new InputStreamReader(conn.getInputStream());
            BufferedReader in = new BufferedReader(stream)) {
            while ((inputLine = in.readLine()) != null) {
                System.out.println(inputLine);
            }
        }
    }
}

Output

在 Output 中可以看出成功拿到了一段內容並未出現例外,連線成功
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>

2016年7月27日 星期三

Through HTTP Protocol to Learn Web Request

注意事項:
    1. 本文內容主要為小編自己的學習路徑分享
    2. 在使用 Telnet 時須注意換行符號,建議純手動打勿複製貼上
    3. 文章中所使用到的網址可以任意更動

Catalog

Abstract

近日小編在工作上遇到許多連線問題,經過一段時間的摸索意外讓小編學會了使用 Socket 來發送 HTTP Request,而後逐步的學會了使用 telnet 和 s_client 等工具來模擬長連結的 HTTP Request,也認識了網路中的各種連線原來都是利用 Socket 實現,本篇文章將透過一個小測試,來讓各位認識 Web 是如何與 Server 進行溝通請求。

關於 HTTP 的小知識 

扣除早期 0.X 版的 HTTP 目前現行的 HTTP Protocol 多為 1.0 版及 1.1 版,最新版本為 2.0 版非目前主流(本篇內容不使用 2.0 版本),在 1.0 與 1.1 最大的差異在於短連結與長連結,1.0 版預設為短連結(Connection 預設為 close 1.1 則反之)
一個標準的 HTTP Protocol 大致分成 Head 與 Body 兩個部分,中間使用一個換行來進行分隔,範例如下:
POST /2016/06/extract-transform-load.html HTTP/1.1
Host: tsai-cookie.blogspot.tw
User-Agent: User Defient/1.0
Content-Type: text/plain; charset=utf-8

<.... Your Data ....>

紅:Method
綠:Path
藍:HTTP Version
橘:Head
紫:Body(許多地方文章稱為 Entity)
P.S 在實驗中,此 POST HTTP Request 伺服器並不支援,僅供參考用。
並不是所有 HTTP Request 都有 body 最常見的四種 GET, POST, DELETE 和 PUT 中,只有 POST 和 PUT 可以攜帶 Body,而沒有攜帶 Body 的 Request 就不用 Content-Type 和 Body,反之則需要。
無 Body 的 Request,範例如下:
GET /2016/06/extract-transform-load.html HTTP/1.1
Host: tsai-cookie.blogspot.tw
User-Agent: User Defient/1.0

Experiment

接下來小編將帶各位做一個簡單的實驗,利用 telnet 及 s_client 向 www.google.com.tw 發送一個手製的 HTTP Request,首先,我們需要一個完整的 HTTP Reuqest,內容如下:
GET / HTTP/1.1
Host: www.google.com.tw
User-Agent: CookieTsai
Connection: close

P.S Connection: close 目的為告訴 Server 做完後結束連線,如不要這行可以連續發送數次。
如您使用的作業系統為 Windows,想要做此實驗須先手動打開 telnet 或安裝 cygwin,本文未提供方法造成不便請見諒。

Telnet 

於 命令提示字元 或 終端機 使用指令
$ telnet www.google.com.tw 80
Trying 64.233.187.94...
Connected to www.google.com.tw.
Escape character is '^]'.
進入後輸入 Request(紅色)並按下 Entry(按 1~2 次需產生一行空白行)即會收到 Server 回應(藍色)
內容如下:
GET / HTTP/1.1
Host: www.google.com.tw
User-Agent: CookieTsai
Connection: close

HTTP/1.1 200 OK
Date: Wed, 27 Jul 2016 11:24:19 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=Big5
P3P: CP="This is not a P3P policy! See https://www.google.com/support/accounts/answer/151657?hl=en for more info."
Server: gws
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Set-Cookie: NID=83=xuZXlGKYIFhYU7tlUD9YzxAcNuOxvrFSNa191FEEdOxB0s8xpW3W-u8t4BQnURrmtGuDVbgAYzq6Ed9MtCwqPdfGndeJ6GieOpNkBF5qaztXmm5H3o5CQ-FukayW1fhH; expires=Thu, 26-Jan-2017 11:24:19 GMT; path=/; domain=.google.com.tw; HttpOnly
Accept-Ranges: none
Vary: Accept-Encoding
Transfer-Encoding: chunked

28ba...(略)

Openssl's s_client 

既然使用 telnet 就可以發送了,為何需要使用 openssl 的 s_client 呢?
許多網站為了資訊安全會使用 HTTPS,這並不是指有一種 Protocol 是 HTTPS,而是一般的 HTTP Protocol + SSL,另一種說法是 HTTP Protocol 在傳送時加上 SSL 的加密方法。這時候單純的 telnet 無法提供 SSL 加解密,因此,要利用 openssl 提供的 s_client 來發送請球,內容大致如下。
於 命令提示字元 或 終端機 使用指令
$ openssl s_client -connect www.google.com.tw:443
CONNECTED(00000003)
depth=2 /C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
verify error:num=20:unable to get local issuer certificate
verify return:0
---
Certificate chain
 0 s:/C=US/ST=California/L=Mountain View/O=Google Inc/CN=google.com
   i:/C=US/O=Google Inc/CN=Google Internet Authority G2
 1 s:/C=US/O=Google Inc/CN=Google Internet Authority G2
   i:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
 2 s:/C=US/O=GeoTrust Inc./CN=GeoTrust Global CA
   i:/C=US/O=Equifax/OU=Equifax Secure Certificate Authority
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIgHDCCHwSgAwIBAgIIEAtlXh5wxiwwDQYJKoZIhvcNAQELBQAwSTELMAkGA1UE
BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxJTAjBgNVBAMTHEdvb2dsZSBJbnRl
cm5ldCBBdXRob3JpdHkgRzIwHhcNMTYwNzEzMTMxNjMyWhcNMTYxMDA1MTMxNjAw
...
...(中間省略非常長)...
...
Q57MUEhLPbQnNPaP5KXQfMB+9GbXrCGwJzX+Uue0T99zo/UuKW1pJUDM8jDhgMP3
Io5fc9LqwWuWDARjvODD6L7ZefN192ovI41+3yJ6ImOUvPJR31M4ZqiMT2MSJ1NT
k2w8H4X3z0pLvtlRFyDoq5TwkU8r6QnBQFD/rC6tAqvx7WGLc2nRXy2bgcKItwC/
uO9p+m2wqZJPPCQOnE0m6A==
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=Mountain View/O=Google Inc/CN=google.com
issuer=/C=US/O=Google Inc/CN=Google Internet Authority G2
---
No client certificate CA names sent
---
SSL handshake has read 10308 bytes and written 456 bytes
---
New, TLSv1/SSLv3, Cipher is AES128-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1
    Cipher    : AES128-SHA
    Session-ID: 13F7455348699FFF98FB6D11865EDDAEB3F904D6AC727041CA4F3857A0E97226
    Session-ID-ctx:
    Master-Key: F74606075CAC3B709F39CA9F2C699FCEA892C16F5E58AF0EC453433F74B0E7F7FD10890168C19E8EEAB1727F5CD4A478
    Key-Arg   : None
    Start Time: 1469623117
    Timeout   : 300 (sec)
    Verify return code: 0 (ok)
---
進入後輸入 Request(紅色)並按下 Entry(按 1~2 次需產生一行空白行)即會收到 Server 回應(藍色)
內容如下:
GET / HTTP/1.1
Host: www.google.com.tw
User-Agent: CookieTsai
Connection: close

HTTP/1.1 200 OK
Date: Wed, 27 Jul 2016 12:39:25 GMT
Expires: -1
Cache-Control: private, max-age=0
Content-Type: text/html; charset=Big5
P3P: CP="This is not a P3P policy! See https://www.google.com/support/accounts/answer/151657?hl=en for more info."
Server: gws
X-XSS-Protection: 1; mode=block
X-Frame-Options: SAMEORIGIN
Set-Cookie: NID=83=kdPJl42ANhiQji2fmjEO4h9aOjwp6ZWcBvXIREOnOVYBfWlS7PMjwn1w8ZTlc_gUjbXvQvnMGkJkKnsZGLy7CcDVO0s40Q7mofOTY4t2Uvt_kVSD7KumameS8PYDvLtj; expires=Thu, 26-Jan-2017 12:39:25 GMT; path=/; domain=.google.com.tw; HttpOnly
Alternate-Protocol: 443:quic
Alt-Svc: quic=":443"; ma=2592000; v="36,35,34,33,32,31,30,29,28,27,26,25"
Accept-Ranges: none
Vary: Accept-Encoding
Connection: close

...(略)

2016年6月5日 星期日

淺談 Extract-Transform-Load (ETL)

注意事項:
    1. 文章內容主要以 Web Log 的資料轉換過程為主要案例,
    2. 文章內容僅作參考

目錄

前言

網頁日誌(Web Log)是一種常見的資料類型,通常可以透過分析日誌來了解,產品或是伺服器目前的現況,甚至是提供產品的未來走向。一般情況下網頁日誌中會存在許多雜訊,這些內容不一定是我們所需要的,因此,在使用時我們需要撰寫一些程式進行轉換。本篇文章內容著重於轉換過程的實現,文章僅提供單一種實現方式,再多數情況是需要依照現有專案進行調整。

ETL

  • Extract — 資料擷取:從資料來源處擷取所需之數據資料。
  • Transform — 資料轉換:針對所擷取出之數據資料進行轉換。
  • Load — 資料載入:將轉換後的資料載入到目的地。

Data Set 

以下內容為網頁日誌,目的是作為本篇文章所使用的假資料集。(僅供練習使用)
1.172.0.185 - - [01/Jun/2011:00:00:00 +0800] "GET /action?;act=view;user=;uuid=6c27cc0b-d35a-addb-feb2-561b6bb28a5;pid=0006604986; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Linux; U; Android 4.1.1; zh-tw; PadFone 2 Build/JRO03L) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30"
61.58.145.131 - - [01/Jun/2011:00:00:00 +0800] "GET /action?;act=view;user=;uuid=280f45c-dccf-fb70-a3a7-1f8f4ee7661a;pid=0024134891; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Linux; U; Android 4.1.2; zh-tw; GT-P3100 Build/JZO54K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30"
114.41.4.218 - - [01/Jun/2011:00:00:01 +0800] "GET /action?;act=order;user=U312622727;uuid=252b97f1-25bd-39ea-6006-3f3ebf52c80;buy=0006944501,1,1069; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0; MAARJS)"
114.43.89.52 - - [01/Jun/2011:00:00:01 +0800] "GET /action?;act=view;user=;uuid=7ec350c-3f5d-7e83-f03b-da5e92c148db;pid=0022226912; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)"
114.34.254.21 - - [01/Jun/2011:00:00:01 +0800] "GET /action?;act=view;user=;uuid=1f56717c-2be-6b6a-554c-b1c93634103a;pid=0023531314; HTTP/1.1" 302 160 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; GTB7.5; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; eSobiSubscriber 2.0.4.16)"
111.184.100.252 - - [01/Jun/2011:00:00:03 +0800] "GET /action?;act=view;user=;uuid=e8caf452-433b-ab1f-976e-aa6b25799823;pid=0003848832; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
218.166.192.18 - - [01/Jun/2011:00:00:03 +0800] "GET /action?;act=view;user=U321001337;uuid=cbcaa5a5-4587-abac-b2f3-e2f2db2683eb;pid=0018926456; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
220.137.3.34 - - [01/Jun/2011:00:00:03 +0800] "GET /action?;act=order;user=U239012343;uuid=92e720da-17be-2b67-3383-9e5ccbd9499f;buy=0006018073,1,1680; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
66.249.80.72 - - [01/Jun/2011:00:00:04 +0800] "GET /action?;act=view;user=;uuid=d4a92f54-2fc7-a175-6c81-9d681cfe642e;pid=0018703860; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.4 (KHTML, like Gecko; Google Web Preview) Chrome/22.0.1229 Safari/537.4"
111.246.75.202 - - [01/Jun/2011:00:00:04 +0800] "GET /action?;act=view;user=;uuid=34bd97b0-49a1-774d-f8a3-ba30cb641173;pid=0022007845; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
114.46.250.60 - - [01/Jun/2011:00:00:18 +0800] "GET /action?;act=view;user=;uuid=a80c3ec-e9e0-9da3-591e-bbbb922de8;pid=0022008265; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 6_1 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Mobile/10B143"
114.35.30.119 - - [01/Jun/2011:00:00:18 +0800] "GET /action?;act=view;user=;uuid=2d9850ec-dd2-b4d3-7af7-6a68d6297723;pid=0001891400; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
114.42.124.225 - - [01/Jun/2011:00:00:19 +0800] "GET /action?;act=order;user=U10007697373;uuid=81b98199-a680-f862-e21-991ba747318d;buy=0002267974,1,285; HTTP/1.1" 302 160 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; AskTbAVR-4/5.15.20.37949)"
59.126.110.102 - - [01/Jun/2011:00:00:19 +0800] "GET /action?;act=view;user=;uuid=73ad381-5de-645-e994-9e432402d967;pid=0004405251; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0"
61.70.205.58 - - [01/Jun/2011:00:00:19 +0800] "GET /action?;act=view;user=;uuid=96823bb7-917b-85e0-3b12-8b55188c71c2;pid=0006402675; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
59.126.110.102 - - [01/Jun/2011:00:01:09 +0800] "GET /action?;act=view;user=;uuid=73ad381-5de-645-e994-9e432402d967;pid=0004862454; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0"
111.249.169.26 - - [01/Jun/2011:00:01:09 +0800] "GET /action?;act=view;user=;uuid=9e2d9243-be4-6942-e17a-90ba2b59eadb;pid=0007258064; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
38.99.122.214 - - [01/Jun/2011:00:01:10 +0800] "GET /action?;act=order;user=U296328517;uuid=69ec3e27-579f-bbb-5572-7a173429f0a;buy=0016144236,1,550; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (X11; U; Linux x86_64; zh-tw) AppleWebKit/534.35 (KHTML, like Gecko)  Chrome/11.0.696.65 Safari/534.35 Puffin/2.9909AP"
122.121.32.128 - - [01/Jun/2011:00:01:11 +0800] "GET /action?;act=view;user=U465077047;uuid=990dedcc-9c10-b3c3-b9b8-42b424cbe05;pid=0011166271; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
118.169.219.170 - - [01/Jun/2011:00:01:11 +0800] "GET /action?;act=view;user=;uuid=88c750fd-dcb3-53f6-ed8d-be6e1b37b124;pid=0013923416; HTTP/1.1" 302 160 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; Foxy/1; GTB7.5; Foxy/1; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.1; .NET4.0C; .NET CLR 1.1.4322; BRI/2)"
123.241.242.61 - - [01/Jun/2011:00:01:35 +0800] "GET /action?;act=view;user=;uuid=9f97cd65-319e-79eb-134b-42132b9ad900;pid=0022827254; HTTP/1.1" 302 160 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; InfoPath.1; OfficeLiveConnector.1.3; OfficeLivePatch.0.0; yie8)"
125.230.67.137 - - [01/Jun/2011:00:01:35 +0800] "GET /action?;act=view;user=U46488849;uuid=d8d2d9f6-52d8-cbb5-2aef-baafd1472995;pid=0006842253; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36"
182.234.93.248 - - [01/Jun/2011:00:01:36 +0800] "GET /action?;act=order;user=U300884570;uuid=97f37967-136a-4422-2776-25bb97c1477a;buy=0014516980122,1,249; HTTP/1.1" 302 160 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0)"
123.194.77.142 - - [01/Jun/2011:00:01:36 +0800] "GET /action?;act=view;user=;uuid=b96731e6-5d2f-5322-bcfc-1734e4264441;pid=0002457490; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; NP08; MAAU; NP08)"
1.172.70.194 - - [01/Jun/2011:00:01:37 +0800] "GET /action?;act=view;user=;uuid=f65099ea-87a0-1a-e7c2-2a9dc5d8f3db;pid=0022772735; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0)"
115.43.52.88 - - [01/Jun/2011:00:01:48 +0800] "GET /action?;act=view;user=;uuid=97cf13d1-2cca-ba6-196c-2aedcb3ffaf4;pid=0000248054; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)"
114.45.248.34 - - [01/Jun/2011:00:01:48 +0800] "GET /action?;act=view;user=;uuid=7cb94b4e-d7cc-423c-d0ee-cc33a55b325a;pid=0023531314; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
59.104.150.64 - - [01/Jun/2011:00:01:48 +0800] "GET /action?;act=order;user=U451050374;uuid=b7c64376-ae33-6b0-3008-7ebe4fdc656b;buy=0004134266,1,1780; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
36.239.20.203 - - [01/Jun/2011:00:01:48 +0800] "GET /action?;act=search;user=U238612347;uuid=27e6f25e-3acf-5951-3dd-dd7350e3aacb; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
175.182.5.59 - - [01/Jun/2011:00:01:48 +0800] "GET /action?;act=view;user=;uuid=4542e80f-c538-e6df-90b7-cd4bb565aa3b;pid=0006437874; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Linux; U; Android 4.0.3; zh-tw; Transformer TF101G Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30"
112.105.111.162 - - [01/Jun/2011:00:01:57 +0800] "GET /action?;act=view;user=;uuid=d97e1a57-1077-9a94-f3f1-862cbd642e7f;pid=0014476265; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
1.175.236.63 - - [01/Jun/2011:00:01:57 +0800] "GET /action?;act=view;user=;uuid=d2a968c-977f-75fb-382d-c98ca0b6460;pid=0019449102; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Linux; U; Android 2.3.5; zh-tw; HTC_DesireHD_A9191 Build/GRJ90) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"
180.176.44.148 - - [01/Jun/2011:00:01:58 +0800] "GET /action?;act=order;user=U465124055;uuid=2c721756-52e8-ac1a-df48-a90ea2e45c25;buy=0012662252,1,488; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
59.126.110.102 - - [01/Jun/2011:00:01:58 +0800] "GET /action?;act=view;user=;uuid=73ad381-5de-645-e994-9e432402d967;pid=0006437863; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0"
123.205.155.39 - - [01/Jun/2011:00:01:58 +0800] "GET /action?;act=view;user=;uuid=7d0c2051-c6b9-dfa-4a63-806e67339460;pid=0007398020; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
220.134.146.147 - - [01/Jun/2011:00:02:18 +0800] "GET /action?;act=view;user=U39528038;uuid=3f864dcd-aa7d-ce64-acfc-52e682c71ffe;pid=0002505510; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36"
36.227.194.82 - - [01/Jun/2011:00:02:18 +0800] "GET /action?;act=view;user=;uuid=5238ae2d-c56e-8905-c9a6-aedb11dc3097;pid=0018692085; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.59.8 (KHTML, like Gecko) Version/5.1.9 Safari/534.59.8"
111.249.190.187 - - [01/Jun/2011:00:02:18 +0800] "GET /action?;act=order;user=U403001364;uuid=b6a5f77f-2baa-d2be-13e0-ad1bb043169;buy=0004401294,1,276; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
112.104.126.65 - - [01/Jun/2011:00:02:19 +0800] "GET /action?;act=view;user=;uuid=f1098ee9-6afa-6d5a-c604-5e52d1b1eb8d;pid=0022657585; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
59.126.110.102 - - [01/Jun/2011:00:02:19 +0800] "GET /action?;act=view;user=;uuid=73ad381-5de-645-e994-9e432402d967;pid=0004405251; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0"
59.126.110.102 - - [01/Jun/2011:00:03:11 +0800] "GET /action?;act=view;user=;uuid=73ad381-5de-645-e994-9e432402d967;pid=0004862454; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0"
59.127.49.69 - - [01/Jun/2011:00:03:11 +0800] "GET /action?;act=view;user=;uuid=33512c49-50b0-235d-1235-f07e7a83113f;pid=0022827254; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
1.169.254.208 - - [01/Jun/2011:00:03:12 +0800] "GET /action?;act=order;user=U465123247;uuid=1d49d8b2-eb7c-fce3-ef73-73a3d2ff7d1d;buy=0000319874,1,2199; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36"
121.254.111.211 - - [01/Jun/2011:00:03:12 +0800] "GET /action?;act=view;user=;uuid=a376c8c5-e5a0-3723-6a13-3633eb4229fd;pid=0011183491; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; NP06)"
220.134.9.192 - - [01/Jun/2011:00:03:12 +0800] "GET /action?;act=view;user=;uuid=9a4fdb50-4adb-5f8a-f9d4-edd89a85b6b8;pid=0018335671; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Linux; U; Android 4.0.4; zh-tw; Enjoy 71 Build/IMM76I) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30"
36.230.144.245 - - [01/Jun/2011:00:03:44 +0800] "GET /action?;act=view;user=;uuid=4aaeaca2-6d9b-dce-3cb7-beab21b171d9;pid=0013818475; HTTP/1.1" 302 160 "--3E" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
1.173.114.187 - - [01/Jun/2011:00:03:44 +0800] "GET /action?;act=view;user=;uuid=ccf35d73-ec1c-c745-dc38-acef82d0d6e1;pid=0022827254; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
114.41.4.218 - - [01/Jun/2011:00:03:45 +0800] "GET /action?;act=order;user=U311808547;uuid=252b97f1-25bd-39ea-6006-3f3ebf52c80;buy=0006944501,1,1069; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0; MAARJS)"
59.126.110.102 - - [01/Jun/2011:00:03:45 +0800] "GET /action?;act=view;user=;uuid=73ad381-5de-645-e994-9e432402d967;pid=0006437911; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0"
111.249.186.158 - - [01/Jun/2011:00:03:45 +0800] "GET /action?;act=view;user=;uuid=293ad664-1e0b-fc36-132b-f254b56fd49f;pid=0003537671; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (iPad; CPU OS 6_1_3 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10B329 Safari/8536.25"
117.56.247.109 - - [01/Jun/2011:00:04:39 +0800] "GET /action?;act=view;user=;uuid=1647c87d-fc32-1ffa-db81-f3905c14b3bf;pid=0018585254; HTTP/1.1" 302 160 "-" "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"
59.126.110.102 - - [01/Jun/2011:00:04:40 +0800] "GET /action?;act=view;user=;uuid=73ad381-5de-645-e994-9e432402d967;pid=0004862454; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0"
118.165.10.71 - - [01/Jun/2011:00:04:40 +0800] "GET /action?;act=order;user=U178630660;uuid=2bccfdfb-1c15-df86-9b27-61e0b5816931;buy=0003248055,1,799; HTTP/1.1" 302 160 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; Zune 4.7)"
36.239.110.197 - - [01/Jun/2011:00:04:40 +0800] "GET /action?;act=view;user=;uuid=89e920ac-aae-4b5-96ce-51c6433bb8;pid=0023620461; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)"
61.70.164.55 - - [01/Jun/2011:00:04:40 +0800] "GET /action?;act=view;user=;uuid=e15e774c-b7e3-5b4d-104f-cb667875cdc;pid=0004931076; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
27.105.27.5 - - [01/Jun/2011:00:05:02 +0800] "GET /action?;act=view;user=;uuid=ee57807e-7ac7-cf3f-2242-3f1916e5c519;pid=0005552761; HTTP/1.1" 302 160 "--1A" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"
118.171.251.122 - - [01/Jun/2011:00:05:03 +0800] "GET /action?;act=view;user=;uuid=1825275b-2cc3-7551-186a-cf8b370eb213;pid=0011092362; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (iPad; CPU OS 6_1_3 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10B329 Safari/8536.25"
114.32.85.222 - - [01/Jun/2011:00:05:03 +0800] "GET /action?;act=order;user=U339736346;uuid=1e66983f-f71c-b6ad-2b3f-a2a95ee25c5b;buy=0018924850,2,792,0000445944,1,404; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; yie10)"
125.230.67.137 - - [01/Jun/2011:00:05:03 +0800] "GET /action?;act=view;user=U46488849;uuid=d8d2d9f6-52d8-cbb5-2aef-baafd1472995;pid=0005246791; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36"
203.145.207.188 - - [01/Jun/2011:00:05:04 +0800] "GET /action?;act=view;user=;uuid=41ee27d6-5f83-b982-69f9-f378dc9fc11b;pid=0006437885; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0"
36.227.194.82 - - [01/Jun/2011:00:05:24 +0800] "GET /action?;act=view;user=;uuid=5238ae2d-c56e-8905-c9a6-aedb11dc3097;pid=0009702873; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/534.59.8 (KHTML, like Gecko) Version/5.1.9 Safari/534.59.8"
175.181.111.196 - - [01/Jun/2011:00:05:25 +0800] "GET /action?;act=view;user=;uuid=d252a0eb-e47c-f173-6f1c-33b4a36dad8e;pid=0000895123; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)"
219.71.161.82 - - [01/Jun/2011:00:05:25 +0800] "GET /action?;act=order;user=U465125772;uuid=5136439-b40a-997c-65ee-8100c0275bc2;buy=0013850723,1,2980; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 5.1; rv:23.0) Gecko/20100101 Firefox/23.0"
114.42.155.197 - - [01/Jun/2011:00:05:27 +0800] "GET /action?;act=view;user=;uuid=c8bdd4e9-3eb0-efa8-210f-1eeb716df30;pid=0018906005; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)"
59.126.110.102 - - [01/Jun/2011:00:05:27 +0800] "GET /action?;act=view;user=;uuid=73ad381-5de-645-e994-9e432402d967;pid=0018307096; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0"
123.240.63.53 - - [01/Jun/2011:00:05:29 +0800] "GET /action?;act=view;user=;uuid=f187192f-bfdb-35c1-6b10-9446e2aefd;pid=0022529850; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0; yie9)"
124.10.91.92 - - [01/Jun/2011:00:05:30 +0800] "GET /action?;act=view;user=U396120416;uuid=3560692f-8134-a93e-8de3-f9197d0d500d;pid=0002940055; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0; MATPJS)"
123.241.44.19 - - [01/Jun/2011:00:05:31 +0800] "GET /action?;act=order;user=U465125671;uuid=b37521a3-de6c-193b-6b1-e2d1ad25205a;buy=0003448524,2,390; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
123.194.132.113 - - [01/Jun/2011:00:05:31 +0800] "GET /action?;act=view;user=;uuid=fe75b088-8c7c-44bc-31a9-e6bba557db64;pid=0024036390; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; yie10)"
1.164.172.173 - - [01/Jun/2011:00:05:31 +0800] "GET /action?;act=view;user=;uuid=3168c1e7-ccfe-3e33-8393-b924b686d71c;pid=0023719010; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
203.67.201.249 - - [01/Jun/2011:00:08:05 +0800] "GET /action?;act=view;user=;uuid=70eb8b32-5e7-c1e5-f50a-8618e2338d44;pid=0006437874; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
114.45.171.181 - - [01/Jun/2011:00:08:05 +0800] "GET /action?;act=view;user=;uuid=158e8a19-bcd2-6468-3776-ce0abc30a533;pid=0011625036; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36"
112.104.18.47 - - [01/Jun/2011:00:08:06 +0800] "GET /action?;act=order;user=U46498056;uuid=59f2aa24-24bc-3ead-59bd-4344c6b84d41;buy=0002689481,1,702; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
112.105.80.242 - - [01/Jun/2011:00:08:06 +0800] "GET /action?;act=view;user=;uuid=715a2c8-95eb-c074-4d7-52e718336da0;pid=0001854930; HTTP/1.1" 302 160 "--1A" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
203.74.127.204 - - [01/Jun/2011:00:08:06 +0800] "GET /action?;act=view;user=;uuid=a1dd90b6-5b7f-82f-9bb9-439e5c4ae5d3;pid=0020225225; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36"
114.44.29.194 - - [01/Jun/2011:00:08:28 +0800] "GET /action?;act=view;user=;uuid=9582bf27-6b8e-777f-6ff5-d516dd535cdc;pid=0018746066; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
59.127.202.153 - - [01/Jun/2011:00:08:28 +0800] "GET /action?;act=view;user=;uuid=f3d5e4b3-420d-487a-6c34-9f4f9cbb27fd;pid=0014469055; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
1.162.213.10 - - [01/Jun/2011:00:08:28 +0800] "GET /action?;act=order;user=U349686362;uuid=5b8d9215-7f1c-596e-eee7-60b55d4ae3e0;buy=0005667605,1,488; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
219.68.8.186 - - [01/Jun/2011:00:08:28 +0800] "GET /action?;act=view;user=;uuid=7734290-d9ac-6bbb-9d4-15ffb4371b;pid=0003327295; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"
123.50.54.134 - - [01/Jun/2011:00:08:28 +0800] "GET /action?;act=view;user=;uuid=22e38b54-c43f-d0a9-8f9f-9dd48eef476f;pid=0014622650; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
203.70.12.83 - - [01/Jun/2011:00:09:30 +0800] "GET /action?;act=view;user=;uuid=882097e0-9f65-f51b-163c-378faa8c1a8f;pid=0012998370; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36"
114.40.13.94 - - [01/Jun/2011:00:09:31 +0800] "GET /action?;act=view;user=U384948322;uuid=3e709ba4-329c-7b9f-3591-65b9653728f6;pid=0018585254; HTTP/1.1" 302 160 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.5; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2)"
220.137.3.34 - - [01/Jun/2011:00:09:31 +0800] "GET /action?;act=order;user=U234579365;uuid=92e720da-17be-2b67-3383-9e5ccbd9499f;buy=0024026973,1,198; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
1.161.156.3 - - [01/Jun/2011:00:09:32 +0800] "GET /action?;act=view;user=;uuid=18a0d6df-7886-e8b5-5620-9b0722f968bd;pid=0023395282; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
123.50.54.134 - - [01/Jun/2011:00:09:32 +0800] "GET /action?;act=view;user=;uuid=22e38b54-c43f-d0a9-8f9f-9dd48eef476f;pid=0001756355; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
66.249.80.72 - - [01/Jun/2011:00:10:04 +0800] "GET /action?;act=view;user=;uuid=12c8ef3-a8a6-8beb-18ff-fde03d55559d;pid=0018523260; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.4 (KHTML, like Gecko; Google Web Preview) Chrome/22.0.1229 Safari/537.4"
59.126.110.102 - - [01/Jun/2011:00:10:04 +0800] "GET /action?;act=view;user=;uuid=73ad381-5de-645-e994-9e432402d967;pid=0004906226; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0"
220.133.231.97 - - [01/Jun/2011:00:10:04 +0800] "GET /action?;act=order;user=;uuid=cf801dc4-c447-d607-e73b-583eafeba97e;buy=; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0"
125.230.67.137 - - [01/Jun/2011:00:10:05 +0800] "GET /action?;act=view;user=U46488849;uuid=d8d2d9f6-52d8-cbb5-2aef-baafd1472995;pid=0018758865; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.57 Safari/537.36"
219.68.11.162 - - [01/Jun/2011:00:10:06 +0800] "GET /action?;act=view;user=;uuid=aec31212-ed7-ec04-92dc-8632b3e8c82d;pid=0018381661; HTTP/1.1" 302 160 "--2" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; GTB7.5; Foxy/1; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C)"
123.204.128.45 - - [01/Jun/2011:00:10:18 +0800] "GET /action?;act=view;user=;uuid=cb0be90a-adcb-2145-74aa-fc4efe7a3cee;pid=0023720970; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (iPad; U; CPU OS 4_3_5 like Mac OS X; zh-tw) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8L1 Safari/6533.18.5"
203.145.207.188 - - [01/Jun/2011:00:10:18 +0800] "GET /action?;act=view;user=;uuid=41ee27d6-5f83-b982-69f9-f378dc9fc11b;pid=0018316266; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0"
220.142.124.5 - - [01/Jun/2011:00:10:18 +0800] "GET /action?;act=order;user=U438707274;uuid=2ee31476-d557-d19a-31c7-3c2ce8f67d4;buy=0023733533,1,1710,0000445966,1,808; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
114.34.148.192 - - [01/Jun/2011:00:10:19 +0800] "GET /action?;act=view;user=U395982321;uuid=493ed0f-54fd-319b-2df9-bdb9d6f21c9c;pid=0018435454; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Linux; U; Android 4.1.1; zh-tw; HTC_One_X Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30"
61.58.178.150 - - [01/Jun/2011:00:10:19 +0800] "GET /action?;act=view;user=;uuid=c4c3c8dc-913a-a218-4dc4-80d442d2d0ce;pid=0006587254; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Linux; U; Android 4.0.3; zh-tw; GT-I9100 Build/IML74K) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30"
203.145.207.188 - - [01/Jun/2011:00:10:37 +0800] "GET /action?;act=view;user=;uuid=41ee27d6-5f83-b982-69f9-f378dc9fc11b;pid=0013038863; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101 Firefox/23.0"
1.162.69.186 - - [01/Jun/2011:00:10:37 +0800] "GET /action?;act=view;user=U126324055;uuid=f0d2caa8-aa16-9af9-cca2-c1f25b5de855;pid=0006437874; HTTP/1.1" 302 160 "-" "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; InfoPath.1; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; YTB730; .NET4.0C; .NET4.0E)"
220.142.124.5 - - [01/Jun/2011:00:10:37 +0800] "GET /action?;act=order;user=U438707274;uuid=2ee31476-d557-d19a-31c7-3c2ce8f67d4;buy=0023733533,1,1710,0000445966,1,808; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"
1.34.131.167 - - [01/Jun/2011:00:10:37 +0800] "GET /action?;act=search;user=;uuid=dc945994-2472-2cf5-2fdc-eb85defc5465; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.62 Safari/537.36"
219.85.82.234 - - [01/Jun/2011:00:10:38 +0800] "GET /action?;act=search;user=;uuid=3357b74b-2e20-7b63-ccd7-6b5613a446c9; HTTP/1.1" 302 160 "-" "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36"

Training 

目標一:Log to CSV 

尚未整理過的 Log 對於任何處理都是不方便的,在很多時候甚至會是效能的瓶頸。所以第一步可以選用常用的格式如:csv, tsv...等,先將要使用的資料進行統一的轉換。

Sample Code:log2csv.py 

import sys
import re
import csv

index = {"ip":0,"day":1,"time":2,"act":3,"user":4,"uuid":5,"buy":6}

writer = csv.writer(sys.stdout)

for line in sys.stdin:
    row=["NA","NA","NA","NA","NA","NA","NA"]

    line = re.sub(r'"\s.*$', '', line)
    m = re.search(r'^([0-9.]+).*\[([^:]+):(\S+).*\?;(\S+)', line)

    row[index["ip"]] = m.group(1)
    row[index["day"]] = m.group(2)
    row[index["time"]] = m.group(3)

    for item in re.findall(r'(\w+)=([^;]+)', m.group(4)):
        key = item[0].strip()
        val = item[1].strip()
        if key in index:
            row[index[key]] = val

    writer.writerow(row)

目標二:CSV to Order's CSV 

本文此次的目標以取出 Web Log 中 act=order 類型的資料為範例。由於 order 的 buy 資料內容為(商品代碼,購買數量,購買金額... 反覆出現),與一般資料如:user 的內容不同,因此,在處理 order 時需要將重複出現的內容再切割成數份。撰寫 csv2order.py 來解決以上問題,詳細做法請看程式碼。

Sample Code:csv2order.py 

import sys
import csv
import re

index = {"day":1,"user":4,"buy":6}

reader = csv.reader(sys.stdin)
writer = csv.writer(sys.stdout)

for row in reader:
    out = ["NA","NA","NA","NA","NA"]
    out[0] = row[index["day"]]
    out[1] = row[index["user"]]

    for item in re.findall(r'([0-9]+),([0-9]+),([0-9]+)', row[index["buy"]]):
        out[2] = item[0]
        out[3] = item[1]
        out[4] = item[2]
        writer.writerow(out)

執行

指令 

$ cat {網頁日誌 路徑} | python log2csv.py | python  csv2order.py

輸出 

01/Jun/2011,U312622727,0006944501,1,1069
01/Jun/2011,U239012343,0006018073,1,1680
01/Jun/2011,U10007697373,0002267974,1,285
01/Jun/2011,U296328517,0016144236,1,550
01/Jun/2011,U300884570,0014516980122,1,249
01/Jun/2011,U451050374,0004134266,1,1780
01/Jun/2011,U465124055,0012662252,1,488
01/Jun/2011,U403001364,0004401294,1,276
01/Jun/2011,U465123247,0000319874,1,2199
01/Jun/2011,U311808547,0006944501,1,1069
01/Jun/2011,U178630660,0003248055,1,799
01/Jun/2011,U339736346,0018924850,2,792
01/Jun/2011,U339736346,0000445944,1,404
01/Jun/2011,U465125772,0013850723,1,2980
01/Jun/2011,U465125671,0003448524,2,390
01/Jun/2011,U46498056,0002689481,1,702
01/Jun/2011,U349686362,0005667605,1,488
01/Jun/2011,U234579365,0024026973,1,198
01/Jun/2011,U438707274,0023733533,1,1710
01/Jun/2011,U438707274,0000445966,1,808
01/Jun/2011,U438707274,0023733533,1,1710
01/Jun/2011,U438707274,0000445966,1,808

後記

與 Hadoop Hive 結合 

  • 以下操作皆在 Localhost 下進行操作
  • 目標為上傳資料至 HDFS 並且使用 Hive 建立相對應表格後查詢 

上傳至 HDFS 

$ hadoop fs -mkdir /table
$ hadoop fs -put {order's csv 檔案路徑} /table

Using Beeline 

$ beeline -u jdbc:hive2://localhost:10000

Create Table 

CREATE EXTERNAL TABLE OrderLog (
    d STRING,
    uid STRING,
    pid STRING,
    cnt INT,
    price INT
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS TEXTFILE
LOCATION '/table';

Select Table 

SELECT * FROM OrderLog;

2016年4月20日 星期三

Getting Started with SLF4J

注意事項:
    1. 文章整理至 SLF4J 官網
    2. 內容僅供參考以官方為主

Catalog

前言

從剛入職場到至今所遇到的每一個專案幾乎都會引用 log4j 這樣的套件來做日誌管理,時至數天前都始終不了解其中運作的好處及機制。近日剛好遇到日誌造成效能不佳的問題,因此抽空將 SLF4J 看了一輪,經過幾天的努力認識自己所用的日誌套件。最後,整理一些自己所看到的重要內容在此分享給各位。(log4j 與 SLF4J 同是日誌的管理套件)
首先,日誌管理是專案必需基本需求之一,其常見的應用如:
  • 專案開發過程中的追蹤
  • 紀錄伺服器發生錯誤時的內容
  • 紀錄 Monitor 統計的數據結果
  • 數據分析的依據
  • ... 
無論用途為何,日誌管理套件都應該提供詳盡且可靠的內容。
現行常見的日誌管理機制都可以找到一套 Level 規則。由於不同的套件通常規則不完全相同,在這邊簡單介紹一下 SLF4J 有 TRACE, DEBUG, INFO, WARN, ERROR 五種等級。通常我們可以通過設定當前的 Level 決定可以日誌會輸出的內容。例如:設定 ERROR 只會輸出 ERROR 而設定 WARN 則會輸出 WARN 和 ERROR... 後面依此類推。
一個比較特別的地方,SLF4J 除了是一個日誌管理套件外,它也是一個橋接管理套件,它可以將 Jakata Commons Logging(JCL), log4j 及 java.util.logging(JUL) 轉嫁至 SLF4J 上。使得管理上變得更為方便,格式及輸出都可以有更好的統一管理。
使用方面相當簡單只需要將 slf4j-api-*.jar 放入 Class Path 中就可以正常使用,橋接方式也僅需要把相對應的套件放入 Class Path 即可。例如:log4j to SLF4J 要放入 log4j-over-slf4j-*.jar 反之則放入 slf4j-log4j12-*.jar。(請注意此兩種 jar 不可同時放入,否則會發生無限迴圈,JCL 及 JUL 同理)
在使用 SLF4J 時需要小心橋接 JUL 官網有提供說明,而小編也實際測試過效能影響重大,不過好加在官網有提供簡覺得方案。第一點是記得使用 LevelChangePropagator 以及盡可能的少呼叫 JUL 系列的 Logger 這樣就可以幾乎不影響到效能。
之後的內容是小編認為比較能快速上手的一些文章剪輯,內容節錄至 SLF4J 官網。其中大致包含一個簡單的 Hello World 的日誌輸出,如何橋接 SLF4J 以及橋接時可能遇到的一些狀況。

SLF4J user manual

The Simple Logging Facade for Java (SLF4J) serves as a simple facade or abstraction for various logging frameworks, such as java.util.logging, logback and log4j. SLF4J allows the end-user to plug in the desired logging framework at deployment time. Note that SLF4J-enabling your library/application implies the addition of only a single mandatory dependency, namely slf4j-api-1.7.21.jar.
SINCE 1.6.0 If no binding is found on the class path, then SLF4J will default to a no-operation implementation.
SINCE 1.7.0 Printing methods in the Logger interface now offer variants accepting varargs instead of Object[]. This change implies that SLF4J requires JDK 1.5 or later. Under the hood the Java compiler transforms the varargs part in methods into Object[]. Thus, the Logger interface generated by the compiler is indistinguishable in 1.7.x from its 1.6.x counterpart. It follows that SLF4J version 1.7.x is totally 100% no-ifs-or-buts compatible with SLF4J version 1.6.x.
SINCE 1.7.5 Significant improvement in logger retrieval times. Given the extent of the improvement, users are highly encouraged to migrate to SLF4J 1.7.5 or later.
SINCE 1.7.9 By setting the slf4j.detectLoggerNameMismatch system property to true, SLF4J can automatically spot incorrectly named loggers.

Hello World

As customary in programming tradition, here is an example illustrating the simplest way to output "Hello world" using SLF4J. It begins by getting a logger with the name "HelloWorld". This logger is in turn used to log the message "Hello World".
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HelloWorld {
  public static void main(String[] args) {
    Logger logger = LoggerFactory.getLogger(HelloWorld.class);
    logger.info("Hello World");
  }
}
To run this example, you first need to download the slf4j distribution, and then to unpack it. Once that is done, add the file slf4j-api-1.7.21.jar to your class path.
Compiling and running HelloWorld will result in the following output being printed on the console.
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder". 
SLF4J: Defaulting to no-operation (NOP) logger implementation 
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details. 
This warning is printed because no slf4j binding could be found on your class path.
The warning will disappear as soon as you add a binding to your class path. Assuming you add slf4j-simple-1.7.21.jar so that your class path contains:
  • slf4j-api-1.7.21.jar
  • slf4j-simple-1.7.21.jar
Compiling and running HelloWorld will now result in the following output on the console.
0 [main] INFO HelloWorld - Hello World

Binding with a logging framework at deployment time

As mentioned previously, SLF4J supports various logging frameworks. The SLF4J distribution ships with several jar files referred to as "SLF4J bindings", with each binding corresponding to a supported framework.

slf4j-log4j12-1.7.21.jar
Binding for log4j version 1.2, a widely used logging framework. You also need to place log4j.jar on your class path.

slf4j-jdk14-1.7.21.jar
Binding for java.util.logging, also referred to as JDK 1.4 logging

slf4j-nop-1.7.21.jar
Binding for NOP, silently discarding all logging.

slf4j-simple-1.7.21.jar
Binding for Simple implementation, which outputs all events to System.err. Only messages of level INFO and higher are printed. This binding may be useful in the context of small applications.

slf4j-jcl-1.7.21.jar
Binding for Jakarta Commons Logging. This binding will delegate all SLF4J logging to JCL.

logback-classic-1.0.13.jar (requires logback-core-1.0.13.jar)
NATIVE IMPLEMENTATION There are also SLF4J bindings external to the SLF4J project, e.g. logback which implements SLF4J natively. Logback's ch.qos.logback.classic.Logger class is a direct implementation of SLF4J's org.slf4j.Logger interface. Thus, using SLF4J in conjunction with logback involves strictly zero memory and computational overhead.
To switch logging frameworks, just replace slf4j bindings on your class path. For example, to switch from java.util.logging to log4j, just replace slf4j-jdk14-1.7.21.jar with slf4j-log4j12-1.7.21.jar.
SLF4J does not rely on any special class loader machinery. In fact, each SLF4J binding is hardwired at compile time to use one and only one specific logging framework. For example, the slf4j-log4j12-1.7.21.jar binding is bound at compile time to use log4j. In your code, in addition to slf4j-api-1.7.21.jar, you simply drop one and only one binding of your choice onto the appropriate class path location. Do not place more than one binding on your class path. Here is a graphical illustration of the general idea.
The SLF4J interfaces and their various adapters are extremely simple. Most developers familiar with the Java language should be able to read and fully understand the code in less than one hour. No knowledge of class loaders is necessary as SLF4J does not make use nor does it directly access any class loaders. As a consequence, SLF4J suffers from none of the class loader problems or memory leaks observed with Jakarta Commons Logging (JCL).
Given the simplicity of the SLF4J interfaces and its deployment model, developers of new logging frameworks should find it very easy to write SLF4J bindings.

Bridging legacy APIs

Often, some of the components you depend on rely on a logging API other than SLF4J. You may also assume that these components will not switch to SLF4J in the immediate future. To deal with such circumstances, SLF4J ships with several bridging modules which redirect calls made to log4j, JCL and java.util.logging APIs to behave as if they were made to the SLF4J API instead. The figure below illustrates the idea.
Please note that for source code under your control, you really should use the slf4j-migrator. The binary-based solutions described in this page are appropriate for software beyond your control.

Gradual migration to SLF4J from Jakarta Commons Logging (JCL)

jcl-over-slf4j.jar

To ease migration to SLF4J from JCL, SLF4J distributions include the jar file jcl-over-slf4j.jar. This jar file is intended as a drop-in replacement for JCL version 1.1.1. It implements the public API of JCL but using SLF4J underneath, hence the name "JCL over SLF4J."
Our JCL over SLF4J implementation will allow you to migrate to SLF4J gradually, especially if some of the libraries your software depends on continue to use JCL for the foreseeable future. You can immediately enjoy the benefits of SLF4J's reliability and preserve backward compatibility at the same time. Just replace commons-logging.jar with jcl-over-slf4j.jar. Subsequently, the selection of the underlying logging framework will be done by SLF4J instead of JCL but without the class loader headaches plaguing JCL. The underlying logging framework can be any of the frameworks supported by SLF4J. Often times, replacing commons-logging.jar with jcl-over-slf4j.jar will immediately and permanently solve class loader issues related to commons logging.

slf4j-jcl.jar

Some of our users after having switched to SLF4J API realize that in some contexts the use of JCL is mandatory and their use of SLF4J can be a problem. For this uncommon but important case, SLF4J offers a JCL binding, found in the file slf4j-jcl.jar. The JCL binding will delegate all logging calls made through SLF4J API to JCL. Thus, if for some reason an existing application must use JCL, your part of that application can still code against the SLF4J API in a manner transparent to the larger application environment. Your choice of SLF4J API will be invisible to the rest of the application which can continue to use JCL.

jcl-over-slf4j.jar should not be confused with slf4j-jcl.jar

JCL-over-SLF4J, i.e. jcl-over-slf4j.jar, comes in handy in situations where JCL needs to be supported for backward compatibility reasons. It can be used to fix problems associated with JCL, without necessarily adopting the SLF4J API, a decision which can be deferred to a later time.
On the other hand, slf4j-jcl.jar is useful after you have already adopted the SLF4J API for your component which needs to be embedded in a larger application environment where JCL is a formal requirement. Your software component can still use SLF4J API without disrupting the larger application. Indeed, slf4j-jcl.jar will delegate all logging decisions to JCL so that the dependency on SLF4J API by your component will be transparent to the larger whole.
Please note that jcl-over-slf4j.jar and slf4j-jcl.jar cannot be deployed at the same time. The former jar file will cause JCL to delegate the choice of the logging system to SLF4J and the latter jar file will cause SLF4J to delegate the choice of the logging system to JCL, resulting in an infinite loop.

log4j-over-slf4j

How does it work?

The log4j-over-slf4j module contains replacements of most widely used log4j classes, namely org.apache.log4j.Category, org.apache.log4j.Logger, org.apache.log4j.Priority, org.apache.log4j.Level, org.apache.log4j.MDC, and org.apache.log4j.BasicConfigurator. These replacement classes redirect all work to their corresponding SLF4J classes.
To use log4j-over-slf4j in your own application, the first step is to locate and then to replace log4j.jar with log4j-over-slf4j.jar. Note that you still need an SLF4J binding and its dependencies for log4j-over-slf4j to work properly.
In most situations, replacing a jar file is all it takes in order to migrate from log4j to SLF4J.
Note that as a result of this migration, log4j configuration files will no longer be picked up. If you need to migrate your log4j.properties file to logback, the log4j translator might be of help. For configuring logback, please refer to its manual.

When does it not work?

The log4j-over-slf4j module will not work when the application calls log4j components that are not present in the bridge. For example, when application code directly references log4j appenders, filters or the PropertyConfigurator, then log4j-over-slf4j would be an insufficient replacement for log4j. However, when log4j is configured through a configuration file, be it log4j.properties or log4j.xml, the log4j-over-slf4j module should just work fine.

What about the overhead?

There overhead of using log4j-over-slf4j instead of log4j directly is relatively small. Given that log4j-over-slf4j immediately delegates all work to SLF4J, the CPU overhead should be negligible, in the order of a few nanoseconds. There is a memory overhead corresponding to an entry in a hashmap per logger, which should be usually acceptable even for very large applications consisting of several thousand loggers. Moreover, if you choose logback as your underlying logging system, and given that logback is both much faster and more memory-efficient than log4j, the gains made by using logback should compensate for the overhead of using log4j-over-slf4j instead of log4j directly.

log4j-over-slf4j.jar and slf4j-log4j12.jar cannot be present simultaneously

The presence of slf4j-log4j12.jar, that is the log4j binding for SLF4J, will force all SLF4J calls to be delegated to log4j. The presence of log4j-over-slf4j.jar will in turn delegate all log4j API calls to their SLF4J equivalents. If both are present simultaneously, slf4j calls will be delegated to log4j, and log4j calls redirected to SLF4j, resulting in an endless loop.

jul-to-slf4j bridge

The jul-to-slf4j module includes a java.util.logging (jul) handler, namely SLF4JBridgeHandler, which routes all incoming jul records to the SLF4j API. Please see SLF4JBridgeHandler javadocs for usage instructions.
NOTE ON PERFORMANCE Contrary to other bridging modules, namely jcl-over-slf4j and log4j-over-slf4j, which reimplement JCL and respectively log4j, the jul-to-slf4j module does not reimplement the java.util.logging because packages under the java.* namespace cannot be replaced. Instead, jul-to-slf4j translates LogRecord objects into their SLF4J equivalent. Please note this translation process incurs the cost of constructing a LogRecord instance regardless of whether the SLF4J logger is disabled for the given level or nor. Consequently, j.u.l. to SLF4J translation can seriously increase the cost of disabled logging statements (60 fold or 6000%) and measurably impact the performance of enabled log statements (20% overall increase). As of logback version 0.9.25, it is possible to completely eliminate the 60 fold translation overhead for disabled log statements with the help of LevelChangePropagator.
If you are concerned about application performance, then use of SLF4JBridgeHandler is appropriate only if any one of the following two conditions is true:
  1. few j.u.l. logging statements are in play
  2. LevelChangePropagator has been installed

jul-to-slf4j.jar and slf4j-jdk14.jar cannot be present simultaneously

The presence of slf4j-jdk14.jar, that is the jul binding for SLF4J, will force SLF4J calls to be delegated to jul. On the other hand, the presence of jul-to-slf4j.jar, plus the installation of SLF4JBridgeHandler, by invoking "SLF4JBridgeHandler.install()" will route jul records to SLF4J. Thus, if both jar are present simultaneously (and SLF4JBridgeHandler is installed), slf4j calls will be delegated to jul and jul records will be routed to SLF4J, resulting in an endless loop.