All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scouter.server.netio.service.handle.XLogService.scala Maven / Gradle / Ivy

/*
*  Copyright 2015 the original author or authors. 
 *  @https://github.com/scouter-project/scouter
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); 
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  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 scouter.server.netio.service.handle;

import scouter.util.StringUtil
import scouter.lang.TextTypes
import scouter.lang.pack.MapPack
import scouter.lang.pack.Pack
import scouter.lang.pack.PackEnum
import scouter.lang.pack.XLogPack
import scouter.lang.pack.XLogProfilePack
import scouter.lang.value._
import scouter.io.DataInputX
import scouter.io.DataOutputX
import scouter.net.RequestCmd
import scouter.net.TcpFlag
import scouter.server.Configure
import scouter.server.Logger
import scouter.server.core.cache.CacheOut
import scouter.server.core.cache.TextCache
import scouter.server.core.cache.XLogCache
import scouter.server.db.XLogProfileRD
import scouter.server.db.XLogRD
import scouter.server.netio.service.anotation.ServiceHandler
import scouter.util.DateUtil
import scouter.util.IPUtil
import scouter.util.IntSet
import scouter.util.StrMatch
import java.io.IOException

import scouter.lang.constants.ParamConstant
import scouter.server.db.TextRD
import scouter.server.util.EnumerScala
import sun.security.provider.certpath.ForwardBuilder
import scouter.util.CastUtil

class XLogService {

    @ServiceHandler(RequestCmd.TRANX_PROFILE)
    def getProfile(din: DataInputX, dout: DataOutputX, login: Boolean) {
        val param = din.readMapPack();

        var date = param.getText("date");
        val txid = param.getLong("txid");
        val max = param.getInt("max");
        if (StringUtil.isEmpty(date)) {
            date = DateUtil.yyyymmdd(System.currentTimeMillis());
        }
        try {
            val profilePacket = XLogProfileRD.getProfile(date, txid, max);
            if (profilePacket != null) {
                dout.writeByte(TcpFlag.HasNEXT);
                val p = new XLogProfilePack();
                p.profile = profilePacket;
                dout.writePack(p); // ProfilePacket
            }
        } catch {
            case e: Exception => e.printStackTrace();
        }
    }

    @ServiceHandler(RequestCmd.TRANX_PROFILE_FULL)
    def getFullProfile(din: DataInputX, dout: DataOutputX, login: Boolean) {
        val param = din.readMapPack();

        var date = param.getText("date");
        val txid = param.getLong("txid");
        val max = -1;
        if (StringUtil.isEmpty(date)) {
            date = DateUtil.yyyymmdd();
        }

        XLogProfileRD.getFullProfile(date, txid, max, (data: Array[Byte]) => {
            dout.writeByte(TcpFlag.HasNEXT);
            dout.writeBlob(data);
        })
    }

    /**
      * get latest XLog data
      * @param din MapPack{index, loop, objHash[]}
      * @param dout {MapPack{loop, index}, XLogPack[]}
      * @param login
      */
    @ServiceHandler(RequestCmd.TRANX_REAL_TIME_GROUP)
    def getRealtimePerfGroup(din: DataInputX, dout: DataOutputX, login: Boolean) {
        val param = din.readMapPack();
        val index = param.getInt("index");
        val loop = param.getLong("loop");
        var limit = param.getInt("limit");
        limit = Math.max(Configure.getInstance().xlog_realtime_lower_bound_ms, limit);
        val objHashLv = param.getList("objHash");

        val intSet = if(objHashLv == null || objHashLv.size() < 1)
                     null
                     else new IntSet(objHashLv.size(), 1.0f)

        EnumerScala.foreach(objHashLv, (obj: DecimalValue) => {
            intSet.add(obj.intValue());
        })

        val d = if(intSet != null)
                XLogCache.get(intSet, loop, index, limit)
                else XLogCache.get(loop, index, limit)

        if (d == null) return ;

        // 첫번째 패킷에 정보를 전송한다.
        val outparam = new MapPack();
        outparam.put("loop", new DecimalValue(d.loop));
        outparam.put("index", new DecimalValue(d.index));
        dout.writeByte(TcpFlag.HasNEXT);
        dout.writePack(outparam);

        EnumerScala.forward(d.data, (p: Array[Byte]) => {
            dout.writeByte(TcpFlag.HasNEXT);
            dout.write(p);
        })

    }

    /**
      * get latest XLog data
      * @param din MapPack{index, loop, count, objHash[]}
      * @param dout {MapPack{loop, index}, XLogPack[]}
      * @param login
      */
    @ServiceHandler(RequestCmd.TRANX_REAL_TIME_GROUP_LATEST)
    def getRealtimePerfGroupLatestCount(din: DataInputX, dout: DataOutputX, login: Boolean) {

        val param = din.readMapPack();
        val index = param.getInt("index");
        val loop = param.getLong("loop");
        var count = param.getInt("count");

        val objHashLv = param.getList("objHash");

        val objHashSet = if(objHashLv == null || objHashLv.size() < 1)
            null
        else new IntSet(objHashLv.size(), 1.0f)

        EnumerScala.foreach(objHashLv, (obj: DecimalValue) => {
            objHashSet.add(obj.intValue());
        })

        val d = if(objHashSet != null)
                    XLogCache.getWithinCount(objHashSet, loop, index, count)
                else XLogCache.getWithinCount(loop, index, count)

        if (d == null)
            return ;

        // 첫번째 패킷에 정보를 전송한다.
        val outparam = new MapPack();
        outparam.put("loop", new DecimalValue(d.loop));
        outparam.put("index", new DecimalValue(d.index));
        dout.writeByte(TcpFlag.HasNEXT);
        dout.writePack(outparam);

        EnumerScala.forward(d.data, (p: Array[Byte]) => {
            dout.writeByte(TcpFlag.HasNEXT);
            dout.write(p);
        })

    }

    /**
      * get past XLog data
      * @param din MapPack{date, stime, etime, max, reverse, objHash[]}
      * @param dout XLogPack[]
      * @param login
      */
    @ServiceHandler(RequestCmd.TRANX_LOAD_TIME_GROUP)
    def getHistoryPerfGroup(din: DataInputX, dout: DataOutputX, login: Boolean) {
        val param = din.readMapPack();
        val date = param.getText("date");
        val stime = param.getLong("stime");
        val etime = param.getLong("etime");
        val limitTime = param.getInt("limit");
        val limit = Math.max(Configure.getInstance().xlog_pasttime_lower_bound_ms, limitTime);
        val max = param.getInt("max");
        val rev = param.getBoolean("reverse");
        val objHashLv = param.getList("objHash");
        if (objHashLv == null || objHashLv.size() < 1) {
            return ;
        }

        val objHashSet = new IntSet();
        EnumerScala.foreach(objHashLv, (obj: DecimalValue) => {
            objHashSet.add(obj.intValue());
        })

        var cnt = 0;
        val handler = (time: Long, data: Array[Byte]) => {
            val x = new DataInputX(data).readPack().asInstanceOf[XLogPack];
            if (objHashSet.contains(x.objHash) && x.elapsed > limit) {
                dout.writeByte(TcpFlag.HasNEXT);
                dout.write(data);
                dout.flush();
                cnt += 1;
            }
            if (max > 0 && cnt >= max) {
                return ;
            }
        }

        if (rev) {
            XLogRD.readFromEndTime(date, stime, etime, handler)
        } else {
            XLogRD.readByTime(date, stime, etime, handler);
        }
    }

    /**
      * get past XLog data by time & object
      *
      * date - String: yyyymmdd
      * stime - long: scan start time (ms)
      * etime - long: scan end time (ms)
      * pageCount - xlog count to get a time
      * lastBucketTime - from previous paging result
      * txid - (last xlog txid) from previous paging result
      * objHash[] - object hashes to retrieve xlog
      * @param din MapPack{date, stime, etime, pageCount, lastBucketTime, txid, objHash[]}
      * @param dout XLogPack[]
      * @param login
      */
    @ServiceHandler(RequestCmd.TRANX_LOAD_TIME_GROUP_V2)
    def getHistoryPerfGroupV2(din: DataInputX, dout: DataOutputX, login: Boolean) {
        val param = din.readMapPack()
        val date = param.getText(ParamConstant.DATE)
        val stime = param.getLong(ParamConstant.XLOG_START_TIME)
        val etime = param.getLong(ParamConstant.XLOG_END_TIME)
        val lastBucketTime = param.getLong(ParamConstant.XLOG_LAST_BUCKET_TIME)
        val txid = param.getLong(ParamConstant.XLOG_TXID)
        val limitCount = param.getInt(ParamConstant.XLOG_PAGE_COUNT)
        val objHashLv = param.getList(ParamConstant.OBJ_HASH)

        if (objHashLv == null || objHashLv.size() < 1) {
            writeHistoryPerfGroupV2MetaPack(dout, false, 0, 0)
            return
        }
        if((txid == 0 && lastBucketTime != 0) || (txid != 0 && lastBucketTime == 0)) {
            writeHistoryPerfGroupV2MetaPack(dout, false, 0, 0)
            return
        }
        if(limitCount == 0) {
            writeHistoryPerfGroupV2MetaPack(dout, false, 0, 0)
            return
        }

        val objHashSet = new IntSet()
        EnumerScala.foreach(objHashLv, (obj: DecimalValue) => {
            objHashSet.add(obj.intValue())
        })

        var lastTime = 0L
        var lastData: XLogPack = null
        var count: Int = 0;

        var start = true
        if(txid != 0L) {
            start = false
        }

        var hasMore = false

        val handler = (time: Long, data: Array[Byte]) =>  {
            val xLog = new DataInputX(data).readPack().asInstanceOf[XLogPack]
            if(!start) {
                if(xLog.txid == txid) {
                    start = true
                }
            } else {
                if (objHashSet.contains(xLog.objHash)) {
                    if(count < limitCount) {
                        dout.writeByte(TcpFlag.HasNEXT)
                        dout.write(data)
                        dout.flush()
                        lastTime = time
                        lastData = xLog
                    } else {
                        hasMore = true
                    }
                    count += 1
                }
            }
            count
        }
        XLogRD.readByTimeLimitCount(date, stime, etime, lastBucketTime, limitCount, handler)

        if(lastTime > 0L) {
            writeHistoryPerfGroupV2MetaPack(dout, hasMore, lastTime, lastData.txid)
        } else {
            writeHistoryPerfGroupV2MetaPack(dout, false, 0, 0)
        }
    }

    def writeHistoryPerfGroupV2MetaPack(dout: DataOutputX, hasMore: Boolean, lastTime: Long, lastTxid: Long): Unit = {
        val metaPack = new MapPack();
        metaPack.put(ParamConstant.XLOG_RESULT_HAS_MORE, new BooleanValue(hasMore))
        metaPack.put(ParamConstant.XLOG_RESULT_LAST_TIME, new DecimalValue(lastTime))
        metaPack.put(ParamConstant.XLOG_RESULT_LAST_TXID, new DecimalValue(lastTxid))

        dout.writeByte(TcpFlag.HasNEXT)
        dout.writePack(metaPack)
    }

    @ServiceHandler(RequestCmd.XLOG_READ_BY_GXID)
    def readByGxId(din: DataInputX, dout: DataOutputX, login: Boolean) {
        val param = din.readMapPack();
        val date = param.getText("date");
        val gxid = param.getLong("gxid");
        try {
            val list = XLogRD.getByGxid(date, gxid);
            EnumerScala.forward(list, (xlog: Array[Byte]) => {
                dout.writeByte(TcpFlag.HasNEXT);
                dout.write(xlog);
                dout.flush();
            })

        } catch {
            case e: Exception => {}
        }
    }

    @ServiceHandler(RequestCmd.XLOG_READ_BY_TXID)
    def readByTxId(din: DataInputX, dout: DataOutputX, login: Boolean) {
        val param = din.readMapPack();
        val date = param.getText("date");
        val txid = param.getLong("txid");
        try {
            val xbytes = XLogRD.getByTxid(date, txid);
            if (xbytes != null) {
                dout.writeByte(TcpFlag.HasNEXT);
                dout.write(xbytes);
                dout.flush();
            }
        } catch {
            case e: Exception => {}
        }
    }

    @ServiceHandler(RequestCmd.XLOG_LOAD_BY_TXIDS)
    def loadByTxIds(din: DataInputX, dout: DataOutputX, login: Boolean) {
        val param = din.readMapPack()
        val date = param.getText("date")
        val txidLv = param.getList("txid")

        var loadCount = 0
        try {
            EnumerScala.foreach(txidLv, (txidValue: DecimalValue) => {
                loadCount += 1;

                if (loadCount >= Configure.getInstance().req_search_xlog_max_count) {
                    return;
                }
                val xbytes = XLogRD.getByTxid(date, txidValue.longValue())
                if(xbytes != null) {
                    dout.writeByte(TcpFlag.HasNEXT)
                    dout.write(xbytes)
                    dout.flush()
                }
            })
        } catch {
            case e: Exception => {}
        }
    }

    @ServiceHandler(RequestCmd.XLOG_LOAD_BY_GXID)
    def loadByGxId(din: DataInputX, dout: DataOutputX, login: Boolean) {
        val param = din.readMapPack();
        val stime = param.getLong("stime");
        val etime = param.getLong("etime");
        val gxid = param.getLong("gxid");
        val date = DateUtil.yyyymmdd(stime);
        val date2 = DateUtil.yyyymmdd(etime);
        try {
            val list = XLogRD.getByGxid(date, gxid);

            EnumerScala.forward(list, (xlog: Array[Byte]) => {
                dout.writeByte(TcpFlag.HasNEXT);
                dout.write(xlog);
                dout.flush();
            })

        } catch {
            case e: Exception => {}
        }
        if (date.equals(date2) == false) {
            try {
                val list = XLogRD.getByGxid(date2, gxid);

                EnumerScala.forward(list, (xlog: Array[Byte]) => {
                    dout.writeByte(TcpFlag.HasNEXT);
                    dout.write(xlog);
                    dout.flush();
                });

            } catch {
                case e: Exception => {}
            }
        }
    }

    @ServiceHandler(RequestCmd.QUICKSEARCH_XLOG_LIST)
    def quickSearchXlogList(din: DataInputX, dout: DataOutputX, login: Boolean) {
        val param = din.readMapPack();
        val date = param.getText("date");
        val txid = param.getLong("txid");
        val gxid = param.getLong("gxid");
        if (txid != 0) {
            try {
                val xbytes = XLogRD.getByTxid(date, txid);
                if (xbytes != null) {
                    dout.writeByte(TcpFlag.HasNEXT);
                    dout.write(xbytes);
                    dout.flush();
                }
            } catch {
                case e: Exception => {}
            }
        }
        if (gxid != 0) {
            try {
                val list = XLogRD.getByGxid(date, gxid);
                if (list == null)
                    return ;
                for (i <- 0 to list.size() - 1) {
                    val xlog = list.get(i);
                    dout.writeByte(TcpFlag.HasNEXT);
                    dout.write(xlog);
                    dout.flush();
                }
            } catch {
                case e: Exception => {}
            }
        }
    }

    @ServiceHandler(RequestCmd.SEARCH_XLOG_LIST)
    def searchXlogList(din: DataInputX, dout: DataOutputX, login: Boolean) {
        val param = din.readMapPack();
        val stime = param.getLong("stime");
        val etime = param.getLong("etime");
        val service = param.getText("service");
        val objHash = param.getInt("objHash");
        val ip = param.getText("ip");
        val login = param.getText("login");
        val desc = param.getText("desc");
        val text1 = param.getText("text1");
        val text2 = param.getText("text2");
        val text3 = param.getText("text3");
        val text4 = param.getText("text4");
        val text5 = param.getText("text5");

        val serviceMatch = if (service == null) null else new StrMatch(service);
        val ipMatch = if (ip == null) null else new StrMatch(ip);
        val loginMatch = if (login == null) null else new StrMatch(login);
        val descMatch = if (desc == null) null else new StrMatch(desc);
        val text1Match = if (text1 == null) null else new StrMatch(text1);
        val text2Match = if (text2 == null) null else new StrMatch(text2);
        val text3Match = if (text3 == null) null else new StrMatch(text3);
        val text4Match = if (text4 == null) null else new StrMatch(text4);
        val text5Match = if (text5 == null) null else new StrMatch(text5);

        val date = DateUtil.yyyymmdd(stime);
        val date2 = DateUtil.yyyymmdd(etime);
        var mtime = 0L;
        var twoDays = false;
        var loadCount = 0;
        if (date.equals(date2) == false) {
            mtime = DateUtil.yyyymmdd(date2);
            twoDays = true;
        }

        val handler = (time: Long, data: Array[Byte]) => {
            if (loadCount >= Configure.getInstance().req_search_xlog_max_count) {
                return ;
            }
            val x = new DataInputX(data).readPack().asInstanceOf[XLogPack];
            var ok = true
            if (ipMatch != null) {
                if (x.ipaddr == null) {
                    ok = false;
                }
                if (ipMatch.include(IPUtil.toString(x.ipaddr)) == false) {
                    ok = false;
                }
            }
            if (objHash != 0 && x.objHash != objHash) {
                ok = false;
            }
            if (serviceMatch != null) {
                var serviceName = TextRD.getString(DateUtil.yyyymmdd(time), TextTypes.SERVICE, x.service);
                if (serviceMatch.include(serviceName) == false) {
                    ok = false;
                }
            }
            if (loginMatch != null) {
                var loginName = TextRD.getString(DateUtil.yyyymmdd(time), TextTypes.LOGIN, x.login);
                if (loginMatch.include(loginName) == false) {
                    ok = false;
                }
            }
            if (descMatch != null) {
                var descName = TextRD.getString(DateUtil.yyyymmdd(time), TextTypes.DESC, x.desc);
                if (descMatch.include(descName) == false) {
                    ok = false;
                }
            }

            if (text1Match != null) {
                var text1Name = x.text1;
                if (text1Match.include(text1Name) == false) {
                    ok = false;
                }
            }

            if (text2Match != null) {
                var text2Name = x.text2;
                if (text2Match.include(text2Name) == false) {
                    ok = false;
                }
            }

            if (text3Match != null) {
                var text3Name = x.text3;
                if (text3Match.include(text3Name) == false) {
                    ok = false;
                }
            }

            if (text4Match != null) {
                var text4Name = x.text4;
                if (text4Match.include(text4Name) == false) {
                    ok = false;
                }
            }

            if (text5Match != null) {
                var text5Name = x.text5;
                if (text5Match.include(text5Name) == false) {
                    ok = false;
                }
            }

            if (ok) {
                dout.writeByte(TcpFlag.HasNEXT);
                dout.write(data);
                dout.flush();
                loadCount += 1;
            }
        }

        if (twoDays) {
            XLogRD.readByTime(date, stime, mtime - 1, handler);
            XLogRD.readByTime(date2, mtime, etime, handler);
        } else {
            XLogRD.readByTime(date, stime, etime, handler);
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy