PageRenderTime 8ms CodeModel.GetById 5ms app.highlight 106ms RepoModel.GetById 1ms app.codeStats 1ms

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

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