@@ -0,0 +1,2848 @@
+/**%0A * Licensed to the Apache Software Foundation (ASF) under one or more%0A * contributor license agreements. See the NOTICE file distributed with this%0A * work for additional information regarding copyright ownership. The ASF%0A * licenses this file to you under the Apache License, Version 2.0 (the%0A * %22License%22); you may not use this file except in compliance with the License.%0A * You may obtain a copy of the License at%0A *%0A * http://www.apache.org/licenses/LICENSE-2.0%0A *%0A * Unless required by applicable law or agreed to in writing, software%0A * distributed under the License is distributed on an %22AS IS%22 BASIS, WITHOUT%0A * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the%0A * License for the specific language governing permissions and limitations under%0A * the License.%0A */%0Apackage org.apache.bookkeeper.stats;%0A%0Aimport org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0A%0A/**%0A * This class is used to raise alert when we detect an event that should never happen in production%0A */%0Apublic class AlertStatsLogger %7B%0A    private static final Logger logger = LoggerFactory.getLogger(AlertStatsLogger.class);%0A%0A    public final String alertStatName;%0A%0A    private final StatsLogger globalStatsLogger;%0A    private final StatsLogger scopedStatsLogger;%0A    private final String scope;%0A    private Counter globalCounter = null;%0A    private Counter scopedCounter = null;%0A%0A    public AlertStatsLogger(StatsLogger globalStatsLogger, String scope, String alertStatName) %7B%0A        this.globalStatsLogger = globalStatsLogger;%0A        this.scope = scope;%0A        this.scopedStatsLogger = globalStatsLogger.scope(scope);%0A        this.alertStatName = alertStatName;%0A    %7D%0A%0A    public AlertStatsLogger(StatsLogger globalStatsLogger, String alertStatName) %7B%0A        this.globalStatsLogger = globalStatsLogger;%0A        this.scope = null;%0A        this.scopedStatsLogger = null;%0A        this.alertStatName = alertStatName;%0A    %7D%0A%0A    private String format(String msg) %7B%0A        return msg.startsWith(%22ALERT!: %22) ? msg :%0A                (%22ALERT!: %22 + (scope != null ? %22(%22 + scope + %22):%22 : %22%22 ) + msg);%0A    %7D%0A%0A    private void initializeCountersIfNeeded() %7B%0A        if (null != globalCounter) %7B%0A            return;%0A        %7D%0A%0A        globalCounter = globalStatsLogger.getCounter(alertStatName);%0A%0A        if (null != scopedStatsLogger) %7B%0A            scopedCounter = scopedStatsLogger.getCounter(alertStatName);%0A        %7D%0A    %7D%0A%0A    /**%0A     * Report an alertable condition%22. Prefixes %22ALERT!: %22 if not already prefixed.%0A     */%0A    public void raise(String msg, Object... args) %7B%0A        initializeCountersIfNeeded();%0A        globalCounter.inc();%0A        if (null != scopedCounter) %7B%0A            scopedCounter.inc();%0A        %7D%0A        logger.error(format(msg), args);%0A        logger.error(%22fake exception to generate stack trace%22, new Exception());%0A    %7D%0A%7D%0A

Introduce the AlertStatsLogger