com.ctrip.infosec.rule.executor.ModelRulesExecutorService.java Source code

Java tutorial

Introduction

Here is the source code for com.ctrip.infosec.rule.executor.ModelRulesExecutorService.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.ctrip.infosec.rule.executor;

import com.ctrip.infosec.common.Constants;
import static com.ctrip.infosec.common.SarsMonitorWrapper.afterInvoke;
import static com.ctrip.infosec.common.SarsMonitorWrapper.beforeInvoke;
import static com.ctrip.infosec.common.SarsMonitorWrapper.fault;
import com.ctrip.infosec.common.model.RiskFact;
import com.ctrip.infosec.configs.Configs;
import com.ctrip.infosec.configs.event.ModelRule;
import com.ctrip.infosec.configs.rule.trace.logger.TraceLogger;
import com.ctrip.infosec.configs.rulemonitor.RuleMonitorHelper;
import com.ctrip.infosec.configs.rulemonitor.RuleMonitorType;
import static com.ctrip.infosec.configs.utils.EventBodyUtils.valueAsString;
import com.ctrip.infosec.configs.utils.Threads;
import com.ctrip.infosec.rule.Contexts;
import com.ctrip.infosec.rule.engine.StatelessModelRuleEngine;
import com.ctrip.infosec.sars.monitor.mq.SarsMqStatRepository;
import com.ctrip.infosec.sars.util.Collections3;
import com.ctrip.infosec.sars.util.SpringContextHolder;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.annotation.PostConstruct;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

/**
 * 
 *
 * @author zhengby
 */
@Service
public class ModelRulesExecutorService {

    private static final Logger logger = LoggerFactory.getLogger(ModelRulesExecutorService.class);
    private LinkedBlockingQueue<RiskFact> queue = new LinkedBlockingQueue<>();

    /**
     * 
     */
    public RiskFact executeModelRules(RiskFact fact) {
        List<ModelRule> matchedRules = Configs.matchModelRules(fact);
        if (!matchedRules.isEmpty()) {
            try {
                fact.ext.put(Constants.key_traceLoggerParentTransId, TraceLogger.getTransId());
                queue.put(fact);
            } catch (InterruptedException ex) {
                // ignored
            }
        }
        return fact;
    }

    @PostConstruct
    public void dequeue() {
        int threads = 1;
        ExecutorService executor = Executors.newFixedThreadPool(threads);
        for (int i = 0; i < threads; i++) {
            executor.submit(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        RiskFact fact = null;
                        beforeInvoke("ModelRules.execute");
                        try {
                            fact = queue.take();
                            TraceLogger.beginTrans(fact.eventId);
                            TraceLogger.setParentTransId(
                                    valueAsString(fact.ext, Constants.key_traceLoggerParentTransId));
                            fact.ext.remove(Constants.key_traceLoggerParentTransId);
                            execute(fact);
                        } catch (Exception ex) {
                            fault("ModelRules.execute");
                            logger.error("dequeue exception.", ex);
                        } finally {
                            afterInvoke("ModelRules.execute");
                            if (fact != null) {
                                TraceLogger.commitTrans();
                            }
                            Threads.sleep(10, TimeUnit.MILLISECONDS);
                        }
                    }
                }
            });
        }
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor();
        scheduler.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                int size = queue.size();
                if (size > 0) {
                    SarsMqStatRepository.put("MODEL_EXECUTE_QUEUE", size);
                    logger.warn("queue size: " + size);
                }
                int max = 10000;
                if (size > max) {
                    do {
                        RiskFact fact = queue.poll();
                        logger.warn("model queue is full. drop message: " + fact.eventId);
                    } while (queue.size() > max);
                }
            }
        }, 30, 30, TimeUnit.SECONDS);
    }

    /**
     * 
     */
    public void execute(RiskFact fact) {

        // matchRules      
        List<ModelRule> matchedRules = Configs.matchModelRules(fact);
        List<String> scriptRulePackageNames = Collections3.extractToList(matchedRules, "ruleNo");
        logger.debug(
                Contexts.getLogPrefix() + "matched model rules: " + StringUtils.join(scriptRulePackageNames, ", "));
        TraceLogger.traceLog("? " + matchedRules.size() + " ? ...");

        StatelessModelRuleEngine statelessModelRuleEngine = SpringContextHolder
                .getBean(StatelessModelRuleEngine.class);
        for (ModelRule rule : matchedRules) {
            RuleMonitorHelper.newTrans(fact, RuleMonitorType.MODEL_RULE, rule.getRuleNo());
            TraceLogger.beginNestedTrans(fact.eventId);
            TraceLogger.setNestedLogPrefix("[" + rule.getRuleNo() + "]");
            Contexts.setPolicyOrRuleNo(rule.getRuleNo());
            try {
                long start = System.currentTimeMillis();

                // add current execute ruleNo and logPrefix before execution
                fact.ext.put(Constants.key_ruleNo, rule.getRuleNo());
                fact.ext.put(Constants.key_isAsync, true);

                statelessModelRuleEngine.execute(rule.getRuleNo(), fact);

                // remove current execute ruleNo when finished execution.
                fact.ext.remove(Constants.key_ruleNo);
                fact.ext.remove(Constants.key_isAsync);

                long handlingTime = System.currentTimeMillis() - start;
                if (handlingTime > 100) {
                    logger.info(Contexts.getLogPrefix() + "modelRule: " + rule.getRuleNo() + ", usage: "
                            + handlingTime + "ms");
                }

                Map<String, Object> result = fact.modelResults.get(rule.getRuleNo());
                if (result != null) {
                    int riskLevel = MapUtils.getIntValue(result, Constants.riskLevel, 0);
                    if (riskLevel > 0) {
                        TraceLogger.traceLog(">>>> [" + rule.getRuleNo() + "] : [] riskLevel = "
                                + result.get(Constants.riskLevel) + ", riskMessage = "
                                + result.get(Constants.riskMessage) + ", usage = " + result.get(Constants.timeUsage)
                                + "ms");
                    }
                }

            } catch (Throwable ex) {
                logger.warn(Contexts.getLogPrefix() + ". modelRule: " + rule.getRuleNo(),
                        ex);
                TraceLogger.traceLog("[" + rule.getRuleNo() + "] EXCEPTION: " + ex.toString());
            } finally {
                TraceLogger.commitNestedTrans();
                RuleMonitorHelper.commitTrans(fact);
                Contexts.clearLogPrefix();
            }
        }

    }
}