Java tutorial
/** * Copyright 2006-2015 handu.com * <p> * 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 * <p> * http://www.apache.org/licenses/LICENSE-2.0 * <p> * 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.handu.open.dubbo.monitor; import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.common.URL; import com.alibaba.dubbo.common.logger.Logger; import com.alibaba.dubbo.common.logger.LoggerFactory; import com.alibaba.dubbo.common.utils.ConfigUtils; import com.alibaba.dubbo.config.annotation.Service; import com.alibaba.dubbo.monitor.MonitorService; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.handu.open.dubbo.monitor.domain.DubboInvoke; import com.handu.open.dubbo.monitor.support.QueryConstructor; import com.handu.open.dubbo.monitor.support.UuidUtil; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Sort; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.aggregation.TypedAggregation; import org.springframework.data.mongodb.core.mapreduce.GroupBy; import org.springframework.data.mongodb.core.mapreduce.GroupByResults; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import javax.annotation.PostConstruct; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; /** * MonitorService * * @author Jinkai.Ma */ @Service(delay = -1) public class DubboMonitorService implements MonitorService { private static final Logger logger = LoggerFactory.getLogger(DubboMonitorService.class); // private static final String[] types = {SUCCESS, FAILURE, ELAPSED, CONCURRENT, MAX_ELAPSED, MAX_CONCURRENT}; private static final String POISON_PROTOCOL = "poison"; private static final String TIMESTAMP = "timestamp"; private volatile boolean running = true; private Thread writeThread; private BlockingQueue<URL> queue; @Autowired private RegistryContainer registryContainer; @Autowired private MongoTemplate mongoTemplate; @PostConstruct private void init() { queue = new LinkedBlockingQueue<URL>( Integer.parseInt(ConfigUtils.getProperty("dubbo.monitor.queue", "100000"))); writeThread = new Thread(new Runnable() { public void run() { while (running) { try { writeToDataBase(); // } catch (Throwable t) { // logger.error("Unexpected error occur at write stat log, cause: " + t.getMessage(), t); try { Thread.sleep(5000); // } catch (Throwable t2) { } } } } }); writeThread.setDaemon(true); writeThread.setName("DubboMonitorAsyncWriteLogThread"); writeThread.start(); } /** * Dubbo??DB * * @throws Exception */ private void writeToDataBase() throws Exception { URL statistics = queue.take(); if (POISON_PROTOCOL.equals(statistics.getProtocol())) { return; } String timestamp = statistics.getParameter(Constants.TIMESTAMP_KEY); Date now; if (timestamp == null || timestamp.length() == 0) { now = new Date(); } else if (timestamp.length() == "yyyyMMddHHmmss".length()) { now = new SimpleDateFormat("yyyyMMddHHmmss").parse(timestamp); } else { now = new Date(Long.parseLong(timestamp)); } DubboInvoke dubboInvoke = new DubboInvoke(); dubboInvoke.setId(UuidUtil.createUUID()); try { if (statistics.hasParameter(PROVIDER)) { dubboInvoke.setType(CONSUMER); dubboInvoke.setConsumer(statistics.getHost()); dubboInvoke.setProvider(statistics.getParameter(PROVIDER)); int i = dubboInvoke.getProvider().indexOf(':'); if (i > 0) { dubboInvoke.setProvider(dubboInvoke.getProvider().substring(0, i)); } } else { dubboInvoke.setType(PROVIDER); String consumer = statistics.getParameter(CONSUMER); if (!StringUtils.isEmpty(consumer)) { dubboInvoke.setConsumer(consumer); int i = dubboInvoke.getConsumer().indexOf(':'); if (i > 0) { dubboInvoke.setConsumer(dubboInvoke.getConsumer().substring(0, i)); } } dubboInvoke.setProvider(statistics.getHost()); } dubboInvoke.setInvokeDate(now); dubboInvoke.setService(statistics.getServiceInterface()); dubboInvoke.setMethod(statistics.getParameter(METHOD)); dubboInvoke.setInvokeTime(statistics.getParameter(TIMESTAMP, System.currentTimeMillis())); dubboInvoke.setSuccess(statistics.getParameter(SUCCESS, 0)); dubboInvoke.setFailure(statistics.getParameter(FAILURE, 0)); dubboInvoke.setElapsed(statistics.getParameter(ELAPSED, 0)); dubboInvoke.setConcurrent(statistics.getParameter(CONCURRENT, 0)); dubboInvoke.setMaxElapsed(statistics.getParameter(MAX_ELAPSED, 0)); dubboInvoke.setMaxConcurrent(statistics.getParameter(MAX_CONCURRENT, 0)); if (dubboInvoke.getSuccess() == 0 && dubboInvoke.getFailure() == 0 && dubboInvoke.getElapsed() == 0 && dubboInvoke.getConcurrent() == 0 && dubboInvoke.getMaxElapsed() == 0 && dubboInvoke.getMaxConcurrent() == 0) { return; } dubboInvoke.setTimeParticle(null); mongoTemplate.insert(dubboInvoke); } catch (Throwable t) { logger.error(t.getMessage(), t); } } public void collect(URL statistics) { queue.offer(statistics); if (logger.isInfoEnabled()) { logger.info("collect statistics: " + statistics); } } public List<URL> lookup(URL query) { // TODO Auto-generated method stub return null; } /** * ? * * @param dubboInvoke */ public List<DubboInvoke> countDubboInvoke(DubboInvoke dubboInvoke) { if (StringUtils.isEmpty(dubboInvoke.getService())) { logger.error("???"); throw new RuntimeException("???"); } TypedAggregation<DubboInvoke> aggregation = Aggregation.newAggregation(DubboInvoke.class, Aggregation.match(Criteria.where("service").is(dubboInvoke.getService()).and("method") .is(dubboInvoke.getMethod()).and("type").is(dubboInvoke.getType()).and("invokeDate") .gte(dubboInvoke.getInvokeDateFrom()).lte(dubboInvoke.getInvokeDateTo())), Aggregation .project("service", "method", "type", "success", "failure", "elapsed", "maxElapsed", "maxConcurrent", "invokeTime") .andExpression("(invokeTime / " + dubboInvoke.getTimeParticle() + ") * " + dubboInvoke.getTimeParticle()) .as("invokeTime"), Aggregation.group("service", "method", "type", "invokeTime").sum("success").as("success") .sum("failure").as("failure").sum("elapsed").as("elapsed").max("maxElapsed") .as("maxElapsed").min("maxConcurrent").as("maxConcurrent"), Aggregation.sort(Sort.Direction.ASC, "invokeTime")); AggregationResults<DubboInvoke> result = mongoTemplate.aggregate(aggregation, "dubboInvoke", DubboInvoke.class); return result.getMappedResults(); } public Set<String> getMethodsByService(DubboInvoke dubboInvoke) { Set<String> methods = Sets.newHashSet(); Query query = QueryConstructor.get().addIsAttribute("service", dubboInvoke.getService()) .addIsAttribute("invokeDate", dubboInvoke.getInvokeDate()) .addIsAttribute("provider", dubboInvoke.getProvider()) .addIsAttribute("consumer", dubboInvoke.getConsumer()).addIsAttribute("type", dubboInvoke.getType()) .addBetweenAttribute("invokeDate", dubboInvoke.getInvokeDateFrom(), dubboInvoke.getInvokeDateTo()) .getQuery(); List<DubboInvoke> result = mongoTemplate.find(query, DubboInvoke.class, "dubboInvoke"); for (DubboInvoke di : result) { methods.add(di.getMethod()); } return methods; } /** * ?? * * @param dubboInvoke * @return */ public List<DubboInvoke> countDubboInvokeInfo(DubboInvoke dubboInvoke) { if (StringUtils.isEmpty(dubboInvoke.getService()) || StringUtils.isEmpty(dubboInvoke.getMethod()) || StringUtils.isEmpty(dubboInvoke.getType())) { logger.error("???"); throw new RuntimeException("???"); } TypedAggregation<DubboInvoke> aggregation = Aggregation.newAggregation(DubboInvoke.class, Aggregation.match(Criteria.where("service").is(dubboInvoke.getService()).and("method") .is(dubboInvoke.getMethod()).and("type").is(dubboInvoke.getType()).and("invokeDate") .gte(dubboInvoke.getInvokeDateFrom()).lte(dubboInvoke.getInvokeDateTo())), Aggregation.group("service", "method").sum("success").as("success").sum("failure").as("failure") .sum("elapsed").as("elapsed").max("maxElapsed").as("maxElapsed").min("maxConcurrent") .as("maxConcurrent")); AggregationResults<DubboInvoke> result = mongoTemplate.aggregate(aggregation, "dubboInvoke", DubboInvoke.class); return result.getMappedResults(); } /** * ?? * * @param dubboInvoke * @return */ public Map<String, List> countDubboInvokeTopTen(DubboInvoke dubboInvoke) { Map<String, List> result = Maps.newHashMap(); Criteria criteris = Criteria.where("invokeDate").gte(dubboInvoke.getInvokeDateFrom()) .lte(dubboInvoke.getInvokeDateTo()).and("type").is(dubboInvoke.getType()); List<DubboInvoke> successList = Lists.newArrayList(); GroupByResults<DubboInvoke> successResults = mongoTemplate.group(criteris, "dubboInvoke", GroupBy.key("service", "method").initialDocument("{ success: 0 }") .reduceFunction("function(doc, prev) { prev.success += doc.success }"), DubboInvoke.class); for (DubboInvoke dubboInvoke1 : successResults) { successList.add(dubboInvoke1); } Collections.sort(successList, new Comparator<DubboInvoke>() { public int compare(DubboInvoke arg0, DubboInvoke arg1) { return (int) (arg1.getSuccess() - arg0.getSuccess()); } }); successList.subList(0, successList.size() > 19 ? 19 : successList.size()); result.put("success", successList); List<DubboInvoke> failureList = Lists.newArrayList(); GroupByResults<DubboInvoke> failureResults = mongoTemplate.group(criteris, "dubboInvoke", GroupBy.key("service", "method").initialDocument("{ failure: 0 }") .reduceFunction("function(doc, prev) { prev.failure += doc.failure }"), DubboInvoke.class); for (DubboInvoke dubboInvoke1 : failureResults) { failureList.add(dubboInvoke1); } Collections.sort(failureList, new Comparator<DubboInvoke>() { public int compare(DubboInvoke arg0, DubboInvoke arg1) { return (int) (arg1.getFailure() - arg0.getFailure()); } }); failureList.subList(0, failureList.size() > 19 ? 19 : failureList.size()); result.put("failure", failureList); return result; } }