PageRenderTime 73ms CodeModel.GetById 2ms app.highlight 63ms RepoModel.GetById 1ms app.codeStats 1ms

/src/main/java/com/alibaba/druid/support/http/stat/WebAppStat.java

https://github.com/hellobaby/druid
Java | 1122 lines | 887 code | 214 blank | 21 comment | 248 complexity | b35b44d2951b439cb1f0ba7fc77f30e1 MD5 | raw file
   1/*
   2 * Copyright 1999-2011 Alibaba Group Holding Ltd.
   3 *
   4 * Licensed under the Apache License, Version 2.0 (the "License");
   5 * you may not use this file except in compliance with the License.
   6 * You may obtain a copy of the License at
   7 *
   8 *      http://www.apache.org/licenses/LICENSE-2.0
   9 *
  10 * Unless required by applicable law or agreed to in writing, software
  11 * distributed under the License is distributed on an "AS IS" BASIS,
  12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 * See the License for the specific language governing permissions and
  14 * limitations under the License.
  15 */
  16package com.alibaba.druid.support.http.stat;
  17
  18import java.util.ArrayList;
  19import java.util.Iterator;
  20import java.util.LinkedHashMap;
  21import java.util.List;
  22import java.util.Map;
  23import java.util.concurrent.ConcurrentHashMap;
  24import java.util.concurrent.ConcurrentMap;
  25import java.util.concurrent.atomic.AtomicInteger;
  26import java.util.concurrent.atomic.AtomicLong;
  27import java.util.concurrent.locks.ReadWriteLock;
  28import java.util.concurrent.locks.ReentrantReadWriteLock;
  29
  30import com.alibaba.druid.support.logging.Log;
  31import com.alibaba.druid.support.logging.LogFactory;
  32import com.alibaba.druid.util.LRUCache;
  33
  34public class WebAppStat {
  35
  36    private final static Log                        LOG                            = LogFactory.getLog(WebAppStat.class);
  37
  38    public final static int                         DEFAULT_MAX_STAT_URI_COUNT     = 1000;
  39    public final static int                         DEFAULT_MAX_STAT_SESSION_COUNT = 1000;
  40
  41    private final static ThreadLocal<WebAppStat>    currentLocal                   = new ThreadLocal<WebAppStat>();
  42
  43    private volatile int                            maxStatUriCount                = DEFAULT_MAX_STAT_URI_COUNT;
  44    private volatile int                            maxStatSessionCount            = DEFAULT_MAX_STAT_SESSION_COUNT;
  45
  46    private final AtomicInteger                     runningCount                   = new AtomicInteger();
  47    private final AtomicInteger                     concurrentMax                  = new AtomicInteger();
  48    private final AtomicLong                        requestCount                   = new AtomicLong(0);
  49    private final AtomicLong                        sessionCount                   = new AtomicLong(0);
  50
  51    private final AtomicLong                        jdbcFetchRowCount              = new AtomicLong();
  52    private final AtomicLong                        jdbcUpdateCount                = new AtomicLong();
  53    private final AtomicLong                        jdbcExecuteCount               = new AtomicLong();
  54    private final AtomicLong                        jdbcExecuteTimeNano            = new AtomicLong();
  55
  56    private final AtomicLong                        jdbcCommitCount                = new AtomicLong();
  57    private final AtomicLong                        jdbcRollbackCount              = new AtomicLong();
  58
  59    private final ConcurrentMap<String, WebURIStat> uriStatMap                     = new ConcurrentHashMap<String, WebURIStat>(16, 0.75f, 1);
  60    private final LRUCache<String, WebSessionStat>  sessionStatMap;
  61
  62    private final ReadWriteLock                     sessionStatLock                = new ReentrantReadWriteLock();
  63
  64    private final AtomicLong                        uriStatMapFullCount            = new AtomicLong();
  65    private final AtomicLong                        uriSessionMapFullCount         = new AtomicLong();
  66
  67    private final AtomicLong                        osMacOSXCount                  = new AtomicLong(0);
  68    private final AtomicLong                        osWindowsCount                 = new AtomicLong(0);
  69    private final AtomicLong                        osLinuxCount                   = new AtomicLong(0);
  70    private final AtomicLong                        osSymbianCount                 = new AtomicLong(0);
  71    private final AtomicLong                        osFreeBSDCount                 = new AtomicLong(0);
  72    private final AtomicLong                        osOpenBSDCount                 = new AtomicLong(0);
  73    private final AtomicLong                        osAndroidCount                 = new AtomicLong(0);
  74
  75    private final AtomicLong                        osWindows98Count               = new AtomicLong();
  76    private final AtomicLong                        osWindowsXPCount               = new AtomicLong();
  77    private final AtomicLong                        osWindows2000Count             = new AtomicLong();
  78    private final AtomicLong                        osWindowsVistaCount            = new AtomicLong();
  79    private final AtomicLong                        osWindows7Count                = new AtomicLong();
  80
  81    private final AtomicLong                        osAndroid15Count               = new AtomicLong(0);
  82    private final AtomicLong                        osAndroid16Count               = new AtomicLong(0);
  83    private final AtomicLong                        osAndroid20Count               = new AtomicLong(0);
  84    private final AtomicLong                        osAndroid21Count               = new AtomicLong(0);
  85    private final AtomicLong                        osAndroid22Count               = new AtomicLong(0);
  86    private final AtomicLong                        osAndroid23Count               = new AtomicLong(0);
  87    private final AtomicLong                        osAndroid30Count               = new AtomicLong(0);
  88    private final AtomicLong                        osAndroid31Count               = new AtomicLong(0);
  89    private final AtomicLong                        osAndroid32Count               = new AtomicLong(0);
  90    private final AtomicLong                        osAndroid40Count               = new AtomicLong(0);
  91
  92    private final AtomicLong                        osLinuxUbuntuCount             = new AtomicLong(0);
  93
  94    private final AtomicLong                        browserIECount                 = new AtomicLong(0);
  95    private final AtomicLong                        browserFirefoxCount            = new AtomicLong(0);
  96    private final AtomicLong                        browserChromeCount             = new AtomicLong(0);
  97    private final AtomicLong                        browserSafariCount             = new AtomicLong(0);
  98    private final AtomicLong                        browserOperaCount              = new AtomicLong(0);
  99
 100    private final AtomicLong                        browserIE5Count                = new AtomicLong(0);
 101    private final AtomicLong                        browserIE6Count                = new AtomicLong(0);
 102    private final AtomicLong                        browserIE7Count                = new AtomicLong(0);
 103    private final AtomicLong                        browserIE8Count                = new AtomicLong(0);
 104    private final AtomicLong                        browserIE9Count                = new AtomicLong(0);
 105    private final AtomicLong                        browserIE10Count               = new AtomicLong(0);
 106
 107    private final AtomicLong                        browser360SECount              = new AtomicLong(0);
 108
 109    private final AtomicLong                        deviceAndroidCount             = new AtomicLong(0);
 110    private final AtomicLong                        deviceIpadCount                = new AtomicLong(0);
 111    private final AtomicLong                        deviceIphoneCount              = new AtomicLong(0);
 112    private final AtomicLong                        deviceWindowsPhoneCount        = new AtomicLong(0);
 113
 114    private final AtomicLong                        botCount                       = new AtomicLong();
 115    private final AtomicLong                        botBaiduCount                  = new AtomicLong();
 116    private final AtomicLong                        botYoudaoCount                 = new AtomicLong();
 117    private final AtomicLong                        botGoogleCount                 = new AtomicLong();
 118    private final AtomicLong                        botMsnCount                    = new AtomicLong();
 119    private final AtomicLong                        botBingCount                   = new AtomicLong();
 120    private final AtomicLong                        botSosoCount                   = new AtomicLong();
 121    private final AtomicLong                        botSogouCount                  = new AtomicLong();
 122    private final AtomicLong                        botYahooCount                  = new AtomicLong();
 123
 124    private String                                  contextPath;
 125
 126    public static WebAppStat current() {
 127        return currentLocal.get();
 128    }
 129
 130    public void reset() {
 131        concurrentMax.set(0);
 132        requestCount.set(0);
 133        requestCount.set(0);
 134        sessionCount.set(0);
 135        
 136        jdbcFetchRowCount.set(0);
 137        jdbcUpdateCount.set(0);
 138        jdbcExecuteCount.set(0);
 139        jdbcExecuteTimeNano.set(0);
 140        jdbcCommitCount.set(0);
 141        jdbcRollbackCount.set(0);
 142
 143        sessionStatLock.readLock().lock();
 144        try {
 145            Iterator<Map.Entry<String, WebSessionStat>> iter = sessionStatMap.entrySet().iterator();
 146            while (iter.hasNext()) {
 147                Map.Entry<String, WebSessionStat> entry = iter.next();
 148                entry.getValue().reset();
 149            }
 150            sessionStatMap.clear();
 151        } finally {
 152            sessionStatLock.readLock().unlock();
 153        }
 154
 155        uriStatMap.clear();
 156
 157        uriStatMapFullCount.set(0);
 158        uriSessionMapFullCount.set(0);
 159
 160        osMacOSXCount.set(0);
 161        osWindowsCount.set(0);
 162        osLinuxCount.set(0);
 163        osSymbianCount.set(0);
 164        osOpenBSDCount.set(0);
 165        osFreeBSDCount.set(0);
 166        osAndroidCount.set(0);
 167
 168        osWindows98Count.set(0);
 169        osWindowsXPCount.set(0);
 170        osWindows2000Count.set(0);
 171        osWindowsVistaCount.set(0);
 172        osWindows7Count.set(0);
 173
 174        osLinuxUbuntuCount.set(0);
 175
 176        osAndroid15Count.set(0);
 177        osAndroid16Count.set(0);
 178        osAndroid20Count.set(0);
 179        osAndroid21Count.set(0);
 180        osAndroid22Count.set(0);
 181        osAndroid23Count.set(0);
 182        osAndroid30Count.set(0);
 183        osAndroid31Count.set(0);
 184        osAndroid32Count.set(0);
 185        osAndroid40Count.set(0);
 186
 187        browserIE6Count.set(0);
 188        browserIE7Count.set(0);
 189        browserIE8Count.set(0);
 190        browserIE9Count.set(0);
 191        browserIE10Count.set(0);
 192
 193        browserIECount.set(0);
 194        browserFirefoxCount.set(0);
 195        browserChromeCount.set(0);
 196        browserSafariCount.set(0);
 197        browserOperaCount.set(0);
 198
 199        browser360SECount.set(0);
 200
 201        deviceAndroidCount.set(0);
 202        deviceIpadCount.set(0);
 203        deviceIphoneCount.set(0);
 204        deviceWindowsPhoneCount.set(0);
 205    }
 206
 207    public WebAppStat(){
 208        this(null);
 209    }
 210
 211    public WebAppStat(String contextPath){
 212        this(contextPath, DEFAULT_MAX_STAT_SESSION_COUNT);
 213    }
 214
 215    public WebAppStat(String contextPath, int maxStatSessionCount){
 216        this.contextPath = contextPath;
 217        this.maxStatSessionCount = maxStatSessionCount;
 218
 219        sessionStatMap = new LRUCache<String, WebSessionStat>(maxStatSessionCount);
 220    }
 221
 222    public String getContextPath() {
 223        return contextPath;
 224    }
 225
 226    public void beforeInvoke() {
 227        currentLocal.set(this);
 228
 229        int running = runningCount.incrementAndGet();
 230
 231        for (;;) {
 232            int max = concurrentMax.get();
 233            if (running > max) {
 234                if (concurrentMax.compareAndSet(max, running)) {
 235                    break;
 236                } else {
 237                    continue;
 238                }
 239            } else {
 240                break;
 241            }
 242        }
 243
 244        requestCount.incrementAndGet();
 245    }
 246
 247    public WebURIStat getURIStat(String uri) {
 248        return getURIStat(uri, false);
 249    }
 250
 251    public WebURIStat getURIStat(String uri, boolean create) {
 252        WebURIStat uriStat = uriStatMap.get(uri);
 253
 254        if (uriStat != null) {
 255            return uriStat;
 256        }
 257
 258        if (!create) {
 259            return null;
 260        }
 261
 262        if (uriStatMap.size() >= this.getMaxStatUriCount()) {
 263            long fullCount = uriStatMapFullCount.getAndIncrement();
 264
 265            if (fullCount == 0) {
 266                LOG.error("uriSessionMapFullCount is full");
 267            }
 268
 269            return null;
 270        }
 271
 272        if (uriStat == null) {
 273            uriStatMap.putIfAbsent(uri, new WebURIStat(uri));
 274            uriStat = uriStatMap.get(uri);
 275        }
 276
 277        return uriStat;
 278    }
 279
 280    public WebSessionStat getSessionStat(String sessionId) {
 281        return getSessionStat(sessionId, false);
 282    }
 283
 284    public Map<String, Object> getSessionStatData(String sessionId) {
 285        WebSessionStat sessionStat = sessionStatMap.get(sessionId);
 286
 287        if (sessionStat == null) {
 288            return null;
 289        }
 290
 291        return sessionStat.getStatData();
 292    }
 293
 294    public Map<String, Object> getURIStatData(String uri) {
 295        WebURIStat uriStat = getURIStat(uri);
 296
 297        if (uriStat == null) {
 298            return null;
 299        }
 300
 301        return uriStat.getStatData();
 302    }
 303
 304    public WebSessionStat getSessionStat(String sessionId, boolean create) {
 305        sessionStatLock.readLock().lock();
 306        try {
 307            WebSessionStat uriStat = sessionStatMap.get(sessionId);
 308
 309            if (uriStat != null) {
 310                return uriStat;
 311            }
 312        } finally {
 313            sessionStatLock.readLock().unlock();
 314        }
 315
 316        if (!create) {
 317            return null;
 318        }
 319
 320        sessionStatLock.writeLock().lock();
 321        try {
 322            WebSessionStat uriStat = sessionStatMap.get(sessionId);
 323
 324            if (uriStat == null) {
 325                if (sessionStatMap.size() >= this.getMaxStatSessionCount()) {
 326                    long fullCount = uriSessionMapFullCount.getAndIncrement();
 327
 328                    if (fullCount == 0) {
 329                        LOG.error("sessionStatMap is full");
 330                    }
 331                }
 332
 333                WebSessionStat newStat = new WebSessionStat(sessionId);
 334
 335                sessionStatMap.put(sessionId, newStat);
 336
 337                return newStat;
 338            }
 339
 340            return uriStat;
 341        } finally {
 342            sessionStatLock.writeLock().unlock();
 343        }
 344    }
 345
 346    public void afterInvoke(Throwable error, long nanoSpan) {
 347        runningCount.decrementAndGet();
 348        currentLocal.set(null);
 349        
 350        WebRequestStat requestStat = WebRequestStat.current();
 351        if (requestStat != null) {
 352            this.addJdbcExecuteCount(requestStat.getJdbcExecuteCount());
 353            this.addJdbcFetchRowCount(requestStat.getJdbcFetchRowCount());
 354            this.addJdbcUpdateCount(requestStat.getJdbcUpdateCount());
 355            this.addJdbcCommitCount(requestStat.getJdbcCommitCount());
 356            this.addJdbcRollbackCount(requestStat.getJdbcRollbackCount());
 357            this.addJdbcExecuteTimeNano(requestStat.getJdbcExecuteTimeNano());
 358        }
 359    }
 360    
 361    public void incrementSessionCount() {
 362        sessionCount.incrementAndGet();
 363    }
 364    
 365    public long getSessionCount() {
 366        return sessionCount.get();
 367    }
 368    
 369    public void addJdbcFetchRowCount(long delta) {
 370        this.jdbcFetchRowCount.addAndGet(delta);
 371    }
 372
 373    public long getJdbcFetchRowCount() {
 374        return jdbcFetchRowCount.get();
 375    }
 376
 377    public void addJdbcUpdateCount(long updateCount) {
 378        this.jdbcUpdateCount.addAndGet(updateCount);
 379    }
 380
 381    public long getJdbcUpdateCount() {
 382        return jdbcUpdateCount.get();
 383    }
 384
 385    public void incrementJdbcExecuteCount() {
 386        jdbcExecuteCount.incrementAndGet();
 387    }
 388
 389    public void addJdbcExecuteCount(long executeCount) {
 390        jdbcExecuteCount.addAndGet(executeCount);
 391    }
 392
 393    public long getJdbcExecuteCount() {
 394        return jdbcExecuteCount.get();
 395    }
 396
 397    public long getJdbcExecuteTimeMillis() {
 398        return getJdbcExecuteTimeNano() / (1000 * 1000);
 399    }
 400
 401    public long getJdbcExecuteTimeNano() {
 402        return jdbcExecuteTimeNano.get();
 403    }
 404
 405    public void addJdbcExecuteTimeNano(long nano) {
 406        jdbcExecuteTimeNano.addAndGet(nano);
 407    }
 408
 409    public void incrementJdbcCommitCount() {
 410        jdbcCommitCount.incrementAndGet();
 411    }
 412
 413    public long getJdbcCommitCount() {
 414        return jdbcCommitCount.get();
 415    }
 416
 417    public void addJdbcCommitCount(long commitCount) {
 418        this.jdbcCommitCount.addAndGet(commitCount);
 419    }
 420
 421    public void incrementJdbcRollbackCount() {
 422        jdbcRollbackCount.incrementAndGet();
 423    }
 424
 425    public long getJdbcRollbackCount() {
 426        return jdbcRollbackCount.get();
 427    }
 428
 429    public void addJdbcRollbackCount(long rollbackCount) {
 430        this.jdbcRollbackCount.addAndGet(rollbackCount);
 431    }
 432
 433    public int getMaxStatUriCount() {
 434        return maxStatUriCount;
 435    }
 436
 437    public void setMaxStatUriCount(int maxStatUriCount) {
 438        this.maxStatUriCount = maxStatUriCount;
 439    }
 440
 441    public int getMaxStatSessionCount() {
 442        return maxStatSessionCount;
 443    }
 444
 445    public void setMaxStatSessionCount(int maxStatSessionCount) {
 446        this.maxStatSessionCount = maxStatSessionCount;
 447    }
 448
 449    public int getRunningCount() {
 450        return this.runningCount.get();
 451    }
 452
 453    public long getConcurrentMax() {
 454        return concurrentMax.get();
 455    }
 456
 457    public long getRequestCount() {
 458        return requestCount.get();
 459    }
 460
 461    public Map<String, Object> getStatData() {
 462        Map<String, Object> data = new LinkedHashMap<String, Object>();
 463
 464        data.put("ContextPath", this.getContextPath());
 465        data.put("RunningCount", this.getRunningCount());
 466        data.put("ConcurrentMax", this.getConcurrentMax());
 467        data.put("RequestCount", this.getRequestCount());
 468        data.put("SessionCount", this.getSessionCount());
 469        
 470        data.put("JdbcCommitCount", this.getJdbcCommitCount());
 471        data.put("JdbcRollbackCount", this.getJdbcRollbackCount());
 472
 473        data.put("JdbcExecuteCount", this.getJdbcExecuteCount());
 474        data.put("JdbcExecuteTimeMillis", this.getJdbcExecuteTimeMillis());
 475        data.put("JdbcFetchRowCount", this.getJdbcFetchRowCount());
 476        data.put("JdbcUpdateCount", this.getJdbcUpdateCount());
 477
 478        data.put("OSMacOSXCount", this.getOSMacOSXCount());
 479        data.put("OSWindowsCount", this.getOSWindowsCount());
 480        data.put("OSLinuxCount", this.getOSLinuxCount());
 481        data.put("OSSymbianCount", this.getOSSymbianCount());
 482        data.put("OSFreeBSDCount", this.getOSFreeBSDCount());
 483        data.put("OSOpenBSDCount", this.getOSOpenBSDCount());
 484        data.put("OSAndroidCount", this.getOSAndroidCount());
 485        data.put("OSWindows98Count", this.getOSWindows98Count());
 486        data.put("OSWindowsXPCount", this.getOSWindowsXPCount());
 487        data.put("OSWindows2000Count", this.getOSWindows2000Count());
 488        data.put("OSWindowsVistaCount", this.getOSWindowsVistaCount());
 489        data.put("OSWindows7Count", this.getOSWindows7Count());
 490
 491        data.put("OSAndroid15Count", this.getOSAndroid15Count());
 492        data.put("OSAndroid16Count", this.getOSAndroid16Count());
 493        data.put("OSAndroid20Count", this.getOSAndroid20Count());
 494        data.put("OSAndroid21Count", this.getOSAndroid21Count());
 495        data.put("OSAndroid22Count", this.getOSAndroid22Count());
 496        data.put("OSAndroid23Count", this.getOSAndroid23Count());
 497        data.put("OSAndroid30Count", this.getOSAndroid30Count());
 498        data.put("OSAndroid31Count", this.getOSAndroid31Count());
 499        data.put("OSAndroid32Count", this.getOSAndroid32Count());
 500        data.put("OSAndroid40Count", this.getOSAndroid40Count());
 501        data.put("OSLinuxUbuntuCount", this.getOSLinuxUbuntuCount());
 502
 503        data.put("BrowserIECount", this.getBrowserIECount());
 504        data.put("BrowserFirefoxCount", this.getBrowserFirefoxCount());
 505        data.put("BrowserChromeCount", this.getBrowserChromeCount());
 506        data.put("BrowserSafariCount", this.getBrowserSafariCount());
 507        data.put("BrowserOperaCount", this.getBrowserOperaCount());
 508
 509        data.put("BrowserIE5Count", this.getBrowserIE5Count());
 510        data.put("BrowserIE6Count", this.getBrowserIE6Count());
 511        data.put("BrowserIE7Count", this.getBrowserIE7Count());
 512        data.put("BrowserIE8Count", this.getBrowserIE8Count());
 513        data.put("BrowserIE9Count", this.getBrowserIE9Count());
 514        data.put("BrowserIE10Count", this.getBrowserIE10Count());
 515
 516        data.put("Browser360SECount", this.getBrowser360SECount());
 517        data.put("DeviceAndroidCount", this.getDeviceAndroidCount());
 518        data.put("DeviceIpadCount", this.getDeviceIpadCount());
 519        data.put("DeviceIphoneCount", this.getDeviceIphoneCount());
 520        data.put("DeviceWindowsPhoneCount", this.getDeviceWindowsPhoneCount());
 521
 522        data.put("BotCount", this.getBotCount());
 523        data.put("BotBaiduCount", this.getBotBaiduCount());
 524        data.put("BotYoudaoCount", this.getBotYoudaoCount());
 525        data.put("BotGoogleCount", this.getBotGoogleCount());
 526        data.put("BotMsnCount", this.getBotMsnCount());
 527        data.put("BotBingCount", this.getBotBingCount());
 528        data.put("BotSosoCount", this.getBotSosoCount());
 529        data.put("BotSogouCount", this.getBotSogouCount());
 530        data.put("BotYahooCount", this.getBotYahooCount());
 531
 532        return data;
 533    }
 534
 535    public List<Map<String, Object>> getURIStatDataList() {
 536        List<Map<String, Object>> uriStatDataList = new ArrayList<Map<String, Object>>(this.uriStatMap.size());
 537        for (WebURIStat uriStat : this.uriStatMap.values()) {
 538            Map<String, Object> uriStatData = uriStat.getStatData();
 539
 540            int runningCount = ((Number) uriStatData.get("RunningCount")).intValue();
 541            long requestCount = (Long) uriStatData.get("RequestCount");
 542
 543            if (runningCount == 0 && requestCount == 0) {
 544                continue;
 545            }
 546
 547            uriStatDataList.add(uriStatData);
 548        }
 549        return uriStatDataList;
 550    }
 551
 552    public List<Map<String, Object>> getSessionStatDataList() {
 553        List<Map<String, Object>> uriStatDataList = new ArrayList<Map<String, Object>>(this.sessionStatMap.size());
 554        for (WebSessionStat sessionStat : this.sessionStatMap.values()) {
 555            Map<String, Object> sessionStatData = sessionStat.getStatData();
 556
 557            int runningCount = ((Number) sessionStatData.get("RunningCount")).intValue();
 558            long requestCount = (Long) sessionStatData.get("RequestCount");
 559
 560            if (runningCount == 0 && requestCount == 0) {
 561                continue;
 562            }
 563
 564            uriStatDataList.add(sessionStatData);
 565        }
 566        return uriStatDataList;
 567    }
 568
 569    public void computeUserAgent(String userAgent) {
 570        if (userAgent == null || userAgent.length() == 0) {
 571            return;
 572        }
 573
 574        // Mozilla/5.0 (compatible;
 575        final int MOZILLA_COMPATIBLE_OFFSET = 25;
 576
 577        boolean is360SE = userAgent.endsWith("360SE)");
 578
 579        if (is360SE) {
 580            browser360SECount.incrementAndGet();
 581        }
 582
 583        boolean isIE = userAgent.startsWith("MSIE", MOZILLA_COMPATIBLE_OFFSET);
 584        int iePrefixIndex = 30; // "Mozilla/5.0 (compatible; MSIE ".length();
 585
 586        boolean isGoogleToolbar = false;
 587
 588        if (!isIE) {
 589            isGoogleToolbar = userAgent.startsWith("GoogleToolbar", MOZILLA_COMPATIBLE_OFFSET);
 590            if (isGoogleToolbar) {
 591                // MSIE
 592                int tmp = userAgent.indexOf("IE ");
 593                if (tmp != -1) {
 594                    isIE = true;
 595                    iePrefixIndex = tmp + 3;
 596                }
 597            }
 598        }
 599
 600        if (isIE) {
 601
 602            browserIECount.incrementAndGet();
 603
 604            char v1 = ' ', v2 = ' ';
 605            if (userAgent.length() > iePrefixIndex + 1) {
 606                v1 = userAgent.charAt(iePrefixIndex);
 607                v2 = userAgent.charAt(iePrefixIndex + 1);
 608            } else if (userAgent.length() > iePrefixIndex) {
 609                v1 = userAgent.charAt(iePrefixIndex);
 610            }
 611
 612            switch (v1) {
 613                case '5':
 614                    browserIE5Count.incrementAndGet();
 615                    break;
 616                case '6':
 617                    browserIE6Count.incrementAndGet();
 618                    break;
 619                case '7':
 620                    browserIE7Count.incrementAndGet();
 621                    break;
 622                case '8':
 623                    browserIE8Count.incrementAndGet();
 624                    break;
 625                case '9':
 626                    browserIE9Count.incrementAndGet();
 627                    break;
 628                case '1':
 629                    if (v2 == '0') {
 630                        browserIE10Count.incrementAndGet();
 631                    }
 632                    break;
 633                default:
 634                    break;
 635            }
 636
 637            osWindowsCount.incrementAndGet();
 638
 639            computeUserAgentIEWindowsVersion(userAgent);
 640
 641            if (userAgent.indexOf("Windows Phone") != -1) {
 642                deviceWindowsPhoneCount.incrementAndGet();
 643            }
 644
 645            return;
 646        }
 647
 648        boolean isWindows = false;
 649        boolean isMac = false;
 650        boolean isIpad = false;
 651        boolean isIPhone = false;
 652        boolean isLinux = false;
 653        boolean isX11 = false;
 654        boolean isBSD = false;
 655
 656        if (userAgent.startsWith("Windows", 13)) {
 657            isWindows = true;
 658        } else if (userAgent.startsWith("Macintosh", 13)) {
 659            isMac = true;
 660        } else if (userAgent.startsWith("iPad", 13)) {
 661            isIpad = true;
 662            isMac = true;
 663        } else if (userAgent.startsWith("iPhone", 13)) {
 664            isIPhone = true;
 665            isMac = true;
 666        } else if (userAgent.startsWith("Linux", 13)) {
 667            isLinux = true;
 668        } else if (userAgent.startsWith("X11", 13)) {
 669            isX11 = true;
 670        }
 671
 672        boolean isAndroid = false;
 673
 674        if (isWindows) {
 675            isWindows = true;
 676
 677            osWindowsCount.incrementAndGet();
 678
 679            if (userAgent.indexOf("Windows Phone") != -1) {
 680                deviceWindowsPhoneCount.incrementAndGet();
 681            }
 682        } else if (isMac) {
 683            isMac = true;
 684            osMacOSXCount.incrementAndGet();
 685            if (isIpad && userAgent.indexOf("iPad") != -1) {
 686                deviceIpadCount.incrementAndGet();
 687            } else if (isIPhone || userAgent.indexOf("iPhone") != -1) {
 688                deviceIphoneCount.incrementAndGet();
 689            }
 690        } else if (isLinux) {
 691            osLinuxCount.incrementAndGet();
 692
 693            isAndroid = computeUserAgentAndroid(userAgent);
 694        } else if (userAgent.indexOf("Symbian") != -1) {
 695            osSymbianCount.incrementAndGet();
 696        } else if (userAgent.indexOf("Ubuntu") != -1) {
 697            osLinuxCount.incrementAndGet();
 698            osLinuxUbuntuCount.incrementAndGet();
 699            isLinux = true;
 700        }
 701
 702        if (isX11) {
 703            if (userAgent.indexOf("OpenBSD") != -1) {
 704                osOpenBSDCount.incrementAndGet();
 705                isBSD = true;
 706            } else if (userAgent.indexOf("FreeBSD") != -1) {
 707                osFreeBSDCount.incrementAndGet();
 708                isBSD = true;
 709            } else if ((!isLinux) && userAgent.indexOf("Linux") != -1) {
 710                osLinuxCount.incrementAndGet();
 711                isLinux = true;
 712            }
 713        }
 714
 715        boolean isOpera = userAgent.startsWith("Opera");
 716
 717        if (isOpera) {
 718            if (userAgent.indexOf("Windows") != -1) {
 719                osWindowsCount.incrementAndGet();
 720            } else if (userAgent.indexOf("Linux") != -1) {
 721                osWindowsCount.incrementAndGet();
 722            } else if (userAgent.indexOf("Macintosh") != -1) {
 723                osMacOSXCount.incrementAndGet();
 724            }
 725            browserOperaCount.incrementAndGet();
 726            return;
 727        }
 728
 729        if (isWindows) {
 730            computeUserAgentFirefoxWindowsVersion(userAgent);
 731        }
 732
 733        if (isWindows || isMac || isLinux || isBSD) {
 734            if (userAgent.indexOf("Chrome") != -1) {
 735                browserChromeCount.incrementAndGet();
 736                return;
 737            }
 738
 739            if ((!isAndroid) && userAgent.indexOf("Safari") != -1) {
 740                browserSafariCount.incrementAndGet();
 741                return;
 742            }
 743
 744            if (userAgent.indexOf("Firefox") != -1) {
 745                browserFirefoxCount.incrementAndGet();
 746                return;
 747            }
 748        }
 749
 750        if (userAgent.startsWith("User-Agent: ")) {
 751            String rest = userAgent.substring("User-Agent: ".length());
 752            computeUserAgent(rest);
 753        }
 754
 755        boolean isJava = userAgent.startsWith("Java");
 756
 757        if (isJava) {
 758            botCount.incrementAndGet();
 759        }
 760
 761        if (userAgent.startsWith("msnbot")) {
 762            botCount.incrementAndGet();
 763            botMsnCount.incrementAndGet();
 764        } else if (userAgent.startsWith("Sosospider+")) {
 765            botCount.incrementAndGet();
 766            botSosoCount.incrementAndGet();
 767        } else if (userAgent.startsWith("Sogou")) {
 768            botCount.incrementAndGet();
 769            botSogouCount.incrementAndGet();
 770        } else if (userAgent.startsWith("HuaweiSymantecSpider")) {
 771            botCount.incrementAndGet();
 772        } else if (userAgent.startsWith("Yeti/")) {
 773            botCount.incrementAndGet();
 774        } else if (userAgent.startsWith("mahonie")) {
 775            botCount.incrementAndGet();
 776        } else if (userAgent.startsWith("findlinks")) {
 777            botCount.incrementAndGet();
 778        } else if (userAgent.startsWith("Updownerbot")) {
 779            botCount.incrementAndGet();
 780        } else if (userAgent.startsWith("DoCoMo/")) {
 781            botCount.incrementAndGet();
 782        } else if (userAgent.startsWith("Crawl")) {
 783            botCount.incrementAndGet();
 784        } else if (userAgent.startsWith("SkimBot")) {
 785            botCount.incrementAndGet();
 786
 787        } else if (userAgent.startsWith("YoudaoBot", MOZILLA_COMPATIBLE_OFFSET)) {
 788            botCount.incrementAndGet();
 789            botYoudaoCount.incrementAndGet();
 790        } else if (userAgent.startsWith("bingbot", MOZILLA_COMPATIBLE_OFFSET)) {
 791            botCount.incrementAndGet();
 792            botBingCount.incrementAndGet();
 793        } else if (userAgent.startsWith("Googlebot", MOZILLA_COMPATIBLE_OFFSET)) {
 794            botCount.incrementAndGet();
 795            botGoogleCount.incrementAndGet();
 796        } else if (userAgent.startsWith("Baiduspider", MOZILLA_COMPATIBLE_OFFSET)) {
 797            botCount.incrementAndGet();
 798            botBaiduCount.incrementAndGet();
 799        } else if (userAgent.startsWith("MJ12bot", MOZILLA_COMPATIBLE_OFFSET)) {
 800            botCount.incrementAndGet();
 801            botBaiduCount.incrementAndGet();
 802        } else if (userAgent.startsWith("Mail.RU/", MOZILLA_COMPATIBLE_OFFSET)) {
 803            botCount.incrementAndGet();
 804        } else if (userAgent.startsWith("Yahoo!", MOZILLA_COMPATIBLE_OFFSET)) {
 805            botCount.incrementAndGet();
 806            botYahooCount.incrementAndGet();
 807        } else if (userAgent.startsWith("KaloogaBot", MOZILLA_COMPATIBLE_OFFSET)) {
 808            botCount.incrementAndGet();
 809        } else if (userAgent.startsWith("YandexBot", MOZILLA_COMPATIBLE_OFFSET)) {
 810            botCount.incrementAndGet();
 811        } else if (userAgent.startsWith("Ezooms/", MOZILLA_COMPATIBLE_OFFSET)) {
 812            botCount.incrementAndGet();
 813        } else if (userAgent.startsWith("Exabot/", MOZILLA_COMPATIBLE_OFFSET)) {
 814            botCount.incrementAndGet();
 815        } else if (userAgent.startsWith("AhrefsBot/", MOZILLA_COMPATIBLE_OFFSET)) {
 816            botCount.incrementAndGet();
 817        } else if (userAgent.startsWith("YodaoBot/", MOZILLA_COMPATIBLE_OFFSET)) {
 818            botCount.incrementAndGet();
 819        } else if (userAgent.startsWith("BeetleBot", MOZILLA_COMPATIBLE_OFFSET)) {
 820            botCount.incrementAndGet();
 821        } else if (userAgent.startsWith("archive.org_bot", MOZILLA_COMPATIBLE_OFFSET)) {
 822            botCount.incrementAndGet();
 823        } else if (userAgent.startsWith("aiHitBot", MOZILLA_COMPATIBLE_OFFSET)) {
 824            botCount.incrementAndGet();
 825        } else if (userAgent.startsWith("EventGuruBot", MOZILLA_COMPATIBLE_OFFSET)) {
 826            botCount.incrementAndGet();
 827
 828        } else if (userAgent.equals("Mozilla/5.0 ()")) {
 829            botCount.incrementAndGet();
 830        } else if (userAgent.equals("\"Mozilla/5.0")) {
 831            botCount.incrementAndGet();
 832        } else if (userAgent.equals("Mozilla")) {
 833            botCount.incrementAndGet();
 834        } else if (userAgent.equals("-")) {
 835            botCount.incrementAndGet();
 836        } else if (userAgent.indexOf("Spider") != -1 || userAgent.indexOf("spider") != -1) {
 837            botCount.incrementAndGet();
 838        } else if (userAgent.indexOf("crawl") != -1 || userAgent.indexOf("Crawl") != -1) {
 839            botCount.incrementAndGet();
 840        } else if (userAgent.indexOf("Bot") != -1 || userAgent.indexOf("bot") != -1) {
 841            botCount.incrementAndGet();
 842        }
 843
 844        // Mozilla/5.0 ()
 845        // Mozilla/5.0 (compatible; Mail.RU/2.0)
 846        // Mozilla/5.0 (compatible; bingbot/2.0;
 847        // YoudaoBot
 848
 849    }
 850
 851    private void computeUserAgentFirefoxWindowsVersion(String userAgent) {
 852        if (userAgent.startsWith("Windows NT 5.1", 13)) {
 853            osWindowsXPCount.incrementAndGet();
 854        } else if (userAgent.startsWith("Windows NT 5.1", 25)) {
 855            osWindowsXPCount.incrementAndGet();
 856
 857        } else if (userAgent.startsWith("Windows NT 6.0", 13)) {
 858            osWindowsVistaCount.incrementAndGet();
 859
 860        } else if (userAgent.startsWith("Windows NT 6.1", 13)) {
 861            osWindows7Count.incrementAndGet();
 862
 863        } else if (userAgent.startsWith("Windows NT 5.0", 13)) {
 864            osWindows2000Count.incrementAndGet();
 865        } else if (userAgent.startsWith("Windows NT 5.0", 25)) {
 866            osWindows2000Count.incrementAndGet();
 867        }
 868    }
 869
 870    private void computeUserAgentIEWindowsVersion(String userAgent) {
 871        if (userAgent.startsWith("Windows NT 5.1", 35)) {
 872            osWindowsXPCount.incrementAndGet();
 873        } else if (userAgent.startsWith("Windows NT 5.0", 35)) {
 874            osWindows2000Count.incrementAndGet();
 875        } else if (userAgent.startsWith("Windows NT 5.0", 36)) {
 876            osWindows2000Count.incrementAndGet();
 877        } else if (userAgent.startsWith("Windows NT 6.0", 35)) {
 878            osWindowsVistaCount.incrementAndGet();
 879        } else if (userAgent.startsWith("Windows NT 6.1", 35)) {
 880            osWindows7Count.incrementAndGet();
 881        } else if (userAgent.startsWith("Windows 98", 36)) {
 882            osWindows98Count.incrementAndGet();
 883        } else if (userAgent.startsWith("Windows 98", 35)) {
 884            osWindows98Count.incrementAndGet();
 885        } else if (userAgent.startsWith("Windows XP", 35)) {
 886            osWindowsXPCount.incrementAndGet();
 887        } else if (userAgent.startsWith("Windows XP", 34)) {
 888            osWindowsXPCount.incrementAndGet();
 889        }
 890    }
 891
 892    private boolean computeUserAgentAndroid(String userAgent) {
 893        boolean isAndroid = userAgent.startsWith("Android", 23);
 894        if (isAndroid) {
 895            osAndroidCount.incrementAndGet();
 896
 897            deviceAndroidCount.incrementAndGet();
 898
 899            int toffset = 31;
 900            if (userAgent.startsWith("1.5", toffset)) {
 901                osAndroid15Count.incrementAndGet();
 902            } else if (userAgent.startsWith("1.6", toffset)) {
 903                osAndroid16Count.incrementAndGet();
 904            } else if (userAgent.startsWith("2.0", toffset)) {
 905                osAndroid20Count.incrementAndGet();
 906            } else if (userAgent.startsWith("2.1", toffset)) {
 907                osAndroid21Count.incrementAndGet();
 908            } else if (userAgent.startsWith("2.2", toffset)) {
 909                osAndroid22Count.incrementAndGet();
 910            } else if (userAgent.startsWith("2.3.3", toffset)) {
 911                osAndroid23Count.incrementAndGet();
 912            } else if (userAgent.startsWith("2.3.4", toffset)) {
 913                osAndroid23Count.incrementAndGet();
 914            } else if (userAgent.startsWith("3.0", toffset)) {
 915                osAndroid30Count.incrementAndGet();
 916            } else if (userAgent.startsWith("3.1", toffset)) {
 917                osAndroid31Count.incrementAndGet();
 918            } else if (userAgent.startsWith("3.2", toffset)) {
 919                osAndroid32Count.incrementAndGet();
 920            } else if (userAgent.startsWith("4.0", toffset)) {
 921                osAndroid40Count.incrementAndGet();
 922            }
 923
 924            return true;
 925        }
 926
 927        return false;
 928    }
 929
 930    public long getOSMacOSXCount() {
 931        return osMacOSXCount.get();
 932    }
 933
 934    public long getOSWindowsCount() {
 935        return osWindowsCount.get();
 936    }
 937
 938    public long getOSLinuxCount() {
 939        return osLinuxCount.get();
 940    }
 941
 942    public long getOSSymbianCount() {
 943        return osSymbianCount.get();
 944    }
 945
 946    public long getOSFreeBSDCount() {
 947        return osFreeBSDCount.get();
 948    }
 949
 950    public long getOSOpenBSDCount() {
 951        return osOpenBSDCount.get();
 952    }
 953
 954    public long getOSAndroidCount() {
 955        return osAndroidCount.get();
 956    }
 957
 958    public long getOSWindows98Count() {
 959        return osWindows98Count.get();
 960    }
 961
 962    public long getOSWindowsXPCount() {
 963        return osWindowsXPCount.get();
 964    }
 965
 966    public long getOSWindows2000Count() {
 967        return osWindows2000Count.get();
 968    }
 969
 970    public long getOSWindowsVistaCount() {
 971        return osWindowsVistaCount.get();
 972    }
 973
 974    public long getOSWindows7Count() {
 975        return osWindows7Count.get();
 976    }
 977
 978    public long getOSAndroid15Count() {
 979        return osAndroid15Count.get();
 980    }
 981
 982    public long getOSAndroid16Count() {
 983        return osAndroid16Count.get();
 984    }
 985
 986    public long getOSAndroid20Count() {
 987        return osAndroid20Count.get();
 988    }
 989
 990    public long getOSAndroid21Count() {
 991        return osAndroid21Count.get();
 992    }
 993
 994    public long getOSAndroid22Count() {
 995        return osAndroid22Count.get();
 996    }
 997
 998    public long getOSAndroid23Count() {
 999        return osAndroid23Count.get();
1000    }
1001
1002    public long getOSAndroid30Count() {
1003        return osAndroid30Count.get();
1004    }
1005
1006    public long getOSAndroid31Count() {
1007        return osAndroid31Count.get();
1008    }
1009
1010    public long getOSAndroid32Count() {
1011        return osAndroid32Count.get();
1012    }
1013
1014    public long getOSAndroid40Count() {
1015        return osAndroid40Count.get();
1016    }
1017
1018    public long getOSLinuxUbuntuCount() {
1019        return osLinuxUbuntuCount.get();
1020    }
1021
1022    public long getBrowserIECount() {
1023        return browserIECount.get();
1024    }
1025
1026    public long getBrowserFirefoxCount() {
1027        return browserFirefoxCount.get();
1028    }
1029
1030    public long getBrowserChromeCount() {
1031        return browserChromeCount.get();
1032    }
1033
1034    public long getBrowserSafariCount() {
1035        return browserSafariCount.get();
1036    }
1037
1038    public long getBrowserOperaCount() {
1039        return browserOperaCount.get();
1040    }
1041
1042    public long getBrowserIE5Count() {
1043        return browserIE5Count.get();
1044    }
1045
1046    public long getBrowserIE6Count() {
1047        return browserIE6Count.get();
1048    }
1049
1050    public long getBrowserIE7Count() {
1051        return browserIE7Count.get();
1052    }
1053
1054    public long getBrowserIE8Count() {
1055        return browserIE8Count.get();
1056    }
1057
1058    public long getBrowserIE9Count() {
1059        return browserIE9Count.get();
1060    }
1061
1062    public long getBrowserIE10Count() {
1063        return browserIE10Count.get();
1064    }
1065
1066    public long getBrowser360SECount() {
1067        return browser360SECount.get();
1068    }
1069
1070    public long getDeviceAndroidCount() {
1071        return deviceAndroidCount.get();
1072    }
1073
1074    public long getDeviceIpadCount() {
1075        return deviceIpadCount.get();
1076    }
1077
1078    public long getDeviceIphoneCount() {
1079        return deviceIphoneCount.get();
1080    }
1081
1082    public long getDeviceWindowsPhoneCount() {
1083        return deviceWindowsPhoneCount.get();
1084    }
1085
1086    public long getBotCount() {
1087        return botCount.get();
1088    }
1089
1090    public long getBotBaiduCount() {
1091        return botBaiduCount.get();
1092    }
1093
1094    public long getBotYoudaoCount() {
1095        return botYoudaoCount.get();
1096    }
1097
1098    public long getBotGoogleCount() {
1099        return botGoogleCount.get();
1100    }
1101
1102    public long getBotMsnCount() {
1103        return botMsnCount.get();
1104    }
1105
1106    public long getBotBingCount() {
1107        return botBingCount.get();
1108    }
1109
1110    public long getBotSosoCount() {
1111        return botSosoCount.get();
1112    }
1113
1114    public long getBotSogouCount() {
1115        return botSogouCount.get();
1116    }
1117
1118    public long getBotYahooCount() {
1119        return botYahooCount.get();
1120    }
1121
1122}