/* * Tencent is pleased to support the open source community by making * Tencent GT (Version 2.4 and subsequent versions) available. * * Notwithstanding anything to the contrary herein, any previous version * of Tencent GT shall not be subject to the license hereunder. * All right, title, and interest, including all intellectual property rights, * in and to the previous version of Tencent GT (including any and all copies thereof) * shall be owned and retained by Tencent and subject to the license under the * Tencent GT End User License Agreement (http://gt.qq.com/wp-content/EULA_EN.html). * * Copyright (C) 2015 THL A29 Limited, a Tencent company. All rights reserved. * * Licensed under the MIT License (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at * * http://opensource.org/licenses/MIT * * Unless required by applicable law or agreed to in writing, software distributed * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ package com.tencent.wstt.gt.ui.model; import com.tencent.wstt.gt.GTApp; import com.tencent.wstt.gt.activity.GTIntervalSettingActivity; import com.tencent.wstt.gt.api.base.GTLog; import com.tencent.wstt.gt.manager.OpPerfBridge; import com.tencent.wstt.gt.utils.ToastUtil; /** * 阈值对象,随着TagTimeEntry对象的初始化而初始化 * @author yoyoqin * */ public class ThresholdEntry { private TagTimeEntry src; private boolean enable = true; // 本告警自身的开关,单独控制告警是否可用 private int duration = Integer.MAX_VALUE; // 连续超出上限阈值的次数,作为告警 private double upperValue = Integer.MAX_VALUE; // 上限阈值,不能用Double的 private double lowerValue = Integer.MIN_VALUE; // 下限阈值,不能用Double的 private int lastUpperBeginSeq; // 当前记录的下限告警起始序列 private boolean isUpperRecordStarted; // 是否已开始上限告警记录 private int lastLowerBeginSeq; // 当前记录的下限告警起始序列 private boolean isLowerRecordStarted; // 是否已开始下限告警记录 private int durUpperTimes = 0;// 连续超上限的次数 private int durLowerTimes = 0;// 连续超下限的次数 private boolean newWarning; // 是否有新告警,也许应该放在OP类中 private WarningEntry lastestWarning; // 记录了已触发告警的范围 private int upperWariningCount; // 上限告警计数 private int lowerWariningCount; // 下限告警计数 private boolean isToasted; // 对于下限大于上限的告警,只弹出一次提示 private static int UPPER = 0; private static int LOWER = 1; protected ThresholdEntry(TagTimeEntry src) { this.src = src; } public void clear() { upperWariningCount = 0; lowerWariningCount = 0; lastUpperBeginSeq = 0; isLowerRecordStarted = false; lastLowerBeginSeq = 0; isLowerRecordStarted = false; newWarning = false; lastestWarning = null; } private void reset() { duration = Integer.MAX_VALUE; upperValue = Integer.MAX_VALUE; lowerValue = Integer.MIN_VALUE; } public int getUpperWariningCount() { return upperWariningCount; } public int getLowerWariningCount() { return lowerWariningCount; } public int getduration() { if (duration == Integer.MAX_VALUE) { return Integer.MAX_VALUE; } /* * 持续时间需要根据采样率进行转换 * 如果采样率可选的是100,500,1000,5000,10000,可以用简单逻辑 * 不过get这个方法不需要加1 */ int temp = duration * GTIntervalSettingActivity.msecond / 1000; // 如果temp小于0,说明计算中超出MAX_VALUE上限了 return temp > 0 ? temp : Integer.MAX_VALUE; } public double getUpperValue() { return upperValue; } public double getLowerValue() { return lowerValue; } /** * * @param duration * @param upperValue * @param lowerValue * @return */ public boolean setThreshold( int duration, double upperValue, double lowerValue) { if (duration == Integer.MAX_VALUE) // 说明没输入持续时间,直接重置 { clear(); reset(); return false; } // 用户输入的持续时间,需要比数据采样率大,采样率单位是毫秒,最好是整数倍 if (duration * 1000 < GTIntervalSettingActivity.msecond) { return false; } // 持续时间需要根据采样率进行转换 int sampleRate = GTIntervalSettingActivity.msecond; /* * 如果采样率可选的是100,500,1000,5000,10000,可以用简单逻辑 * 否则结果应该加1 */ if (duration * 1000 % sampleRate > 0) { this.duration = duration * 1000 / sampleRate + 1; } else { this.duration = duration * 1000 / sampleRate; } this.upperValue = upperValue; this.lowerValue = lowerValue; /* * 需要重新统计告警,增加告警后通知UI */ lastestWarning = null; upperWariningCount = 0; lowerWariningCount = 0; return true; } public boolean isNewWarning() { return newWarning; } /** * 记录最新一次告警 * @param begin * @param end */ private void recordLastestWaring(int begin, int end, int type, double value) { lastestWarning = new WarningEntry(src, begin, end); OpPerfBridge.getOpWarningManager().add(lastestWarning); String name = src.getParent() == null ? src.name : src.getParent().name + "_" + src.name; if (type == UPPER) { GTLog.logW(name, "Exceeds threshold value:" + value + " upper than " + upperValue); } else if (type == LOWER) { GTLog.logW(name, "Exceeds threshold value:" + value + " lower than " + lowerValue); } } private void judgeToast() { if (upperValue <= lowerValue && !isToasted) { isToasted = true; ToastUtil.ShowLongToast( GTApp.getContext(), "lower value must less than upper value!"); return; } else if (upperValue <= lowerValue && isToasted) { return; } isToasted = false; } /** * 不记录历史数据的情况下统计告警,暂不使用 * @param data */ public void add(long data) { if (!enable) { return; } double realUpperV = upperValue; double realLowerV = lowerValue; judgeToast(); // 上限小于下限会弹一次toast告警 // 需要做数据转换 double d = data / src.getCarry_l2d(); if (d > realUpperV) // 本次数据大于上限阈值 { durUpperTimes++; if (isUpperRecordStarted) // 已开始记录过或持续次数为1 { if (durUpperTimes == duration) // 一次新的告警生成 { // 新告警,如在性能页面,需要在页面刷新后重置告警为false newWarning = true; upperWariningCount++; recordLastestWaring(-1, -1, UPPER , d); } } else if (!isUpperRecordStarted && duration == 1) // 直接记录为一次告警 { isUpperRecordStarted = true; // 新告警,如在性能页面,需要在页面刷新后重置告警为false newWarning = true; upperWariningCount++; recordLastestWaring(-1, -1, UPPER , d); } else // 第一次超上限,需要持续观察 { isUpperRecordStarted = true; } } else if (d < realLowerV) // 本次数据小于下限阈值 { durLowerTimes++; if (isLowerRecordStarted) // 已开始记录过或持续次数为1 { if (durLowerTimes == duration) // 一次新的告警生成 { // 新告警,如在性能页面,需要在页面刷新后重置告警为false newWarning = true; lowerWariningCount++; recordLastestWaring(-1, -1, LOWER , d); } } else if (!isLowerRecordStarted && duration == 1) // 直接记录为一次告警 { isLowerRecordStarted = true; // 新告警,如在性能页面,需要在页面刷新后重置告警为false newWarning = true; lowerWariningCount++; recordLastestWaring(-1, -1, LOWER , d); } else // 第一次超下限,需要持续观察 { isLowerRecordStarted = true; } } else // 阈值内,重置告警 { isUpperRecordStarted = false; lastUpperBeginSeq = -1; isLowerRecordStarted = false; lastLowerBeginSeq = -1; durUpperTimes = 0; durLowerTimes = 0; } } public void add(long data, int seq) { if (!enable) { return; } /* * 这两个值是兼容用户输入的上限值小于下限值设定的 * 但这时只写一个数时不好处理,不知道它是上限还是下限,所以恢复原来逻辑 */ double realUpperV = upperValue; double realLowerV = lowerValue; judgeToast(); // 上限小于下限会弹一次toast告警 // 需要做数据转换 double d = data / src.getCarry_l2d(); if (d > realUpperV) // 本次数据大于上限阈值 { if (isUpperRecordStarted) // 已开始记录过或持续次数为1 { int seqReduce = seq - lastUpperBeginSeq; if (seqReduce > duration && null != lastestWarning) // 持续超出阈值 { // 更新最后一次告警对象(延长告警结束seq为当前seq) lastestWarning.end = seq; } else if (seqReduce == duration) // 一次新的告警生成 { // TODO 新告警,如在性能页面,需要在页面刷新后重置告警为false newWarning = true; upperWariningCount++; recordLastestWaring(lastUpperBeginSeq, seq, UPPER, d); } } else if (!isUpperRecordStarted && duration == 1) // 直接记录为一次告警 { isUpperRecordStarted = true; lastUpperBeginSeq = seq; // TODO 新告警,如在性能页面,需要在页面刷新后重置告警为false newWarning = true; upperWariningCount++; recordLastestWaring(lastUpperBeginSeq, seq, UPPER, d); } else // 第一次超上限,需要持续观察 { isUpperRecordStarted = true; lastUpperBeginSeq = seq; } // 清理下限记录(因为一开始限定了下限不能大于上限) isLowerRecordStarted = false; lastLowerBeginSeq = -1; } else if (d < realLowerV) // 本次数据小于下限阈值 { if (isLowerRecordStarted) { int seqReduce = seq - lastLowerBeginSeq; if (seqReduce > duration && null != lastestWarning) // 持续超出阈值 { // 更新最后一次告警对象(延长告警结束seq为当前seq) lastestWarning.end = seq; } else if (seqReduce == duration) // 一次新的告警生成 { // TODO 新告警,如在性能页面,需要在页面刷新后重置告警为false newWarning = true; lowerWariningCount++; recordLastestWaring(lastLowerBeginSeq, seq, LOWER, d); } } else if (!isLowerRecordStarted && duration == 1) // 直接记录为一次告警 { isLowerRecordStarted = true; lastLowerBeginSeq = seq; // TODO 新告警,如在性能页面,需要在页面刷新后重置告警为false newWarning = true; lowerWariningCount++; recordLastestWaring(lastLowerBeginSeq, seq, LOWER, d); } else // 第一次超下限,需要持续观察 { isLowerRecordStarted = true; lastLowerBeginSeq = seq; } // 清理上限记录(因为一开始限定了下限不能大于上限) isUpperRecordStarted = false; lastUpperBeginSeq = -1; } else // 阈值内,重置告警 { isUpperRecordStarted = false; lastUpperBeginSeq = -1; isLowerRecordStarted = false; lastLowerBeginSeq = -1; } } public boolean isEnable() { return enable; } public void setEnable(boolean enable) { this.enable = enable; if (!enable) { clear(); } } }