<|start_filename|>saluki-ops/spring-boot-starter-salukiops/src/main/resources/META-INF/static/assets/js/vendor/json-prettify-0.1.js<|end_filename|>
/*
 * Copyright 2016 LINE Corporation
 *
 * LINE Corporation licenses this file to you 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.
 */
// A modified version of JSON.minify() by <NAME> that prettifies a JSON string without fully parsing it.
(function(global){
  if (typeof global.JSON == "undefined" || !global.JSON) {
    global.JSON = {};
  }

  global.JSON.prettify = function(json) {

    var tokenizer = /"|\n|\r/g,
        in_string = false,
        tmp, tmp2, new_str = [], ns = 0, from = 0, lc, rc;

    tokenizer.lastIndex = 0;

    var indentation = 0;

    function prettify(ch, indentation) {
      var prettified;
      switch (ch) {
        case ':':
          prettified = ': ';
          break;
        case '{':
        case '[':
          indentation++;
          prettified = ch + '\n' + '  '.repeat(indentation);
          break;
        case '}':
        case ']':
          indentation--;
          prettified = '\n' + '  '.repeat(indentation) + ch;
          break;
        case ',':
          prettified = ',\n' + '  '.repeat(indentation);
          break;
        default:
          prettified = ch;
      }

      return [ prettified, indentation ];
    }

    while (tmp = tokenizer.exec(json)) {
      lc = RegExp.leftContext;
      rc = RegExp.rightContext;

      tmp2 = lc.substring(from);
      if (!in_string) {
        tmp2 = tmp2.replace(/(\n|\r|\s)*/g,"");
        for (var i = 0; i < tmp2.length; i++) {
          var prettified = prettify(tmp2.charAt(i), indentation);
          new_str[ns++] = prettified[0];
          indentation = prettified[1];
        }
      } else {
        new_str[ns++] = tmp2;
      }
      from = tokenizer.lastIndex;

      if (tmp[0] == "\"") {
        tmp2 = lc.match(/(\\)*$/);
        if (!in_string || !tmp2 || (tmp2[0].length % 2) == 0) {	// start of string with ", or unescaped " character found to end string
          in_string = !in_string;
        }
        from--; // include " character in next catch
        rc = json.substring(from);
      }
      else if (!(/\n|\r|\s/.test(tmp[0]))) {
        new_str[ns++] = tmp[0];
      }
    }

    for (var i = 0; i < rc.length; i++) {
      var prettified = prettify(rc.charAt(i), indentation);
      new_str[ns++] = prettified[0];
      indentation = prettified[1];
    }

    return new_str.join("");
  };
})(this);


<|start_filename|>spring-boot-starter-saluki/src/main/java/io/github/saluki/boot/autoconfigure/WebAppAutoConfiguration.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and proprietary
 * information of Quancheng-ec.com ("Confidential Information"). You shall not disclose such Confidential Information
 * and shall use it only in accordance with the terms of the license agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.boot.autoconfigure;

import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.web.context.WebServerInitializedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;

/**
 * @author shimingliu 2016年12月17日 上午12:14:31
 * @version WebAppAutoConfiguration.java, v 0.0.1 2016年12月17日 上午12:14:31 shimingliu
 */

@Configuration
@ConditionalOnBean(value = GrpcProperties.class)
public class WebAppAutoConfiguration implements ApplicationListener<WebServerInitializedEvent> {

    private final GrpcProperties grpcProperties;

    public WebAppAutoConfiguration(GrpcProperties thrallProperties) {
        this.grpcProperties = thrallProperties;
    }

    @Override
    public void onApplicationEvent(WebServerInitializedEvent event) {
        int httpPort = event.getWebServer().getPort();
        if (grpcProperties.getRegistryHttpPort() == 0) {
            if (httpPort != 0) {
                grpcProperties.setRegistryHttpPort(httpPort);
            }
        }
    }

}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/client/internal/GrpcCallOptions.java<|end_filename|>
/*
 * Copyright 2014-2017 the original author or authors.
 *
 * 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 io.github.saluki.grpc.client.internal;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.google.common.collect.Maps;
import io.github.saluki.common.GrpcURL;

import io.grpc.CallOptions;

/**
 * @author liushiming
 * @version GrpcClientCall.java, v 0.0.1 2017年8月16日 下午6:20:23 liushiming
 * @since JDK 1.8
 */
public abstract class GrpcCallOptions {
  public static final CallOptions.Key<ConcurrentHashMap<String, Object>> CALLOPTIONS_CUSTOME_KEY =
      CallOptions.Key.of("custom_options", new ConcurrentHashMap<String, Object>());

  public static final String GRPC_REF_URL = "grpc-refurl";

  public static final String GRPC_CURRENT_ADDR_KEY = "current-address";

  public static final String GRPC_NAMERESOVER_ATTRIBUTES = "nameresolver-attributes";

  private static final Map<String, CallOptions> CACHEOPTIONS_CACHE = Maps.newConcurrentMap();

  public static CallOptions createCallOptions(final GrpcURL refUrl) {
    String serviceName = refUrl.getServiceInterface();
    CallOptions options = CACHEOPTIONS_CACHE.get(serviceName);
    if (options == null) {
      ConcurrentHashMap<String, Object> customOptions = new ConcurrentHashMap<String, Object>();
      customOptions.put(GRPC_REF_URL, refUrl);
      options = CallOptions.DEFAULT.withOption(CALLOPTIONS_CUSTOME_KEY, customOptions);
      CACHEOPTIONS_CACHE.put(serviceName, options);
      return options;
    } else {
      return options;
    }
  }

  public static Map<String, Object> getAffinity(final GrpcURL refUrl) {
    String serviceName = refUrl.getServiceInterface();
    return CACHEOPTIONS_CACHE.get(serviceName).getOption(CALLOPTIONS_CUSTOME_KEY);
  }


}


<|start_filename|>saluki-ops/saluki-ops-console/src/main/java/io/github/saluki/monitor/ops/controller/ApplicationController.java<|end_filename|>
package io.github.saluki.monitor.ops.controller;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import io.github.saluki.monitor.dao.domain.Application;
import io.github.saluki.monitor.dao.domain.ApplicationDependcy;
import io.github.saluki.monitor.ops.service.ApplicationDependcyService;
import io.github.saluki.monitor.ops.service.ConsulRegistryService;

@RestController
@RequestMapping(value = "/api/application")
public class ApplicationController {

    private static final Logger log = LoggerFactory.getLogger(ApplicationController.class);

    @Autowired
    private ConsulRegistryService registrySerivce;

    @Autowired
    private ApplicationDependcyService appDependcyService;

    @RequestMapping(value = "list", method = RequestMethod.GET)
    public List<Application> listAllApps() {
        log.info("Return all application from registry");
        return registrySerivce.getAllApplication();
    }

    @RequestMapping(value = "dependcy", method = RequestMethod.GET)
    public List<ApplicationDependcy> listDependcyApps() {
        return appDependcyService.queryApplicationDependcy();
    }

}


<|start_filename|>saluki-example/saluki-example-api/src/main/java/com/saluki/example/model/First.java<|end_filename|>
package com.saluki.example.model;

/**
 * Created by guoyubo on 2017/7/22.
 */
public interface First {
}


<|start_filename|>saluki-ops/spring-boot-starter-salukiops/src/main/java/io/github/saluki/monitor/dao/domain/GrpcHost.java<|end_filename|>
package io.github.saluki.monitor.dao.domain;

import java.io.Serializable;

public class GrpcHost implements Serializable {

    private static final long serialVersionUID = 1L;

    private String            status;

    private String            url;

    private final String      host;

    private final String      httpPort;

    private final String      rpcPort;

    public GrpcHost(String host, String httpPort, String rpcPort){
        this.host = host;
        this.httpPort = httpPort;
        this.rpcPort = rpcPort;
    }

    public GrpcHost(String hostRpcPort, String httpPort){
        String[] hostRpcPort_ = hostRpcPort.split(":");
        this.host = hostRpcPort_[0];
        this.httpPort = httpPort;
        this.rpcPort = hostRpcPort_[1];
    }

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getHost() {
        return host;
    }

    public String getHttpPort() {
        return httpPort;
    }

    public String getRpcPort() {
        return rpcPort;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((host == null) ? 0 : host.hashCode());
        result = prime * result + ((httpPort == null) ? 0 : httpPort.hashCode());
        result = prime * result + ((rpcPort == null) ? 0 : rpcPort.hashCode());
        result = prime * result + ((status == null) ? 0 : status.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        GrpcHost other = (GrpcHost) obj;
        if (host == null) {
            if (other.host != null) return false;
        } else if (!host.equals(other.host)) return false;
        if (httpPort == null) {
            if (other.httpPort != null) return false;
        } else if (!httpPort.equals(other.httpPort)) return false;
        if (rpcPort == null) {
            if (other.rpcPort != null) return false;
        } else if (!rpcPort.equals(other.rpcPort)) return false;
        if (status == null) {
            if (other.status != null) return false;
        } else if (!status.equals(other.status)) return false;
        return true;
    }

    @Override
    public String toString() {
        return "SalukiHost [status=" + status + ", url=" + url + ", host=" + host + ", httpPort=" + httpPort
               + ", rpcPort=" + rpcPort + "]";
    }

}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/service/GenericService.java<|end_filename|>
package io.github.saluki.grpc.service;

import com.google.protobuf.DynamicMessage;

import io.grpc.MethodDescriptor;

public interface GenericService {

  Object $invoke(String serviceName, String group, String version, String method, Object[] args);

  Object $invoke(String serviceName, String group, String version, String method,
      MethodDescriptor<DynamicMessage, DynamicMessage> methodDesc, DynamicMessage message);

}


<|start_filename|>saluki-ops/saluki-ops-console/src/main/resources/static/sourse/src/index.js<|end_filename|>
// import '!!script!jquery';

import Vue from 'vue';
import VueRouter from 'vue-router';
// import Vuex from 'vuex';
import VueResource from 'vue-resource';
// import { sync } from 'vuex-router-sync';

import routes from './libs/routes';
// import store from './vuex/store';
import App from './App.vue';

//开启debug模式
Vue.config.debug = true;

Vue.use(VueResource);

//路由
Vue.use(VueRouter);
const router = new VueRouter({
  // mode: 'history',
  routes,
  linkActiveClass: 'active'
});
// sync(store, router);

//创建和挂载根实例。
const app = new Vue({
  router,
  render: h => h(App)
}).$mount('#app')


<|start_filename|>saluki-ops/saluki-ops-console/src/main/java/io/github/saluki/monitor/ops/service/ApplicationDependcyService.java<|end_filename|>
package io.github.saluki.monitor.ops.service;

import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.tuple.ImmutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import io.github.saluki.monitor.dao.domain.ApplicationDependcy;
import io.github.saluki.monitor.ops.repository.InvokeMapper;

@Service
public class ApplicationDependcyService {

    @Autowired
    private InvokeMapper invokeMapper;

    public List<ApplicationDependcy> queryApplicationDependcy() {
        List<Map<String, String>> allConsumers = invokeMapper.queryConsumer();
        List<ApplicationDependcy> appDepencys = Lists.newArrayList();
        for (Map<String, String> consumer : allConsumers) {
            String appName = consumer.get("application");
            String service = consumer.get("service");
            String privider = consumer.get("provider");
            String callCount = String.valueOf(consumer.get("callCount"));
            ApplicationDependcy hasAddedApp = null;
            for (ApplicationDependcy ApplicationDependcy : appDepencys) {
                if (ApplicationDependcy.getAppName().equals(appName)) {
                    hasAddedApp = ApplicationDependcy;
                }
            }
            if (hasAddedApp == null) {
                hasAddedApp = new ApplicationDependcy(appName);
                appDepencys.add(hasAddedApp);
            }
            Map<String, String> providerParam = Maps.newHashMap();
            providerParam.put("service", service);
            List<Map<String, String>> providerAppMaps = invokeMapper.queryProvider(providerParam);
            String parentAppName = null;
            if (providerAppMaps != null && providerAppMaps.size() == 1) {
                parentAppName = providerAppMaps.get(0).get("application");
            } else if (providerAppMaps != null && providerAppMaps.size() > 1) {
                for (Map<String, String> providerAppMap : providerAppMaps) {
                    if (providerAppMap.get("provider").equals(privider)) {
                        parentAppName = providerAppMap.get("application");
                        break;
                    }
                }
                if (parentAppName == null) {
                    parentAppName = "No monitor provider data";
                }
            } else {
                parentAppName = "No monitor provider data";
            }
            hasAddedApp.addDependcyService(parentAppName,
                                           new ImmutablePair<String, Integer>(service, Integer.valueOf(callCount)));
        }
        return appDepencys;
    }

}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/client/internal/unary/GrpcUnaryClientCall.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.grpc.client.internal.unary;



import java.util.Collections;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ExecutionException;

import com.google.common.util.concurrent.ListenableFuture;
import com.google.protobuf.Message;
import io.github.saluki.common.GrpcURL;
import io.github.saluki.grpc.client.internal.GrpcCallOptions;

import io.grpc.CallOptions;
import io.grpc.Channel;
import io.grpc.MethodDescriptor;
import io.grpc.Status;

/**
 * @author shimingliu 2016年12月14日 下午9:54:44
 * @version GrpcAsyncCall.java, v 0.0.1 2016年12月14日 下午9:54:44 shimingliu
 */
public interface GrpcUnaryClientCall {

  public ListenableFuture<Message> unaryFuture(Message request,
      MethodDescriptor<Message, Message> method);

  public Message blockingUnaryResult(Message request, MethodDescriptor<Message, Message> method);

  public static GrpcUnaryClientCall create(final Channel channel, final Integer retryOptions,
      final GrpcURL refUrl) {
    final CallOptions callOptions = GrpcCallOptions.createCallOptions(refUrl);
    return new GrpcUnaryClientCall() {

      private FailOverUnaryFuture<Message, Message> newFailOverUnaryFuture(
          final MethodDescriptor<Message, Message> method) {
        if (FAILOVER_UNARAY_FUTRURES.containsKey(method)) {
          return FAILOVER_UNARAY_FUTRURES.get(method);
        } else {
          return new FailOverUnaryFuture<Message, Message>(method);
        }
      }


      @Override
      public ListenableFuture<Message> unaryFuture(Message request,
          MethodDescriptor<Message, Message> method) {
        FailOverUnaryFuture<Message, Message> retryCallListener = newFailOverUnaryFuture(method);
        retryCallListener.setRequest(request);
        retryCallListener.setMaxRetries(retryOptions);
        retryCallListener.setChannel(channel);
        retryCallListener.setCallOptions(callOptions);
        retryCallListener.run();
        return retryCallListener.getFuture();
      }

      @Override
      public Message blockingUnaryResult(Message request,
          MethodDescriptor<Message, Message> method) {
        FailOverUnaryFuture<Message, Message> retryCallListener = newFailOverUnaryFuture(method);
        retryCallListener.setRequest(request);
        retryCallListener.setMaxRetries(retryOptions);
        retryCallListener.setChannel(channel);
        retryCallListener.setCallOptions(callOptions);
        try {
          retryCallListener.run();
          return retryCallListener.getFuture().get();
        } catch (InterruptedException e) {
          retryCallListener.cancel();
          throw Status.CANCELLED.withCause(e).asRuntimeException();
        } catch (ExecutionException e) {
          retryCallListener.cancel();
          throw Status.fromThrowable(e).asRuntimeException();
        }
      }
    };
  }

  static final Map<MethodDescriptor<Message, Message>, FailOverUnaryFuture<Message, Message>> FAILOVER_UNARAY_FUTRURES =
      Collections.synchronizedMap(
          new WeakHashMap<MethodDescriptor<Message, Message>, FailOverUnaryFuture<Message, Message>>());

}


<|start_filename|>saluki-ops/spring-boot-starter-salukiops/src/main/resources/META-INF/static/assets/js/saluki.js<|end_filename|>
$(document).ready(function(){
	var TTEXT_MIME_TYPE = 'application/x-thrift; protocol=TTEXT';
    var specification = {};
    var navTemplate = Handlebars.compile($('#nav-template').html());
    var previousFragmentPath = null;
    var options = {
              mode: 'form',
              modes: ['code', 'form', 'text', 'tree', 'view'],
    };
    var container_request = document.getElementById("editor_holder_request");
	var editor_request = new JSONEditor(container_request, options);
	var container_response = document.getElementById("editor_holder_response");
	var editor_response = new JSONEditor(container_response, options);
    $.getJSON('service/getAllService', function (data) {
	      specification = {services:data}
	      $('.sidebar').html(navTemplate({specification: specification}));
	});
	$('#function').hide();
	$('#functionbutton').hide();
    $(window).trigger('hashchange');
    $(window).on('hashchange', function () {
        render(URI(window.location.href));
    });
    $('#editor_btn_submitParam').click(function() {
             editor_response.set('{There is have no response}');
             $('#editor_btn_submitParam').attr('disabled',"true");
	         var data = {
	           service:$('#servicetest_serviceName').val(),
	           method:$('#servicetest_methodName').val(),
	           parameterType:$('#servicetest_requestType').val(),
	           returnType:$('#servicetest_responseType').val(),
	           parameter:JSON.stringify(editor_request.get()) 
	         };
	         $.ajax({ 
	            type: "POST", 
	            url: "service/testLocal?routerRule="+URLencode($('#routerRule').val()), 
	            contentType: "application/json",  
	            data: JSON.stringify(data),
	            success: function(result) { 
	               $('#editor_btn_submitParam').removeAttr("disabled");
	               editor_response.set(result);
	            },
	            error : function(jqXHR, textStatus, errorThrown){
	                $('#editor_holder_response').width(600);
	                $('#editor_holder_response').height(200);
	                $('#editor_holder_response').html("<p class='text-info'>"+jqXHR.responseText+"</p>");
	                $('#editor_btn_submitParam').removeAttr("disabled");
	                setInterval(function(){
	                   self.local="/doc";
	                }, 3000);  
	            }
	         }); 
    });
    function URLencode(sStr){
       return escape(sStr).replace(/\+/g, '%2B').replace(/\"/g,'%22').replace(/\'/g, '%27').replace(/\//g,'%2F');
    }
    function render(uri) {
	    var fragmentUri = uri.fragment(true);
	    var path = fragmentUri.pathname();
	    if (path == previousFragmentPath) {
	      return;
	    }
	    previousFragmentPath = path;
	    var hashSplit = path.split('/');
	    var prefix = hashSplit[0];
	    var mapping = {
	      'function': function (serviceName, functionName) {
	        renderFunction(serviceName, functionName);
	      }
	    };
	    if (mapping[prefix]) {
	       mapping[prefix].apply(this, hashSplit.slice(1));
	    } 
    }
    function renderFunction(serviceName, functionName){
         $('#home').hide();
         $('#function').show();
         $('#functionbutton').show();
         $('#page_header').html('<code title="'+serviceName+'.'+functionName+'()">'+serviceName+'.'+functionName+'()</code>');
         $('#servicetest_serviceName').val(serviceName)
         $('#servicetest_methodName').val(functionName),
         $.getJSON("service/getMethod",{ service: serviceName, method: functionName },function(result){
			 editor_request.set(result.parameterTypes[0]);
			 $('#servicetest_requestType').val(result.parameterTypes[0].class);
			 $('#servicetest_responseType').val(result.returnType.class);
		 });
    }
    
}); 



<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/server/internal/ServerInvocation.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.grpc.server.internal;

import java.lang.reflect.Method;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.protobuf.Message;
import io.github.saluki.common.Constants;
import io.github.saluki.common.GrpcURL;
import io.github.saluki.common.NamedThreadFactory;
import io.github.saluki.common.RpcContext;
import io.github.saluki.grpc.annotation.GrpcMethodType;
import io.github.saluki.grpc.service.MonitorService;
import io.github.saluki.grpc.stream.PoJo2ProtoStreamObserver;
import io.github.saluki.grpc.stream.Proto2PoJoStreamObserver;
import io.github.saluki.grpc.util.SerializerUtil;

import io.grpc.Status;
import io.grpc.StatusRuntimeException;
import io.grpc.stub.ServerCalls.BidiStreamingMethod;
import io.grpc.stub.ServerCalls.ClientStreamingMethod;
import io.grpc.stub.ServerCalls.ServerStreamingMethod;
import io.grpc.stub.StreamObserver;
import io.netty.util.internal.ThrowableUtil;

/**
 * @author shimingliu 2016年12月14日 下午10:14:18
 * @version ServerInvocation.java, v 0.0.1 2016年12月14日 下午10:14:18 shimingliu
 */
@SuppressWarnings("unchecked")
public class ServerInvocation implements io.grpc.stub.ServerCalls.UnaryMethod<Message, Message>,
    ServerStreamingMethod<Message, Message>, ClientStreamingMethod<Message, Message>,
    BidiStreamingMethod<Message, Message> {

  private static final Logger log = LoggerFactory.getLogger(ServerInvocation.class);

  private final MonitorService salukiMonitor;

  private final Object serviceToInvoke;

  private final Method method;

  private final GrpcURL providerUrl;

  private final GrpcMethodType grpcMethodType;

  private final ConcurrentMap<String, AtomicInteger> concurrents;

  private static final ExecutorService collectLogExecutor =
      Executors.newSingleThreadExecutor(new NamedThreadFactory("salukiCollectTask", true));

  private volatile String remote;

  public ServerInvocation(Object serviceToInvoke, Method method, GrpcMethodType grpcMethodType,
      GrpcURL providerUrl, ConcurrentMap<String, AtomicInteger> concurrents,
      MonitorService salukiMonitor) {
    this.serviceToInvoke = serviceToInvoke;
    this.method = method;
    this.grpcMethodType = grpcMethodType;
    this.salukiMonitor = salukiMonitor;
    this.providerUrl = providerUrl;
    this.concurrents = concurrents;
  }

  @Override
  public StreamObserver<Message> invoke(StreamObserver<Message> responseObserver) {
    try {
      this.remote = RpcContext.getContext().getAttachment(Constants.REMOTE_ADDRESS);
      Class<?> requestType = grpcMethodType.requestType();
      PoJo2ProtoStreamObserver servserResponseObserver =
          PoJo2ProtoStreamObserver.newObserverWrap(responseObserver);
      Object result = method.invoke(serviceToInvoke, servserResponseObserver);
      return Proto2PoJoStreamObserver.newObserverWrap((StreamObserver<Object>) result, requestType);
    } catch (Throwable e) {
      String stackTrace = ThrowableUtil.stackTraceToString(e);
      log.error(e.getMessage(), e);
      StatusRuntimeException statusException =
          Status.UNAVAILABLE.withDescription(stackTrace).asRuntimeException();
      responseObserver.onError(statusException);
    } finally {
      log.debug(String.format("Service: %s  Method: %s  RemoteAddress: %s",
          providerUrl.getServiceInterface(), method.getName(), this.remote));
    }
    return null;
  }


  @Override
  public void invoke(Message request, StreamObserver<Message> responseObserver) {
    this.remote = RpcContext.getContext().getAttachment(Constants.REMOTE_ADDRESS);
    switch (grpcMethodType.methodType()) {
      case UNARY:
        unaryCall(request, responseObserver);
        break;
      case SERVER_STREAMING:
        streamCall(request, responseObserver);
        break;
      default:
        break;
    }
  }


  private void streamCall(Message request, StreamObserver<Message> responseObserver) {
    try {
      Class<?> requestType = grpcMethodType.requestType();
      Object reqPojo = SerializerUtil.protobuf2Pojo(request, requestType);
      Object[] requestParams =
          new Object[] {reqPojo, PoJo2ProtoStreamObserver.newObserverWrap(responseObserver)};
      method.invoke(serviceToInvoke, requestParams);
    } catch (Throwable e) {
      String stackTrace = ThrowableUtil.stackTraceToString(e);
      log.error(e.getMessage(), e);
      StatusRuntimeException statusException =
          Status.UNAVAILABLE.withDescription(stackTrace).asRuntimeException();
      responseObserver.onError(statusException);
    } finally {
      log.debug(String.format("Service: %s  Method: %s  RemoteAddress: %s",
          providerUrl.getServiceInterface(), method.getName(), this.remote));
    }
  }


  private void unaryCall(Message request, StreamObserver<Message> responseObserver) {
    final Message reqProtoBufer = request;
    Message respProtoBufer = null;
    long start = System.currentTimeMillis();
    try {
      getConcurrent().getAndIncrement();
      Class<?> requestType = grpcMethodType.requestType();
      final Object reqPojo = SerializerUtil.protobuf2Pojo(reqProtoBufer, requestType);
      final Object respPojo = method.invoke(serviceToInvoke, new Object[] {reqPojo});
      respProtoBufer = SerializerUtil.pojo2Protobuf(respPojo);
      final Message collectMessage = respProtoBufer;
      collectLogExecutor.execute(new Runnable() {


        @Override
        public void run() {
          collect(reqProtoBufer, collectMessage, start, false);
        }
      });
      responseObserver.onNext(respProtoBufer);
      responseObserver.onCompleted();
    } catch (Throwable e) {
      String stackTrace = ThrowableUtil.stackTraceToString(e);
      log.error(e.getMessage(), e);
      final Message collectMessage = respProtoBufer;
      collectLogExecutor.execute(new Runnable() {


        @Override
        public void run() {
          collect(reqProtoBufer, collectMessage, start, true);
        }
      });
      StatusRuntimeException statusException =
          Status.UNAVAILABLE.withDescription(stackTrace).asRuntimeException();
      responseObserver.onError(statusException);
    } finally {
      log.info(String.format("Service: %s  Method: %s  RemoteAddress: %s",
          providerUrl.getServiceInterface(), method.getName(), this.remote));
      getConcurrent().decrementAndGet();
    }
  }

  // 信息采集
  private void collect(Message request, Message response, long start, boolean error) {
    try {
      if (request == null || response == null) {
        return;
      }
      long elapsed = System.currentTimeMillis() - start; // 计算调用耗时
      int concurrent = getConcurrent().get(); // 当前并发数
      String service = providerUrl.getServiceInterface(); // 获取服务名称
      String method = this.method.getName(); // 获取方法名
      String consumer = this.remote;// 远程服务器地址
      String host = providerUrl.getHost();
      int rpcPort = providerUrl.getPort();
      int registryRpcPort = providerUrl.getParameter(Constants.REGISTRY_RPC_PORT_KEY, rpcPort);
      salukiMonitor.collect(new GrpcURL(Constants.MONITOR_PROTOCOL, host, //
          registryRpcPort, //
          service + "/" + method, //
          MonitorService.TIMESTAMP, String.valueOf(start), //
          MonitorService.APPLICATION, providerUrl.getParameter(Constants.APPLICATION_NAME), //
          MonitorService.INTERFACE, service, //
          MonitorService.METHOD, method, //
          MonitorService.CONSUMER, consumer, //
          error ? MonitorService.FAILURE : MonitorService.SUCCESS, "1", //
          MonitorService.ELAPSED, String.valueOf(elapsed), //
          MonitorService.CONCURRENT, String.valueOf(concurrent), //
          MonitorService.INPUT, String.valueOf(request.getSerializedSize()), //
          MonitorService.OUTPUT, String.valueOf(response.getSerializedSize())));
    } catch (Throwable t) {
      log.warn("Failed to monitor count service " + this.serviceToInvoke.getClass() + ", cause: "
          + t.getMessage());
    }

  }

  public String getRpcName() {
    return this.providerUrl.getServiceInterface() + ":" + method.getName();
  }

  public String getLocalAddressString() {
    return this.providerUrl.getAddress();
  }

  private AtomicInteger getConcurrent() {
    String key = serviceToInvoke.getClass().getName() + "." + method.getName();
    AtomicInteger concurrent = concurrents.get(key);
    if (concurrent == null) {
      concurrents.putIfAbsent(key, new AtomicInteger());
      concurrent = concurrents.get(key);
    }
    return concurrent;
  }
}


<|start_filename|>saluki-example/saluki-example-client/Dockerfile<|end_filename|>
FROM yingjunjiao/runtime-image:1.0
ENV TZ="Asia/Shanghai"
ENV LANG C.UTF-8
ADD saluki-example/saluki-example-client/target/saluki-example-client-1.5.2-SNAPSHOT.jar /root/app.jar
ADD bin/ /root/
RUN chmod +x /root/*.sh;mkdir /root/logs
ENV JAVA_OPTS ""
ENV APP_NAME saluki-example-consumer
WORKDIR /root
CMD ["./start.sh"]

<|start_filename|>spring-boot-starter-saluki/src/main/java/io/github/saluki/boot/runner/GrpcReferenceRunner.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.boot.runner;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.env.Environment;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import io.github.saluki.boot.SalukiReference;
import io.github.saluki.boot.autoconfigure.GrpcProperties;
import io.github.saluki.config.RpcReferenceConfig;
import io.github.saluki.grpc.service.GenericService;
import io.github.saluki.utils.CollectionUtils;

import io.grpc.stub.AbstractStub;

/**
 * @author shimingliu 2016年12月16日 下午5:07:02
 * @version GrpcReferenceRunner.java, v 0.0.1 2016年12月16日 下午5:07:02 shimingliu
 */
public class GrpcReferenceRunner extends InstantiationAwareBeanPostProcessorAdapter {

  private static final Logger logger = LoggerFactory.getLogger(GrpcReferenceRunner.class);

  private static final Pattern REPLACE_PATTERN = Pattern.compile("#\\{(.*?)\\}");

  private final Map<String, Object> serviceBean = Maps.newConcurrentMap();

  private final List<Map<String, String>> servcieReferenceDefintions = Lists.newArrayList();

  private final GrpcProperties grpcProperties;

  @Value("${spring.application.name}")
  private String applicationName;

  @Value("${server.port}")
  private int httpPort;

  @Autowired
  private AbstractApplicationContext applicationContext;

  @Autowired
  private Environment env;

  public GrpcReferenceRunner(GrpcProperties props) {
    this.grpcProperties = props;
    String referenceDefinPath = props.getReferenceDefinition();
    if (StringUtils.isNoneBlank(referenceDefinPath)) {
      InputStream in =
          GrpcReferenceRunner.class.getClassLoader().getResourceAsStream(referenceDefinPath);
      servcieReferenceDefintions.addAll(new Gson().fromJson(new InputStreamReader(in),
          new TypeToken<List<Map<String, String>>>() {}.getType()));
    } else {
      logger.warn("Waring! there is no reference config in classpath,You must config in annoation");
    }
  }

  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName)
      throws BeansException {
    Class<?> searchType = bean.getClass();
    while (!Object.class.equals(searchType) && searchType != null) {
      Field[] fields = searchType.getDeclaredFields();
      for (Field field : fields) {
        SalukiReference reference = field.getAnnotation(SalukiReference.class);
        if (reference != null) {
          Object value = null;
          try {
            value = applicationContext.getBean(field.getType());
          } catch (NoSuchBeanDefinitionException e) {
            value = null;
          }
          if (value == null) {
            value = refer(reference, field.getType());
          }
          try {
            if (!field.isAccessible()) {
              field.setAccessible(true);
            }
            field.set(bean, value);
          } catch (Throwable e) {
            logger.error("Failed to init remote service reference at filed " + field.getName()
                + " in class " + bean.getClass().getName() + ", cause: " + e.getMessage(), e);
          }
        }
      }
      searchType = searchType.getSuperclass();
    }
    return bean;
  }

  private Object refer(SalukiReference reference, Class<?> referenceClass) {
    RpcReferenceConfig rpcReferenceConfig = new RpcReferenceConfig();
    String serviceName = this.getServiceName(reference, referenceClass);
    if (serviceBean.containsKey(serviceName) && !isGrpcStubClient(referenceClass)
        && !isGenericClient(referenceClass)) {
      return serviceBean.get(serviceName);
    } else {
      rpcReferenceConfig.setServiceName(serviceName);
      rpcReferenceConfig.setApplication(applicationName);
      String group = this.getGroup(reference, serviceName, referenceClass);
      rpcReferenceConfig.setGroup(group);
      String version = this.getVersion(reference, serviceName, referenceClass);
      rpcReferenceConfig.setVersion(version);
      this.addHaRetries(reference, rpcReferenceConfig);
      this.addFallback(reference, rpcReferenceConfig);
      this.addRegistyAddress(rpcReferenceConfig);
      this.addAsyncAndTimeOut(reference, rpcReferenceConfig);
      this.addMonitorInterval(rpcReferenceConfig);
      this.addHostAndPort(rpcReferenceConfig);
      this.addValidatorGroups(reference, rpcReferenceConfig);
      if (this.isGenericClient(referenceClass)) {
        rpcReferenceConfig.setGeneric(true);
      }
      if (this.isGrpcStubClient(referenceClass)) {
        rpcReferenceConfig.setGrpcStub(true);
        rpcReferenceConfig.setServiceClass(referenceClass);
      }
      Object bean = rpcReferenceConfig.getProxyObj();
      serviceBean.putIfAbsent(serviceName, bean);
      return bean;
    }
  }

  @SuppressWarnings({"rawtypes"})
  private void addValidatorGroups(final SalukiReference reference,
      final RpcReferenceConfig rpcReferenceConfig) {
    if (reference.validatorGroups() != null && reference.validatorGroups().length > 0) {
      logger.info("Have validator groups: " + reference.validatorGroups());
      rpcReferenceConfig
          .setValidatorGroups(new HashSet<Class>(Arrays.asList(reference.validatorGroups())));
    }
  }

  private void addHostAndPort(RpcReferenceConfig rpcReferenceConfig) {
    String host = grpcProperties.getHost();
    int registryHttpPort = grpcProperties.getRegistryHttpPort();
    if (StringUtils.isNoneBlank(host)) {
      rpcReferenceConfig.setHost(host);
    }
    if (registryHttpPort == 0) {
      if (this.httpPort != 0) {
        rpcReferenceConfig.setHttpPort(this.httpPort);
        grpcProperties.setRegistryHttpPort(this.httpPort);
      } else {
        throw new java.lang.IllegalArgumentException("http port must be set in properties");
      }
    } else {
      rpcReferenceConfig.setHttpPort(registryHttpPort);
    }

  }

  private void addMonitorInterval(RpcReferenceConfig rpcReferenceConfig) {
    if (grpcProperties.getMonitorinterval() != 0) {
      rpcReferenceConfig.setMonitorinterval(grpcProperties.getMonitorinterval());
    }
  }

  private void addAsyncAndTimeOut(SalukiReference reference,
      RpcReferenceConfig rpcReferenceConfig) {
    rpcReferenceConfig.setAsync(reference.async());
    if (reference.timeOut() != 0) {
      rpcReferenceConfig.setTimeout(reference.timeOut());
    }
  }

  private void addRegistyAddress(RpcReferenceConfig rpcReferenceConfig) {
    String registryAddress = grpcProperties.getRegistryAddress();
    if (StringUtils.isBlank(registryAddress)) {
      throw new java.lang.IllegalArgumentException("registry address can not be null or empty");
    } else {
      String[] registryHostAndPort = StringUtils.split(registryAddress, ":");
      if (registryHostAndPort.length < 2) {
        throw new java.lang.IllegalArgumentException(
            "the pattern of registry address is host:port");
      }
      rpcReferenceConfig.setRegistryAddress(registryHostAndPort[0]);
      rpcReferenceConfig.setRegistryPort(Integer.valueOf(registryHostAndPort[1]));
    }
  }

  private void addHaRetries(SalukiReference reference, RpcReferenceConfig rpcReferenceConfig) {
    if (reference.retries() > 1) {
      if (CollectionUtils.isEmpty(reference.retryMethods())) {
        logger.warn("Have set retries,but not have set method,will set all method to retry");
        rpcReferenceConfig
            .setRetryMethods(new HashSet<String>(Arrays.asList(reference.retryMethods())));
        rpcReferenceConfig.setReties(reference.retries());
      }
    }
  }

  private void addFallback(SalukiReference reference, RpcReferenceConfig rpcReferenceConfig) {
    Boolean isEnableFallback = reference.fallback();
    if (isEnableFallback) {
      rpcReferenceConfig.setEnabledFallBack(isEnableFallback);
      if (CollectionUtils.isEmpty(reference.fallBackMethods())) {
        logger.warn("Have set fallback,but not have set method,will set all method to fallback");
        rpcReferenceConfig
            .setFallbackMethods(new HashSet<String>(Arrays.asList(reference.retryMethods())));
      }
    }
  }

  private String getServiceName(SalukiReference reference, Class<?> referenceClass) {
    String serviceName = reference.service();
    if (StringUtils.isBlank(serviceName)) {
      if (this.isGrpcStubClient(referenceClass)) {
        throw new java.lang.IllegalArgumentException("reference service can not be null or empty");
      } else {
        serviceName = referenceClass.getName();
      }
    }
    return serviceName;
  }

  private String getGroup(SalukiReference reference, String serviceName, Class<?> referenceClass) {
    Pair<String, String> groupVersion = findGroupAndVersionByServiceName(serviceName);
    if (StringUtils.isNoneBlank(reference.group())) {
      return reference.group();
    } else if (StringUtils.isNoneBlank(groupVersion.getLeft())) {
      String replaceGroup = groupVersion.getLeft();
      Matcher matcher = REPLACE_PATTERN.matcher(replaceGroup);
      if (matcher.find()) {
        String replace = matcher.group().substring(2, matcher.group().length() - 1).trim();
        String[] replaces = StringUtils.split(replace, ":");
        if (replaces.length == 2) {
          String realGroup = env.getProperty(replaces[0], replaces[1]);
          return realGroup;
        } else {
          throw new IllegalArgumentException("replaces formater is #{XXXgroup:groupName}");
        }
      } else {
        return replaceGroup;
      }
    } else if (this.isGenericClient(referenceClass)) {
      return StringUtils.EMPTY;
    }
    throw new java.lang.IllegalArgumentException(String
        .format("reference group can not be null or empty,the servicName is %s", serviceName));

  }

  private String getVersion(SalukiReference reference, String serviceName,
      Class<?> referenceClass) {
    Pair<String, String> groupVersion = findGroupAndVersionByServiceName(serviceName);
    if (StringUtils.isNoneBlank(reference.version())) {
      return reference.version();
    } else if (StringUtils.isNoneBlank(groupVersion.getRight())) {
      String replaceVersion = groupVersion.getRight();
      Matcher matcher = REPLACE_PATTERN.matcher(replaceVersion);
      if (matcher.find()) {
        String replace = matcher.group().substring(2, matcher.group().length() - 1).trim();
        String[] replaces = StringUtils.split(replace, ":");
        if (replaces.length == 2) {
          String realVersion = env.getProperty(replaces[0], replaces[1]);
          return realVersion;
        } else {
          throw new IllegalArgumentException("replaces formater is #{XXXservice:1.0.0}");
        }
      } else {
        return replaceVersion;
      }
    } else if (this.isGenericClient(referenceClass)) {
      return StringUtils.EMPTY;
    } else {
      throw new java.lang.IllegalArgumentException("reference version can not be null or empty");
    }
  }

  private Pair<String, String> findGroupAndVersionByServiceName(String serviceName) {
    for (Map<String, String> referenceDefintion : servcieReferenceDefintions) {
      String servcieDefineName = referenceDefintion.get("service");
      if (servcieDefineName.equals(serviceName)) {
        String group = referenceDefintion.get("group");
        String version = referenceDefintion.get("version");
        return new ImmutablePair<String, String>(group, version);
      }
    }
    return new ImmutablePair<String, String>(null, null);
  }

  private boolean isGrpcStubClient(Class<?> referenceClass) {
    if (AbstractStub.class.isAssignableFrom(referenceClass)) {
      return true;
    } else {
      return false;
    }
  }

  private boolean isGenericClient(Class<?> referenceClass) {
    if (GenericService.class.isAssignableFrom(referenceClass)) {
      return true;
    } else {
      return false;
    }
  }

}


<|start_filename|>saluki-ops/saluki-ops-console/Dockerfile<|end_filename|>
FROM yingjunjiao/runtime-image:1.0
ENV TZ="Asia/Shanghai"
ENV LANG C.UTF-8
RUN apk add --update curl && \
    rm -rf /var/cache/apk/*
ADD saluki-monitor/saluki-monitor-console/target/saluki-monitor-console-1.5.3-SNAPSHOT.jar /root/app.jar
ADD bin /root/
RUN chmod +x /root/*.sh;mkdir /root/logs
RUN mkdir /root/pinpoint-agent-1.6.1-SNAPSHOT \
    && curl -o /root/pinpoint-agent-1.6.1-SNAPSHOT/pinpoint-agent-1.6.1-SNAPSHOT.zip --user 'liushiming:Hello899' http://repo.quancheng-ec.com/repository/documentation/pinpoint-agent-1.6.1-SNAPSHOT.zip \
	&& unzip -o -d /root/pinpoint-agent-1.6.1-SNAPSHOT /root/pinpoint-agent-1.6.1-SNAPSHOT/pinpoint-agent-1.6.1-SNAPSHOT.zip \
    && rm -r /root/pinpoint-agent-1.6.1-SNAPSHOT/pinpoint-agent-1.6.1-SNAPSHOT.zip
ENV JAVA_OPTS ""
ENV APP_NAME monitor
WORKDIR /root
CMD ["./start.sh"]

<|start_filename|>saluki-plugin/saluki-plugin-common/src/main/java/io/github/saluki/plugin/common/PrintEnumFile.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the
 * confidential and proprietary information of Quancheng-ec.com ("Confidential
 * Information"). You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement you entered
 * into with Quancheng-ec.com.
 */
package io.github.saluki.plugin.common;

import java.util.List;

import com.google.common.collect.Lists;
import com.google.protobuf.DescriptorProtos.EnumValueDescriptorProto;

/**
 * @author shimingliu 2016年12月19日 下午3:14:06
 * @version GenerateFileUtil.java, v 0.0.1 2016年12月19日 下午3:14:06 shimingliu
 */
public final class PrintEnumFile extends AbstractPrint {

    private List<EnumValueDescriptorProto> enumFields;

    public PrintEnumFile(String fileRootPath, String sourcePackageName, String className){
        super(fileRootPath, sourcePackageName, className);
    }

    public void setEnumFields(List<EnumValueDescriptorProto> enumFields) {
        this.enumFields = enumFields;
    }

    @Override
    protected List<String> collectFileData() {
        String className = super.getClassName();
        String packageName = super.getSourcePackageName().toLowerCase();
        List<String> fileData = Lists.newArrayList();
        fileData.add("package " + packageName + ";");
        fileData.add("");

        fileData.add("public enum " + className + "{");
        fileData.add("");

        for (int i = 0; i < enumFields.size(); i++) {
            EnumValueDescriptorProto enumField = enumFields.get(i);
            if (i == enumFields.size() - 1) {
                fileData.add("  " + enumField.getName() + "(" + enumField.getNumber() + ");");
            } else {
                fileData.add("  " + enumField.getName() + "(" + enumField.getNumber() + "),");
            }
        }

        fileData.add("");

        fileData.add("  private final int value;");
        fileData.add("");

        fileData.add("  private " + className + "(int value) {");
        fileData.add("      this.value = value;");
        fileData.add("  }");
        fileData.add("");

        fileData.add("  public final int getNumber() {");
        fileData.add("      return value;");
        fileData.add("  }");
        fileData.add("");

        fileData.add("  public static " + className + " forNumber(Integer value) {");
        fileData.add("      switch (value) {");
        for (int i = 0; i < enumFields.size(); i++) {
            EnumValueDescriptorProto enumField = enumFields.get(i);
            if (i == enumFields.size() - 1) {
                fileData.add("      case " + enumField.getNumber() + ":");
                fileData.add("          return " + enumField.getName() + ";");
                fileData.add("      default:");
                fileData.add("          return null;");
            } else {
                fileData.add("      case " + enumField.getNumber() + ":");
                fileData.add("          return " + enumField.getName() + ";");
            }
        }
        fileData.add("      }");
        fileData.add("");

        fileData.add("  }");
        fileData.add("");

        fileData.add("}");
        return fileData;
    }

}


<|start_filename|>saluki-example/saluki-example-server/src/main/java/io/github/saluki/example/server/StubHelloService.java<|end_filename|>
package io.github.saluki.example.server;
///*
// * Copyright 2014-2017 the original author or authors.
// *
// * 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 io.github.saluki.example.server;
//
//import io.github.examples.model.Hello;
//import io.github.examples.service.HelloServiceGrpc;
//import io.github.saluki.boot.SalukiService;
//
///**
// * @author liushiming
// * @version StubHellService.java, v 0.0.1 2017年6月20日 上午11:15:45 liushiming
// * @since JDK 1.8
// */
//@SalukiService(service = "io.github.examples.service.HelloService")
//public class StubHellService extends HelloServiceGrpc.HelloServiceImplBase {
//
//  @Override
//  public void sayHello(io.github.examples.model.Hello.HelloRequest request,
//      io.grpc.stub.StreamObserver<io.github.examples.model.Hello.HelloReply> responseObserver) {
//    Hello.HelloReply.Builder replyBuild = Hello.HelloReply.newBuilder();
//    replyBuild.setMessage(request.getName());
//    responseObserver.onNext(replyBuild.build());
//    responseObserver.onCompleted();
//  }
//}


<|start_filename|>saluki-ops/saluki-ops-console/src/main/java/io/github/saluki/monitor/ops/controller/RegistryController.java<|end_filename|>
package io.github.saluki.monitor.ops.controller;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import io.github.saluki.monitor.dao.domain.GrpcService;
import io.github.saluki.monitor.ops.service.ConsulRegistryService;

@RestController
@RequestMapping(value = "/api/service")
public class RegistryController {

    private static final Logger log = LoggerFactory.getLogger(RegistryController.class);

    @Autowired
    private ConsulRegistryService registrySerivce;

    @RequestMapping(value = "/fuzzyapp", method = RequestMethod.GET)
    public List<GrpcService> queryByApp(@RequestParam(value = "search", required = true) String search) {
        log.info("Return all service from registry");
        return registrySerivce.queryPassingServiceByApp(search, Boolean.FALSE);
    }

    @RequestMapping(value = "/fuzzyservice", method = RequestMethod.GET)
    public List<GrpcService> queryByService(@RequestParam(value = "search", required = true) String search) {
        log.info("Return all service from registry");
        return registrySerivce.queryPassingServiceByService(search, Boolean.FALSE);
    }

    @RequestMapping(value = "/accurateapp", method = RequestMethod.GET)
    public List<GrpcService> getByApp(@RequestParam(value = "search", required = true) String search) {
        log.info("Return all service from registry");
        return registrySerivce.queryPassingServiceByApp(search, Boolean.TRUE);
    }

    @RequestMapping(value = "/accurateservice", method = RequestMethod.GET)
    public List<GrpcService> getByService(@RequestParam(value = "search", required = true) String search) {
        log.info("Return all service from registry");
        return registrySerivce.queryPassingServiceByService(search, Boolean.TRUE);
    }

}


<|start_filename|>saluki-example/saluki-example-api/src/main/java/com/saluki/example/model/Second.java<|end_filename|>
package com.saluki.example.model;

/**
 * Created by guoyubo on 2017/7/22.
 */
public interface Second {
}


<|start_filename|>saluki-ops/spring-boot-starter-salukiops/src/main/java/io/github/saluki/monitor/jaket/util/GenericInvokeUtils.java<|end_filename|>
package io.github.saluki.monitor.jaket.util;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.github.saluki.monitor.jaket.model.GenericInvokeMetadata;
import io.github.saluki.monitor.jaket.model.MetadataType;
import io.github.saluki.monitor.jaket.model.MethodDefinition;
import io.github.saluki.monitor.jaket.model.ServiceDefinition;
import io.github.saluki.monitor.jaket.model.TypeDefinition;

/**
 * @author bw on 11/25/15.
 */
public class GenericInvokeUtils {

    private static Logger  logger             = LoggerFactory.getLogger(GenericInvokeUtils.class);
    private static Pattern COLLECTION_PATTERN = Pattern.compile("^java\\.util\\..*(Set|List|Queue|Collection|Deque)(<.*>)*$");
    private static Pattern MAP_PATTERN        = Pattern.compile("^java\\.util\\..*Map.*(<.*>)*$");

    public static GenericInvokeMetadata getGenericInvokeMetadata(ServiceDefinition serviceDefinition,
                                                                 String methodSignature, MetadataType metadataType) {
        MethodDefinition methodDefinition = findMethodDefinition(serviceDefinition, methodSignature);
        if (methodDefinition == null) {
            return null;
        }

        GenericInvokeMetadata genericInvokeMetadata = new GenericInvokeMetadata();
        Object returnType = generateReturnType(serviceDefinition, methodDefinition, metadataType);
        genericInvokeMetadata.setReturnType(returnType);
        List<Object> parameterTypes = generateParameterTypes(serviceDefinition, methodDefinition, metadataType);
        genericInvokeMetadata.setParameterTypes(parameterTypes);
        genericInvokeMetadata.setSignature(methodSignature);
        return genericInvokeMetadata;
    }

    public static String[] findParameterTypes(String methodSignature, boolean erase) {
        String parameterStr = StringUtils.substringAfter(methodSignature, "~");
        String[] types = StringUtils.split(parameterStr, ';');
        if (erase) {
            for (int i = 0; i < types.length; i++) {
                types[i] = StringUtils.substringBefore(types[i], "<");
            }
        }
        return types;
    }

    public static String findMethodName(String methodSignature) {
        return StringUtils.substringBefore(methodSignature, "~");
    }

    static void generateComplexType(ServiceDefinition def, TypeDefinition td, Map<String, Object> map,
                                    MetadataType metadataType, Set<String> resolvedTypes) {
        Map<String, TypeDefinition> properties = td.getProperties();
        if (properties.isEmpty()) {
            logger.warn("unrecognized type: {}", td.getType());
            // FIXME: for unrecognized type, should we simply return without put its type in 'class' key?
        }

        String type = td.getType();
        map.put("class", type);
        if (resolvedTypes.contains(type)) {
            return;
        }
        resolvedTypes.add(type);
        properties.keySet().stream().forEach(key -> generateEnclosedType(def, key, properties.get(key), map,
                                                                         metadataType, resolvedTypes));
    }

    static Object generateType(ServiceDefinition def, String type, MetadataType metadataType,
                               Set<String> resolvedTypes) {
        TypeDefinition td = findTypeDefinition(def, type);
        return generateType(def, td, metadataType, resolvedTypes);
    }

    private static Object generateType(ServiceDefinition def, TypeDefinition td, MetadataType metadataType,
                                       Set<String> resolvedTypes) {
        String type = td.getType();
        return isPrimitiveType(td) ? generate(def, td,
                                              metadataType) : isArray(td) ? generateArrayType(def, type, metadataType,
                                                                                              resolvedTypes) : isCollection(td) ? generateCollectionType(def,
                                                                                                                                                         type, metadataType, resolvedTypes) : isMap(td) ? generateMapType(def,
                                                                                                                                                                                                                          td,
                                                                                                                                                                                                                          metadataType,
                                                                                                                                                                                                                          resolvedTypes) : isEnum(td) ? generate(def,
                                                                                                                                                                                                                                                                 td, metadataType) : isCircularReferenceType(td) ? generate(def,
                                                                                                                                                                                                                                                                                                                            td, metadataType) : generateComplexType(def,
                                                                                                                                                                                                                                                                                                                                                                    td,
                                                                                                                                                                                                                                                                                                                                                                    metadataType,
                                                                                                                                                                                                                                                                                                                                                                    resolvedTypes);
    }

    private static void generateEnclosedType(ServiceDefinition def, String key, TypeDefinition enclosedType,
                                             Map<String, Object> map, MetadataType metadataType,
                                             Set<String> resolvedTypes) {
        if (enclosedType.getProperties() == null || enclosedType.getProperties().isEmpty()) {
            map.put(key, generateType(def, enclosedType, metadataType, resolvedTypes));
        } else {
            Map<String, Object> enclosedMap = new HashMap<>();
            map.put(key, enclosedMap);
            generateComplexType(def, enclosedType, enclosedMap, metadataType, resolvedTypes);
        }
    }

    private static Object generate(ServiceDefinition def, TypeDefinition td, MetadataType metadataType) {
        if (metadataType == MetadataType.CLASS_TYPE) {
            return td.getType();
        } else if (metadataType == MetadataType.DEFAULT_VALUE) {
            if (isEnum(td)) {
                return generateEnumType(def, td);
            } else {
                return defaultValue(td.getType());
            }
        } else {
            logger.error("invalid metadata type: {}", metadataType);
            throw new IllegalArgumentException("invalid metadata type " + metadataType);
        }
    }

    private static Object generateComplexType(ServiceDefinition def, TypeDefinition td, MetadataType metadataType,
                                              Set<String> resolvedTypes) {
        Map<String, Object> map = new HashMap<>();
        if (resolvedTypes == Collections.EMPTY_SET) {
            resolvedTypes = new HashSet<>();
        }
        generateComplexType(def, td, map, metadataType, resolvedTypes);
        return map;
    }

    private static Object generateEnumType(ServiceDefinition def, TypeDefinition td) {
        return td.getEnums().get(0);
    }

    private static Object generateArrayType(ServiceDefinition def, String type, MetadataType metadataType,
                                            Set<String> resolvedTypes) {
        type = StringUtils.substringBeforeLast(type, "[]");
        return new Object[] { generateType(def, type, metadataType, resolvedTypes) };
    }

    private static Object generateCollectionType(ServiceDefinition def, String type, MetadataType metadataType,
                                                 Set<String> resolvedTypes) {
        type = StringUtils.substringAfter(type, "<");
        type = StringUtils.substringBefore(type, ">");
        if (StringUtils.isEmpty(type)) {
            type = "java.lang.Object";
        }
        return new Object[] { generateType(def, type, metadataType, resolvedTypes) };
    }

    // FIXME: cannot generate correct json string when the key is complex type
    private static Object generateMapType(ServiceDefinition def, TypeDefinition td, MetadataType metadataType,
                                          Set<String> resolvedTypes) {
        String keyType = StringUtils.substringAfter(td.getType(), "<");
        keyType = StringUtils.substringBefore(keyType, ",");
        keyType = StringUtils.strip(keyType);
        keyType = StringUtils.isNotEmpty(keyType) ? keyType : "java.lang.Object";
        Object key = generateType(def, keyType, metadataType, resolvedTypes);

        String valueType = StringUtils.substringAfter(td.getType(), ",");
        valueType = StringUtils.substringBefore(valueType, ">");
        valueType = StringUtils.strip(valueType);
        valueType = StringUtils.isNotEmpty(valueType) ? valueType : "java.lang.Object";
        Object value = generateType(def, valueType, metadataType, resolvedTypes);

        Map<Object, Object> map = new HashMap<>();
        map.put(key, value);
        return map;
    }

    private static Object defaultValue(String type) {
        switch (type) {
            case "short":
            case "java.lang.Short":
            case "int":
            case "java.lang.Integer":
            case "long":
            case "java.lang.Long":
                return 0;
            case "float":
            case "java.lang.Float":
            case "double":
            case "java.lang.Double":
                return 0.0;
            case "boolean":
            case "java.lang.Boolean":
                return true;
            case "java.lang.String":
                return "";
            case "java.lang.Object":
                return "{}";
            case "java.util.Date":
                return System.currentTimeMillis();
            default:
                return "{}";
        }
    }

    private static List<Object> generateParameterTypes(ServiceDefinition sd, MethodDefinition md,
                                                       MetadataType metadataType) {
        return Stream.of(md.getParameterTypes()).map(t -> generateType(sd, t, metadataType,
                                                                       Collections.emptySet())).collect(Collectors.toList());
    }

    private static Object generateReturnType(ServiceDefinition sd, MethodDefinition md, MetadataType metadataType) {
        return generateType(sd, md.getReturnType(), metadataType, Collections.emptySet());
    }

    private static TypeDefinition findTypeDefinition(ServiceDefinition def, String type) {
        return def.getTypes().stream().filter(t -> t.getType().equals(type)).findFirst().orElse(new TypeDefinition(type));
    }

    private static boolean isArray(TypeDefinition def) {
        return StringUtils.endsWith(def.getType(), "[]");
    }

    private static boolean isCircularReferenceType(TypeDefinition td) {
        return StringUtils.isNotEmpty(td.get$ref());
    }

    static boolean isCollection(TypeDefinition def) {
        Matcher matcher = COLLECTION_PATTERN.matcher(def.getType());
        return matcher.matches();
    }

    private static boolean isEnum(TypeDefinition td) {
        return td.getEnums() != null && !td.getEnums().isEmpty();
    }

    static boolean isMap(TypeDefinition def) {
        Matcher matcher = MAP_PATTERN.matcher(def.getType());
        return matcher.matches();
    }

    private static boolean isPrimitiveType(TypeDefinition def) {
        String type = def.getType();
        return type.equals("byte") || type.equals("java.lang.Byte") || type.equals("short")
               || type.equals("java.lang.Short") || type.equals("int") || type.equals("java.lang.Integer")
               || type.equals("long") || type.equals("java.lang.Long") || type.equals("float")
               || type.equals("java.lang.Float") || type.equals("double") || type.equals("java.lang.Double")
               || type.equals("boolean") || type.equals("java.lang.Boolean") || type.equals("void")
               || type.equals("java.lang.Void") || type.equals("java.lang.String") || type.equals("java.util.Date")
               || type.equals("java.lang.Object");
    }

    private static MethodDefinition findMethodDefinition(ServiceDefinition serviceDefinition, String methodSignature) {
        Optional<MethodDefinition> typeDefinition = serviceDefinition.getMethods().stream().filter(m -> m.getName().equals(findMethodName(methodSignature))
                                                                                                        && Arrays.equals(m.getParameterTypes(),
                                                                                                                         findParameterTypes(methodSignature,
                                                                                                                                            false))).findFirst();
        return typeDefinition.isPresent() ? typeDefinition.get() : null;
    }
}


<|start_filename|>saluki-plugin/saluki-maven-plugin/src/main/java/io/github/saluki/plugin/maven/Proto2Java.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.plugin.maven;

import java.io.File;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;

import com.google.common.collect.Lists;

import io.github.saluki.plugin.common.CommonProto2Java;

/**
 * @author shimingliu 2016年12月17日 下午12:31:10
 * @version CountMojo.java, v 0.0.1 2016年12月17日 下午12:31:10 shimingliu
 */
@Mojo(name = "proto2java", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
public class Proto2Java extends AbstractMojo {

  @Parameter(defaultValue = "src/main/proto")
  private String protoPath;

  @Parameter(defaultValue = "src/main/java")
  private String buildPath;

  private List<File> allProtoFile = Lists.newArrayList();

  @Override
  public void execute() throws MojoExecutionException, MojoFailureException {
    File deirectory = new File(protoPath);
    listAllProtoFile(deirectory);
    CommonProto2Java protp2ServicePojo = CommonProto2Java.forConfig(protoPath, buildPath);
    for (File file : allProtoFile) {
      if (file.exists()) {
        String protoFilePath = file.getPath();
        protp2ServicePojo.generateFile(protoFilePath);
      }
    }
  }

  private File listAllProtoFile(File file) {
    if (file != null) {
      if (file.isDirectory()) {
        File[] fileArray = file.listFiles();
        if (fileArray != null) {
          for (int i = 0; i < fileArray.length; i++) {
            listAllProtoFile(fileArray[i]);
          }
        }
      } else {
        if (StringUtils.endsWith(file.getName(), "proto")) {
          allProtoFile.add(file);
        }
      }
    }
    return null;
  }
}


<|start_filename|>saluki-ops/spring-boot-starter-salukiops/src/main/java/io/github/saluki/monitor/jaket/model/ServiceDefinition.java<|end_filename|>
package io.github.saluki.monitor.jaket.model;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by huangsheng.hs on 2015/1/27.
 */
public class ServiceDefinition {

    private String canonicalName;
    private String codeSource;
    private List<MethodDefinition> methods;
    private List<TypeDefinition> types;

    public String getCanonicalName() {
        return canonicalName;
    }

    public String getCodeSource() {
        return codeSource;
    }

    public List<MethodDefinition> getMethods() {
        if (methods == null) {
            methods = new ArrayList<MethodDefinition>();
        }
        return methods;
    }

    public List<TypeDefinition> getTypes() {
        if (types == null) {
            types = new ArrayList<TypeDefinition>();
        }
        return types;
    }

    public String getUniqueId() {
        return canonicalName + "@" + codeSource;
    }

    public void setCanonicalName(String canonicalName) {
        this.canonicalName = canonicalName;
    }

    public void setCodeSource(String codeSource) {
        this.codeSource = codeSource;
    }

    public void setMethods(List<MethodDefinition> methods) {
        this.methods = methods;
    }

    public void setTypes(List<TypeDefinition> types) {
        this.types = types;
    }

    @Override
    public String toString() {
        return "ServiceDefinition [canonicalName=" + canonicalName + ", codeSource=" + codeSource + ", methods="
                + methods + "]";
    }

}


<|start_filename|>saluki-example/saluki-example-client/src/main/java/io/github/saluki/example/client/ProxyServiceController.java<|end_filename|>
package io.github.saluki.example.client;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.saluki.example.model.First;
import com.saluki.example.model.Second;

import io.github.examples.model.hello.HelloReply;
import io.github.examples.model.hello.HelloRequest;
import io.github.examples.service.HelloService;
import io.github.saluki.boot.SalukiReference;
import io.github.saluki.common.RpcContext;
import io.grpc.stub.StreamObserver;

@RestController
@RequestMapping("/proxy")
public class ProxyServiceController {


  @SalukiReference(retries = 3, validatorGroups = {First.class, Second.class})
  private HelloService helloService;


  @RequestMapping("/hello")
  public HelloReply hello(@RequestParam(value = "name", required = false) String name) {
    return call(name);
  }


  @RequestMapping("/serverstream")
  public HelloReply serverstream(@RequestParam(value = "name", required = false) String name) {
    HelloRequest request = new HelloRequest();
    request.setName(name);
    helloService.sayHelloServerStream(request, responseObserver());
    return null;
  }

  @RequestMapping("/clientstream")
  public HelloReply clientstream(@RequestParam(value = "name", required = false) String name) {
    HelloRequest request = new HelloRequest();
    request.setName(name);
    RpcContext.getContext().set("123", "123");
    StreamObserver<io.github.examples.model.hello.HelloRequest> requestObserver =
        helloService.sayHelloClientStream(responseObserver());
    try {
      for (int i = 0; i < 10; i++) {
        requestObserver.onNext(request);
      }
    } catch (Exception e) {
      requestObserver.onError(e);
    }
    requestObserver.onCompleted();
    return null;
  }

  @RequestMapping("/bodistream")
  public HelloReply bodistream(@RequestParam(value = "name", required = false) String name) {
    HelloRequest request = new HelloRequest();
    request.setName(name);
    StreamObserver<io.github.examples.model.hello.HelloRequest> requestObserver =
        helloService.sayHelloBidiStream(responseObserver());
    try {
      for (int i = 0; i < 10; i++) {
        requestObserver.onNext(request);
      }
    } catch (Exception e) {
      requestObserver.onError(e);
    }
    requestObserver.onCompleted();
    return null;
  }


  private StreamObserver<io.github.examples.model.hello.HelloReply> responseObserver() {
    StreamObserver<io.github.examples.model.hello.HelloReply> responseObserver =
        new StreamObserver<io.github.examples.model.hello.HelloReply>() {
          @Override
          public void onNext(io.github.examples.model.hello.HelloReply summary) {
            System.out.println(summary.getMessage());
          }

          @Override
          public void onError(Throwable t) {
            t.printStackTrace();
          }

          @Override
          public void onCompleted() {

        }
        };
    return responseObserver;
  }



  private HelloReply call(final String name) {
    RpcContext.getContext().set("123", "123");
    HelloRequest request = new HelloRequest();
    request.setName(name);
    HelloReply reply = helloService.sayHello(request);
    // System.out.println(RpcContext.getContext().get("123"));
    return reply;
  }


}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/config/RpcServiceConfig.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.config;

import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import io.github.saluki.common.Constants;
import io.github.saluki.common.GrpcURL;

/**
 * @author shimingliu 2016年12月14日 下午2:14:34
 * @version RpcServiceConfig.java, v 0.0.1 2016年12月14日 下午2:14:34 shimingliu
 */
public class RpcServiceConfig extends RpcBaseConfig {

  private static final long serialVersionUID = 2638920613685526606L;

  private final Set<RpcServiceSingleConfig<Object>> singleServiceConfigs = Sets.newHashSet();

  private transient io.grpc.Server internalServer;

  public void destroy() {
    internalServer.shutdown();
  }

  public void await() {
    try {
      internalServer.awaitTermination();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }

  public void addServiceDefinition(String serviceName, String group, String version,
      Object instance) {
    RpcServiceSingleConfig<Object> singleServiceConfig = new RpcServiceSingleConfig<Object>();
    singleServiceConfig.setGroup(group);
    singleServiceConfig.setVersion(version);
    singleServiceConfig.setServiceName(serviceName);
    singleServiceConfig.setRef(instance);
    singleServiceConfigs.add(singleServiceConfig);
  }

  public synchronized void export() {
    Map<GrpcURL, Object> providerUrls = Maps.newHashMap();
    for (RpcServiceSingleConfig<Object> singleServiceConfig : singleServiceConfigs) {
      String serviceName = singleServiceConfig.getServiceName();
      Object serviceRef = singleServiceConfig.getRef();
      Map<String, String> params = Maps.newHashMap();
      this.addGroup(singleServiceConfig, params);
      this.addVersion(singleServiceConfig, params);
      this.addApplication(params);
      this.addInterval(params);
      this.addRegistryRpcPort(params);
      this.addHttpPort(params);
      GrpcURL providerUrl = new GrpcURL(Constants.REMOTE_PROTOCOL, super.getHost(),
          super.getRealityRpcPort(), serviceName, params);
      providerUrls.put(providerUrl, serviceRef);
    }
    try {
      internalServer =
          super.getGrpcEngine().getServer(providerUrls, super.getRealityRpcPort()).start();
    } catch (Exception e) {
      throw new IllegalStateException(e.getMessage(), e);
    }

  }

  private void addGroup(RpcServiceSingleConfig<Object> singleConfig, Map<String, String> params) {
    String group = singleConfig.getGroup();
    if (StringUtils.isNotBlank(group)) {
      params.put(Constants.GROUP_KEY, group);
    } else {
      String application = super.getApplication();
      if (StringUtils.isNotBlank(application)) {
        params.put(Constants.GROUP_KEY, application);
      }
    }
  }

  private void addVersion(RpcServiceSingleConfig<Object> singleConfig, Map<String, String> params) {
    String version = singleConfig.getVersion();
    if (StringUtils.isNotBlank(version)) {
      params.put(Constants.VERSION_KEY, version);
    }
  }

  private void addApplication(Map<String, String> params) {
    String application = super.getApplication();
    if (StringUtils.isNotBlank(application)) {
      params.put(Constants.APPLICATION_NAME, application);
    }
  }

  private void addInterval(Map<String, String> params) {
    Integer interval = getMonitorinterval();
    if (interval != 0) {
      params.put(Constants.MONITOR_INTERVAL, interval.toString());
    }
  }

  private void addRegistryRpcPort(Map<String, String> params) {
    Integer registryRpcPort = super.getRegistryRpcPort();
    if (registryRpcPort != 0) {
      params.put(Constants.REGISTRY_RPC_PORT_KEY, registryRpcPort.toString());
    }
  }

}


<|start_filename|>saluki-ops/spring-boot-starter-salukiops/src/main/resources/META-INF/static/assets/fonts/fonts.css<|end_filename|>
/* Source Sans Pro */

@font-face {
  font-family: 'Source Sans Pro';
  font-weight: normal;
  font-style: normal;
  font-stretch: normal;
  src: url('EOT/SourceSansPro-Regular.eot') format('embedded-opentype'),
       url('WOFF2/TTF/SourceSansPro-Regular.ttf.woff2') format('woff2'),
       url('WOFF/OTF/SourceSansPro-Regular.otf.woff') format('woff'),
       url('OTF/SourceSansPro-Regular.otf') format('opentype'),
       url('TTF/SourceSansPro-Regular.ttf') format('truetype');
}

@font-face {
  font-family: 'Source Sans Pro';
  font-weight: normal;
  font-style: italic;
  font-stretch: normal;
  src: url('EOT/SourceSansPro-It.eot') format('embedded-opentype'),
       url('WOFF2/TTF/SourceSansPro-It.ttf.woff2') format('woff2'),
       url('WOFF/OTF/SourceSansPro-It.otf.woff') format('woff'),
       url('OTF/SourceSansPro-It.otf') format('opentype'),
       url('TTF/SourceSansPro-It.ttf') format('truetype');
}

@font-face {
  font-family: 'Source Sans Pro';
  font-weight: bold;
  font-style: normal;
  font-stretch: normal;
  src: url('EOT/SourceSansPro-Bold.eot') format('embedded-opentype'),
       url('WOFF2/TTF/SourceSansPro-Bold.ttf.woff2') format('woff2'),
       url('WOFF/OTF/SourceSansPro-Bold.otf.woff') format('woff'),
       url('OTF/SourceSansPro-Bold.otf') format('opentype'),
       url('TTF/SourceSansPro-Bold.ttf') format('truetype');
}

@font-face {
  font-family: 'Source Sans Pro';
  font-weight: bold;
  font-style: italic;
  font-stretch: normal;
  src: url('EOT/SourceSansPro-BoldIt.eot') format('embedded-opentype'),
       url('WOFF2/TTF/SourceSansPro-BoldIt.ttf.woff2') format('woff2'),
       url('WOFF/OTF/SourceSansPro-BoldIt.otf.woff') format('woff'),
       url('OTF/SourceSansPro-BoldIt.otf') format('opentype'),
       url('TTF/SourceSansPro-BoldIt.ttf') format('truetype');
}

/* Source Code Pro */

@font-face {
  font-family: 'Source Code Pro';
  font-weight: normal;
  font-style: normal;
  font-stretch: normal;
  src: url('EOT/SourceCodePro-Regular.eot') format('embedded-opentype'),
       url('WOFF2/TTF/SourceCodePro-Regular.ttf.woff2') format('woff2'),
       url('WOFF/OTF/SourceCodePro-Regular.otf.woff') format('woff'),
       url('OTF/SourceCodePro-Regular.otf') format('opentype'),
       url('TTF/SourceCodePro-Regular.ttf') format('truetype');
}

@font-face {
  font-family: 'Source Code Pro';
  font-weight: normal;
  font-style: italic;
  font-stretch: normal;
  src: url('EOT/SourceCodePro-It.eot') format('embedded-opentype'),
       url('WOFF2/TTF/SourceCodePro-It.ttf.woff2') format('woff2'),
       url('WOFF/OTF/SourceCodePro-It.otf.woff') format('woff'),
       url('OTF/SourceCodePro-It.otf') format('opentype'),
       url('TTF/SourceCodePro-It.ttf') format('truetype');
}

@font-face {
  font-family: 'Source Code Pro';
  font-weight: bold;
  font-style: normal;
  font-stretch: normal;
  src: url('EOT/SourceCodePro-Bold.eot') format('embedded-opentype'),
       url('WOFF2/TTF/SourceCodePro-Bold.ttf.woff2') format('woff2'),
       url('WOFF/OTF/SourceCodePro-Bold.otf.woff') format('woff'),
       url('OTF/SourceCodePro-Bold.otf') format('opentype'),
       url('TTF/SourceCodePro-Bold.ttf') format('truetype');
}

@font-face {
  font-family: 'Source Code Pro';
  font-weight: bold;
  font-style: italic;
  font-stretch: normal;
  src: url('EOT/SourceCodePro-BoldIt.eot') format('embedded-opentype'),
       url('WOFF2/TTF/SourceCodePro-BoldIt.ttf.woff2') format('woff2'),
       url('WOFF/OTF/SourceCodePro-BoldIt.otf.woff') format('woff'),
       url('OTF/SourceCodePro-BoldIt.otf') format('opentype'),
       url('TTF/SourceCodePro-BoldIt.ttf') format('truetype');
}

/* Apply font styles */

body {
  font-family: 'Source Sans Pro', 'Nanum Barun Gothic', 'Nanum Gothic', 'Malgun Gothic',
               'Helvetica', 'Arial', sans-serif;
}

pre, code, kbd, var, samp, tt, .code {
  font-family: 'Source Code Pro', 'Consolas', 'Menlo', 'Monaco', 'Lucida Console', 'Liberation Mono',
               'DejaVu Sans Mono', monospace;
}

h1 > code, h2 > code, td > code {
  /* Source Code Pro looks like it has extra left margin; compensate. */
  position: relative;
  left: -0.20em;
}


<|start_filename|>saluki-ops/spring-boot-starter-salukiops/src/main/java/io/github/saluki/monitor/dao/domain/GrpcInvoke.java<|end_filename|>

package io.github.saluki.monitor.dao.domain;

import java.io.Serializable;
import java.util.Date;

import org.apache.commons.lang3.StringUtils;

public class GrpcInvoke implements Serializable {

    private static final long serialVersionUID = 1L;

    private String            id;

    private Date              invokeDate;

    private String            application;

    private String            service;

    private String            method;

    private String            consumer;

    private String            provider;

    private String            type;

    private int               concurrent;

    private int               maxInput;

    private int               maxOutput;

    private double            maxElapsed;

    private int               maxConcurrent;

    private int               success;

    private int               failure;

    private double            input;

    private double            output;

    private double            elapsed;

    public Date getInvokeDate() {
        return invokeDate;
    }

    public void setInvokeDate(Date invokeDate) {
        this.invokeDate = invokeDate;
    }

    public String getService() {
        return service;
    }

    public void setService(String service) {
        this.service = service;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    public String getConsumer() {
        return consumer;
    }

    public void setConsumer(String consumer) {
        this.consumer = consumer;
    }

    public String getProvider() {
        return provider;
    }

    public void setProvider(String provider) {
        this.provider = provider;
    }

    public String getType() {
        if (StringUtils.isEmpty(type)) {
            return "provider";
        }
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getId() {
        return id;
    }

    public int getSuccess() {
        return success;
    }

    public void setSuccess(int success) {
        this.success = success;
    }

    public int getFailure() {
        return failure;
    }

    public void setFailure(int failure) {
        this.failure = failure;
    }

    public double getElapsed() {
        return elapsed;
    }

    public void setElapsed(double elapsed) {
        this.elapsed = elapsed;
    }

    public int getConcurrent() {
        return concurrent;
    }

    public void setConcurrent(int concurrent) {
        this.concurrent = concurrent;
    }

    public int getMaxInput() {
        return maxInput;
    }

    public void setMaxInput(int maxInput) {
        this.maxInput = maxInput;
    }

    public int getMaxOutput() {
        return maxOutput;
    }

    public void setMaxOutput(int maxOutput) {
        this.maxOutput = maxOutput;
    }

    public double getMaxElapsed() {
        return maxElapsed;
    }

    public void setMaxElapsed(double maxElapsed) {
        this.maxElapsed = maxElapsed;
    }

    public int getMaxConcurrent() {
        return maxConcurrent;
    }

    public void setMaxConcurrent(int maxConcurrent) {
        this.maxConcurrent = maxConcurrent;
    }

    public double getInput() {
        return input;
    }

    public void setInput(double input) {
        this.input = input;
    }

    public double getOutput() {
        return output;
    }

    public void setOutput(double output) {
        this.output = output;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getApplication() {
        return application;
    }

    public void setApplication(String application) {
        this.application = application;
    }

}


<|start_filename|>saluki-ops/saluki-ops-console/src/main/java/io/github/saluki/monitor/ops/MonitorApplication.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and proprietary
 * information of Quancheng-ec.com ("Confidential Information"). You shall not disclose such Confidential Information
 * and shall use it only in accordance with the terms of the license agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.monitor.ops;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author shimingliu 2016年12月20日 下午5:39:55
 * @version MonitorApplication.java, v 0.0.1 2016年12月20日 下午5:39:55 shimingliu
 */
@SpringBootApplication
public class MonitorApplication {

    public static void main(String[] args) {
        SpringApplication.run(MonitorApplication.class, args);
    }

}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/registry/Registry.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.registry;

import java.util.List;

import io.github.saluki.common.GrpcURL;

/**
 * @author shimingliu 2016年12月14日 下午1:46:29
 * @version Registry.java, v 0.0.1 2016年12月14日 下午1:46:29 shimingliu
 */
public interface Registry {

  /**
   * 注册服务
   */
  void register(GrpcURL url);

  /**
   * 取消注册
   */
  void unregister(GrpcURL url);

  /**
   * 订阅服务
   */
  void subscribe(GrpcURL url, NotifyListener.NotifyServiceListener listener);

  /**
   * 订阅服务路由信息
   */
  void subscribe(GrpcURL url, NotifyListener.NotifyRouterListener listener);

  /**
   * 取消订阅
   */
  void unsubscribe(GrpcURL url, NotifyListener.NotifyServiceListener listener);

  /**
   * 取消订阅路由信息
   */
  void unsubscribe(GrpcURL url, NotifyListener.NotifyRouterListener listener);

  /**
   * 查询服务
   */
  List<GrpcURL> discover(GrpcURL url);

}


<|start_filename|>spring-boot-starter-saluki/src/main/java/io/github/saluki/boot/autoconfigure/GrpcProperties.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.boot.autoconfigure;

import org.springframework.boot.context.properties.ConfigurationProperties;

/**
 * @author shimingliu 2016年12月16日 下午4:58:23
 * @version GrpcProperties.java, v 0.0.1 2016年12月16日 下午4:58:23 shimingliu
 */

@ConfigurationProperties(prefix = "saluki.grpc")
public class GrpcProperties {

  /**
   * consumer
   */
  private String referenceDefinition;

  /**
   * provider
   */
  private String group;

  private String version;

  private int realityRpcPort;

  private int registryRpcPort;

  /**
   * commom
   */
  private String host;

  private int registryHttpPort;

  private int monitorinterval;

  private String registryAddress;

  public String getHost() {
    return host;
  }

  public void setHost(String host) {
    this.host = host;
  }

  public int getRealityRpcPort() {
    return realityRpcPort;
  }

  public void setRealityRpcPort(int realityRpcPort) {
    this.realityRpcPort = realityRpcPort;
  }

  public int getRegistryRpcPort() {
    return registryRpcPort;
  }

  public void setRegistryRpcPort(int registryRpcPort) {
    this.registryRpcPort = registryRpcPort;
  }

  public void setRegistryHttpPort(int registryHttpPort) {
    this.registryHttpPort = registryHttpPort;
  }

  public String getRegistryAddress() {
    return registryAddress;
  }

  public void setRegistryAddress(String registryAddress) {
    this.registryAddress = registryAddress;
  }

  public String getReferenceDefinition() {
    return referenceDefinition;
  }

  public void setReferenceDefinition(String referenceDefinition) {
    this.referenceDefinition = referenceDefinition;
  }

  public int getRegistryHttpPort() {
    return registryHttpPort;
  }

  public int getMonitorinterval() {
    return monitorinterval;
  }

  public void setMonitorinterval(int monitorinterval) {
    this.monitorinterval = monitorinterval;
  }

  public String getGroup() {
    return group;
  }

  public void setGroup(String group) {
    this.group = group;
  }

  public String getVersion() {
    return version;
  }

  public void setVersion(String version) {
    this.version = version;
  }

}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/client/internal/unary/GrpcFutureUnaryCommand.java<|end_filename|>
/*
 * Copyright 1999-2012 DianRong.
 * 
 * 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 io.github.saluki.grpc.client.internal.unary;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.protobuf.Message;
import io.github.saluki.grpc.exception.RpcErrorMsgConstant;
import io.github.saluki.grpc.exception.RpcServiceException;

import io.grpc.MethodDescriptor;

/**
 * @author liushiming 2017年4月26日 下午5:21:49
 * @version $Id: UnaryCommand.java, v 0.0.1 2017年4月26日 下午5:21:49 liushiming
 */
public class GrpcFutureUnaryCommand extends GrpcHystrixCommand {

  private static final Logger logger = LoggerFactory.getLogger(GrpcHystrixCommand.class);


  public GrpcFutureUnaryCommand(String serviceName, String methodName, Boolean isEnabledFallBack) {
    super(serviceName, methodName, isEnabledFallBack);
  }

  /**
   * @see io.github.saluki.grpc.client.internal.unary.GrpcHystrixCommand#run0(com.google.protobuf.Message,
   *      io.grpc.MethodDescriptor, java.lang.Integer,
   *      io.github.saluki.grpc.client.internal.unary.GrpcUnaryClientCall)
   */
  @Override
  protected Message run0(Message req, MethodDescriptor<Message, Message> methodDesc,
      Integer timeOut, GrpcUnaryClientCall clientCall) {
    try {
      return clientCall.unaryFuture(req, methodDesc).get(timeOut, TimeUnit.MILLISECONDS);
    } catch (Throwable e) {
      logger.error(e.getMessage(), e);
      super.cacheCurrentServer();
      if (e instanceof TimeoutException) {
        RpcServiceException rpcService =
            new RpcServiceException(e, RpcErrorMsgConstant.SERVICE_TIMEOUT);
        throw rpcService;
      } else {
        RpcServiceException rpcService =
            new RpcServiceException(e, RpcErrorMsgConstant.BIZ_DEFAULT_EXCEPTION);
        throw rpcService;
      }
    }
  }


}


<|start_filename|>saluki-ops/spring-boot-starter-salukiops/src/main/java/io/github/saluki/monitor/dao/domain/GrpcServiceTestModel.java<|end_filename|>
package io.github.saluki.monitor.dao.domain;

public class GrpcServiceTestModel {

    private String service;

    private String method;

    private String parameterType;

    private String returnType;

    private String parameter;

    public String getService() {
        return service;
    }

    public void setService(String service) {
        this.service = service;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    public String getParameterType() {
        return parameterType;
    }

    public void setParameterType(String parameterType) {
        this.parameterType = parameterType;
    }

    public String getReturnType() {
        return returnType;
    }

    public void setReturnType(String returnType) {
        this.returnType = returnType;
    }

    public String getParameter() {
        return parameter;
    }

    public void setParameter(String parameter) {
        this.parameter = parameter;
    }

}


<|start_filename|>saluki-example/saluki-example-client/src/main/java/io/github/saluki/example/performance/OkHttpUtil.java<|end_filename|>
/*
 * Copyright 2014-2017 the original author or authors.
 *
 * 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 io.github.saluki.example.performance;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

/**
 * @author liushiming
 * @version OkHttpUtil.java, v 0.0.1 2017年10月20日 下午9:18:43 liushiming
 */
public class OkHttpUtil {
  private static OkHttpClient okHttpclient = null;

  static {
    okHttpclient = new OkHttpClient.Builder().connectTimeout(3, TimeUnit.SECONDS).build();
  }

  public static String run(String url) throws Exception {
    Request request = new Request.Builder().url(url).build();
    Response response = okHttpclient.newCall(request).execute();
    if (!response.isSuccessful()) {
      throw new IOException("Unexpected code " + response);
    }
    return response.body().string();

  }
}


<|start_filename|>saluki-ops/saluki-ops-console/src/main/java/io/github/saluki/monitor/ops/repository/ConsulRegistryRepository.java<|end_filename|>
package io.github.saluki.monitor.ops.repository;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.ImmutableTriple;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.commons.lang3.tuple.Triple;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;

import com.ecwid.consul.v1.ConsulClient;
import com.ecwid.consul.v1.agent.model.Check;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import io.github.saluki.common.Constants;
import io.github.saluki.common.GrpcURL;
import io.github.saluki.common.NamedThreadFactory;
import io.github.saluki.monitor.dao.domain.GrpcHost;

@Repository
public class ConsulRegistryRepository {
    private static final Logger log = LoggerFactory.getLogger(ConsulRegistryRepository.class);
    @Value("${saluki.monitor.consulhost}")
    private String agentHost;
    private ConsulClient consulClient;
    private final Map<String, Pair<Set<GrpcHost>, Set<GrpcHost>>> servicesPassing = Maps.newConcurrentMap();
    private final Map<String, Pair<Set<GrpcHost>, Set<GrpcHost>>> servicesFailing = Maps.newConcurrentMap();
    private final ScheduledExecutorService executor =
        Executors.newScheduledThreadPool(1, new NamedThreadFactory("ConsulLookUpService", true));;

    @PostConstruct
    public void init() {
        consulClient = new ConsulClient(agentHost);
        executor.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                try {
                    log.info("begin to load from registry");
                    servicesPassing.clear();
                    servicesFailing.clear();
                    loadAllServiceFromConsul();
                } catch (Throwable e) {
                    log.error(e.getMessage(), e);
                }
            }
        }, 0, 1, TimeUnit.MINUTES);
    }

    public void loadAllServiceFromConsul() {
        Map<String, Check> allServices = consulClient.getAgentChecks().getValue();
        for (Map.Entry<String, Check> entry : allServices.entrySet()) {
            Check serviceCheck = entry.getValue();
            String group = serviceCheck.getServiceName();
            if (StringUtils.startsWith(group, Constants.CONSUL_SERVICE_PRE)) {
                Triple<String, String, String> hostPortServiceVersion = getPortHostService(serviceCheck.getServiceId());
                String hostRpcPort = hostPortServiceVersion.getLeft();
                String service = hostPortServiceVersion.getMiddle();
                String version = hostPortServiceVersion.getRight();
                String serviceKey = generateServicekey(group, service, version);
                if (serviceCheck.getStatus() == Check.CheckStatus.PASSING) {
                    Pair<Set<GrpcHost>, Set<GrpcHost>> providerAndConsumer =
                        getProviderAndConsumer(group, service, version);
                    if (providerAndConsumer != null) {
                        servicesPassing.put(serviceKey, providerAndConsumer);
                    }
                } else {
                    Pair<Set<GrpcHost>, Set<GrpcHost>> providerAndConsumer = servicesFailing.get(serviceKey);
                    GrpcHost providerHost = new GrpcHost(hostRpcPort, "0");
                    providerHost.setStatus("failing");
                    providerHost.setUrl("service:" + hostRpcPort + "-" + service + "-" + version);
                    if (servicesFailing.get(serviceKey) == null) {
                        Set<GrpcHost> provider = Sets.newHashSet(providerHost);
                        providerAndConsumer = new ImmutablePair<Set<GrpcHost>, Set<GrpcHost>>(provider, null);
                        servicesFailing.put(serviceKey, providerAndConsumer);
                    }
                    providerAndConsumer.getLeft().add(providerHost);
                }
            }
        }
    }

    public Map<String, Pair<Set<GrpcHost>, Set<GrpcHost>>> getAllPassingService() {
        return this.servicesPassing;
    }

    public Map<String, Pair<Set<GrpcHost>, Set<GrpcHost>>> getAllFailingService() {
        return this.servicesFailing;
    }

    private Pair<Set<GrpcHost>, Set<GrpcHost>> getProviderAndConsumer(String group, String service, String version) {
        Set<GrpcHost> providerHosts = Sets.newHashSet();
        Set<GrpcHost> comsumerHosts = Sets.newHashSet();
        List<String> providerAndConsumerKvs =
            consulClient.getKVKeysOnly(group + "/" + service + "/" + version).getValue();
        if (providerAndConsumerKvs != null) {
            for (String providerAndConsumerKv : providerAndConsumerKvs) {
                Triple<String, String, String> machineInfo =
                    getmachineInfo(providerAndConsumerKv, group + "/" + service);
                String appFlag = machineInfo.getLeft();
                String[] appHostRpcPort = machineInfo.getMiddle().split(":");
                String appHttpPort = machineInfo.getRight();
                if (appFlag.equals(Constants.PROVIDERS_CATEGORY)) {
                    GrpcHost host = new GrpcHost(appHostRpcPort[0], appHttpPort, appHostRpcPort[1]);
                    host.setStatus("passing");
                    host.setUrl(
                        "service:" + appHostRpcPort[0] + ":" + appHostRpcPort[1] + "-" + service + "-" + version);
                    providerHosts.add(host);
                } else if (appFlag.equals(Constants.CONSUMERS_CATEGORY)) {
                    GrpcHost host = new GrpcHost(appHostRpcPort[0], appHttpPort, "0");
                    host.setStatus("passing");
                    host.setUrl(null);
                    comsumerHosts.add(host);
                }
            }
            return new ImmutablePair<Set<GrpcHost>, Set<GrpcHost>>(providerHosts, comsumerHosts);
        }
        return null;
    }

    /**
     * ==============help method=============
     */
    private Triple<String, String, String> getmachineInfo(String providerAndConsumerKv, String groupService) {
        String thralUrl = consulClient.getKVValue(providerAndConsumerKv).getValue().getDecodedValue();
        GrpcURL url = GrpcURL.valueOf(thralUrl);
        String flagAndIp = StringUtils.remove(providerAndConsumerKv, groupService + "/");
        String[] serverInfos = StringUtils.split(flagAndIp, "/");
        String machineFlag = serverInfos[1];
        return new ImmutableTriple<String, String, String>(machineFlag, url.getAddress(),
            url.getParameter(Constants.HTTP_PORT_KEY));
    }

    private Triple<String, String, String> getPortHostService(String serviceId) {
        String[] args = StringUtils.split(serviceId, "-");
        String hostRpcPort = args[0];
        String service = args[1];
        String version = "1.0.0";
        if (args.length > 2) {
            version = args[2];
        }
        return new ImmutableTriple<String, String, String>(hostRpcPort, service, version);
    }

    private String generateServicekey(String group, String service, String version) {
        return StringUtils.remove(group, Constants.CONSUL_SERVICE_PRE) + ":" + service + ":" + version;
    }

    public String getAgentHost() {
        return agentHost;
    }

    public void setAgentHost(String agentHost) {
        this.agentHost = agentHost;
    }
}


<|start_filename|>saluki-ops/saluki-ops-console/src/main/java/io/github/saluki/monitor/ops/controller/ServiceTestController.java<|end_filename|>
package io.github.saluki.monitor.ops.controller;

import java.util.List;

import javax.annotation.PostConstruct;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;

import io.github.saluki.monitor.dao.domain.GrpcServiceTestModel;
import io.github.saluki.monitor.jaket.model.GenericInvokeMetadata;
import io.github.saluki.monitor.jaket.model.MethodDefinition;

@RestController
@RequestMapping("/api/serviceMeasure")
public class ServiceTestController {

  private HttpClient httpClient;

  private Gson gson;

  @PostConstruct
  public void init() {
    httpClient = HttpClientBuilder.create().build();
    gson = new GsonBuilder().create();
  }

  @RequestMapping(value = "getAllMethod", method = RequestMethod.GET)
  public List<MethodDefinition> getAllMethod(
      @RequestParam(value = "ipPort", required = true) String ipPort,
      @RequestParam(value = "service", required = true) String service) throws Exception {

    String methdUrl = "http://" + ipPort + "/service/getAllMethod?service=" + service;
    HttpGet request = new HttpGet(methdUrl);
    request.addHeader("content-type", "application/json");
    request.addHeader("Accept", "application/json");
    try {
      HttpResponse httpResponse = httpClient.execute(request);
      if (httpResponse.getStatusLine().getStatusCode() == 200) {
        String minitorJson = EntityUtils.toString(httpResponse.getEntity());
        List<MethodDefinition> allMethods =
            gson.fromJson(minitorJson, new TypeToken<List<MethodDefinition>>() {}.getType());
        return allMethods;
      }
    } catch (Exception e) {
      throw e;
    }
    return null;
  }

  @RequestMapping(value = "getMethod", method = RequestMethod.GET)
  public GenericInvokeMetadata getMethod(
      @RequestParam(value = "ipPort", required = true) String ipPort,
      @RequestParam(value = "service", required = true) String service,
      @RequestParam(value = "method", required = true) String method) throws Exception {
    String methdUrl =
        "http://" + ipPort + "/service/getMethod?service=" + service + "&method=" + method;
    HttpGet request = new HttpGet(methdUrl);
    request.addHeader("content-type", "application/json");
    request.addHeader("Accept", "application/json");
    try {
      HttpResponse httpResponse = httpClient.execute(request);
      if (httpResponse.getStatusLine().getStatusCode() == 200) {
        String minitorJson = EntityUtils.toString(httpResponse.getEntity());
        GenericInvokeMetadata methodmeta =
            gson.fromJson(minitorJson, new TypeToken<GenericInvokeMetadata>() {}.getType());
        return methodmeta;
      }
    } catch (Exception e) {
      throw e;
    }
    return null;
  }

  @RequestMapping(value = "testService", method = RequestMethod.POST)
  public Object testService(@RequestParam(value = "ipPort", required = true) String ipPort,
      @RequestBody GrpcServiceTestModel model) throws Exception {
    String serviceUrl = "http://" + ipPort + "/service/test";
    HttpPost request = new HttpPost(serviceUrl);
    request.addHeader("content-type", "application/json");
    request.addHeader("Accept", "application/json");
    try {
      StringEntity entity = new StringEntity(gson.toJson(model), "utf-8");
      entity.setContentEncoding("UTF-8");
      entity.setContentType("application/json");
      request.setEntity(entity);
      HttpResponse httpResponse = httpClient.execute(request);
      if (httpResponse.getStatusLine().getStatusCode() == 200) {
        String minitorJson = EntityUtils.toString(httpResponse.getEntity());
        Object response = gson.fromJson(minitorJson, new TypeToken<Object>() {}.getType());
        return response;
      }
    } catch (Exception e) {
      throw e;
    }
    return null;
  }

}


<|start_filename|>saluki-registry/saluki-registry-consul/src/main/java/io/github/saluki/registry/consul/GrpcURLUtils.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.registry.consul;

import io.github.saluki.common.Constants;
import io.github.saluki.common.GrpcURL;
import io.github.saluki.registry.consul.model.ThrallRoleType;

/**
 * @author shimingliu 2016年12月20日 下午9:14:15
 * @version ThrallURLUtils.java, v 0.0.1 2016年12月20日 下午9:14:15 shimingliu
 */
public class GrpcURLUtils {

  private GrpcURLUtils() {

  }

  /**** help method *****/
  public static String toServiceName(String group) {
    return Constants.CONSUL_SERVICE_PRE + group;
  }

  public static String toRoutePath(GrpcURL url) {
    String name = url.getServiceInterface();
    String group = url.getGroup();
    return Constants.CONSUL_SERVICE_PRE + group + Constants.PATH_SEPARATOR + name;
  }


  private static String toServicePath(GrpcURL url) {
    String name = url.getServiceInterface();
    String group = url.getGroup();
    return group + Constants.PATH_SEPARATOR + GrpcURL.encode(name);
  }

  public static String toCategoryPathNotIncludeVersion(GrpcURL url, ThrallRoleType roleType) {
    switch (roleType) {
      case CONSUMER:
        return toServicePath(url) + Constants.PATH_SEPARATOR + Constants.CONSUMERS_CATEGORY;
      case PROVIDER:
        return toServicePath(url) + Constants.PATH_SEPARATOR + Constants.PROVIDERS_CATEGORY;
      default:
        throw new java.lang.IllegalArgumentException("there is no role type");
    }

  }

  public static String toCategoryPathIncludeVersion(GrpcURL url, ThrallRoleType roleType) {
    switch (roleType) {
      case CONSUMER:
        return toServicePath(url) + Constants.PATH_SEPARATOR + url.getVersion()
            + Constants.PATH_SEPARATOR + Constants.CONSUMERS_CATEGORY;
      case PROVIDER:
        return toServicePath(url) + Constants.PATH_SEPARATOR + url.getVersion()
            + Constants.PATH_SEPARATOR + Constants.PROVIDERS_CATEGORY;
      default:
        throw new java.lang.IllegalArgumentException("there is no role type");
    }

  }

  public static String healthServicePath(GrpcURL url, ThrallRoleType roleType) {
    return toCategoryPathNotIncludeVersion(url, roleType) + Constants.PATH_SEPARATOR
        + GrpcURL.encode(url.toFullString());
  }

  public static String ephemralNodePath(GrpcURL url, ThrallRoleType roleType) {
    return Constants.CONSUL_SERVICE_PRE + toCategoryPathIncludeVersion(url, roleType)
        + Constants.PATH_SEPARATOR + url.getAddress();
  }

}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/client/internal/unary/GrpcHystrixCommand.java<|end_filename|>
/*
 * Copyright 1999-2012 DianRong.
 * 
 * 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 io.github.saluki.grpc.client.internal.unary;

import java.net.InetSocketAddress;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.commons.lang3.tuple.ImmutableTriple;
import org.apache.commons.lang3.tuple.Triple;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Maps;
import com.google.protobuf.Message;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixThreadPoolProperties;
import io.github.saluki.common.Constants;
import io.github.saluki.common.GrpcURL;
import io.github.saluki.common.NamedThreadFactory;
import io.github.saluki.common.RpcContext;
import io.github.saluki.grpc.client.GrpcRequest;
import io.github.saluki.grpc.client.GrpcResponse;
import io.github.saluki.grpc.client.internal.GrpcCallOptions;
import io.github.saluki.grpc.exception.RpcFrameworkException;
import io.github.saluki.grpc.service.ClientServerMonitor;
import io.github.saluki.grpc.service.MonitorService;
import io.github.saluki.grpc.util.GrpcUtil;
import io.github.saluki.grpc.util.SerializerUtil;
import io.github.saluki.serializer.exception.ProtobufException;

import io.grpc.MethodDescriptor;

/**
 * @author liushiming 2017年4月26日 下午6:16:32
 * @version $Id: GrpcHystrixObservableCommand.java, v 0.0.1 2017年4月26日 下午6:16:32 liushiming
 */
@SuppressWarnings("rawtypes")
public abstract class GrpcHystrixCommand extends HystrixCommand<Object> {

  private static final Logger logger = LoggerFactory.getLogger(GrpcHystrixCommand.class);

  private static final ConcurrentMap<String, AtomicInteger> concurrents = Maps.newConcurrentMap();

  private final String serviceName;

  private final String methodName;

  private final long start;

  private final Triple<Map<String, String>, Map<String, Object>, Set<Class>> rpcContext;

  private GrpcRequest request;

  private GrpcUnaryClientCall clientCall;

  private ClientServerMonitor clientServerMonitor;

  private static final ExecutorService collectLogExecutor =
      Executors.newSingleThreadExecutor(new NamedThreadFactory("salukiCollectTask", true));


  public GrpcHystrixCommand(String serviceName, String methodName, Boolean isEnabledFallBack) {
    super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(serviceName))//
        .andCommandKey(HystrixCommandKey.Factory.asKey(serviceName + ":" + methodName))//
        .andCommandPropertiesDefaults(
            HystrixCommandProperties.Setter().withCircuitBreakerRequestVolumeThreshold(20)// 10秒钟内至少19此请求失败，熔断器才发挥起作用
                .withCircuitBreakerSleepWindowInMilliseconds(30000)// 熔断器中断请求30秒后会进入半打开状态,放部分流量过去重试
                .withCircuitBreakerErrorThresholdPercentage(50)// 错误率达到50开启熔断保护
                .withExecutionTimeoutEnabled(false)// 禁用这里的超时
                .withFallbackEnabled(isEnabledFallBack))//
        .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(100)
            .withAllowMaximumSizeToDivergeFromCoreSize(true).withMaximumSize(Integer.MAX_VALUE)));
    this.serviceName = serviceName;
    this.methodName = methodName;
    this.start = System.currentTimeMillis();
    this.rpcContext = new ImmutableTriple<Map<String, String>, Map<String, Object>, Set<Class>>(
        RpcContext.getContext().getAttachments(), RpcContext.getContext().get(),
        RpcContext.getContext().getHoldenGroups());
    RpcContext.removeContext();
  }

  public void setRequest(GrpcRequest request) {
    this.request = request;
  }

  public void setClientCall(GrpcUnaryClientCall clientCall) {
    this.clientCall = clientCall;
  }

  public void setClientServerMonitor(ClientServerMonitor clientServerMonitor) {
    this.clientServerMonitor = clientServerMonitor;
  }

  @Override
  public Object execute() {
    try {
      currentConcurrent(this.serviceName, this.methodName).incrementAndGet();
      return super.execute();
    } finally {
      currentConcurrent(this.serviceName, this.methodName).decrementAndGet();
    }
  }

  @Override
  protected Object run() throws Exception {
    try {
      RpcContext.getContext().setAttachments(rpcContext.getLeft());
      RpcContext.getContext().set(rpcContext.getMiddle());
      RpcContext.getContext().setHoldenGroups(rpcContext.getRight());
      MethodDescriptor<Message, Message> methodDesc = this.request.getMethodDescriptor();
      Integer timeOut = this.request.getCallTimeout();
      Message request = getRequestMessage();
      Message response = this.run0(request, methodDesc, timeOut, clientCall);
      Object obj = this.transformMessage(response);
      collectLogExecutor.execute(new Runnable() {

        @Override
        public void run() {
          collect(serviceName, methodName, request, response, false);
        }
      });
      return obj;
    } finally {
      RpcContext.removeContext();
    }
  }

  @Override
  protected Object getFallback() {
    Class<?> responseType = this.request.getResponseType();
    Message response = GrpcUtil.createDefaultInstance(responseType);
    Object obj = this.transformMessage(response);
    collectLogExecutor.execute(new Runnable() {

      @Override
      public void run() {
        collect(serviceName, methodName, getRequestMessage(), response, true);
      }
    });
    return obj;
  }

  protected AtomicInteger currentConcurrent(String serviceName, String methodName) {
    String key = serviceName + ":" + methodName;
    AtomicInteger concurrent = concurrents.get(key);
    if (concurrent == null) {
      concurrents.putIfAbsent(key, new AtomicInteger());
      concurrent = concurrents.get(key);
    }
    return concurrent;
  }

  private Message getRequestMessage() {
    try {
      Object param = this.request.getRequestParam();
      return SerializerUtil.pojo2Protobuf(param);
    } catch (ProtobufException e) {
      RpcFrameworkException rpcFramwork = new RpcFrameworkException(e);
      throw rpcFramwork;
    }
  }

  private Object transformMessage(Message message) {
    Class<?> respPojoType = request.getResponseType();
    GrpcResponse response = new GrpcResponse.Default(message, respPojoType);
    try {
      return response.getResponseArg();
    } catch (ProtobufException e) {
      RpcFrameworkException rpcFramwork = new RpcFrameworkException(e);
      throw rpcFramwork;
    }
  }

  private void collect(String serviceName, String methodName, Message request, Message response,
      boolean error) {
    try {
      InetSocketAddress provider = (InetSocketAddress) GrpcCallOptions
          .getAffinity(this.request.getRefUrl()).get(GrpcCallOptions.GRPC_CURRENT_ADDR_KEY);
      if (request == null || response == null || provider == null) {
        return;
      }
      long elapsed = System.currentTimeMillis() - this.start; // 计算调用耗时
      int concurrent = this.currentConcurrent(serviceName, methodName).get(); // 当前并发数
      String service = serviceName; // 获取服务名称
      String method = methodName; // 获取方法名
      GrpcURL refUrl = this.request.getRefUrl();
      String host = refUrl.getHost();
      Integer port = refUrl.getPort();
      clientServerMonitor.collect(new GrpcURL(Constants.MONITOR_PROTOCOL, host, port, //
          service + "/" + method, //
          MonitorService.TIMESTAMP, String.valueOf(start), //
          MonitorService.APPLICATION, refUrl.getParameter(Constants.APPLICATION_NAME), //
          MonitorService.INTERFACE, service, //
          MonitorService.METHOD, method, //
          MonitorService.PROVIDER, provider.getHostName(), //
          error ? MonitorService.FAILURE : MonitorService.SUCCESS, "1", //
          MonitorService.ELAPSED, String.valueOf(elapsed), //
          MonitorService.CONCURRENT, String.valueOf(concurrent), //
          MonitorService.INPUT, String.valueOf(request.getSerializedSize()), //
          MonitorService.OUTPUT, String.valueOf(response.getSerializedSize())));
    } catch (Throwable t) {
      logger.warn("Failed to monitor count service " + serviceName + ", cause: " + t.getMessage());
    }
  }

  protected abstract Message run0(Message req, MethodDescriptor<Message, Message> methodDesc,
      Integer timeOut, GrpcUnaryClientCall clientCall);

  protected void cacheCurrentServer() {
    Object obj = GrpcCallOptions.getAffinity(this.request.getRefUrl())
        .get(GrpcCallOptions.GRPC_CURRENT_ADDR_KEY);
    if (obj != null) {
      InetSocketAddress currentServer = (InetSocketAddress) obj;
      RpcContext.getContext().setAttachment(Constants.REMOTE_ADDRESS, currentServer.getHostName());
    }
  }
}


<|start_filename|>saluki-ops/spring-boot-starter-salukiops/src/main/java/io/github/saluki/monitor/jaket/JaketTypeBuilder.java<|end_filename|>
package io.github.saluki.monitor.jaket;

import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.github.saluki.monitor.jaket.builder.ArrayTypeBuilder;
import io.github.saluki.monitor.jaket.builder.CollectionTypeBuilder;
import io.github.saluki.monitor.jaket.builder.DefaultTypeBuilder;
import io.github.saluki.monitor.jaket.builder.EnumTypeBuilder;
import io.github.saluki.monitor.jaket.builder.MapTypeBuilder;
import io.github.saluki.monitor.jaket.builder.TypeBuilder;
import io.github.saluki.monitor.jaket.model.TypeDefinition;

/**
 * Created by huangsheng.hs on 2015/1/27.
 */
public class JaketTypeBuilder {

    private static final List<TypeBuilder> builders = new ArrayList<TypeBuilder>();

    static {
        builders.add(new ArrayTypeBuilder());
        builders.add(new CollectionTypeBuilder());
        builders.add(new MapTypeBuilder());
        builders.add(new EnumTypeBuilder());
    }

    public static TypeDefinition build(Type type, Class<?> clazz, Map<Class<?>, TypeDefinition> typeCache) {
        TypeBuilder builder = getGenericTypeBuilder(type, clazz);
        TypeDefinition td = null;
        if (builder != null) {
            td = builder.build(type, clazz, typeCache);
        } else {
            td = DefaultTypeBuilder.build(clazz, typeCache);
        }
        return td;
    }

    private static TypeBuilder getGenericTypeBuilder(Type type, Class<?> clazz) {
        for (TypeBuilder builder : builders) {
            if (builder.accept(type, clazz)) {
                return builder;
            }
        }
        return null;
    }

    private Map<Class<?>, TypeDefinition> typeCache = new HashMap<Class<?>, TypeDefinition>();

    public TypeDefinition build(Type type, Class<?> clazz) {
        return build(type, clazz, typeCache);
    }

    public List<TypeDefinition> getTypeDefinitions() {
        return new ArrayList<TypeDefinition>(typeCache.values());
    }

}


<|start_filename|>saluki-serializer/src/main/java/io/github/saluki/serializer/help/Protobuf2PojoHelp.java<|end_filename|>
/*
 * Copyright 2014-2017 the original author or authors.
 *
 * 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 io.github.saluki.serializer.help;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.protobuf.Message;
import com.google.protobuf.ProtocolMessageEnum;
import io.github.saluki.serializer.ProtobufAttribute;
import io.github.saluki.serializer.ProtobufEntity;
import io.github.saluki.serializer.ProtobufSerializer;
import io.github.saluki.serializer.exception.ProtobufException;
import io.github.saluki.serializer.internal.ProtobufSerializerUtils;
import io.github.saluki.serializer.utils.JException;
import io.github.saluki.serializer.utils.JReflectionUtils;

/**
 * @author liushiming
 * @version Protobuf2PojoHelp.java, v 0.0.1 2017年7月18日 下午1:54:59 liushiming
 * @since JDK 1.8
 */
public class Protobuf2PojoHelp {

  private Protobuf2PojoHelp() {

  }

  public static final Object serializeFromProtobufEntity(Message protoBuf, Class<?> pojoClazz)
      throws JException {
    final ProtobufEntity protoBufEntity = ProtobufSerializerUtils.getProtobufEntity(pojoClazz);
    if (protoBufEntity == null) {
      return protoBuf;
    }
    return new ProtobufSerializer().fromProtobuf(protoBuf, pojoClazz);
  }

  @SuppressWarnings("rawtypes")
  public static final Object getProtobufFieldValue(Message protoBuf,
      ProtobufAttribute protobufAttribute, Field field)
      throws JException, InstantiationException, IllegalAccessException {
    final String getter = ProtobufSerializerUtils.getProtobufGetter(protobufAttribute, field);
    // This is used to determine if the Protobuf message has populated this value
    Boolean isCollection = Boolean.FALSE;
    if (Collection.class.isAssignableFrom(field.getType())) {
      isCollection = Boolean.TRUE;
    }
    // Go ahead and fun the getter
    Object protobufValue = JReflectionUtils.runMethod(protoBuf, getter, (Object[]) null);
    if (isCollection && ((Collection) protobufValue).isEmpty()) {
      return null;
    }
    // If the field itself is a ProtbufEntity, serialize that!
    if (protobufValue instanceof Message
        && ProtobufSerializerUtils.isProtbufEntity(field.getType())) {
      protobufValue = serializeFromProtobufEntity((Message) protobufValue, field.getType());
    }
    if (protobufValue instanceof Collection) {
      protobufValue = convertCollectionFromProtobufs(field, (Collection<?>) protobufValue);
      if (((Collection) protobufValue).isEmpty()) {
        return null;
      }
    }
    if (protobufValue instanceof ProtocolMessageEnum) {
      protobufValue = JReflectionUtils.runStaticMethod(field.getType(), "forNumber",
          ((ProtocolMessageEnum) protobufValue).getNumber());
    }
    return protobufValue;
  }

  public static final void setPojoFieldValue(Object pojo, String setter, Object protobufValue,
      ProtobufAttribute protobufAttribute, Field field)
      throws InstantiationException, IllegalAccessException, JException {
    Class<? extends Object> argClazz = null;
    if (protobufValue instanceof List) {
      final ArrayList<Object> newCollectionValues = new ArrayList<>();
      newCollectionValues.addAll((Collection<?>) protobufValue);
      protobufValue = newCollectionValues;
      argClazz = ArrayList.class;
    } else if (protobufValue instanceof Map) {
      final Map<Object, Object> newMapValues = new HashMap<>();
      newMapValues.putAll((Map<?, ?>) protobufValue);
      protobufValue = newMapValues;
      argClazz = Map.class;
    } else if (protobufValue instanceof ProtocolMessageEnum) {
      Class<?> fieldType = field.getType();
      protobufValue = JReflectionUtils.runStaticMethod(fieldType, "forNumber",
          ((ProtocolMessageEnum) protobufValue).getNumber());
      argClazz = field.getType();
    } else {
      protobufValue.getClass();
    }
    JReflectionUtils.runSetter(pojo, setter, protobufValue, argClazz);
  }

  private static Object convertCollectionFromProtobufs(Field field,
      Collection<?> collectionOfProtobufs)
      throws JException, InstantiationException, IllegalAccessException {
    if (collectionOfProtobufs.isEmpty()) {
      return collectionOfProtobufs;
    }
    final ParameterizedType listType = (ParameterizedType) field.getGenericType();
    final Class<?> collectionClazzType = (Class<?>) listType.getActualTypeArguments()[0];
    final ProtobufEntity protoBufEntityAnno =
        ProtobufSerializerUtils.getProtobufEntity(collectionClazzType);
    final Object first = collectionOfProtobufs.toArray()[0];
    if (!(first instanceof Message) && protoBufEntityAnno == null) {
      return collectionOfProtobufs;
    }
    final Collection<Object> newCollectionOfValues = new ArrayList<>();
    for (Object protobufValue : collectionOfProtobufs) {
      if (!(protobufValue instanceof Message)) {
        throw new ProtobufException(
            "Collection contains an object of type " + protobufValue.getClass()
                + " which is not an instanceof GeneratedMessage, can not (de)serialize this");
      }
      newCollectionOfValues
          .add(serializeFromProtobufEntity((Message) protobufValue, collectionClazzType));
    }

    return newCollectionOfValues;
  }

}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/client/GrpcRequest.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.grpc.client;

import java.lang.reflect.Method;

import com.google.protobuf.DynamicMessage;
import com.google.protobuf.Message;

import io.github.saluki.common.Constants;
import io.github.saluki.common.GrpcURL;
import io.github.saluki.grpc.annotation.GrpcMethodType;
import io.github.saluki.grpc.exception.RpcFrameworkException;
import io.github.saluki.grpc.util.GrpcUtil;
import io.github.saluki.utils.ReflectUtils;
import io.grpc.Channel;
import io.grpc.MethodDescriptor;

/**
 * @author shimingliu 2016年12月14日 下午5:51:01
 * @version GrpcRequest.java, v 0.0.1 2016年12月14日 下午5:51:01 shimingliu
 */
public abstract class GrpcRequest {

  public Class<?> getResponseType() {
    return null;
  }

  public MethodDescriptor<Message, Message> getMethodDescriptor() {
    return null;
  }

  public Channel getChannel() {
    return null;
  }

  public String getServiceName() {
    return null;
  }

  public String getMethodName() {
    return null;
  }

  public Object getRequestParam() {
    return null;
  }

  public Object getResponseOberver() {
    return null;
  }

  public GrpcURL getRefUrl() {
    return null;
  }

  public int getCallType() {
    return 0;
  }

  public int getCallTimeout() {
    return 0;
  }

  public io.grpc.MethodDescriptor.MethodType getMethodType() {
    return null;
  }


  public static class Dynamic extends GrpcRequest {

    private final GrpcURL refUrl;

    private final String methodName;

    private final Channel channel;

    private final int callType;

    private final int callTimeout;

    private final MethodDescriptor<Message, Message> methodDesc;

    private final DynamicMessage message;

    public Dynamic(GrpcURL refUrl, GrpcProtocolClient.ChannelCall channelPool,
        MethodDescriptor<Message, Message> methodDesc, DynamicMessage message, int callType,
        int callTimeout) {
      super();
      this.refUrl = refUrl;
      this.methodName = refUrl.getParameter(Constants.METHOD_KEY);
      this.channel = channelPool.getChannel(refUrl);
      this.callType = callType;
      this.callTimeout = callTimeout;
      this.methodDesc = methodDesc;
      this.message = message;
    }


    @Override
    public MethodDescriptor<Message, Message> getMethodDescriptor() {
      return this.methodDesc;
    }

    @Override
    public Channel getChannel() {
      return this.channel;
    }

    @Override
    public String getServiceName() {
      return refUrl.getServiceInterface();
    }

    @Override
    public String getMethodName() {
      return this.methodName;
    }

    @Override
    public Object getRequestParam() {
      return message;
    }

    @Override
    public Class<?> getResponseType() {
      return Message.class;
    }

    @Override
    public GrpcURL getRefUrl() {
      return this.refUrl;
    }

    @Override
    public int getCallType() {
      return this.callType;
    }

    @Override
    public int getCallTimeout() {
      return this.callTimeout;
    }

    @Override
    public io.grpc.MethodDescriptor.MethodType getMethodType() {
      return methodDesc.getType();
    }


  }


  public static class Default extends GrpcRequest {


    private final GrpcURL refUrl;

    private final Channel channel;

    private final String methodName;

    private final Object[] args;

    private final int callType;

    private final int callTimeout;

    private final GrpcMethodType grpcMethodType;

    public Default(GrpcURL refUrl, GrpcProtocolClient.ChannelCall chanelPool, String methodName,
        Object[] args, int callType, int callTimeout) {
      super();
      this.refUrl = refUrl.addParameter(Constants.METHOD_KEY, methodName);
      this.channel = chanelPool.getChannel(refUrl);
      this.methodName = methodName;
      if (args.length > 2) {
        throw new IllegalArgumentException(
            "grpc not support multiple args,args is " + args + " length is " + args.length);
      } else {
        this.args = args;
      }
      this.callType = callType;
      this.callTimeout = callTimeout;
      try {
        Class<?> service = ReflectUtils.forName(this.getServiceName());
        Method method = ReflectUtils.findMethodByMethodName(service, this.getMethodName());
        grpcMethodType = method.getAnnotation(GrpcMethodType.class);
      } catch (Exception e) {
        RpcFrameworkException framworkException = new RpcFrameworkException(e);
        throw framworkException;
      }
    }

    @Override
    public Object getRequestParam() {
      return args[0];
    }

    @Override
    public MethodDescriptor<Message, Message> getMethodDescriptor() {
      return GrpcUtil.createMethodDescriptor(this.getServiceName(), methodName, grpcMethodType);
    }

    @Override
    public Class<?> getResponseType() {
      return grpcMethodType.responseType();
    }

    @Override
    public Channel getChannel() {
      return channel;
    }

    @Override
    public String getServiceName() {
      return refUrl.getServiceInterface();
    }

    @Override
    public GrpcURL getRefUrl() {
      return this.refUrl;
    }

    @Override
    public String getMethodName() {
      return this.methodName;
    }

    @Override
    public int getCallType() {
      return this.callType;
    }

    @Override
    public int getCallTimeout() {
      return this.callTimeout;
    }

    @Override
    public io.grpc.MethodDescriptor.MethodType getMethodType() {
      return this.grpcMethodType.methodType();
    }


    @Override
    public Object getResponseOberver() {
      return args[1];
    }

  }

}


<|start_filename|>saluki-ops/saluki-ops-console/src/main/resources/static/sourse/src/libs/routes.js<|end_filename|>
const RouterConfig = [
  {
    path: '/',
    name: 'view:index',
    redirect: { path: '/group/relation' }
  },
  {
    path: '/home',
    name: 'view:home',
    component: require('./../views/Home/index.vue')
  },
  {
    path: '/about',
    name: 'view:about',
    component: require('./../views/About/index.vue')
  },
  {
    path: '/group/relation',
    name: 'view:group.relation',
    title: '应用调用',
    component: require('./../views/GroupRelation/index.vue')
  },
  {
    path: '/service/group',
    name: 'view:service.group',
    title: '应用列表',
    component: require('./../views/ServiceGroup/index.vue')
  },
  {
    path: '/service/search',
    name: 'view:service.search',
    title: '服务查询',
    component: require('./../views/ServiceSearch/index.vue')
  },
  {
    path: '/service/detail/:service',
    name: 'view:service.detail',
    title: '服务详情',
    component: require('./../views/ServiceDetail/index.vue')
  },
  {
    path: '/service/map',
    name: 'view:service.map',
    title: '服务信息',
    component: require('./../views/ServiceMap/index.vue')
  },
  {
    path: '/service/chart/:service/:typelist',
    name: 'view:service.chart',
    title: '服务统计',
    component: require('./../views/ServiceChart/index4.vue')
  },
  {
    path: '/service/test/:ipPort/:service',
    name: 'view:service.test',
    title: '服务测试',
    component: require('./../views/ServiceTest/index.vue')
  },
  {
    path: '/route/rule/list',
    name: 'view:route.rule.list',
    title: '路由规则',
    component: require('./../views/RouteRule/index.vue')
  },
  {
    path: '/route/rule/add',
    name: 'view:route.rule.add',
    title: '路由规则',
    component: require('./../views/RouteRule/add.vue')
  }
]

export default RouterConfig;


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/interceptor/HeaderServerInterceptor.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.grpc.interceptor;

import java.net.InetSocketAddress;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.gson.reflect.TypeToken;
import io.github.saluki.common.Constants;
import io.github.saluki.common.RpcContext;
import io.github.saluki.grpc.util.GrpcUtil;
import io.github.saluki.grpc.util.SerializerUtil;

import io.grpc.Grpc;
import io.grpc.Metadata;
import io.grpc.ServerCall;
import io.grpc.ServerCall.Listener;
import io.grpc.ServerCallHandler;
import io.grpc.ServerInterceptor;

/**
 * @author shimingliu 2016年12月14日 下午10:29:37
 * @version HeaderServerInterceptor.java, v 0.0.1 2016年12月14日 下午10:29:37 shimingliu
 */
public class HeaderServerInterceptor implements ServerInterceptor {

  private static final Logger log = LoggerFactory.getLogger(HeaderServerInterceptor.class);


  public static ServerInterceptor instance() {
    return new HeaderServerInterceptor();
  }

  private HeaderServerInterceptor() {}

  @Override
  public <ReqT, RespT> Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call,
      final Metadata headers, ServerCallHandler<ReqT, RespT> next) {
    final class ServerCallHandlerWrap implements ServerCallHandler<ReqT, RespT> {

      private final ServerCallHandler<ReqT, RespT> handler;

      public ServerCallHandlerWrap(ServerCallHandler<ReqT, RespT> handler) {
        this.handler = handler;
      }

      @Override
      public Listener<ReqT> startCall(ServerCall<ReqT, RespT> call, Metadata headers) {
        try {
          contextCopy(call, headers);
          return handler.startCall(call, headers);
        } finally {
          RpcContext.removeContext();
        }
      }

    }

    final class ListenerWrap extends Listener<ReqT> {

      private final Listener<ReqT> listener;

      public ListenerWrap(Listener<ReqT> listener) {
        this.listener = listener;
      }

      @Override
      public void onMessage(ReqT message) {
        listener.onMessage(message);
      }

      @Override
      public void onHalfClose() {
        try {
          contextCopy(call, headers);
          listener.onHalfClose();
        } finally {
          RpcContext.removeContext();
        }
      }

      @Override
      public void onCancel() {
        listener.onCancel();
      }

      @Override
      public void onComplete() {
        listener.onComplete();
      }

      @Override
      public void onReady() {
        listener.onReady();
      }

    };
    return new ListenerWrap(new ServerCallHandlerWrap(next).startCall(call, headers));
  }


  private void contextCopy(ServerCall<?, ?> call, final Metadata headers) {
    copyMetadataToThreadLocal(headers);
    InetSocketAddress remoteAddress =
        (InetSocketAddress) call.getAttributes().get(Grpc.TRANSPORT_ATTR_REMOTE_ADDR);
    RpcContext.getContext().setAttachment(Constants.REMOTE_ADDRESS, remoteAddress.getHostString());
  }

  private void copyMetadataToThreadLocal(Metadata headers) {
    String attachments = headers.get(GrpcUtil.GRPC_CONTEXT_ATTACHMENTS);
    String values = headers.get(GrpcUtil.GRPC_CONTEXT_VALUES);
    try {
      if (attachments != null) {
        Map<String, String> attachmentsMap =
            SerializerUtil.fromJson(attachments, new TypeToken<Map<String, String>>() {}.getType());
        RpcContext.getContext().setAttachments(attachmentsMap);
      }
      if (values != null) {
        Map<String, Object> valuesMap =
            SerializerUtil.fromJson(values, new TypeToken<Map<String, Object>>() {}.getType());
        for (Map.Entry<String, Object> entry : valuesMap.entrySet()) {
          RpcContext.getContext().set(entry.getKey(), entry.getValue());
        }
      }
    } catch (Throwable e) {
      log.error(e.getMessage(), e);
    }
  }
}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/GrpcEngine.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.grpc;

import java.io.InputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

import javax.net.ssl.SSLException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.github.saluki.common.Constants;
import io.github.saluki.common.GrpcURL;
import io.github.saluki.common.NamedThreadFactory;
import io.github.saluki.grpc.client.GrpcClientStrategy;
import io.github.saluki.grpc.client.GrpcProtocolClient;
import io.github.saluki.grpc.exception.RpcFrameworkException;
import io.github.saluki.grpc.interceptor.HeaderClientInterceptor;
import io.github.saluki.grpc.interceptor.HeaderServerInterceptor;
import io.github.saluki.grpc.server.GrpcServerStrategy;
import io.github.saluki.grpc.util.SslUtil;
import io.github.saluki.registry.Registry;
import io.github.saluki.registry.RegistryProvider;

import io.grpc.Attributes;
import io.grpc.Channel;
import io.grpc.ClientInterceptors;
import io.grpc.Internal;
import io.grpc.LoadBalancer;
import io.grpc.ServerInterceptor;
import io.grpc.ServerInterceptors;
import io.grpc.ServerServiceDefinition;
import io.grpc.ServerTransportFilter;
import io.grpc.netty.GrpcSslContexts;
import io.grpc.netty.NegotiationType;
import io.grpc.netty.NettyChannelBuilder;
import io.grpc.netty.NettyServerBuilder;
import io.grpc.util.TransmitStatusRuntimeExceptionInterceptor;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;

/**
 * @author shimingliu 2016年12月14日 下午10:43:19
 * @version GrpcEngine1.java, v 0.0.1 2016年12月14日 下午10:43:19 shimingliu
 */
@Internal
public final class GrpcEngine {

  private static final Logger log = LoggerFactory.getLogger(GrpcEngine.class);

  private static final Map<String, Channel> CHANNEL_SERVICE_POOL =
      Collections.synchronizedMap(new WeakHashMap<String, Channel>());

  private final GrpcURL registryUrl;

  private final Registry registry;


  public GrpcEngine(GrpcURL registryUrl) {
    this.registryUrl = registryUrl;
    this.registry = RegistryProvider.asFactory().newRegistry(registryUrl);
  }


  public Object getClient(GrpcURL refUrl) throws Exception {
    GrpcProtocolClient.ChannelCall channelCall = new GrpcProtocolClient.ChannelCall() {

      @Override
      public Channel getChannel(final GrpcURL realRefUrl) {
        GrpcURL subscribeUrl = realRefUrl;
        if (subscribeUrl == null) {
          subscribeUrl = refUrl;
        }
        String serviceKey = subscribeUrl.getServiceKey();
        Channel channel = CHANNEL_SERVICE_POOL.get(serviceKey);
        if (channel == null) {
          channel = this.create(subscribeUrl);
          CHANNEL_SERVICE_POOL.put(serviceKey, channel);
        }
        return channel;
      }

      private Channel create(GrpcURL subscribeUrl) {
        Channel channel = NettyChannelBuilder.forTarget(registryUrl.toJavaURI().toString())//
            .nameResolverFactory(new GrpcNameResolverProvider(subscribeUrl))//
            .loadBalancerFactory(buildLoadBalanceFactory())//
            .sslContext(buildClientSslContext())//
            .negotiationType(NegotiationType.TLS)//
            .eventLoopGroup(createWorkEventLoopGroup())//
            .keepAliveTime(60, TimeUnit.SECONDS)//
            .maxHeaderListSize(4 * 1024 * 1024)//
            .directExecutor()//
            .build();//
        return ClientInterceptors.intercept(channel,
            Arrays.asList(HeaderClientInterceptor.instance()));
      }

    };
    GrpcClientStrategy strategy = new GrpcClientStrategy(refUrl, channelCall);
    return strategy.getGrpcClient();
  }



  public io.grpc.Server getServer(Map<GrpcURL, Object> providerUrls, int rpcPort) throws Exception {

    final NettyServerBuilder remoteServer = NettyServerBuilder.forPort(rpcPort)//
        .sslContext(buildServerSslContext())//
        .keepAliveTime(60, TimeUnit.SECONDS)//
        .bossEventLoopGroup(createBossEventLoopGroup())//
        .workerEventLoopGroup(createWorkEventLoopGroup())//
        .maxHeaderListSize(4 * 1024 * 1024)//
        .addTransportFilter(new ServerTransportFilter() {
          @Override
          public Attributes transportReady(Attributes transportAttrs) {
            log.debug("network transport is ready!");
            return transportAttrs;
          }

          @Override
          public void transportTerminated(Attributes transportAttrs) {
            log.debug("network transport is terminated!");
          }
        }).directExecutor();

    final List<ServerInterceptor> interceptors = Arrays.asList(HeaderServerInterceptor.instance(),
        TransmitStatusRuntimeExceptionInterceptor.instance());

    for (Map.Entry<GrpcURL, Object> entry : providerUrls.entrySet()) {
      GrpcURL providerUrl = entry.getKey();
      Object protocolImpl = entry.getValue();
      GrpcServerStrategy strategy = new GrpcServerStrategy(providerUrl, protocolImpl);
      ServerServiceDefinition serviceDefinition =
          ServerInterceptors.intercept(strategy.getServerDefintion(), interceptors);
      remoteServer.addService(serviceDefinition);
      int registryRpcPort = providerUrl.getParameter(Constants.REGISTRY_RPC_PORT_KEY, rpcPort);
      providerUrl = providerUrl.setPort(registryRpcPort);
      registry.register(providerUrl);
    }
    log.info("grpc server is build complete ");
    return remoteServer.build();

  }

  private SslContext buildClientSslContext() {
    try {
      InputStream certs = SslUtil.loadInputStreamCert("server.pem");
      return GrpcSslContexts
          .configure(SslContextBuilder.forClient()//
              .trustManager(certs))//
          .build();
    } catch (SSLException e) {
      throw new RpcFrameworkException(e);
    }
  }

  private LoadBalancer.Factory buildLoadBalanceFactory() {
    return GrpcRouteRoundRobinLbFactory.getInstance();
  }

  private SslContext buildServerSslContext() {
    try {
      InputStream certs = SslUtil.loadInputStreamCert("server.pem");
      InputStream keys = SslUtil.loadInputStreamCert("server_pkcs8.key");
      return GrpcSslContexts.configure(SslContextBuilder.forServer(certs, keys)).build();
    } catch (SSLException e) {
      throw new RpcFrameworkException(e);
    }
  }

  private NioEventLoopGroup createBossEventLoopGroup() {
    ThreadFactory threadFactory = new NamedThreadFactory("grpc-default-boss-ELG", true);
    return new NioEventLoopGroup(1, Executors.newCachedThreadPool(threadFactory));
  }

  private NioEventLoopGroup createWorkEventLoopGroup() {
    ThreadFactory threadFactory = new NamedThreadFactory("grpc-default-worker-ELG", true);
    return new NioEventLoopGroup(0, Executors.newCachedThreadPool(threadFactory));
  }

}


<|start_filename|>saluki-registry/saluki-registry-consul/src/main/java/io/github/saluki/registry/consul/model/ConsulEphemralNode.java<|end_filename|>
package io.github.saluki.registry.consul.model;

import com.ecwid.consul.v1.session.model.NewSession;
import com.ecwid.consul.v1.session.model.Session;
import io.github.saluki.common.GrpcURL;
import io.github.saluki.registry.consul.GrpcURLUtils;

public final class ConsulEphemralNode {

    private final GrpcURL        url;

    private final String         interval;

    private final ThrallRoleType ephemralType;

    private ConsulEphemralNode(Builder builder){
        this.url = builder.url;
        this.interval = builder.interval;
        this.ephemralType = builder.ephemralType;
    }

    public NewSession getNewSession() {
        NewSession newSersson = new NewSession();
        newSersson.setName(getSessionName());
        newSersson.setLockDelay(15);
        newSersson.setBehavior(Session.Behavior.DELETE);
        newSersson.setTtl(this.interval + "s");
        return newSersson;
    }

    public String getSessionName() {
        return ephemralType.name() + "_" + url.getHost() + "_" + url.getPort();
    }

    public String getEphemralNodeKey() {
        return GrpcURLUtils.ephemralNodePath(url, ephemralType);
    }

    public String getEphemralNodeValue() {
        return url.toFullString();
    }

    public static Builder newEphemralNode() {
        return new Builder();
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((ephemralType == null) ? 0 : ephemralType.hashCode());
        result = prime * result + ((interval == null) ? 0 : interval.hashCode());
        result = prime * result + ((url == null) ? 0 : url.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        ConsulEphemralNode other = (ConsulEphemralNode) obj;
        if (ephemralType != other.ephemralType) return false;
        if (interval == null) {
            if (other.interval != null) return false;
        } else if (!interval.equals(other.interval)) return false;
        if (url == null) {
            if (other.url != null) return false;
        } else if (!url.equals(other.url)) return false;
        return true;
    }

    @Override
    public String toString() {
        return "ConsulEphemralNode [url=" + url + ", interval=" + interval + ", ephemralType=" + ephemralType + "]";
    }

    public static class Builder extends AbstractBuilder {

        private GrpcURL        url;

        private String         interval;

        private ThrallRoleType ephemralType;

        public Builder withUrl(GrpcURL url) {
            this.url = url;
            return this;
        }

        public Builder withEphemralType(ThrallRoleType ephemralType) {
            this.ephemralType = ephemralType;
            return this;
        }

        public Builder withCheckInterval(String interval) {
            this.interval = substituteEnvironmentVariables(interval);
            return this;
        }

        public ConsulEphemralNode build() {
            return new ConsulEphemralNode(this);
        }

    }

}


<|start_filename|>saluki-serializer/src/main/java/io/github/saluki/serializer/utils/JReflectionUtils.java<|end_filename|>
package io.github.saluki.serializer.utils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;

public class JReflectionUtils {
  private static final Map<String, Map<String, Method>> METHOD_FIELD_MAP_CACHE =
      Collections.synchronizedMap(new WeakHashMap<String, Map<String, Method>>());

  private JReflectionUtils() {}

  public static Object runGetter(Object object, Field field)
      throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    final Class<?> clazz = object.getClass();
    final String fieldName = field.getName();
    Map<String, Method> fieldMethodMap =
        METHOD_FIELD_MAP_CACHE.get(object.getClass().getCanonicalName());
    if (fieldMethodMap != null) {
      final Method fieldMethod = fieldMethodMap.get(fieldName);
      if (fieldMethod != null) {
        return fieldMethod.invoke(object);
      }
    } else {
      fieldMethodMap = new HashMap<>();
    }
    try {
      final Method method = clazz
          .getMethod(JStringUtils.GET + JStringUtils.upperCaseFirst(fieldName), new Class<?>[] {});
      fieldMethodMap.put(fieldName, method);
      METHOD_FIELD_MAP_CACHE.put(object.getClass().getCanonicalName(), fieldMethodMap);
      return method.invoke(object);
    } catch (Exception e) {
      // Swallow exception so that we loop through the rest.
    }
    for (Method method : clazz.getMethods()) {
      final String methodName = method.getName();
      if (((methodName.startsWith(JStringUtils.GET))
          && (methodName.length() == (fieldName.length() + JStringUtils.GET.length())))
          || ((methodName.startsWith(JStringUtils.IS))
              && (methodName.length() == (fieldName.length() + JStringUtils.IS.length())))) {
        if (methodName.toLowerCase().endsWith(fieldName.toLowerCase())) {
          fieldMethodMap.put(fieldName, method);
          METHOD_FIELD_MAP_CACHE.put(object.getClass().getCanonicalName(), fieldMethodMap);
          return method.invoke(object);
        }
      }
    }
    return null;
  }

  public static Object runSetter(Object object, String method, Object arg,
      Class<? extends Object> argClazz) throws JException {
    try {
      if (argClazz == null) {
        argClazz = arg.getClass();
      }
      final Method m = object.getClass().getMethod(method, argClazz);
      return m.invoke(object, arg);
    } catch (Exception e) {
      throw new JException(e);
    }
  }

  public static Object runMethod(Object object, String method, Object... args) throws JException {
    try {
      final Method m = object.getClass().getMethod(method);
      return m.invoke(object, args);
    } catch (Exception e) {
      throw new JException(e);
    }
  }

  /**
   * 执行静态方法
   */
  public static Object runStaticMethod(Class<?> clzz, String method, Object... args)
      throws JException {
    try {
      Class<?>[] parameterTypes = null;
      if (args.length != 0) {
        parameterTypes = new Class[args.length];
        for (int i = 0; i < args.length; i++) {
          parameterTypes[i] = args[i].getClass();
        }
      }
      Method m;
      if (parameterTypes == null) {
        m = clzz.getMethod(method);
      } else {
        m = clzz.getMethod(method, parameterTypes);
      }
      return m.invoke(null, args);
    } catch (Exception e) {
      throw new JException(e);
    }
  }

  public static List<Field> getAllFields(List<Field> fields, Class<?> clazz) {
    for (Field field : clazz.getDeclaredFields()) {
      fields.add(field);
    }

    if (clazz.getSuperclass() != null) {
      fields = getAllFields(fields, clazz.getSuperclass());
    }

    return fields;
  }

  public static List<Method> getAllMethods(List<Method> methods, Class<?> clazz) {
    for (Method method : clazz.getDeclaredMethods()) {
      methods.add(method);
    }

    if (clazz.getSuperclass() != null) {
      methods = getAllMethods(methods, clazz.getSuperclass());
    }

    return methods;
  }

  public static Method getMethodByName(Class<?> clazz, String name) {
    final List<Method> methods = JReflectionUtils.getAllMethods(new ArrayList<Method>(), clazz);

    for (Method method : methods) {
      if (method.getName().equals(name)) {
        return method;
      }
    }
    return null;
  }
}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/client/internal/GenericProxyClient.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.grpc.client.internal;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.google.protobuf.DynamicMessage;
import com.google.protobuf.Message;
import io.github.saluki.common.Constants;
import io.github.saluki.common.GrpcURL;
import io.github.saluki.grpc.client.GrpcProtocolClient;
import io.github.saluki.grpc.client.GrpcRequest;
import io.github.saluki.grpc.service.GenericService;
import io.github.saluki.utils.ClassHelper;

import io.grpc.MethodDescriptor;

/**
 * @author shimingliu 2016年12月14日 下午9:50:27
 * @version GenericProxyClient.java, v 0.0.1 2016年12月14日 下午9:50:27 shimingliu
 */
public class GenericProxyClient<T> implements GrpcProtocolClient<T> {


  private final GrpcURL refUrl;

  public GenericProxyClient(GrpcURL refUrl) {
    this.refUrl = refUrl;
  }


  @SuppressWarnings("unchecked")
  @Override
  public T getGrpcClient(GrpcProtocolClient.ChannelCall channelPool, int callType,
      int callTimeout) {
    return (T) Proxy.newProxyInstance(ClassHelper.getClassLoader(),
        new Class[] {GenericService.class},
        new GenericProxyClientInvocation(channelPool, callType, callTimeout));
  }

  private class GenericProxyClientInvocation extends AbstractClientInvocation {

    private final GrpcProtocolClient.ChannelCall channelPool;
    private final int callType;
    private final int callTimeout;

    public GenericProxyClientInvocation(GrpcProtocolClient.ChannelCall channelPool, int callType,
        int callTimeout) {
      super(GenericProxyClient.this.refUrl);
      this.channelPool = channelPool;
      this.callType = callType;
      this.callTimeout = callTimeout;
    }

    @SuppressWarnings("unchecked")
    @Override
    protected GrpcRequest buildGrpcRequest(Method method, Object[] args) {
      if (!isDynamicCall(args)) {
        GrpcURL resetRefUrl = GenericProxyClient.this.refUrl;
        resetRefUrl = resetRefUrl.setPath(getServiceName(args));
        resetRefUrl = resetRefUrl.addParameter(Constants.GROUP_KEY, getGroup(args));
        resetRefUrl = resetRefUrl.addParameter(Constants.VERSION_KEY, getVersion(args));
        GrpcRequest request = new GrpcRequest.Default(resetRefUrl, channelPool,
            this.getMethod(args), this.getArg(args), callType, callTimeout);
        return request;
      } else {
        GrpcURL resetRefUrl = GenericProxyClient.this.refUrl;
        resetRefUrl = resetRefUrl.setPath(getServiceName(args));
        resetRefUrl = resetRefUrl.addParameter(Constants.METHOD_KEY, getMethod(args));
        resetRefUrl = resetRefUrl.addParameter(Constants.GROUP_KEY, getGroup(args));
        resetRefUrl = resetRefUrl.addParameter(Constants.VERSION_KEY, getVersion(args));
        MethodDescriptor<Message, Message> methodDesc =
            (MethodDescriptor<Message, Message>) args[4];
        DynamicMessage message = (DynamicMessage) args[5];
        GrpcRequest request = new GrpcRequest.Dynamic(resetRefUrl, channelPool, methodDesc, message,
            callType, callTimeout);
        return request;
      }
    }

    private Boolean isDynamicCall(Object[] args) {
      for (Object obj : args) {
        if (obj instanceof MethodDescriptor) {
          return true;
        }
      }
      return false;
    }

    private String getServiceName(Object[] args) {
      return (String) args[0];
    }

    private String getGroup(Object[] args) {
      return (String) args[1];
    }

    private String getVersion(Object[] args) {
      return (String) args[2];
    }

    private String getMethod(Object[] args) {
      return (String) args[3];
    }

    private Object[] getArg(Object[] args) {
      Object[] param = (Object[]) args[4];
      return param;
    }

  }
}


<|start_filename|>saluki-serializer/src/main/java/io/github/saluki/serializer/ProtobufSerializer.java<|end_filename|>
/*
 * Copyright 2014-2017 the original author or authors.
 *
 * 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 io.github.saluki.serializer;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;

import com.google.protobuf.AbstractMessage.Builder;
import com.google.protobuf.GeneratedMessageV3;
import com.google.protobuf.Message;
import io.github.saluki.serializer.exception.ProtobufAnnotationException;
import io.github.saluki.serializer.exception.ProtobufException;
import io.github.saluki.serializer.help.Pojo2ProtobufHelp;
import io.github.saluki.serializer.help.Protobuf2PojoHelp;
import io.github.saluki.serializer.internal.ProtobufSerializerUtils;
import io.github.saluki.serializer.utils.JReflectionUtils;


/**
 * @author liushiming
 * @version ProtobufSerializer2.java, v 0.0.1 2017年7月18日 下午12:49:24 liushiming
 * @since JDK 1.8
 */
public class ProtobufSerializer implements IProtobufSerializer {

  /**
   * @see io.github.saluki.serializer.IProtobufSerializer#toProtobuf(java.lang.Object)
   */
  @Override
  @SuppressWarnings({"unchecked", "rawtypes", "unused"})
  public Message toProtobuf(Object pojo) throws ProtobufException {
    try {
      final Class<?> fromClazz = (Class<?>) pojo.getClass();
      final Class<? extends GeneratedMessageV3> protoClazz =
          ProtobufSerializerUtils.getProtobufClassFromPojoAnno(fromClazz);
      if (protoClazz == null) {
        throw new ProtobufAnnotationException(
            "Doesn't seem like " + fromClazz + " is ProtobufEntity");
      }
      final Map<Field, ProtobufAttribute> protoBufFields =
          ProtobufSerializerUtils.getAllProtbufFields(fromClazz);
      if (protoBufFields.isEmpty()) {
        return null;
      }
      final Method newBuilderMethod = protoClazz.getMethod("newBuilder");
      final Builder protoObjBuilder = (Builder) newBuilderMethod.invoke(null);
      for (Entry<Field, ProtobufAttribute> entry : protoBufFields.entrySet()) {
        final Field field = entry.getKey();
        final ProtobufAttribute gpbAnnotation = entry.getValue();
        final String fieldName = field.getName();
        // 1. Determine validity of value
        Object value = Pojo2ProtobufHelp.getPojoFieldValue(pojo, gpbAnnotation, field);
        // If value is null and it is not required, skip, as the default for Protobuf values is null
        if (value == null) {
          continue;
        }
        // 2. Call recursively if this is a ProtobufEntity
        value = Pojo2ProtobufHelp.serializeToProtobufEntity(value);
        // 3. Special recursively if this is a ProtobufEntity
        if (value instanceof Collection) {
          value = Pojo2ProtobufHelp.convertCollectionToProtobufs((Collection<Object>) value);
          if (((Collection) value).isEmpty()) {
            continue;
          }
        }
        if (value instanceof Map) {
          value = Pojo2ProtobufHelp.convertMapToProtobufs((Map) value);
          if (((Map) value).isEmpty()) {
            continue;
          }
        }
        String setter = ProtobufSerializerUtils.getProtobufSetter(gpbAnnotation, field, value);
        if (value instanceof Enum) {
          value = JReflectionUtils.runMethod(value, "getNumber");
          setter = setter + "Value";
        }
        Pojo2ProtobufHelp.setProtobufFieldValue(gpbAnnotation, protoObjBuilder, setter, value);
      }
      return protoObjBuilder.build();
    } catch (Exception e) {
      throw new ProtobufException(
          "Could not generate Protobuf object for " + pojo.getClass() + ": " + e, e);
    }
  }

  /**
   * @see io.github.saluki.serializer.IProtobufSerializer#fromProtobuf(com.google.protobuf.Message,
   *      java.lang.Class)
   */
  @Override
  public Object fromProtobuf(Message protobuf, Class<?> pojoClazz) throws ProtobufException {
    try {
      final Class<? extends Message> protoClazz =
          ProtobufSerializerUtils.getProtobufClassFromPojoAnno(pojoClazz);
      if (protoClazz == null) {
        throw new ProtobufAnnotationException(
            "Doesn't seem like " + pojoClazz + " is ProtobufEntity");
      }
      final Map<Field, ProtobufAttribute> protobufFields =
          ProtobufSerializerUtils.getAllProtbufFields(pojoClazz);
      if (protobufFields.isEmpty()) {
        throw new ProtobufException("No protoBuf fields have been annotated on the class "
            + pojoClazz + ", thus cannot continue.");
      }
      Object pojo = pojoClazz.newInstance();
      for (Entry<Field, ProtobufAttribute> entry : protobufFields.entrySet()) {
        final Field field = entry.getKey();
        final ProtobufAttribute protobufAttribute = entry.getValue();
        final String setter = ProtobufSerializerUtils.getPojoSetter(protobufAttribute, field);
        Object protobufValue =
            Protobuf2PojoHelp.getProtobufFieldValue(protobuf, protobufAttribute, field);
        if (protobufValue == null) {
          continue;
        }
        Protobuf2PojoHelp.setPojoFieldValue(pojo, setter, protobufValue, protobufAttribute, field);
      }
      return pojo;
    } catch (Exception e) {
      throw new ProtobufException("Could not generate POJO of type " + pojoClazz
          + " from Protobuf object " + protobuf.getClass() + ": " + e, e);
    }
  }



}


<|start_filename|>saluki-ops/spring-boot-starter-salukiops/src/main/java/io/github/saluki/monitor/MonitorAutoconfiguration.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and proprietary
 * information of Quancheng-ec.com ("Confidential Information"). You shall not disclose such Confidential Information
 * and shall use it only in accordance with the terms of the license agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.monitor;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;

/**
 * @author shimingliu 2016年12月20日 下午3:44:35
 * @version MonitorAutoconfiguration.java, v 0.0.1 2016年12月20日 下午3:44:35 shimingliu
 */
@SuppressWarnings("deprecation")
@Configuration
@ConditionalOnExpression("${saluki.monitor.enabled:true}")
public class MonitorAutoconfiguration {

    private static final Logger log = LoggerFactory.getLogger(MonitorAutoconfiguration.class);

    @Bean
    public BeanFactoryPostProcessor beanFactoryPostProcessor(ApplicationContext applicationContext) {
        return new BeanFactoryPostProcessor() {

            @Override
            public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
                if (beanFactory instanceof BeanDefinitionRegistry) {
                    try {
                        BeanDefinitionRegistry registry = (BeanDefinitionRegistry)beanFactory;
                        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry);
                        scanner.setResourceLoader(applicationContext);
                        scanner.scan("io.github.saluki.monitor.rest");
                    } catch (Throwable e) {
                        log.error(e.getMessage(), e);
                    }
                }

            }

        };
    }

    @Configuration
    @AutoConfigureAfter(WebMvcAutoConfiguration.class)
    public static class WebMvcAutoconfig extends WebMvcConfigurerAdapter {

        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/assets/**")//
                .addResourceLocations("classpath:/META-INF/static/assets/");
            registry.addResourceHandler("doc.html").//
                addResourceLocations("classpath:/META-INF/static/");
        }

        @Override
        public void addViewControllers(ViewControllerRegistry registry) {
            registry.addViewController("/doc").setViewName("/doc.html");
        }

    };

    @Configuration
    @AutoConfigureAfter(WebMvcAutoConfiguration.class)
    public static class HystrixEventStreamConfig {

        @Bean
        public HystrixMetricsStreamServlet hystrixMetricsStreamServlet() {
            return new HystrixMetricsStreamServlet();
        }

        @Bean
        public ServletRegistrationBean registration(HystrixMetricsStreamServlet servlet) {
            ServletRegistrationBean registrationBean = new ServletRegistrationBean();
            registrationBean.setServlet(servlet);
            registrationBean.setEnabled(true);
            registrationBean.addUrlMappings("/hystrix.stream");
            return registrationBean;
        }
    }

}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/client/GrpcProtocolClient.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.grpc.client;

import io.github.saluki.common.GrpcURL;

import io.grpc.Channel;

/**
 * @author shimingliu 2016年12月14日 下午5:50:42
 * @version GrpcProtocolClient.java, v 0.0.1 2016年12月14日 下午5:50:42 shimingliu
 */
public interface GrpcProtocolClient<T> {

  public T getGrpcClient(ChannelCall channelCall, int callType, int callTimeout);

  public interface ChannelCall {

    public Channel getChannel(final GrpcURL refUrl);

  }

}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/registry/RegistryProvider.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the
 * confidential and proprietary information of Quancheng-ec.com ("Confidential
 * Information"). You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement you entered
 * into with Quancheng-ec.com.
 */
package io.github.saluki.registry;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

import com.google.common.collect.Lists;
import io.github.saluki.common.Constants;
import io.github.saluki.common.GrpcURL;
import io.github.saluki.registry.internal.RegistryFactory;

import io.grpc.Internal;

/**
 * @author shimingliu 2016年12月14日 下午1:48:47
 * @version RegistryProvider.java, v 0.0.1 2016年12月14日 下午1:48:47 shimingliu
 */
@Internal
public abstract class RegistryProvider extends RegistryFactory {

    private static final List<RegistryProvider> registryProviders = load();

    private static final RegistryFactory        internalFactory   = new InternalRegistryFactory(registryProviders);

    static List<RegistryProvider> load() {
        Iterable<RegistryProvider> candidates = ServiceLoader.load(RegistryProvider.class, getCorrectClassLoader());
        List<RegistryProvider> list = Lists.newArrayList();
        for (RegistryProvider current : candidates) {
            if (!current.isAvailable()) {
                continue;
            }
            list.add(current);
        }
        Collections.sort(list, Collections.reverseOrder(new Comparator<RegistryProvider>() {

            @Override
            public int compare(RegistryProvider provider1, RegistryProvider provider2) {
                return provider1.priority() - provider2.priority();
            }
        }));
        return Collections.unmodifiableList(list);
    }

    protected abstract boolean isAvailable();

    protected abstract int priority();

    public static RegistryFactory asFactory() {
        return internalFactory;
    }

    private static ClassLoader getCorrectClassLoader() {
        return Thread.currentThread().getContextClassLoader();
    }

    private static class InternalRegistryFactory extends RegistryFactory {

        private final List<RegistryProvider>       providers;
        private static final ReentrantLock         LOCK       = new ReentrantLock();
        private static final Map<String, Registry> REGISTRIES = new ConcurrentHashMap<String, Registry>();

        public InternalRegistryFactory(List<RegistryProvider> providers){
            this.providers = providers;
        }

        @Override
        public Registry newRegistry(GrpcURL url) {
            url = url.setPath(Registry.class.getName())//
                     .addParameter(Constants.INTERFACE_KEY, Registry.class.getName());
            String key = url.toServiceString();
            LOCK.lock();
            try {
                Registry registry = REGISTRIES.get(key);
                if (registry != null) {
                    return registry;
                }
                for (RegistryProvider provider : providers) {
                    registry = provider.newRegistry(url);
                    if (registry != null) {
                        continue;
                    }
                }
                if (registry == null) {
                    throw new IllegalStateException("Can not create registry " + url);
                }
                REGISTRIES.put(key, registry);
                return registry;
            } finally {
                LOCK.unlock();
            }
        }
    }
}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/client/internal/unary/FailOverUnaryFuture.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.grpc.client.internal.unary;

import java.net.SocketAddress;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicInteger;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.util.concurrent.ListenableFuture;
import io.github.saluki.grpc.client.internal.GrpcCallOptions;

import io.grpc.CallOptions;
import io.grpc.Channel;
import io.grpc.ClientCall;
import io.grpc.Grpc;
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;
import io.grpc.Status;
import io.grpc.internal.GrpcUtil;

/**
 * @author liushiming 2017年5月2日 下午5:42:42
 * @version FailOverListener.java, v 0.0.1 2017年5月2日 下午5:42:42 liushiming
 */
public class FailOverUnaryFuture<Request, Response> extends ClientCall.Listener<Response>
    implements Runnable {

  private final static Logger logger = LoggerFactory.getLogger(FailOverUnaryFuture.class);

  private final ScheduledExecutorService scheduleRetryService = GrpcUtil.TIMER_SERVICE.create();

  private final AtomicInteger currentRetries = new AtomicInteger(0);

  private final MethodDescriptor<Request, Response> method;

  private CompletionFuture<Response> completionFuture;

  private ClientCall<Request, Response> clientCall;

  private Request request;
  private Response response;
  private Integer maxRetries;
  private boolean enabledRetry;
  private CallOptions callOptions;
  private Channel channel;

  public FailOverUnaryFuture(final MethodDescriptor<Request, Response> method) {
    this.method = method;
  }

  public void setCallOptions(CallOptions callOptions) {
    this.callOptions = callOptions;
  }

  public void setChannel(Channel channel) {
    this.channel = channel;
  }

  public void setMaxRetries(Integer maxRetries) {
    this.maxRetries = maxRetries;
    this.enabledRetry = maxRetries > 0 ? true : false;
  }

  public void setRequest(Request request) {
    this.request = request;
  }

  @Override
  public void onMessage(Response message) {
    if (this.response != null && !enabledRetry) {
      throw Status.INTERNAL.withDescription("More than one value received for unary call")
          .asRuntimeException();
    }
    this.response = message;
  }


  @Override
  public void onClose(Status status, Metadata trailers) {
    try {
      SocketAddress remoteServer = clientCall.getAttributes().get(Grpc.TRANSPORT_ATTR_REMOTE_ADDR);
      callOptions.getOption(GrpcCallOptions.CALLOPTIONS_CUSTOME_KEY)
          .put(GrpcCallOptions.GRPC_CURRENT_ADDR_KEY, remoteServer);
    } finally {
      if (status.isOk()) {
        statusOk(trailers);
      } else {
        statusError(status, trailers);
      }
    }
  }

  private void statusOk(Metadata trailers) {
    try {
      if (enabledRetry) {
        final NameResolverNotify nameResolverNotify = this.createNameResolverNotify();
        nameResolverNotify.resetChannel();
      }
    } finally {
      if (response == null) {
        completionFuture.setException(Status.INTERNAL
            .withDescription("No value received for unary call").asRuntimeException(trailers));
      }
      completionFuture.set(response);
    }
  }


  private void statusError(Status status, Metadata trailers) {
    if (enabledRetry) {
      final NameResolverNotify nameResolverNotify = this.createNameResolverNotify();
      boolean retryHaveDone = this.retryHaveDone();
      if (retryHaveDone) {
        completionFuture.setException(status.asRuntimeException(trailers));
      } else {
        nameResolverNotify.refreshChannel();
        scheduleRetryService.execute(this);
        SocketAddress remoteAddress =
            (SocketAddress) callOptions.getOption(GrpcCallOptions.CALLOPTIONS_CUSTOME_KEY)
                .get(GrpcCallOptions.GRPC_CURRENT_ADDR_KEY);
        logger.error(String.format("Retrying failed call. Failure #%d，Failure Server: %s",
            currentRetries.get(), String.valueOf(remoteAddress)));
        currentRetries.getAndIncrement();
      }
    } else {
      completionFuture.setException(status.asRuntimeException(trailers));
    }

  }

  private NameResolverNotify createNameResolverNotify() {
    Map<String, Object> affinity = callOptions.getOption(GrpcCallOptions.CALLOPTIONS_CUSTOME_KEY);
    NameResolverNotify nameResolverNotify = NameResolverNotify.newNameResolverNotify();
    nameResolverNotify.refreshAffinity(affinity);
    return nameResolverNotify;
  }

  private boolean retryHaveDone() {
    return currentRetries.get() >= maxRetries;
  }

  @Override
  public void run() {
    this.clientCall = channel.newCall(method, callOptions);
    this.completionFuture = new CompletionFuture<Response>(this.clientCall);
    this.clientCall.start(this, new Metadata());
    this.clientCall.sendMessage(request);
    this.clientCall.halfClose();
    this.clientCall.request(1);
  }


  public ListenableFuture<Response> getFuture() {
    return completionFuture;
  }

  public void cancel() {
    if (clientCall != null) {
      clientCall.cancel("User requested cancelation.", null);
    }
  }

}


<|start_filename|>saluki-ops/spring-boot-starter-salukiops/src/main/java/io/github/saluki/monitor/config/MybatisMapperScannerConfig.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.monitor.config;

import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author shimingliu 2016年12月21日 下午8:08:56
 * @version MybatisMapperScannerConfig.java, v 0.0.1 2016年12月21日 下午8:08:56 shimingliu
 */
@Configuration
@ConditionalOnExpression("${saluki.monitor.enabled:true}")
@AutoConfigureAfter(MybatisConfiguration.class)
public class MybatisMapperScannerConfig {

  @Bean
  public MapperScannerConfigurer mapperScannerConfigurer() {
    MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
    mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
    mapperScannerConfigurer.setBasePackage("io.github.saluki.monitor.dao");
    return mapperScannerConfigurer;
  }
}


<|start_filename|>saluki-plugin/saluki-plugin-common/src/main/java/io/github/saluki/plugin/common/PrintServiceFile.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.plugin.common;

import java.util.List;
import java.util.Map;

import com.google.common.collect.Lists;
import com.google.protobuf.DescriptorProtos.MethodDescriptorProto;

/**
 * @author shimingliu 2016年12月21日 下午3:39:54
 * @version PrintServiceFile.java, v 0.0.1 2016年12月21日 下午3:39:54 shimingliu
 */
public final class PrintServiceFile extends AbstractPrint {

  private Map<String, String> pojoTypeCache;

  private List<MethodDescriptorProto> serviceMethods;

  public PrintServiceFile(String fileRootPath, String sourcePackageName, String className) {
    super(fileRootPath, sourcePackageName, className);
  }

  public void setPojoTypeCache(Map<String, String> pojoTypeCache) {
    this.pojoTypeCache = pojoTypeCache;
  }

  public void setServiceMethods(List<MethodDescriptorProto> serviceMethods) {
    this.serviceMethods = serviceMethods;
  }

  @Override
  protected List<String> collectFileData() {
    String className = super.getClassName();
    String packageName = super.getSourcePackageName().toLowerCase();
    List<String> fileData = Lists.newArrayList();
    fileData.add("package " + packageName + ";");
    fileData.add("public interface " + className + "{");
    for (MethodDescriptorProto method : serviceMethods) {
      String outPutType = method.getOutputType();
      String inPutType = method.getInputType();
      String methodName = method.getName();
      inPutType = CommonUtils.findPojoTypeFromCache(inPutType, pojoTypeCache);
      outPutType = CommonUtils.findPojoTypeFromCache(outPutType, pojoTypeCache);
      String stream = generateGrpcStream(method, inPutType, outPutType);
      if (method.getServerStreaming() || method.getClientStreaming()) {
        outPutType = "io.grpc.stub.StreamObserver<" + outPutType + ">";
      }
      String inputValue = CommonUtils.findNotIncludePackageType(inPutType).toLowerCase();
      if (method.getClientStreaming()) {
        inPutType = "io.grpc.stub.StreamObserver<" + inPutType + ">";
      }
      if (stream != null)
        fileData.add(stream);
      String methodStr = generateMethod(method, inPutType, outPutType, methodName, inputValue);
      fileData.add(methodStr);
    }
    fileData.add("}");
    return fileData;
  }

  private String generateGrpcStream(MethodDescriptorProto method, String inPutType,
      String outPutType) {
    String format =
        "@io.github.saluki.grpc.annotation.GrpcMethodType(methodType=%s,requestType=%s,responseType=%s)";
    if (method.getServerStreaming() && method.getClientStreaming()) {
      String stream = String.format(format, "io.grpc.MethodDescriptor.MethodType.BIDI_STREAMING",
          inPutType + ".class", outPutType + ".class");
      return stream;
    } else {
      if (!method.getServerStreaming() && method.getClientStreaming()) {
        String stream =
            String.format(format, "io.grpc.MethodDescriptor.MethodType.CLIENT_STREAMING",
                inPutType + ".class", outPutType + ".class");
        return stream;
      } else if (method.getServerStreaming() && !method.getClientStreaming()) {
        String stream =
            String.format(format, "io.grpc.MethodDescriptor.MethodType.SERVER_STREAMING",
                inPutType + ".class", outPutType + ".class");
        return stream;
      }
      return String.format(format, "io.grpc.MethodDescriptor.MethodType.UNARY",
          inPutType + ".class", outPutType + ".class");
    }
  }

  private String generateMethod(MethodDescriptorProto method, String inPutType, String outPutType,
      String methodName, String inputValue) {
    String methodStr =
        "public " + outPutType + " " + methodName + "(" + inPutType + " " + inputValue + ");";
    boolean isClientStream = !method.getServerStreaming() && method.getClientStreaming();
    boolean isBidiStream = method.getServerStreaming() && method.getClientStreaming();
    boolean isServerStream = method.getServerStreaming() && !method.getClientStreaming();
    if (isClientStream || isBidiStream) {
      methodStr =
          "public " + inPutType + " " + methodName + "(" + outPutType + " responseObserver);";
    } else if (isServerStream) {
      methodStr = "public void " + methodName + "(" + inPutType + " " + inputValue + ","
          + outPutType + " responseObserver);";
    }
    return methodStr;
  }


}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/config/RpcBaseConfig.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the
 * confidential and proprietary information of Quancheng-ec.com ("Confidential
 * Information"). You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement you entered
 * into with Quancheng-ec.com.
 */
package io.github.saluki.config;

import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

import org.apache.commons.lang3.StringUtils;

import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import io.github.saluki.common.Constants;
import io.github.saluki.common.GrpcURL;
import io.github.saluki.grpc.GrpcEngine;
import io.github.saluki.utils.NetUtils;

/**
 * @author shimingliu 2016年12月14日 下午1:34:20
 * @version RpcBaseConfig.java, v 0.0.1 2016年12月14日 下午1:34:20 shimingliu
 */
public class RpcBaseConfig implements Serializable {

    private static final long serialVersionUID = -8963353064840744509L;

    private String            application;

    private String            registryAddress;

    private Integer           registryPort;

    private Integer           monitorinterval;

    private String            host;

    private Integer           realityRpcPort;

    private Integer           registryRpcPort;

    private Integer           httpPort;

    public String getApplication() {
        return application;
    }

    public void setApplication(String application) {
        this.application = application;
    }

    public String getRegistryAddress() {
        return registryAddress;
    }

    public void setRegistryAddress(String registryAddress) {
        this.registryAddress = registryAddress;
    }

    public Integer getRegistryPort() {
        return registryPort;
    }

    public void setRegistryPort(Integer registryPort) {
        this.registryPort = registryPort;
    }

    public Integer getMonitorinterval() {
        return monitorinterval;
    }

    public void setMonitorinterval(Integer monitorinterval) {
        this.monitorinterval = monitorinterval;
    }

    public String getHost() {
        String host = this.host;
        Boolean isLocal = NetUtils.isLocalHost(host);
        return (isLocal || StringUtils.isBlank(host)) ? NetUtils.getLocalHost() : host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public Integer getRegistryRpcPort() {
        return registryRpcPort;
    }

    public void setRegistryRpcPort(Integer registryRpcPort) {
        this.registryRpcPort = registryRpcPort;
    }

    public Integer getRealityRpcPort() {
        return realityRpcPort;
    }

    public void setRealityRpcPort(Integer realityRpcPort) {
        this.realityRpcPort = realityRpcPort;
    }

    public Integer getHttpPort() {
        return httpPort;
    }

    public void setHttpPort(Integer httpPort) {
        this.httpPort = httpPort;
    }

    protected void addHttpPort(Map<String, String> params) {
        Integer httpport = getHttpPort();
        if (httpport != null && httpport != 0) {
            params.put(Constants.HTTP_PORT_KEY, httpport.toString());
        }
    }

    protected void addMonitorInterval(Map<String, String> params) {
        Integer monitorInterval = getMonitorinterval();
        if (monitorInterval!=null && monitorInterval != 0) {
            params.put("monitorinterval", monitorInterval.toString());
        }
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((application == null) ? 0 : application.hashCode());
        result = prime * result + ((host == null) ? 0 : host.hashCode());
        result = prime * result + ((httpPort == null) ? 0 : httpPort.hashCode());
        result = prime * result + ((monitorinterval == null) ? 0 : monitorinterval.hashCode());
        result = prime * result + ((realityRpcPort == null) ? 0 : realityRpcPort.hashCode());
        result = prime * result + ((registryAddress == null) ? 0 : registryAddress.hashCode());
        result = prime * result + ((registryPort == null) ? 0 : registryPort.hashCode());
        result = prime * result + ((registryRpcPort == null) ? 0 : registryRpcPort.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null) return false;
        if (getClass() != obj.getClass()) return false;
        RpcBaseConfig other = (RpcBaseConfig) obj;
        if (application == null) {
            if (other.application != null) return false;
        } else if (!application.equals(other.application)) return false;
        if (host == null) {
            if (other.host != null) return false;
        } else if (!host.equals(other.host)) return false;
        if (httpPort == null) {
            if (other.httpPort != null) return false;
        } else if (!httpPort.equals(other.httpPort)) return false;
        if (monitorinterval == null) {
            if (other.monitorinterval != null) return false;
        } else if (!monitorinterval.equals(other.monitorinterval)) return false;
        if (realityRpcPort == null) {
            if (other.realityRpcPort != null) return false;
        } else if (!realityRpcPort.equals(other.realityRpcPort)) return false;
        if (registryAddress == null) {
            if (other.registryAddress != null) return false;
        } else if (!registryAddress.equals(other.registryAddress)) return false;
        if (registryPort == null) {
            if (other.registryPort != null) return false;
        } else if (!registryPort.equals(other.registryPort)) return false;
        if (registryRpcPort == null) {
            if (other.registryRpcPort != null) return false;
        } else if (!registryRpcPort.equals(other.registryRpcPort)) return false;
        return true;
    }

    @Override
    public String toString() {
        return "RpcBaseConfig [application=" + application + ", registryAddress=" + registryAddress + ", registryPort="
               + registryPort + ", monitorinterval=" + monitorinterval + ", host=" + host + ", realityRpcPort="
               + realityRpcPort + ", registryRpcPort=" + registryRpcPort + ", httpPort=" + httpPort + "]";
    }

    public GrpcEngine getGrpcEngine() {
        return GrpcEngineHolder.getEngine(registryAddress, registryPort);
    }

    private static class GrpcEngineHolder {

        private static final ReentrantLock           LOCK    = new ReentrantLock();

        private static final Map<String, GrpcEngine> ENGINES = Maps.newConcurrentMap();

        private static class GrpcEngineHolderSingleton {

            private static final GrpcEngineHolder INSTANCE = new GrpcEngineHolder();
        }

        private GrpcEngineHolder(){
        }

        private GrpcEngine getGrpcEngine(String registryAddress, int registryPort) {
            String key = registryAddress + ":" + registryPort;
            LOCK.lock();
            try {
                GrpcEngine engine = ENGINES.get(key);
                if (engine != null) {
                    return engine;
                }
                Preconditions.checkNotNull(registryAddress, "registryAddress  is not Null", registryAddress);
                Preconditions.checkState(registryPort != 0, "RegistryPort can not be zero", registryPort);
                GrpcURL registryUrl = new GrpcURL(Constants.REGISTRY_PROTOCOL, registryAddress, registryPort);
                engine = new GrpcEngine(registryUrl);
                ENGINES.put(key, engine);
                return engine;
            } finally {
                LOCK.unlock();
            }
        }

        public static final GrpcEngine getEngine(String registryAddress, Integer registryPort) {
            return GrpcEngineHolderSingleton.INSTANCE.getGrpcEngine(registryAddress, registryPort);
        }

    }

}


<|start_filename|>saluki-ops/spring-boot-starter-salukiops/src/main/java/io/github/saluki/monitor/rest/DataController.java<|end_filename|>
package io.github.saluki.monitor.rest;

import java.lang.management.ManagementFactory;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.google.common.collect.Maps;
import io.github.saluki.boot.autoconfigure.GrpcProperties;
import io.github.saluki.common.NamedThreadFactory;
import io.github.saluki.utils.NetUtils;
import io.github.saluki.utils.Version;
import io.github.saluki.monitor.MonitorUtil;
import io.github.saluki.monitor.dao.InvokeMapper;
import io.github.saluki.monitor.dao.domain.GrpcInvoke;

@RestController
@RequestMapping("monitor")
public class DataController {

    private SimpleDateFormat               formatter         = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS Z");

    private final InvokeMapper             mapper            = MonitorUtil.getBean(InvokeMapper.class);

    private final ScheduledExecutorService scheduleClearData = Executors.newScheduledThreadPool(1,
                                                                                                new NamedThreadFactory("ClearMonitorData",
                                                                                                                       true));
    @Autowired
    private GrpcProperties               thrallProperties;

    public void init() {
        scheduleClearData.scheduleAtFixedRate(new Runnable() {

            @Override
            public void run() {
                clearData();
            }
        }, 0, 1, TimeUnit.HOURS);
    }

    @RequestMapping(value = "/system", method = RequestMethod.GET)
    public Map<String, Object> system() {
        List<String[]> rows = new ArrayList<String[]>();
        rows.add(new String[] { "Saluki_Version", Version.getVersion() });
        rows.add(new String[] { "Host",
                                thrallProperties.getHost() != null ? thrallProperties.getHost() : NetUtils.getLocalHost() });
        rows.add(new String[] { "OS", System.getProperty("os.name") + " " + System.getProperty("os.version") });
        rows.add(new String[] { "JVM",
                                System.getProperty("java.runtime.name") + " "
                                       + System.getProperty("java.runtime.version") + ",<br/>"
                                       + System.getProperty("java.vm.name") + " "
                                       + System.getProperty("java.vm.version") + " "
                                       + System.getProperty("java.vm.info", "") });

        rows.add(new String[] { "CPU", System.getProperty("os.arch", "") + ", "
                                       + String.valueOf(Runtime.getRuntime().availableProcessors()) + " cores" });

        rows.add(new String[] { "Locale", Locale.getDefault().toString() + "/" + System.getProperty("file.encoding") });

        rows.add(new String[] { "Uptime", MonitorUtil.formatUptime(ManagementFactory.getRuntimeMXBean().getUptime()) });

        rows.add(new String[] { "Time", formatter.format(new Date()) });

        Map<String, Object> model = Maps.newHashMap();
        model.put("rows", rows);
        return model;
    }

    @RequestMapping(value = "statistics", method = RequestMethod.GET)
    public List<GrpcInvoke> statistics() {
        List<GrpcInvoke> statistics = mapper.queryData();
        return statistics;
    }

    @RequestMapping(value = "/clean", method = RequestMethod.GET)
    public void cleanData() {
        clearData();
    }

    private void clearData() {
        mapper.truncateTable();
    }

}


<|start_filename|>saluki-example/saluki-example-client/src/main/java/io/github/saluki/example/SalukiExampleClientApp.java<|end_filename|>
package io.github.saluki.example;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import io.github.examples.model.hello.HelloRequest;
import io.github.examples.service.HelloService;
import io.github.saluki.boot.SalukiReference;

@SpringBootApplication
public class SalukiExampleClientApp implements CommandLineRunner {

  @SalukiReference
  private HelloService helloService;

  private int threads = 50;
  private int rounds = 10000;

  public static void main(String[] args) {
    SpringApplication.run(SalukiExampleClientApp.class, args);
  }

  @Override
  public void run(String... arg0) throws Exception {
    // Thread.sleep(1000 * 10);
    // long start = System.currentTimeMillis();
    // Thread[] ts = new Thread[threads];
    // for (int i = 0; i < threads; i++) {
    // ts[i] = new Thread(new Runnable() {
    //
    // @Override
    // public void run() {
    // for (int i = 0; i < rounds; i++) {
    // HelloRequest request = new HelloRequest();
    // request.setName("liushiming");
    // helloService.sayHello(request);
    // }
    // }
    //
    // });
    // }
    // for (int i = 0; i < threads; i++) {
    // ts[i].start();
    // }
    // for (int i = 0; i < threads; i++) {
    // ts[i].join();
    // }
    // System.out.println(
    // " qps=" + ((long) threads * rounds * 1000 / (System.currentTimeMillis() - start + 1)));
    // double ms = (System.currentTimeMillis() - start + 1) / ((double) threads * rounds);
    // System.out.println("ms=" + ms);
  }


}


<|start_filename|>saluki-registry/saluki-registry-consul/src/main/java/io/github/saluki/registry/consul/model/ThrallRoleType.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the
 * confidential and proprietary information of Quancheng-ec.com ("Confidential
 * Information"). You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement you entered
 * into with Quancheng-ec.com.
 */
package io.github.saluki.registry.consul.model;

/**
 * @author shimingliu 2016年12月16日 上午10:49:33
 * @version EphemralType.java, v 0.0.1 2016年12月16日 上午10:49:33 shimingliu
 */
public enum ThrallRoleType {
                          CONSUMER(0),

                          PROVIDER(1);

    private final int value;

    private ThrallRoleType(int value){
        this.value = value;
    }

    public final int getNumber() {
        return value;
    }

    public static ThrallRoleType forNumber(Integer value) {
        switch (value) {
            case 0:
                return CONSUMER;
            case 1:
                return CONSUMER;
            default:
                return null;
        }
    }
}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/GrpcNameResolverProvider.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.grpc;

import java.net.SocketAddress;
import java.net.URI;
import java.util.List;
import java.util.Map;

import io.github.saluki.common.GrpcURL;

import io.grpc.Attributes;
import io.grpc.Internal;
import io.grpc.NameResolver;
import io.grpc.NameResolverProvider;

/**
 * @author shimingliu 2016年12月14日 下午5:15:00
 * @version ThrallNameResolverProvider1.java, v 0.0.1 2016年12月14日 下午5:15:00 shimingliu
 */
@Internal
public class GrpcNameResolverProvider extends NameResolverProvider {


  public static final Attributes.Key<Map<List<SocketAddress>, GrpcURL>> GRPC_ADDRESS_GRPCURL_MAPPING =
      Attributes.Key.of("grpc-address-mapping");

  public static final Attributes.Key<List<SocketAddress>> REMOTE_ADDR_KEYS =
      Attributes.Key.of("remote-addresss");

  public static final Attributes.Key<NameResolver.Listener> NAMERESOVER_LISTENER =
      Attributes.Key.of("nameResolver-Listener");

  private final GrpcURL subscribeUrl;

  public GrpcNameResolverProvider(GrpcURL subscribeUrl) {
    this.subscribeUrl = subscribeUrl;
  }

  @Override
  protected boolean isAvailable() {
    return true;
  }

  @Override
  protected int priority() {
    return 5;
  }

  @Override
  public NameResolver newNameResolver(URI targetUri, Attributes params) {
    return new GrpcNameResolver(targetUri, params, subscribeUrl);
  }

  @Override
  public String getDefaultScheme() {
    return null;
  }

}


<|start_filename|>spring-boot-starter-saluki/src/main/java/io/github/saluki/boot/SalukiReference.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.boot;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import io.github.saluki.common.Constants;

/**
 * @author shimingliu 2016年12月16日 下午1:59:58
 * @version SalukiReference.java, v 0.0.1 2016年12月16日 下午1:59:58 shimingliu
 */
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface SalukiReference {

  String service() default "";

  String group() default "";

  String version() default "";

  int retries() default 0;

  String[] retryMethods() default {};

  boolean async() default true;

  boolean fallback() default false;

  String[] fallBackMethods() default {};

  @SuppressWarnings("rawtypes")
  Class[] validatorGroups() default {};

  int timeOut() default Constants.RPC_ASYNC_DEFAULT_TIMEOUT;

}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/registry/internal/AbstractRegistry.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.registry.internal;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import io.github.saluki.common.Constants;
import io.github.saluki.common.GrpcURL;
import io.github.saluki.common.NamedThreadFactory;
import io.github.saluki.registry.NotifyListener;
import io.github.saluki.registry.Registry;
import io.github.saluki.utils.GrpcURLUtils;

/**
 * @author shimingliu 2016年12月14日 下午1:55:28
 * @version AbstractRegistry1.java, v 0.0.1 2016年12月14日 下午1:55:28 shimingliu
 */
public abstract class AbstractRegistry implements Registry {

  protected final Logger logger = LoggerFactory.getLogger(getClass());
  private final GrpcURL registryUrl;
  private final Set<GrpcURL> registered = Sets.newConcurrentHashSet();
  private final ConcurrentMap<GrpcURL, Set<NotifyListener.NotifyServiceListener>> subscribed =
      Maps.newConcurrentMap();
  private final ConcurrentMap<GrpcURL, Map<NotifyListener.NotifyServiceListener, List<GrpcURL>>> notified =
      Maps.newConcurrentMap();
  private final ExecutorService notifyExecutor;

  public AbstractRegistry(GrpcURL registryUrl) {
    if (registryUrl == null) {
      throw new IllegalArgumentException("registry url == null");
    }
    this.registryUrl = registryUrl;
    this.notifyExecutor = Executors.newCachedThreadPool(
        new NamedThreadFactory("SalukiNotifyListener.NotifyServiceListener", true));
  }

  public GrpcURL getRegistryUrl() {
    return registryUrl;
  }

  public Set<GrpcURL> getRegistered() {
    return registered;
  }

  public Map<GrpcURL, Set<NotifyListener.NotifyServiceListener>> getSubscribed() {
    return subscribed;
  }

  public Map<GrpcURL, Map<NotifyListener.NotifyServiceListener, List<GrpcURL>>> getNotified() {
    return notified;
  }

  public List<GrpcURL> discover(GrpcURL url) {
    String[] keys = new String[] {Constants.ASYNC_KEY, Constants.GENERIC_KEY, Constants.TIMEOUT};
    url = url.removeParameters(keys);
    List<GrpcURL> result = new ArrayList<GrpcURL>();
    Map<NotifyListener.NotifyServiceListener, List<GrpcURL>> notifiedUrls = getNotified().get(url);
    if (notifiedUrls != null && notifiedUrls.size() > 0) {
      for (List<GrpcURL> urls : notifiedUrls.values()) {
        for (GrpcURL u : urls) {
          result.add(u);
        }
      }
    } else {
      final AtomicReference<List<GrpcURL>> reference = new AtomicReference<List<GrpcURL>>();
      NotifyListener.NotifyServiceListener listener = new NotifyListener.NotifyServiceListener() {

        public void notify(GrpcURL url, List<GrpcURL> urls) {
          reference.set(urls);
        }
      };
      subscribe(url, listener); // 订阅逻辑保证第一次notify后再返回
      List<GrpcURL> urls = reference.get();
      if (urls != null && urls.size() > 0) {
        for (GrpcURL u : urls) {
          result.add(u);
        }
      }
    }
    return result;
  }

  public void register(GrpcURL url) {
    if (url == null) {
      throw new IllegalArgumentException("register url == null");
    }
    if (logger.isInfoEnabled()) {
      logger.info("Register: " + url);
    }
    registered.add(url);
  }

  public void unregister(GrpcURL url) {
    if (url == null) {
      throw new IllegalArgumentException("unregister url == null");
    }
    if (logger.isInfoEnabled()) {
      logger.info("Unregister: " + url);
    }
    registered.remove(url);
  }

  public void subscribe(GrpcURL url, NotifyListener.NotifyServiceListener listener) {
    if (url == null) {
      throw new IllegalArgumentException("subscribe url == null");
    }
    if (listener == null) {
      throw new IllegalArgumentException("subscribe listener == null");
    }
    String[] keys = new String[] {Constants.ASYNC_KEY, Constants.GENERIC_KEY, Constants.TIMEOUT};
    url = url.removeParameters(keys);
    if (logger.isInfoEnabled()) {
      logger.info("Subscribe: " + url);
    }
    Set<NotifyListener.NotifyServiceListener> listeners = subscribed.get(url);
    if (listeners == null) {
      subscribed.putIfAbsent(url, Sets.newConcurrentHashSet());
      listeners = subscribed.get(url);
    }
    listeners.add(listener);
  }

  public void unsubscribe(GrpcURL url, NotifyListener.NotifyServiceListener listener) {
    if (url == null) {
      throw new IllegalArgumentException("unsubscribe url == null");
    }
    if (listener == null) {
      throw new IllegalArgumentException("unsubscribe listener == null");
    }
    if (logger.isInfoEnabled()) {
      logger.info("Unsubscribe: " + url);
    }
    Set<NotifyListener.NotifyServiceListener> listeners = subscribed.get(url);
    if (listeners != null) {
      listeners.remove(listener);
    }
  }

  protected void notify(List<GrpcURL> providerUrls) {
    if (providerUrls == null || providerUrls.isEmpty())
      return;
    for (Map.Entry<GrpcURL, Set<NotifyListener.NotifyServiceListener>> entry : getSubscribed()
        .entrySet()) {
      GrpcURL subscribedUrl = entry.getKey();
      if (!GrpcURLUtils.isMatch(subscribedUrl, providerUrls.get(0))) {
        continue;
      }
      Set<NotifyListener.NotifyServiceListener> listeners = entry.getValue();
      if (listeners != null) {
        for (NotifyListener.NotifyServiceListener listener : listeners) {
          notify(subscribedUrl, listener, providerUrls);
        }
      }
    }
  }

  protected void notify(GrpcURL subscribedUrl, NotifyListener.NotifyServiceListener listener,
      List<GrpcURL> providerUrls) {
    addNotified(subscribedUrl, listener, providerUrls);
    notifyExecutor.submit(new Runnable() {

      @Override
      public void run() {
        listener.notify(subscribedUrl, providerUrls);
      }
    });
  }

  protected void recover() throws Exception {
    // register
    Set<GrpcURL> recoverRegistered = Sets.newHashSet(getRegistered());
    if (!recoverRegistered.isEmpty()) {
      if (logger.isInfoEnabled()) {
        logger.info("Recover register url " + recoverRegistered);
      }
      for (GrpcURL url : recoverRegistered) {
        register(url);
      }
    }
    // subscribe
    Map<GrpcURL, Set<NotifyListener.NotifyServiceListener>> recoverSubscribed =
        Maps.newHashMap(getSubscribed());
    if (!recoverSubscribed.isEmpty()) {
      if (logger.isInfoEnabled()) {
        logger.info("Recover subscribe url " + recoverSubscribed.keySet());
      }
      for (Map.Entry<GrpcURL, Set<NotifyListener.NotifyServiceListener>> entry : recoverSubscribed
          .entrySet()) {
        GrpcURL url = entry.getKey();
        for (NotifyListener.NotifyServiceListener listener : entry.getValue()) {
          subscribe(url, listener);
        }
      }
    }
  }

  private void addNotified(GrpcURL subscribedUrl, NotifyListener.NotifyServiceListener listener,
      List<GrpcURL> providerUrls) {
    Map<NotifyListener.NotifyServiceListener, List<GrpcURL>> notifiedUrlMap =
        notified.get(subscribedUrl);
    List<GrpcURL> notifiedUrlList;
    if (notifiedUrlMap == null) {
      notifiedUrlMap = Maps.newConcurrentMap();
      notifiedUrlList = providerUrls;
    } else {
      notifiedUrlList = notifiedUrlMap.get(listener);
      if (notifiedUrlList == null) {
        notifiedUrlList = Lists.newArrayList();
      }
      notifiedUrlList.addAll(providerUrls);
    }
    notifiedUrlMap.putIfAbsent(listener, notifiedUrlList);
    notified.putIfAbsent(subscribedUrl, notifiedUrlMap);
  }
}


<|start_filename|>saluki-ops/spring-boot-starter-salukiops/src/main/java/io/github/saluki/monitor/GrpcMonitorService.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.monitor;

import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.github.saluki.common.Constants;
import io.github.saluki.common.GrpcURL;
import io.github.saluki.grpc.service.MonitorService;
import io.github.saluki.monitor.MonitorUtil;
import io.github.saluki.monitor.dao.InvokeMapper;
import io.github.saluki.monitor.dao.domain.GrpcInvoke;

/**
 * @author shimingliu 2016年12月21日 下午7:15:56
 * @version MonitorService.java, v 0.0.1 2016年12月21日 下午7:15:56 shimingliu
 */
public class GrpcMonitorService implements MonitorService {

  private static final Logger logger = LoggerFactory.getLogger(GrpcMonitorService.class);
  private final InvokeMapper invokeMapping;

  public GrpcMonitorService() {
    invokeMapping = MonitorUtil.getBean(InvokeMapper.class);
  }

  @Override
  public void collect(GrpcURL statistics) {
    if (!Constants.MONITOR_PROTOCOL.equals(statistics.getProtocol())) {
      return;
    }
    try {
      GrpcInvoke invoke = new GrpcInvoke();
      invoke.setId(MonitorUtil.createUUID());
      if (statistics.hasParameter(PROVIDER)) {
        invoke.setType(CONSUMER);
        invoke.setConsumer(statistics.getAddress());
        invoke.setProvider(statistics.getParameter(PROVIDER));
      } else {
        invoke.setType(PROVIDER);
        invoke.setConsumer(statistics.getParameter(CONSUMER));
        invoke.setProvider(statistics.getAddress());
      }
      invoke.setInvokeDate(new Date(Long.valueOf(statistics.getParameter(TIMESTAMP))));
      invoke.setApplication(statistics.getParameter(APPLICATION));
      invoke.setService(statistics.getServiceInterface());
      invoke.setMethod(statistics.getParameter(METHOD));
      invoke.setConcurrent(statistics.getParameter(CONCURRENT, 1));
      invoke.setMaxElapsed(statistics.getParameter(MAX_ELAPSED, 0));
      invoke.setMaxConcurrent(statistics.getParameter(MAX_CONCURRENT, 0));
      invoke.setMaxInput(statistics.getParameter(MAX_INPUT, 0));
      invoke.setMaxOutput(statistics.getParameter(MAX_OUTPUT, 0));
      invoke.setSuccess(statistics.getParameter(SUCCESS, 0));
      invoke.setFailure(statistics.getParameter(FAILURE, 0));
      invoke.setElapsed(statistics.getParameter(MonitorService.ELAPSED, 0));
      invoke.setInput(statistics.getParameter(MonitorService.INPUT, 0));
      invoke.setOutput(statistics.getParameter(MonitorService.OUTPUT, 0));
      if (invoke.getSuccess() == 0 && invoke.getFailure() == 0 && invoke.getElapsed() == 0
          && invoke.getConcurrent() == 0 && invoke.getMaxElapsed() == 0
          && invoke.getMaxConcurrent() == 0) {
        return;
      }
      invokeMapping.addInvoke(invoke);
    } catch (Throwable t) {
      logger.error(t.getMessage(), t);
    }

  }

}


<|start_filename|>saluki-example/saluki-example-server/Dockerfile<|end_filename|>
FROM yingjunjiao/runtime-image:1.0
ENV TZ="Asia/Shanghai"
ENV LANG C.UTF-8
ADD saluki-example/saluki-example-server/target/saluki-example-server-1.5.2-SNAPSHOT.jar /root/app.jar
ADD bin /root/
RUN chmod +x /root/*.sh;mkdir /root/logs
ENV JAVA_OPTS ""
ENV APP_NAME saluki-example-provider
WORKDIR /root
CMD ["./start.sh"]

<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/router/internal/ScriptRouter.java<|end_filename|>
/*
 * Copyright (c) 2017, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.grpc.router.internal;

import java.util.List;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.github.saluki.common.GrpcURL;
import io.github.saluki.grpc.router.GrpcRouter;

/**
 * @author shimingliu 2017年1月9日 下午2:24:56
 * @version ScriptRouter.java, v 0.0.1 2017年1月9日 下午2:24:56 shimingliu
 */
public class ScriptRouter extends GrpcRouter {

  private static final Logger log = LoggerFactory.getLogger(ScriptRouter.class);

  private ScriptEngine engine;

  public ScriptRouter(String type, String rule) {
    super(rule);
    engine = new ScriptEngineManager().getEngineByName(type);
    if (engine == null && StringUtils.equals(type, "javascript")) {
      engine = new ScriptEngineManager().getEngineByName("js");
    }
    if (engine == null) {
      throw new IllegalStateException("Unsupported route rule type: " + type + ", rule: " + rule);
    }
  }

  @Override
  protected void parseRouter() {
    // do nothing
  }

  @Override
  public boolean match(List<GrpcURL> providerUrls) {
    String rule = super.getRule();
    try {
      engine.eval(super.getRule());
      Invocable invocable = (Invocable) engine;
      GrpcURL refUrl = super.getRefUrl();
      Object obj = invocable.invokeFunction("route", refUrl, providerUrls);
      if (obj instanceof Boolean) {
        return (Boolean) obj;
      } else {
        return true;
      }
    } catch (ScriptException | NoSuchMethodException e) {
      log.error("route error , rule has been ignored. rule: " + rule + ", url: " + providerUrls, e);
      return true;
    }
  }

}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/GrpcRouteRoundRobinLbFactory.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.grpc;

import static com.google.common.base.Preconditions.checkNotNull;
import static io.grpc.ConnectivityState.CONNECTING;
import static io.grpc.ConnectivityState.IDLE;
import static io.grpc.ConnectivityState.READY;
import static io.grpc.ConnectivityState.TRANSIENT_FAILURE;

import java.util.ArrayList;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;

import javax.annotation.Nullable;

import com.google.common.annotations.VisibleForTesting;

import io.grpc.Attributes;
import io.grpc.ConnectivityState;
import io.grpc.ConnectivityStateInfo;
import io.grpc.EquivalentAddressGroup;
import io.grpc.Internal;
import io.grpc.LoadBalancer;
import io.grpc.LoadBalancer.Helper;
import io.grpc.Status;

/**
 * @author shimingliu 2016年12月14日 下午5:31:11
 * @version ThrallRoundRobinLoadBalanceFactory1.java, v 0.0.1 2016年12月14日 下午5:31:11 shimingliu
 */

@Internal
public class GrpcRouteRoundRobinLbFactory extends LoadBalancer.Factory {

  private static final GrpcRouteRoundRobinLbFactory instance = new GrpcRouteRoundRobinLbFactory();

  private GrpcRouteRoundRobinLbFactory() {}

  public static GrpcRouteRoundRobinLbFactory getInstance() {
    return instance;
  }

  @Override
  public LoadBalancer newLoadBalancer(Helper helper) {
    return new GrpcRoundRobinLoadBalancer(helper);
  }

  private static class GrpcRoundRobinLoadBalancer extends LoadBalancer {

    private final Helper helper;
    private final Map<EquivalentAddressGroup, Subchannel> subchannels =
        new HashMap<EquivalentAddressGroup, Subchannel>();

    @VisibleForTesting
    static final Attributes.Key<AtomicReference<ConnectivityStateInfo>> STATE_INFO =
        Attributes.Key.of("state-info");

    private Attributes attributes;

    GrpcRoundRobinLoadBalancer(Helper helper) {
      this.helper = checkNotNull(helper, "helper");
    }

    @Override
    public void handleResolvedAddressGroups(List<EquivalentAddressGroup> servers,
        Attributes attributes) {
      this.attributes = attributes;
      Set<EquivalentAddressGroup> currentAddrs = subchannels.keySet();
      Set<EquivalentAddressGroup> latestAddrs = stripAttrs(servers);
      Set<EquivalentAddressGroup> addedAddrs = setsDifference(latestAddrs, currentAddrs);
      Set<EquivalentAddressGroup> removedAddrs = setsDifference(currentAddrs, latestAddrs);

      // Create new subchannels for new addresses.
      for (EquivalentAddressGroup addressGroup : addedAddrs) {
        // NB(lukaszx0): we don't merge `attributes` with `subchannelAttr` because subchannel
        // doesn't need them. They're describing the resolved server list but we're not taking
        // any action based on this information.
        Attributes subchannelAttrs = Attributes.newBuilder()
            // NB(lukaszx0): because attributes are immutable we can't set
            // new value for the key
            // after creation but since we can mutate the values we leverge
            // that and set
            // AtomicReference which will allow mutating state info for given
            // channel.
            .set(STATE_INFO,
                new AtomicReference<ConnectivityStateInfo>(ConnectivityStateInfo.forNonError(IDLE)))
            .build();

        Subchannel subchannel =
            checkNotNull(helper.createSubchannel(addressGroup, subchannelAttrs), "subchannel");
        subchannels.put(addressGroup, subchannel);
        subchannel.requestConnection();
      }

      // Shutdown subchannels for removed addresses.
      for (EquivalentAddressGroup addressGroup : removedAddrs) {
        Subchannel subchannel = subchannels.remove(addressGroup);
        subchannel.shutdown();
      }
      updateBalancingState(getAggregatedState(), getAggregatedError());
    }

    @Override
    public void handleNameResolutionError(Status error) {
      updateBalancingState(TRANSIENT_FAILURE, error);
    }

    @Override
    public void handleSubchannelState(Subchannel subchannel, ConnectivityStateInfo stateInfo) {
      if (!subchannels.containsValue(subchannel)) {
        return;
      }
      if (stateInfo.getState() == IDLE) {
        subchannel.requestConnection();
      }
      getSubchannelStateInfoRef(subchannel).set(stateInfo);
      updateBalancingState(getAggregatedState(), getAggregatedError());
    }

    @Override
    public void shutdown() {
      for (Subchannel subchannel : getSubchannels()) {
        subchannel.shutdown();
      }
    }

    /**
     * Updates picker with the list of active subchannels (state == READY).
     */
    private void updateBalancingState(ConnectivityState state, Status error) {
      List<Subchannel> activeList = filterNonFailingSubchannels(getSubchannels());
      helper.updateBalancingState(state, new GrpcRoutePicker(activeList, error, attributes));
    }

    /**
     * Filters out non-ready subchannels.
     */
    private static List<Subchannel> filterNonFailingSubchannels(
        Collection<Subchannel> subchannels) {
      List<Subchannel> readySubchannels = new ArrayList<Subchannel>(subchannels.size());
      for (Subchannel subchannel : subchannels) {
        if (getSubchannelStateInfoRef(subchannel).get().getState() == READY) {
          readySubchannels.add(subchannel);
        }
      }
      return readySubchannels;
    }

    /**
     * Converts list of {@link EquivalentAddressGroup} to {@link EquivalentAddressGroup} set and
     * remove all attributes.
     */
    private static Set<EquivalentAddressGroup> stripAttrs(List<EquivalentAddressGroup> groupList) {
      Set<EquivalentAddressGroup> addrs = new HashSet<EquivalentAddressGroup>();
      for (EquivalentAddressGroup group : groupList) {
        addrs.add(new EquivalentAddressGroup(group.getAddresses()));
      }
      return addrs;
    }

    /**
     * If all subchannels are TRANSIENT_FAILURE, return the Status associated with an arbitrary
     * subchannel otherwise, return null.
     */
    @Nullable
    private Status getAggregatedError() {
      Status status = null;
      for (Subchannel subchannel : getSubchannels()) {
        ConnectivityStateInfo stateInfo = getSubchannelStateInfoRef(subchannel).get();
        if (stateInfo.getState() != TRANSIENT_FAILURE) {
          return null;
        }
        status = stateInfo.getStatus();
      }
      return status;
    }

    private ConnectivityState getAggregatedState() {
      Set<ConnectivityState> states = EnumSet.noneOf(ConnectivityState.class);
      for (Subchannel subchannel : getSubchannels()) {
        states.add(getSubchannelStateInfoRef(subchannel).get().getState());
      }
      if (states.contains(READY)) {
        return READY;
      }
      if (states.contains(CONNECTING)) {
        return CONNECTING;
      }
      if (states.contains(IDLE)) {
        return CONNECTING;
      }
      return TRANSIENT_FAILURE;
    }

    @VisibleForTesting
    Collection<Subchannel> getSubchannels() {
      return subchannels.values();
    }

    private static AtomicReference<ConnectivityStateInfo> getSubchannelStateInfoRef(
        Subchannel subchannel) {
      return checkNotNull(subchannel.getAttributes().get(STATE_INFO), "STATE_INFO");
    }

    private static <T> Set<T> setsDifference(Set<T> a, Set<T> b) {
      Set<T> aCopy = new HashSet<T>(a);
      aCopy.removeAll(b);
      return aCopy;
    }
  }

}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/client/internal/stream/StreamObserverToCallListenerAdapter.java<|end_filename|>
/*
 * Copyright 2014-2017 the original author or authors.
 *
 * 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 io.github.saluki.grpc.client.internal.stream;

import io.grpc.ClientCall;
import io.grpc.Metadata;
import io.grpc.Status;
import io.grpc.stub.ClientResponseObserver;
import io.grpc.stub.StreamObserver;

/**
 * @author liushiming
 * @version StreamObserverToCallListenerAdapter.java, v 0.0.1 2017年8月16日 下午5:31:23 liushiming
 * @since JDK 1.8
 */
public class StreamObserverToCallListenerAdapter<Request, Response>
    extends ClientCall.Listener<Response> {
  private final StreamObserver<Response> observer;
  private final CallToStreamObserverAdapter<Request, Response> adapter;
  private final boolean streamingResponse;
  private boolean firstResponseReceived;

  StreamObserverToCallListenerAdapter(StreamObserver<Response> observer,
      CallToStreamObserverAdapter<Request, Response> adapter, boolean streamingResponse) {
    this.observer = observer;
    this.streamingResponse = streamingResponse;
    this.adapter = adapter;
    if (observer instanceof ClientResponseObserver) {
      @SuppressWarnings("unchecked")
      ClientResponseObserver<Request, Response> clientResponseObserver =
          (ClientResponseObserver<Request, Response>) observer;
      clientResponseObserver.beforeStart(adapter);
    }
    adapter.freeze();
  }

  @Override
  public void onHeaders(Metadata headers) {}

  @Override
  public void onMessage(Response message) {
    if (firstResponseReceived && !streamingResponse) {
      throw Status.INTERNAL
          .withDescription("More than one responses received for unary or client-streaming call")
          .asRuntimeException();
    }
    firstResponseReceived = true;
    observer.onNext(message);
    if (streamingResponse && adapter.isAutoFlowControlEnabled()) {
      adapter.request(1);
    }
  }

  @Override
  public void onClose(Status status, Metadata trailers) {
    if (status.isOk()) {
      observer.onCompleted();
    } else {
      observer.onError(status.asRuntimeException(trailers));
    }
  }

  @Override
  public void onReady() {
    Runnable runnable = adapter.getOnReadyHandler();
    if (runnable != null) {
      runnable.run();
    }
  }
}


<|start_filename|>saluki-ops/saluki-ops-console/src/main/java/io/github/saluki/monitor/ops/controller/MonitorController.java<|end_filename|>
package io.github.saluki.monitor.ops.controller;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import io.github.saluki.monitor.dao.domain.GrpcnvokeStatistics;
import io.github.saluki.monitor.ops.service.MonitorDataService;

@RestController
@RequestMapping(value = "/api/monitor")
public class MonitorController {

    private static final Logger log = LoggerFactory.getLogger(MonitorController.class);

    @Autowired
    private MonitorDataService minitorDataService;

    private HttpClient httpClient;

    private Gson gson;

    @PostConstruct
    public void init() {
        httpClient = HttpClientBuilder.create().build();
        gson = new Gson();
    }

    @RequestMapping(value = "statistics", method = RequestMethod.GET)
    public Map<String, List<GrpcnvokeStatistics>> statistics(@RequestParam(value = "ips", required = true) String ips,
        @RequestParam(value = "service", required = true) String service,
        @RequestParam(value = "type", required = true) String type,
        @RequestParam(value = "datatype", required = true) String dataType,
        @RequestParam(value = "invokeDateFrom", required = true) String invokeDateFrom,
        @RequestParam(value = "invokeDateTo", required = true) String invokeDateTo) throws Exception {
        log.info("Return statistics monitor data");
        String[] ipArray = StringUtils.split(ips, ",");
        List<String> ipList = Arrays.asList(ipArray);
        java.text.SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date from = formatter.parse(invokeDateFrom);
        Date to = formatter.parse(invokeDateTo);
        return minitorDataService.queryDataByMachines(service, type, dataType, ipList, from, to);
    }

    @RequestMapping(value = "sumstatistics", method = RequestMethod.GET)
    public List<GrpcnvokeStatistics> statistics(@RequestParam(value = "service", required = true) String service,
        @RequestParam(value = "type", required = true) String type,
        @RequestParam(value = "datatype", required = true) String dataType,
        @RequestParam(value = "invokeDateFrom", required = true) String invokeDateFrom,
        @RequestParam(value = "invokeDateTo", required = true) String invokeDateTo) throws Exception {
        log.info("Return statistics monitor data");
        java.text.SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date from = formatter.parse(invokeDateFrom);
        Date to = formatter.parse(invokeDateTo);
        return minitorDataService.querySumDataByService(service, type, dataType, from, to);
    }

    @RequestMapping(value = "system", method = RequestMethod.GET)
    public Map<String, Object> system(@RequestParam(value = "ipPort", required = true) String ipPort) throws Exception {
        log.info("Return all monitor data");
        String monitordataUrl = "http://" + ipPort + "/monitor/system";
        HttpGet request = new HttpGet(monitordataUrl);
        request.addHeader("content-type", "application/json");
        request.addHeader("Accept", "application/json");
        try {
            HttpResponse httpResponse = httpClient.execute(request);
            String minitorJson = EntityUtils.toString(httpResponse.getEntity());
            Map<String, Object> system = gson.fromJson(minitorJson, new TypeToken<Map<String, Object>>() {
            }.getType());
            return system;
        } catch (Exception e) {
            throw e;
        }
    }

}


<|start_filename|>saluki-serializer/src/main/java/io/github/saluki/serializer/IProtobufConverter.java<|end_filename|>
package io.github.saluki.serializer;

import io.github.saluki.serializer.exception.ProtobufAnnotationException;

public interface IProtobufConverter {

    Object convertToProtobuf(Object sourceObject) throws ProtobufAnnotationException;

    Object convertFromProtobuf(Object sourceObject) throws ProtobufAnnotationException;
}


<|start_filename|>saluki-ops/spring-boot-starter-salukiops/src/main/java/io/github/saluki/monitor/jaket/model/TypeDefinition.java<|end_filename|>
package io.github.saluki.monitor.jaket.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by huangsheng.hs on 2015/1/27.
 */
public class TypeDefinition {

    private String                      id;

    private String                      type;

    private List<TypeDefinition>        items;

    private List<String>                enums;

    private String                      $ref;

    private Map<String, TypeDefinition> properties;

    public TypeDefinition(String type){
        this.type = type;
    }

    public String get$ref() {
        return $ref;
    }

    public List<String> getEnums() {
        if (enums == null) {
            enums = new ArrayList<String>();
        }
        return enums;
    }

    public String getId() {
        return id;
    }

    public List<TypeDefinition> getItems() {
        if (items == null) {
            items = new ArrayList<TypeDefinition>();
        }
        return items;
    }

    public Map<String, TypeDefinition> getProperties() {
        if (properties == null) {
            properties = new HashMap<String, TypeDefinition>();
        }
        return properties;
    }

    public String getType() {
        return type;
    }

    public void set$ref(String $ref) {
        this.$ref = $ref;
    }

    public void setEnums(List<String> enums) {
        this.enums = enums;
    }

    public void setId(String id) {
        this.id = id;
    }

    public void setItems(List<TypeDefinition> items) {
        this.items = items;
    }

    public void setProperties(Map<String, TypeDefinition> properties) {
        this.properties = properties;
    }

    public void setType(String type) {
        this.type = type;
    }

    @Override
    public String toString() {
        return "TypeDefinition [id=" + id + ", type=" + type + ", properties=" + properties + ", $ref=" + $ref + "]";
    }

}


<|start_filename|>saluki-plugin/saluki-plugin-common/src/main/java/io/github/saluki/plugin/common/CommonUtils.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the
 * confidential and proprietary information of Quancheng-ec.com ("Confidential
 * Information"). You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement you entered
 * into with Quancheng-ec.com.
 */
package io.github.saluki.plugin.common;

import java.util.Map;

import org.apache.commons.lang3.StringUtils;

/**
 * @author shimingliu 2016年12月21日 下午3:40:44
 * @version CommonUtils.java, v 0.0.1 2016年12月21日 下午3:40:44 shimingliu
 */
public final class CommonUtils {

    private CommonUtils(){

    }

    public static String findPojoTypeFromCache(String sourceType, Map<String, String> pojoTypes) {
        String type = StringUtils.substring(sourceType, StringUtils.lastIndexOf(sourceType, ".") + 1);
        return pojoTypes.get(type);
    }

    public static String findNotIncludePackageType(String sourceType) {
        String type = StringUtils.substring(sourceType, StringUtils.lastIndexOf(sourceType, ".") + 1);
        return type;
    }

}


<|start_filename|>saluki-ops/spring-boot-starter-salukiops/src/main/java/io/github/saluki/monitor/jaket/util/ClassUtils.java<|end_filename|>
package io.github.saluki.monitor.jaket.util;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by huangsheng.hs on 2015/1/27.
 */
public final class ClassUtils {

    /**
     * Get the code source file or class path of the Class passed in.
     *
     * @param clazz
     *            Class to find.
     * @return Jar file name or class path.
     */
    public static String getCodeSource(Class<?> clazz) {
        ProtectionDomain protectionDomain = clazz.getProtectionDomain();
        if (protectionDomain == null || protectionDomain.getCodeSource() == null) {
            return null;
        }

        CodeSource codeSource = clazz.getProtectionDomain().getCodeSource();
        URL location = codeSource.getLocation();
        if (location == null) {
            return null;
        }

        String path = codeSource.getLocation().toExternalForm();

        if (path.endsWith(".jar") && path.contains("/")) {
            return path.substring(path.lastIndexOf('/') + 1);
        }
        return path;
    }

    /**
     * Get all non-static fields of the Class passed in or its super classes.
     *
     * @param clazz
     *            Class to parse.
     * @return field list
     */
    public static List<Field> getNonStaticFields(final Class<?> clazz) {
        List<Field> result = new ArrayList<Field>();
        Class<?> target = clazz;
        while (target != null) {
            if (JaketConfigurationUtils.isExcludedType(target)) {
                break;
            }

            Field[] fields = target.getDeclaredFields();
            for (Field field : fields) {
                int modifiers = field.getModifiers();
                if (Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers)) {
                    continue;
                }

                result.add(field);
            }
            target = target.getSuperclass();
        }

        return result;
    }

    /**
     * Get all public, non-static methods of the Class passed in.
     *
     * @param clazz
     *            Class to parse.
     * @return methods list
     */
    public static List<Method> getPublicMethods(final Class<?> clazz) {
        List<Method> result = new ArrayList<Method>();

        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            int mod = method.getModifiers();
            if (Modifier.isPublic(mod)) {
                result.add(method);
            }
        }
        return result;
    }

    /**
     * Get all public, non-static methods of the Class passed in.
     *
     * @param clazz
     *            Class to parse.
     * @return methods list
     */
    public static List<Method> getPublicNonStaticMethods(final Class<?> clazz) {
        List<Method> result = new ArrayList<Method>();

        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            int mod = method.getModifiers();
            if (Modifier.isPublic(mod) && !Modifier.isStatic(mod)) {
                result.add(method);
            }
        }
        return result;
    }

    private ClassUtils() {
    }
}


<|start_filename|>saluki-ops/saluki-ops-console/src/main/resources/static/sourse/webpack.config.babel.js<|end_filename|>
// 导入html-webpack-plugin
import webpack from 'webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import ExtractTextPlugin from 'extract-text-webpack-plugin';

/*
 导出一个函数, webpack会执行该函数, 把函数返回结果作为配置对象
 函数接受一个类型为对象的参数. 当我们在命令行中执行:
 webpack --env.dev --env.server localhost
 该参数为 { dev: true, server: 'localhost' }
 该参数对 webpack-dev-server 命令同样有效
 */
export default function(options = {}) {
  const config = {
    // 配置页面入口js文件
    entry: {
      // 属性名index用来和下面的output.filename配合使用
      index: './src/index.js',
      vendor: [
        './src/vendor.js',
        'vue','vue-router','vue-resource','echarts','moment'
      ]
    },

    // 配置打包输出相关
    output: {
      // 打包输出目录
      path: __dirname + '/dist',
      /*
       浏览器引用文件时的路径前缀, 不包含域名
       比如, 如果域名是www.example.com, publicPath为 /assets/, 那么我们可以通过
       http://www.example.com/assets/index.js
       访问入口js文件
       */
      publicPath: '/',
      /*
       entry字段配置的入口js的打包输出文件名
       [name]作为占位符, 在输出时会被替换为entry里配置的属性名, 比如这里会被替换为"index"
       [chunkhash]是打包后输出文件的hash值的占位符, 把?[chunkhash]跟在文件名后面可以防止浏览器缓存,
       这里, webpack会生成以下代码插入到index.html中:
       <script type="text/javascript" src="/assets/index.js?d835352892e6aac768bf"></script>
       这里/assets/目录前缀是下面的publicPath配置的

       options.dev是命令行传入的参数. 这里是由于使用webpack-dev-server启动开发环境时, 是没有chunkhash的, 用了会报错
       因此我们不得已在使用webpack-dev-server启动项目时, 不在后面跟chunkhash, 启动命令如下:
       webpack-dev-server --hot --inline --env.dev
       --hot和--inline下面讲

       有人可能注意到官网文档中还有一个[hash]占位符, 这个hash是源文件的hash值, 它是始终存在的.
       那为什么不用它呢?
       因为当我们在源文件里使用import和System.import()时, 如果文件本身没有改变, 但引用的文件发生了改变,
       那么打包后的文件也会改变, 因为它里面记录的引用文件的打包输出的文件名发生了变化(通过下面的chunkFilename配置).
       但[hash]是源文件的hash, 所以没有跟着变, 意味着无法防止缓存问题.
       */
      filename: options.dev ? '[name].js' : '[name].js?[chunkhash]',

      /*

       */
      chunkFilename: '[id].js?[chunkhash]',
    },

    module: {
      loaders: [
        {test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'},
        {test: /\.html$/, loader: 'html-loader'},
        {test: /\.css$/, loader: 'style-loader!css-loader!postcss-loader'},
        {test: /\.vue$/, loader: 'vue-loader'},
        {test: /\.json$/, loader: 'json-loader'},
        {
          test: /\.(png|jpg|jpeg|gif|eot|ttf|woff|woff2|svg|svgz)(\?.+)?$/,
          exclude: /favicon\.png$/,
          loader: 'url-loader?limit=10000&name=statics/[name].[hash].[ext]'
        }
      ]
    },

    plugins: [
      new HtmlWebpackPlugin({
        template: 'src/index.html'
      }),
      new webpack.optimize.UglifyJsPlugin({
        compress: {
          drop_debugger: true,
          drop_console: true
        }
      }),
      new webpack.optimize.CommonsChunkPlugin({
        name: ['vendor','manifest']
      })
    ],

    resolve: {
      alias: {vue: 'vue/dist/vue.js'}
    },

    devServer: {
      port: 8010,
      contentBase: './dist',
      historyApiFallback: {
        index: '/assets/'
      },
      host: require("os").networkInterfaces()['en0'][1].address,
      // historyApiFallback: true,
      proxy: {
        '/api/*': {
          target: 'http://saluki.dev.quancheng-ec.com/',
          changeOrigin: true,
          pathRewrite: {'^/api' : '/api'}
        }
      }
    }
  };

  // 返回配置对象给webpack
  return config;
}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/registry/internal/FailbackRegistry.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.registry.internal;

import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import io.github.saluki.common.Constants;
import io.github.saluki.common.GrpcURL;
import io.github.saluki.common.NamedThreadFactory;
import io.github.saluki.registry.NotifyListener;

/**
 * @author shimingliu 2016年12月14日 下午1:55:42
 * @version FailBackRegistry1.java, v 0.0.1 2016年12月14日 下午1:55:42 shimingliu
 */
public abstract class FailbackRegistry extends AbstractRegistry {

  // 定时任务执行器
  private final ScheduledExecutorService retryExecutor = Executors.newScheduledThreadPool(1,
      new NamedThreadFactory("SalukiRegistryFailedRetryTimer", true));
  // 失败重试定时器，定时检查是否有请求失败，如有，无限次重试
  private final ScheduledFuture<?> retryFuture;
  private final Set<GrpcURL> failedRegistered = Sets.newConcurrentHashSet();
  private final Set<GrpcURL> failedUnregistered = Sets.newConcurrentHashSet();
  private final ConcurrentMap<GrpcURL, Set<NotifyListener.NotifyServiceListener>> failedSubscribed =
      Maps.newConcurrentMap();
  private final ConcurrentMap<GrpcURL, Set<NotifyListener.NotifyServiceListener>> failedUnsubscribed =
      Maps.newConcurrentMap();
  private final ConcurrentMap<GrpcURL, Map<NotifyListener.NotifyServiceListener, List<GrpcURL>>> failedNotified =
      Maps.newConcurrentMap();

  public FailbackRegistry(GrpcURL url) {
    super(url);
    int retryPeriod = url.getParameter(Constants.REGISTRY_RETRY_PERIOD_KEY,
        Constants.DEFAULT_REGISTRY_RETRY_PERIOD);
    this.retryFuture = retryExecutor.scheduleWithFixedDelay(new Runnable() {

      public void run() {
        // 检测并连接注册中心
        try {
          retry();
        } catch (Throwable t) { // 防御性容错
          logger.error("Unexpected error occur at failed retry, cause: " + t.getMessage(), t);
        }
      }
    }, retryPeriod, retryPeriod, TimeUnit.MILLISECONDS);
  }

  private void retry() {
    if (!failedRegistered.isEmpty()) {
      Set<GrpcURL> failed = new HashSet<GrpcURL>(failedRegistered);
      if (failed.size() > 0) {
        if (logger.isInfoEnabled()) {
          logger.info("Retry register " + failed);
        }
        try {
          for (GrpcURL url : failed) {
            try {
              doRegister(url);
              failedRegistered.remove(url);
            } catch (Throwable t) { // 忽略所有异常，等待下次重试
              logger.warn("Failed to retry register " + failed + ", waiting for again, cause: "
                  + t.getMessage(), t);
            }
          }
        } catch (Throwable t) { // 忽略所有异常，等待下次重试
          logger.warn("Failed to retry register " + failed + ", waiting for again, cause: "
              + t.getMessage(), t);
        }
      }
    }
    if (!failedUnregistered.isEmpty()) {
      Set<GrpcURL> failed = new HashSet<GrpcURL>(failedUnregistered);
      if (failed.size() > 0) {
        if (logger.isInfoEnabled()) {
          logger.info("Retry unregister " + failed);
        }
        try {
          for (GrpcURL url : failed) {
            try {
              doUnregister(url);
              failedUnregistered.remove(url);
            } catch (Throwable t) { // 忽略所有异常，等待下次重试
              logger.warn("Failed to retry unregister  " + failed + ", waiting for again, cause: "
                  + t.getMessage(), t);
            }
          }
        } catch (Throwable t) { // 忽略所有异常，等待下次重试
          logger.warn("Failed to retry unregister  " + failed + ", waiting for again, cause: "
              + t.getMessage(), t);
        }
      }
    }
    if (!failedSubscribed.isEmpty()) {
      Map<GrpcURL, Set<NotifyListener.NotifyServiceListener>> failed =
          new HashMap<GrpcURL, Set<NotifyListener.NotifyServiceListener>>(failedSubscribed);
      for (Map.Entry<GrpcURL, Set<NotifyListener.NotifyServiceListener>> entry : new HashMap<GrpcURL, Set<NotifyListener.NotifyServiceListener>>(
          failed).entrySet()) {
        if (entry.getValue() == null || entry.getValue().size() == 0) {
          failed.remove(entry.getKey());
        }
      }
      if (failed.size() > 0) {
        if (logger.isInfoEnabled()) {
          logger.info("Retry subscribe " + failed);
        }
        try {
          for (Map.Entry<GrpcURL, Set<NotifyListener.NotifyServiceListener>> entry : failed
              .entrySet()) {
            GrpcURL url = entry.getKey();
            Set<NotifyListener.NotifyServiceListener> listeners = entry.getValue();
            for (NotifyListener.NotifyServiceListener listener : listeners) {
              try {
                doSubscribe(url, listener);
                listeners.remove(listener);
              } catch (Throwable t) { // 忽略所有异常，等待下次重试
                logger.warn("Failed to retry subscribe " + failed + ", waiting for again, cause: "
                    + t.getMessage(), t);
              }
            }
          }
        } catch (Throwable t) { // 忽略所有异常，等待下次重试
          logger.warn("Failed to retry subscribe " + failed + ", waiting for again, cause: "
              + t.getMessage(), t);
        }
      }
    }
    if (!failedUnsubscribed.isEmpty()) {
      Map<GrpcURL, Set<NotifyListener.NotifyServiceListener>> failed =
          new HashMap<GrpcURL, Set<NotifyListener.NotifyServiceListener>>(failedUnsubscribed);
      for (Map.Entry<GrpcURL, Set<NotifyListener.NotifyServiceListener>> entry : new HashMap<GrpcURL, Set<NotifyListener.NotifyServiceListener>>(
          failed).entrySet()) {
        if (entry.getValue() == null || entry.getValue().size() == 0) {
          failed.remove(entry.getKey());
        }
      }
      if (failed.size() > 0) {
        if (logger.isInfoEnabled()) {
          logger.info("Retry unsubscribe " + failed);
        }
        try {
          for (Map.Entry<GrpcURL, Set<NotifyListener.NotifyServiceListener>> entry : failed
              .entrySet()) {
            GrpcURL url = entry.getKey();
            Set<NotifyListener.NotifyServiceListener> listeners = entry.getValue();
            for (NotifyListener.NotifyServiceListener listener : listeners) {
              try {
                doUnsubscribe(url, listener);
                listeners.remove(listener);
              } catch (Throwable t) { // 忽略所有异常，等待下次重试
                logger.warn("Failed to retry unsubscribe " + failed + ", waiting for again, cause: "
                    + t.getMessage(), t);
              }
            }
          }
        } catch (Throwable t) { // 忽略所有异常，等待下次重试
          logger.warn("Failed to retry unsubscribe " + failed + ", waiting for again, cause: "
              + t.getMessage(), t);
        }
      }
    }
    if (!failedNotified.isEmpty()) {
      Map<GrpcURL, Map<NotifyListener.NotifyServiceListener, List<GrpcURL>>> failed =
          new HashMap<GrpcURL, Map<NotifyListener.NotifyServiceListener, List<GrpcURL>>>(
              failedNotified);
      for (Map.Entry<GrpcURL, Map<NotifyListener.NotifyServiceListener, List<GrpcURL>>> entry : new HashMap<GrpcURL, Map<NotifyListener.NotifyServiceListener, List<GrpcURL>>>(
          failed).entrySet()) {
        if (entry.getValue() == null || entry.getValue().size() == 0) {
          failed.remove(entry.getKey());
        }
      }
      if (failed.size() > 0) {
        if (logger.isInfoEnabled()) {
          logger.info("Retry notify " + failed);
        }
        try {
          for (Map.Entry<GrpcURL, Map<NotifyListener.NotifyServiceListener, List<GrpcURL>>> entrySub : failed
              .entrySet()) {
            GrpcURL subscribeUrl = entrySub.getKey();
            Map<NotifyListener.NotifyServiceListener, List<GrpcURL>> values = entrySub.getValue();
            for (Map.Entry<NotifyListener.NotifyServiceListener, List<GrpcURL>> entry : values
                .entrySet()) {
              try {
                NotifyListener.NotifyServiceListener listener = entry.getKey();
                List<GrpcURL> urls = entry.getValue();
                listener.notify(subscribeUrl, urls);
                values.remove(listener);
              } catch (Throwable t) { // 忽略所有异常，等待下次重试
                logger.warn("Failed to retry notify " + failed + ", waiting for again, cause: "
                    + t.getMessage(), t);
              }
            }
          }
        } catch (Throwable t) { // 忽略所有异常，等待下次重试
          logger.warn(
              "Failed to retry notify " + failed + ", waiting for again, cause: " + t.getMessage(),
              t);
        }
      }
    }
  }

  public Future<?> getRetryFuture() {
    return retryFuture;
  }

  public Set<GrpcURL> getFailedRegistered() {
    return failedRegistered;
  }

  public Set<GrpcURL> getFailedUnregistered() {
    return failedUnregistered;
  }

  public Map<GrpcURL, Set<NotifyListener.NotifyServiceListener>> getFailedSubscribed() {
    return failedSubscribed;
  }

  public Map<GrpcURL, Set<NotifyListener.NotifyServiceListener>> getFailedUnsubscribed() {
    return failedUnsubscribed;
  }

  public Map<GrpcURL, Map<NotifyListener.NotifyServiceListener, List<GrpcURL>>> getFailedNotified() {
    return failedNotified;
  }

  private void addFailedSubscribed(GrpcURL url, NotifyListener.NotifyServiceListener listener) {
    Set<NotifyListener.NotifyServiceListener> listeners = failedSubscribed.get(url);
    if (listeners == null) {
      listeners = Sets.newConcurrentHashSet();
      listeners = failedSubscribed.putIfAbsent(url, listeners);
    }
    listeners.add(listener);
  }

  private void removeFailedSubscribed(GrpcURL url, NotifyListener.NotifyServiceListener listener) {
    Set<NotifyListener.NotifyServiceListener> listeners = failedSubscribed.get(url);
    if (listeners != null) {
      listeners.remove(listener);
    }
    listeners = failedUnsubscribed.get(url);
    if (listeners != null) {
      listeners.remove(listener);
    }
    Map<NotifyListener.NotifyServiceListener, List<GrpcURL>> notified = failedNotified.get(url);
    if (notified != null) {
      notified.remove(listener);
    }
  }

  @Override
  public void register(GrpcURL url) {
    super.register(url);
    failedRegistered.remove(url);
    failedUnregistered.remove(url);
    try {
      // 向服务器端发送注册请求
      doRegister(url);
    } catch (Exception e) {
      logger.error("Failed to uregister " + url + ", waiting for retry, cause: " + e.getMessage(),
          e);
      // 将失败的取消注册请求记录到失败列表，定时重试
      failedUnregistered.add(url);
    }
  }

  @Override
  public void unregister(GrpcURL url) {
    super.unregister(url);
    failedRegistered.remove(url);
    failedUnregistered.remove(url);
    try {
      // 向服务器端发送取消注册请求
      doUnregister(url);
    } catch (Exception e) {
      logger.error("Failed to uregister " + url + ", waiting for retry, cause: " + e.getMessage(),
          e);
      // 将失败的取消注册请求记录到失败列表，定时重试
      failedUnregistered.add(url);
    }
  }

  @Override
  public void subscribe(GrpcURL url, NotifyListener.NotifyServiceListener listener) {
    super.subscribe(url, listener);
    removeFailedSubscribed(url, listener);
    try {
      // 向服务器端发送订阅请求
      doSubscribe(url, listener);
    } catch (Exception e) {
      logger.error("Failed to subscribe " + url + ", waiting for retry, cause: " + e.getMessage(),
          e);
      // 将失败的订阅请求记录到失败列表，定时重试
      addFailedSubscribed(url, listener);
    }
  }

  @Override
  public void unsubscribe(GrpcURL url, NotifyListener.NotifyServiceListener listener) {
    super.unsubscribe(url, listener);
    removeFailedSubscribed(url, listener);
    try {
      // 向服务器端发送取消订阅请求
      doUnsubscribe(url, listener);
    } catch (Exception e) {
      logger.error("Failed to unsubscribe " + url + ", waiting for retry, cause: " + e.getMessage(),
          e);
      // 将失败的取消订阅请求记录到失败列表，定时重试
      Set<NotifyListener.NotifyServiceListener> listeners = failedUnsubscribed.get(url);
      if (listeners == null) {
        listeners = Sets.newConcurrentHashSet();
        listeners = failedUnsubscribed.putIfAbsent(url, listeners);
      }
      listeners.add(listener);
    }
  }

  @Override
  protected void notify(GrpcURL url, NotifyListener.NotifyServiceListener listener,
      List<GrpcURL> urls) {
    if (url == null) {
      throw new IllegalArgumentException("notify url == null");
    }
    if (listener == null) {
      throw new IllegalArgumentException("notify listener == null");
    }
    try {
      doNotify(url, listener, urls);
    } catch (Exception t) {
      // 将失败的通知请求记录到失败列表，定时重试
      Map<NotifyListener.NotifyServiceListener, List<GrpcURL>> listeners = failedNotified.get(url);
      if (listeners == null) {
        failedNotified.putIfAbsent(url, Maps.newConcurrentMap());
        listeners = failedNotified.get(url);
      }
      listeners.put(listener, urls);
      logger.error(
          "Failed to notify for subscribe " + url + ", waiting for retry, cause: " + t.getMessage(),
          t);
    }
  }

  protected void doNotify(GrpcURL url, NotifyListener.NotifyServiceListener listener,
      List<GrpcURL> urls) {
    super.notify(url, listener, urls);
  }

  @Override
  protected void recover() throws Exception {
    // register
    Set<GrpcURL> recoverRegistered = Sets.newHashSet(getRegistered());
    if (!recoverRegistered.isEmpty()) {
      if (logger.isInfoEnabled()) {
        logger.info("Recover register url " + recoverRegistered);
      }
      for (GrpcURL url : recoverRegistered) {
        failedRegistered.add(url);
      }
    }
    // subscribe
    Map<GrpcURL, Set<NotifyListener.NotifyServiceListener>> recoverSubscribed =
        Maps.newHashMap(getSubscribed());
    if (!recoverSubscribed.isEmpty()) {
      if (logger.isInfoEnabled()) {
        logger.info("Recover subscribe url " + recoverSubscribed.keySet());
      }
      for (Map.Entry<GrpcURL, Set<NotifyListener.NotifyServiceListener>> entry : recoverSubscribed
          .entrySet()) {
        GrpcURL url = entry.getKey();
        for (NotifyListener.NotifyServiceListener listener : entry.getValue()) {
          addFailedSubscribed(url, listener);
        }
      }
    }
  }

  // ==== 模板方法 ====
  protected abstract void doRegister(GrpcURL url);

  protected abstract void doUnregister(GrpcURL url);

  protected abstract void doSubscribe(GrpcURL url, NotifyListener.NotifyServiceListener listener);

  protected abstract void doUnsubscribe(GrpcURL url, NotifyListener.NotifyServiceListener listener);
}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/client/internal/DefaultProxyClient.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.grpc.client.internal;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import io.github.saluki.common.GrpcURL;
import io.github.saluki.grpc.client.GrpcProtocolClient;
import io.github.saluki.grpc.client.GrpcRequest;
import io.github.saluki.utils.ClassHelper;
import io.github.saluki.utils.ReflectUtils;

/**
 * @author shimingliu 2016年12月14日 下午9:35:56
 * @version ProxyClient.java, v 0.0.1 2016年12月14日 下午9:35:56 shimingliu
 */
public class DefaultProxyClient<T> implements GrpcProtocolClient<T> {

  private final Class<?> interfaceClass;

  private final GrpcURL refUrl;

  public DefaultProxyClient(GrpcURL refUrl) {
    this.refUrl = refUrl;
    String serviceName = refUrl.getServiceInterface();
    try {
      this.interfaceClass = ReflectUtils.name2class(serviceName);
    } catch (ClassNotFoundException e) {
      throw new IllegalArgumentException(e.getMessage(), e);
    }
  }

  @SuppressWarnings("unchecked")
  @Override
  public T getGrpcClient(GrpcProtocolClient.ChannelCall channelPoll, int callType,
      int callTimeout) {
    return (T) Proxy.newProxyInstance(ClassHelper.getClassLoader(), new Class[] {interfaceClass},
        new DefaultProxyClientInvocation(channelPoll, callType, callTimeout));
  }

  private class DefaultProxyClientInvocation extends AbstractClientInvocation {

    private final GrpcProtocolClient.ChannelCall channelPool;
    private final int callType;
    private final int callTimeout;

    public DefaultProxyClientInvocation(GrpcProtocolClient.ChannelCall call, int callType,
        int callTimeout) {
      super(DefaultProxyClient.this.refUrl);
      this.channelPool = call;
      this.callType = callType;
      this.callTimeout = callTimeout;
    }

    @Override
    protected GrpcRequest buildGrpcRequest(Method method, Object[] args) {
      boolean isLegalMethod = ReflectUtils.isLegal(method);
      if (isLegalMethod) {
        throw new IllegalArgumentException(
            "remote call type do not support this method " + method.getName());
      }
      GrpcRequest request = new GrpcRequest.Default(DefaultProxyClient.this.refUrl, channelPool,
          method.getName(), args, callType, callTimeout);
      return request;
    }

  }

}


<|start_filename|>saluki-serializer/src/main/java/io/github/saluki/serializer/help/Pojo2ProtobufHelp.java<|end_filename|>
/*
 * Copyright 2014-2017 the original author or authors.
 *
 * 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 io.github.saluki.serializer.help;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.google.protobuf.Message.Builder;
import io.github.saluki.serializer.ProtobufAttribute;
import io.github.saluki.serializer.ProtobufEntity;
import io.github.saluki.serializer.ProtobufSerializer;
import io.github.saluki.serializer.exception.ProtobufAnnotationException;
import io.github.saluki.serializer.internal.ProtobufSerializerUtils;
import io.github.saluki.serializer.utils.JException;
import io.github.saluki.serializer.utils.JReflectionUtils;

/**
 * @author liushiming
 * @version Pojo2ProtobufHelp.java, v 0.0.1 2017年7月18日 下午1:49:19 liushiming
 * @since JDK 1.8
 */
public class Pojo2ProtobufHelp {

  private Pojo2ProtobufHelp() {

  }

  public static final Object getPojoFieldValue(Object pojo, ProtobufAttribute protobufAttribute,
      Field field) throws ProtobufAnnotationException {
    final String getter = protobufAttribute.pojoGetter();

    Object value = null;
    if (!getter.isEmpty()) {
      try {
        return JReflectionUtils.runMethod(pojo, getter);
      } catch (Exception e) {
        throw new ProtobufAnnotationException("Could not get a value for field " + field.getName()
            + " using configured getter of " + getter, e);
      }
    }

    try {
      value = JReflectionUtils.runGetter(pojo, field);
    } catch (Exception ee) {
      throw new ProtobufAnnotationException("Could not execute getter " + getter + " on class "
          + pojo.getClass().getCanonicalName() + ": " + ee, ee);
    }

    if (value == null && protobufAttribute.required()) {
      throw new ProtobufAnnotationException("Required field " + field.getName() + " on class "
          + pojo.getClass().getCanonicalName() + " is null");
    }

    return value;
  }

  public static final Object serializeToProtobufEntity(Object pojo) throws JException {
    final ProtobufEntity protoBufEntity =
        ProtobufSerializerUtils.getProtobufEntity(pojo.getClass());
    if (protoBufEntity == null) {
      return pojo;
    }
    return new ProtobufSerializer().toProtobuf(pojo);
  }

  public static final void setProtobufFieldValue(ProtobufAttribute protobufAttribute,
      Builder protoObjBuilder, String setter, Object fieldValue) throws NoSuchMethodException,
      SecurityException, ProtobufAnnotationException, InstantiationException,
      IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    Class<? extends Object> fieldValueClass = fieldValue.getClass();
    Class<? extends Object> gpbClass = fieldValueClass;
    // Need to convert the argument class from non-primitives to primitives, as Protobuf uses these.
    gpbClass = ProtobufSerializerUtils.getProtobufClass(fieldValue, gpbClass);
    final Method gpbMethod = protoObjBuilder.getClass().getDeclaredMethod(setter, gpbClass);
    gpbMethod.invoke(protoObjBuilder, fieldValue);
  }

  /**
   * 集合元素转化为Protobuf
   */
  public static final Object convertCollectionToProtobufs(
      Collection<Object> collectionOfNonProtobufs) throws JException {
    if (collectionOfNonProtobufs.isEmpty()) {
      return collectionOfNonProtobufs;
    }
    final Object first = collectionOfNonProtobufs.toArray()[0];
    if (!ProtobufSerializerUtils.isProtbufEntity(first)) {
      return collectionOfNonProtobufs;
    }
    final Collection<Object> newCollectionValues;
    if (collectionOfNonProtobufs instanceof Set) {
      newCollectionValues = new HashSet<>();
    } else {
      newCollectionValues = new ArrayList<>();
    }
    for (Object iProtobufGenObj : collectionOfNonProtobufs) {
      newCollectionValues.add(Pojo2ProtobufHelp.serializeToProtobufEntity(iProtobufGenObj));
    }
    return newCollectionValues;
  }

  /**
   * Map元素转化为Protobuf
   */
  @SuppressWarnings({"unchecked", "rawtypes"})
  public static final Object convertMapToProtobufs(Map<?, ?> mapOfNonProtobufs) throws JException {
    if (mapOfNonProtobufs.isEmpty()) {
      return mapOfNonProtobufs;
    }
    final Object keyFirst = mapOfNonProtobufs.keySet().toArray()[0];
    final Object valueFirst = mapOfNonProtobufs.get(keyFirst);
    if (!ProtobufSerializerUtils.isProtbufEntity(keyFirst)
        && !ProtobufSerializerUtils.isProtbufEntity(valueFirst)) {
      return mapOfNonProtobufs;
    }
    final Map newMapValues = new HashMap<>();
    for (Map.Entry<?, ?> entry : mapOfNonProtobufs.entrySet()) {
      Object newMapValuesKey = Pojo2ProtobufHelp.serializeToProtobufEntity(entry.getKey());
      Object newMapValuesValue = Pojo2ProtobufHelp.serializeToProtobufEntity(entry.getValue());
      newMapValues.put(newMapValuesKey, newMapValuesValue);
    }
    return newMapValues;
  }

}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/common/RpcContext.java<|end_filename|>
package io.github.saluki.common;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import com.google.common.collect.Sets;

@SuppressWarnings("rawtypes")
public class RpcContext {

  private static final ThreadLocal<RpcContext> LOCAL = new InheritableThreadLocal<RpcContext>() {

    @Override
    protected RpcContext initialValue() {
      return new RpcContext();
    }
  };

  private final Map<String, String> attachments = new HashMap<String, String>();
  private final Map<String, Object> values = new HashMap<String, Object>();
  private final Set<Class> validatorGroup = Sets.newHashSet();


  public static RpcContext getContext() {
    return LOCAL.get();
  }

  public static void removeContext() {
    LOCAL.remove();
  }

  private RpcContext() {}


  public RpcContext setHoldenGroups(Set<Class> groups) {
    if (groups != null && groups.size() > 0) {
      validatorGroup.addAll(groups);
    }
    return this;
  }

  public Set<Class> getHoldenGroups() {
    return validatorGroup;
  }

  public String getAttachment(String key) {
    return attachments.get(key);
  }

  public boolean containAttachment(String key) {
    return attachments.containsKey(key);
  }

  public RpcContext setAttachment(String key, String value) {
    if (value == null) {
      attachments.remove(key);
    } else {
      attachments.put(key, value);
    }
    return this;
  }

  public RpcContext removeAttachment(String key) {
    attachments.remove(key);
    return this;
  }

  public Map<String, String> getAttachments() {
    return attachments;
  }

  public RpcContext setAttachments(Map<String, String> attachment) {
    if (attachment != null && attachment.size() > 0) {
      this.attachments.putAll(attachment);
    }
    return this;
  }

  public void clear() {
    this.attachments.clear();
    this.values.clear();
  }

  public Map<String, Object> get() {
    return values;
  }

  public RpcContext set(String key, Object value) {
    if (value == null) {
      values.remove(key);
    } else {
      values.put(key, value);
    }
    return this;
  }

  public RpcContext set(Map<String, Object> value) {
    if (value != null && value.size() > 0) {
      values.putAll(value);
    }
    return this;
  }

  public RpcContext remove(String key) {
    values.remove(key);
    return this;
  }

  public Object get(String key) {
    return values.get(key);
  }

  public boolean contain(String key) {
    return values.containsKey(key);
  }

}


<|start_filename|>saluki-example/saluki-example-server/src/main/java/io/github/saluki/example/monitor/ServiceMonitor.java<|end_filename|>
/*
 * Copyright (c) 2017, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.example.monitor;

/**
 * @author shimingliu 2017年2月17日 上午10:44:23
 * @version ServiceMonitor.java, v 0.0.1 2017年2月17日 上午10:44:23 shimingliu
 */
// @Aspect
// @Component
// public class ServiceMonitor {
//
// @Before("execution(* com..*Service.*(..))")
// public void logServiceAccess(JoinPoint joinPoint) {
// System.out.println("Completed: " + joinPoint);
// }
// }


<|start_filename|>saluki-core/src/main/java/io/github/saluki/common/Constants.java<|end_filename|>
package io.github.saluki.common;

import java.util.regex.Pattern;

public class Constants {

  public static final Pattern COMMA_SPLIT_PATTERN = Pattern.compile("\\s*[,]+\\s*");

  public static final String INTERFACE_KEY = "interface";
  public static final String INTERFACECLASS_KEY = "interfaceClass";
  public static final String GRPC_STUB_KEY = "grpcstub";
  public static final String GRPC_FALLBACK_KEY = "grpcfallback";
  public static final String GENERIC_KEY = "generic";
  public static final String GROUP_KEY = "group";
  public static final String VERSION_KEY = "version";
  public static final String REGISTRY_RPC_PORT_KEY = "registryrpcport";
  public static final String HTTP_PORT_KEY = "httpport";
  public static final String MONITOR_INTERVAL = "monitorinterval";
  public static final String APPLICATION_NAME = "application";
  public static final String TIMEOUT = "timeout";
  public static final String DEFAULT_GROUP = "Default";
  public static final String DEFAULT_VERSION = "1.0.0";
  public static final String LOCALHOST_KEY = "localhost";
  public static final String ANYHOST_KEY = "anyhost";
  public static final String RETRY_METHODS_KEY = "retrymethods";
  public static final String FALLBACK_METHODS_KEY = "fallbackmethods";
  public static final String METHOD_KEY = "method";
  public static final String METHOD_RETRY_KEY = "retries";
  public static final String ANYHOST_VALUE = "0.0.0.0";

  public static final String REGISTRY_RETRY_PERIOD_KEY = "retry.period";
  public static final int DEFAULT_REGISTRY_RETRY_PERIOD = 5 * 1000;
  public static final String ENABLED_KEY = "enabled";
  public static final String DISABLED_KEY = "disabled";

  public static final String CONSUL_SERVICE_PRE = "saluki_";
  public static final String PATH_SEPARATOR = "/";
  public static final String PROVIDERS_CATEGORY = "providers";
  public static final String CONSUMERS_CATEGORY = "consumers";

  public static final String REGISTRY_PROTOCOL = "registry";
  public static final String REMOTE_PROTOCOL = "grpc";
  public static final String MONITOR_PROTOCOL = "monitor";

  public static final String ASYNC_KEY = "async";
  public static final int RPCTYPE_ASYNC = 1;
  public static final int RPCTYPE_BLOCKING = 2;
  public static final int RPC_ASYNC_DEFAULT_TIMEOUT = 5000;

  public static final String REMOTE_ADDRESS = "remote";

  public static final String VALIDATOR_GROUPS = "validator.groups";

}


<|start_filename|>saluki-serializer/src/main/java/io/github/saluki/serializer/IProtobufSerializer.java<|end_filename|>
package io.github.saluki.serializer;

import com.google.protobuf.Message;
import io.github.saluki.serializer.exception.ProtobufException;

public interface IProtobufSerializer {

    Message toProtobuf(Object pojo) throws ProtobufException;

    Object fromProtobuf(Message protoBuf, Class<? extends Object> pojoClazz) throws ProtobufException;
}


<|start_filename|>saluki-plugin/saluki-plugin-common/src/main/java/io/github/saluki/plugin/common/CommandProtoc.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.plugin.common;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.Path;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.os72.protocjar.Protoc;
import com.google.common.collect.ImmutableList;
import com.google.protobuf.DescriptorProtos.FileDescriptorSet;

/**
 * @author shimingliu 2016年12月21日 下午3:06:47
 * @version CommondProtoc.java, v 0.0.1 2016年12月21日 下午3:06:47 shimingliu
 */
public class CommandProtoc {

  private static final Logger logger = LoggerFactory.getLogger(CommandProtoc.class);

  private final String discoveryRoot;


  private CommandProtoc(String discoveryRoot) {
    this.discoveryRoot = discoveryRoot;
  }

  public static CommandProtoc configProtoPath(String discoveryRoot) {
    return new CommandProtoc(discoveryRoot);
  }

  public FileDescriptorSet invoke(String protoPath) {
    try {
      Path descriptorPath = Files.createTempFile("descriptor", ".pb.bin");
      ImmutableList.Builder<String> builder = ImmutableList.<String>builder()//
          .add("--include_std_types")//
          .add("-I" + discoveryRoot)
          .add("--descriptor_set_out=" + descriptorPath.toAbsolutePath().toString())//
      ;
      ImmutableList<String> protocArgs = builder.add(protoPath).build();

      int status;
      String[] protocLogLines;
      PrintStream stdoutBackup = System.out;
      try {
        ByteArrayOutputStream protocStdout = new ByteArrayOutputStream();
        System.setOut(new PrintStream(protocStdout));
        status = Protoc.runProtoc(protocArgs.toArray(new String[0]));
        protocLogLines = protocStdout.toString().split("\n");
      } catch (IOException | InterruptedException e) {
        throw new IllegalArgumentException("Unable to execute protoc binary", e);
      } finally {
        System.setOut(stdoutBackup);
      }
      if (status != 0) {
        logger.warn("Protoc invocation failed with status: " + status);
        for (String line : protocLogLines) {
          logger.warn("[Protoc log] " + line);
        }

        throw new IllegalArgumentException(
            String.format("Got exit code [%d] from protoc with args [%s]", status, protocArgs));
      }
      return FileDescriptorSet.parseFrom(Files.readAllBytes(descriptorPath));
    } catch (IOException e) {
      throw new IllegalArgumentException(e);
    }
  }

}


<|start_filename|>saluki-example/saluki-example-client/src/main/java/io/github/saluki/example/performance/TpsWorkbeanch.java<|end_filename|>
/*
 * Copyright 2014-2017 the original author or authors.
 *
 * 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 io.github.saluki.example.performance;

import java.math.RoundingMode;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import com.google.common.math.LongMath;

/**
 * @author liushiming
 * @version TpsWorkbeanch.java, v 0.0.1 2017年10月20日 下午9:17:25 liushiming
 */
public class TpsWorkbeanch {
  /** 线程数量 */
  public static final int N_THRESHOLDS = 100;

  /** 60 秒总时间 */
  public static final int TIME_THRESHOLDS = 60 * 2;

  /** 用原子变量来统计执行时间，便于作原子递减 */
  private static AtomicInteger totalTime = new AtomicInteger(TIME_THRESHOLDS);

  /** 用于统计执行的事物总数，用原子方式累加记录 */
  private static AtomicLong totalExecCount = new AtomicLong(0L);

  /** 需要到等到所有线程都在同一起跑线，才开始统计计数，类似于发令枪 */
  private static CyclicBarrier barrier = new CyclicBarrier(N_THRESHOLDS);

  /** 执行时间到达时，所有的线程需要依次退出，主线程才开始统计执行事物总数 */
  private static CountDownLatch countDownLatch = new CountDownLatch(N_THRESHOLDS);

  /** 线程执行标记 , 用volatile修饰，使变量修改具有线程可见性 */
  private static volatile boolean runnning = true;

  /** 用线程池来执行统计 */
  private static ExecutorService executorService;

  /**
   * 用接口来作模拟统计
   */
  interface Job {
    void execute() throws Exception;
  }

  /**
   * 具体Job，模拟完成一次Http请求 BTW:内部类用static修饰
   */
  static class JobDetail implements Job {

    public void execute() throws Exception {
      String run = OkHttpUtil.run("http://localhost:8081/proxy/hello?name=liushiming");
    }
  }

  /**
   * Worker执行Job
   */
  static class Worker implements Runnable {

    private Job job;

    Worker(Job job) {
      this.job = job;
    }

    // 每个线程执行的事物统计量
    int innerCount = 0;

    public void run() {
      try {
        barrier.await(); // 等到所有线程都在起跑线
        while (runnning) {
          this.job.execute();
          innerCount++;
        }
      } catch (Exception e) {
        System.out.println("线程Id：" + Thread.currentThread().getId() + " " + e.getMessage());
      } finally {
        // 累加到总记录统计量
        System.out.println("线程Id：" + Thread.currentThread().getId() + " 执行事物次数为：" + innerCount);
        totalExecCount.getAndAdd(innerCount);
        // 线程结束后，依次计数, 便于主线程继续执行
        countDownLatch.countDown();
      }
    }
  }

  public static void run() throws Exception {
    Job job = new JobDetail(); // 创建Job
    executorService = Executors.newFixedThreadPool(N_THRESHOLDS); // 新建固定大小线程的池子
    for (int i = 0; i < N_THRESHOLDS; i++) {
      executorService.submit(new Worker(job)); // 提交线程到池子中
    }
    // 还需要一个线程，用于周期检查执行时间是否到达
    final ScheduledExecutorService scheduledExcutor = Executors.newSingleThreadScheduledExecutor();
    scheduledExcutor.scheduleAtFixedRate(new Runnable() {
      public void run() {
        if (totalTime.decrementAndGet() == 0) { // 执行时间递减到0
          runnning = false; // 告诉线程，时间到了，所有线程不再执行
          scheduledExcutor.shutdownNow();
        }
      }
    }, 1L, 1L, TimeUnit.SECONDS);

    // 主线程等到所有的线程都退出，则开始统计
    countDownLatch.await();

    long totalExeCount = totalExecCount.get();
    System.out.println(N_THRESHOLDS + " 个线程，" + TIME_THRESHOLDS + " 秒内总共执行的事物数量：" + totalExeCount);

    long tps = LongMath.divide(totalExeCount, TIME_THRESHOLDS, RoundingMode.HALF_EVEN);

    System.out.println("OKHttp执行的TPS: " + tps);

    executorService.shutdownNow(); // 关闭线程池


  }

  public static void main(String[] args) throws Exception {
    run();
  }

}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/stream/PoJo2ProtoStreamObserver.java<|end_filename|>
/*
 * Copyright 2014-2017 the original author or authors.
 *
 * 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 io.github.saluki.grpc.stream;

import com.google.protobuf.Message;
import io.github.saluki.grpc.util.SerializerUtil;
import io.github.saluki.serializer.exception.ProtobufException;

import io.grpc.Status;
import io.grpc.StatusRuntimeException;
import io.grpc.stub.StreamObserver;
import io.netty.util.internal.ThrowableUtil;

/**
 * @author liushiming
 * @version ServerCallStreamObserverWrap.java, v 0.0.1 2017年8月15日 上午11:30:58 liushiming
 * @since JDK 1.8
 */
public class PoJo2ProtoStreamObserver implements StreamObserver<Object> {

  private final StreamObserver<Message> streamObserver;

  private PoJo2ProtoStreamObserver(StreamObserver<Message> streamObserver) {
    this.streamObserver = streamObserver;
  }

  public static PoJo2ProtoStreamObserver newObserverWrap(StreamObserver<Message> streamObserver) {
    return new PoJo2ProtoStreamObserver(streamObserver);
  }

  @Override
  public void onNext(Object value) {
    try {
      Object respPojo = value;
      Message respProtoBufer = SerializerUtil.pojo2Protobuf(respPojo);
      streamObserver.onNext(respProtoBufer);
    } catch (ProtobufException e) {
      String stackTrace = ThrowableUtil.stackTraceToString(e);
      StatusRuntimeException statusException =
          Status.UNAVAILABLE.withDescription(stackTrace).asRuntimeException();
      streamObserver.onError(statusException);
    }
  }


  @Override
  public void onError(Throwable t) {
    streamObserver.onError(t);;
  }


  @Override
  public void onCompleted() {
    streamObserver.onCompleted();
  }


}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/GrpcNameResolver.java<|end_filename|>
/*
 * Copyright 2014-2016 the original author or authors.
 *
 * 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 io.github.saluki.grpc;

import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.net.InetAddresses;
import io.github.saluki.common.GrpcURL;
import io.github.saluki.grpc.router.GrpcRouterFactory;
import io.github.saluki.registry.NotifyListener;
import io.github.saluki.registry.Registry;
import io.github.saluki.registry.RegistryProvider;
import io.github.saluki.utils.NetUtils;

import io.grpc.Attributes;
import io.grpc.EquivalentAddressGroup;
import io.grpc.Internal;
import io.grpc.NameResolver;
import io.grpc.Status;

/**
 * @author liushiming 2017年5月19日 下午1:43:22
 * @version: GrpcNameResolver.java, v 0.0.1 2017年5月19日 下午1:43:22 liushiming
 */
@Internal
public class GrpcNameResolver extends NameResolver {

  private static final Logger log = LoggerFactory.getLogger(GrpcNameResolver.class);

  private final Registry registry;

  private final GrpcURL subscribeUrl;

  private final NotifyListener.NotifyServiceListener serviceListener =
      new NotifyListener.NotifyServiceListener() {

        @Override
        public void notify(GrpcURL subscribeUrl, List<GrpcURL> urls) {
          log.info("Grpc nameresolve started listener,Receive notify from registry, prividerUrl is"
              + Arrays.toString(urls.toArray()));
          GrpcNameResolver.this.urls.put(subscribeUrl, urls);
          notifyLoadBalance(subscribeUrl, urls);
        }

      };

  private final NotifyListener.NotifyRouterListener routeListener =
      new NotifyListener.NotifyRouterListener() {

        @Override
        public void notify(GrpcURL subscribeUrl, String routerCondition) {
          GrpcRouterFactory.getInstance().cacheRoute(subscribeUrl.getServiceKey(), routerCondition);
        }
      };


  private Listener listener;

  private volatile Map<GrpcURL, List<SocketAddress>> addresses = Maps.newConcurrentMap();

  private volatile Map<GrpcURL, List<GrpcURL>> urls = Maps.newConcurrentMap();

  public GrpcNameResolver(URI targetUri, Attributes params, GrpcURL subscribeUrl) {
    GrpcURL registryUrl = GrpcURL.valueOf(targetUri.toString());
    this.registry = RegistryProvider.asFactory().newRegistry(registryUrl);
    this.subscribeUrl = subscribeUrl;
  }

  @Override
  public final String getServiceAuthority() {
    return "grpc";
  }

  @Override
  public final synchronized void start(Listener listener) {
    Preconditions.checkState(this.listener == null, "already started");
    this.listener = listener;
    this.listener = Preconditions.checkNotNull(listener, "listener");
    resolve();
  }

  @Override
  public final synchronized void refresh() {
    Preconditions.checkState(listener != null, "not started");
    resolve();
  }

  private void resolve() {
    registry.subscribe(subscribeUrl, serviceListener);
    registry.subscribe(subscribeUrl, routeListener);
  }


  @Override
  public void shutdown() {
    registry.unsubscribe(subscribeUrl, serviceListener);
    registry.unsubscribe(subscribeUrl, routeListener);
  }



  /**** help method *****/
  private void notifyLoadBalance(GrpcURL subscribeUrl, List<GrpcURL> urls) {
    if (urls != null && !urls.isEmpty()) {
      List<EquivalentAddressGroup> servers = Lists.newArrayList();
      List<SocketAddress> addresses = Lists.newArrayList();
      Map<List<SocketAddress>, GrpcURL> addressUrlMapping = Maps.newHashMap();
      for (GrpcURL url : urls) {
        String host = url.getHost();
        int port = url.getPort();
        List<SocketAddress> hostAddressMapping;
        if (NetUtils.isIP(host)) {
          hostAddressMapping = IpResolved(servers, addresses, host, port);
        } else {
          hostAddressMapping = DnsResolved(servers, addresses, host, port);
        }
        addressUrlMapping.put(hostAddressMapping, url);
      }
      this.addresses.put(subscribeUrl, addresses);
      Attributes config = this.buildAttributes(subscribeUrl, addressUrlMapping);
      GrpcNameResolver.this.listener.onAddresses(servers, config);
    } else {
      GrpcNameResolver.this.listener
          .onError(Status.NOT_FOUND.withDescription("There is no service registy in consul "));
    }
  }

  private List<SocketAddress> DnsResolved(List<EquivalentAddressGroup> servers,
      List<SocketAddress> addresses, String host, int port) {
    List<SocketAddress> hostAddressMapping = Lists.newArrayList();
    try {
      InetAddress[] inetAddrs = InetAddress.getAllByName(host);
      for (int j = 0; j < inetAddrs.length; j++) {
        InetAddress inetAddr = inetAddrs[j];
        SocketAddress sock = new InetSocketAddress(inetAddr, port);
        hostAddressMapping.add(sock);
        addSocketAddress(servers, addresses, sock);
      }
      return hostAddressMapping;
    } catch (UnknownHostException e) {
      GrpcNameResolver.this.listener.onError(Status.UNAVAILABLE.withCause(e));
    }
    return hostAddressMapping;
  }

  private List<SocketAddress> IpResolved(List<EquivalentAddressGroup> servers,
      List<SocketAddress> addresses, String host, int port) {
    List<SocketAddress> hostAddressMapping = Lists.newArrayList();
    SocketAddress sock = new InetSocketAddress(InetAddresses.forString(host), port);
    hostAddressMapping.add(sock);
    addSocketAddress(servers, addresses, sock);
    return hostAddressMapping;
  }

  private void addSocketAddress(List<EquivalentAddressGroup> servers, List<SocketAddress> addresses,
      SocketAddress sock) {
    EquivalentAddressGroup server = new EquivalentAddressGroup(sock);
    servers.add(server);
    addresses.add(sock);
  }

  private Attributes buildAttributes(GrpcURL subscribeUrl,
      Map<List<SocketAddress>, GrpcURL> addressUrlMapping) {
    Attributes.Builder builder = Attributes.newBuilder();
    if (listener != null) {
      builder.set(GrpcNameResolverProvider.NAMERESOVER_LISTENER, listener);
    }
    if (addresses.get(subscribeUrl) != null) {
      builder.set(GrpcNameResolverProvider.REMOTE_ADDR_KEYS, addresses.get(subscribeUrl));
    }
    if (!addressUrlMapping.isEmpty()) {
      builder.set(GrpcNameResolverProvider.GRPC_ADDRESS_GRPCURL_MAPPING, addressUrlMapping);
    }
    return builder.build();
  }


}


<|start_filename|>saluki-ops/saluki-ops-console/src/main/java/io/github/saluki/monitor/ops/configuration/MybatisConfiguration.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and proprietary
 * information of Quancheng-ec.com ("Confidential Information"). You shall not disclose such Confidential Information
 * and shall use it only in accordance with the terms of the license agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.monitor.ops.configuration;

import java.sql.SQLException;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;

/**
 * @author shimingliu 2016年12月20日 下午3:07:34
 * @version MonitorConfiguration.java, v 0.0.1 2016年12月20日 下午3:07:34 shimingliu
 */
@Configuration
@EnableTransactionManagement
public class MybatisConfiguration extends SingleDataSourceConfig implements TransactionManagementConfigurer {

    @Bean
    public DataSource datasource() throws SQLException {
        return createDataSource();
    }

    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setTypeAliasesPackage("io.github.saluki.monitor.ops.domain");
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        try {
            bean.setMapperLocations(resolver.getResources("classpath:mappers/*.xml"));
            return bean.getObject();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        if (sqlSessionFactory == null) {
            return null;
        }
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean
    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        try {
            return new DataSourceTransactionManager(datasource());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
}


<|start_filename|>saluki-ops/spring-boot-starter-salukiops/src/main/java/io/github/saluki/monitor/config/MybatisConfiguration.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.monitor.config;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;

/**
 * @author shimingliu 2016年12月20日 下午3:07:34
 * @version MonitorConfiguration.java, v 0.0.1 2016年12月20日 下午3:07:34 shimingliu
 */
@Configuration
@ConditionalOnExpression("${saluki.monitor.enabled:true}")
public class MybatisConfiguration {

  @Bean
  @ConditionalOnMissingBean(EmbeddedDatabase.class)
  public EmbeddedDatabase dataSource() {
    EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder();
    EmbeddedDatabase db = builder.setType(EmbeddedDatabaseType.H2) //
        .setName("grpcmonitor")//
        .addScript("mapper/create-db.sql")//
        .build();
    return db;
  }

  @Bean(name = "sqlSessionFactory")
  public SqlSessionFactory sqlSessionFactoryBean(EmbeddedDatabase dataSource) {
    SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
    bean.setDataSource(dataSource);
    bean.setTypeAliasesPackage("io.github.saluki.monitor.dao.domain");
    ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    try {
      bean.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));
      return bean.getObject();
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  @Bean
  public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
    return new SqlSessionTemplate(sqlSessionFactory);
  }

  @Configuration
  @EnableTransactionManagement
  @ConditionalOnExpression("${saluki.monitor.enabled:true}")
  protected static class TransactionConfig implements TransactionManagementConfigurer {

    @Autowired
    private EmbeddedDatabase dataSource;

    @Bean
    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
      return new DataSourceTransactionManager(dataSource);
    }

  }

}


<|start_filename|>saluki-serializer/src/main/java/io/github/saluki/serializer/exception/ProtobufAnnotationException.java<|end_filename|>

package io.github.saluki.serializer.exception;

public class ProtobufAnnotationException extends ProtobufException {

    private static final long serialVersionUID = 1L;

    public ProtobufAnnotationException(Exception exception){
        super(exception);
    }

    public ProtobufAnnotationException(String string){
        super(string);
    }

    public ProtobufAnnotationException(String string, Exception exception){
        super(string, exception);
    }
}


<|start_filename|>saluki-ops/saluki-ops-console/src/main/java/io/github/saluki/monitor/ops/repository/InvokeMapper.java<|end_filename|>
package io.github.saluki.monitor.ops.repository;

import java.util.List;
import java.util.Map;

import org.apache.ibatis.annotations.Mapper;

import io.github.saluki.monitor.dao.domain.GrpcInvoke;
import io.github.saluki.monitor.dao.domain.GrpcnvokeStatistics;

@Mapper
public interface InvokeMapper {

    void addInvoke(List<GrpcInvoke> invokes);

    List<GrpcnvokeStatistics> queryData(Map<String, String> paramter);

    List<Map<String, String>> queryConsumer();

    List<Map<String, String>> queryProvider(Map<String, String> paramter);

}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/client/GrpcClassLoader.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.grpc.client;

import java.io.File;
import java.io.FilenameFilter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Set;

import com.google.common.collect.Sets;

/**
 * @author shimingliu 2016年12月14日 下午9:58:47
 * @version ThrallClassLoader.java, v 0.0.1 2016年12月14日 下午9:58:47 shimingliu
 */
public class GrpcClassLoader extends URLClassLoader {

  private static final String API_REPOSITORY =
      System.getProperty("user.home") + File.separator + "saluki";

  private Set<URL> cachedJarUrls = Sets.newConcurrentHashSet();

  private ClassLoader systemClassLoader;

  public GrpcClassLoader() {
    super(new URL[] {}, null);
    this.addURL();
  }

  private void addURL() {
    File file = new File(API_REPOSITORY);
    if (file.exists() && file.isDirectory()) {
      String[] jars = file.list(new FilenameFilter() {

        @Override
        public boolean accept(File dir, String name) {
          if (name.endsWith(".jar")) {
            return true;
          }
          return false;
        }
      });
      for (int i = 0; i < jars.length; i++) {
        try {
          URL url = new File(file.getAbsolutePath(), jars[i]).toURI().toURL();
          if (cachedJarUrls.contains(url)) {
            continue;
          }
          cachedJarUrls.add(url);
          super.addURL(url);
        } catch (MalformedURLException e) {
          // igore
        }
      }
    }
  }

  @Override
  protected synchronized Class<?> loadClass(String name, boolean resolve)
      throws ClassNotFoundException {
    Class<?> clazz = null;
    clazz = resolveClassPath(name, resolve);
    if (clazz == null) {
      clazz = resolveSystemClassLoader(name, resolve);
    }
    if (clazz == null) {
      throw new ClassNotFoundException(name);
    }
    return clazz;
  }

  private Class<?> resolveClassPath(String name, boolean resolve) {
    try {
      Class<?> clazz = super.loadClass(name, resolve);
      return clazz;
    } catch (ClassNotFoundException ex) {
      // Ignore.
    }

    return null;
  }

  private Class<?> resolveSystemClassLoader(String name, boolean resolve) {
    if (systemClassLoader != null) {
      try {
        Class<?> clazz = systemClassLoader.loadClass(name);
        if (resolve) {
          resolveClass(clazz);
        }
        return clazz;
      } catch (ClassNotFoundException ex) {
        // Ignore.
      }
    }

    return null;
  }

  public void setSystemClassLoader(ClassLoader classLoader) {
    this.systemClassLoader = classLoader;
  }
}


<|start_filename|>saluki-plugin/saluki-plugin-common/src/main/java/io/github/saluki/plugin/common/PrintMessageFile.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the confidential and
 * proprietary information of Quancheng-ec.com ("Confidential Information"). You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with Quancheng-ec.com.
 */
package io.github.saluki.plugin.common;

import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.protobuf.DescriptorProtos.DescriptorProto;
import com.google.protobuf.DescriptorProtos.FieldDescriptorProto;
import com.google.protobuf.DescriptorProtos.FieldDescriptorProto.Label;

/**
 * @author shimingliu 2016年12月21日 下午3:42:47
 * @version PrintMessageFile.java, v 0.0.1 2016年12月21日 下午3:42:47 shimingliu
 */
public final class PrintMessageFile extends AbstractPrint {

  private static final Logger logger = LoggerFactory.getLogger(PrintMessageFile.class);

  private List<FieldDescriptorProto> messageFields;

  private Map<String, String> pojoTypeCache;

  private DescriptorProto sourceMessageDesc;

  public PrintMessageFile(String fileRootPath, String sourcePackageName, String className) {
    super(fileRootPath, sourcePackageName, className);
  }

  public void setMessageFields(List<FieldDescriptorProto> messageFields) {
    this.messageFields = messageFields;
  }

  public void setPojoTypeCache(Map<String, String> pojoTypeCache) {
    this.pojoTypeCache = pojoTypeCache;
  }

  public void setSourceMessageDesc(DescriptorProto sourceMessageDesc) {
    this.sourceMessageDesc = sourceMessageDesc;
  }

  @Override
  protected List<String> collectFileData() {
    String sourePackageName = super.getSourcePackageName();
    String className = super.getClassName();
    String packageName = sourePackageName.toLowerCase();
    List<String> fileData = Lists.newArrayList();
    fileData.add("package " + packageName + ";");
    fileData.add(System.getProperty("line.separator"));
    fileData.add("import io.github.saluki.serializer.ProtobufAttribute;");
    fileData.add("import io.github.saluki.serializer.ProtobufEntity;");
    fileData.add(System.getProperty("line.separator"));
    fileData.add("@ProtobufEntity(" + sourePackageName + "." + className + ".class)");
    fileData.add("public class " + className + "{");
    for (int i = 0; i < messageFields.size(); i++) {
      FieldDescriptorProto messageField = messageFields.get(i);
      String javaType = findJavaType(packageName, sourceMessageDesc, messageField);
      if (messageField.getLabel() == Label.LABEL_REPEATED && javaType != null) {
        if (!javaType.contains("java.util.Map")) {
          javaType = "java.util.ArrayList<" + javaType + ">";
        }
      }
      String fieldName = messageField.getName();
      fileData.add(System.getProperty("line.separator"));
      fileData.add("    @ProtobufAttribute");
      fileData.add("    private " + javaType + " " + fieldName + ";");
      fileData.add(System.getProperty("line.separator"));
      fileData.add("    public " + javaType + " get" + captureName(fieldName) + "(){");
      fileData.add("        return this." + fieldName + ";");
      fileData.add("}");
      fileData.add(System.getProperty("line.separator"));
      fileData.add(
          "    public void set" + captureName(fieldName) + "(" + javaType + " " + fieldName + "){");
      fileData.add("        this." + fieldName + "=" + fieldName + ";");
      fileData.add("}");
      fileData.add(System.getProperty("line.separator"));
    }
    fileData.add("}");
    return fileData;

  }

  private String findJavaType(String packageName, DescriptorProto sourceMessageDesc,
      FieldDescriptorProto field) {
    switch (field.getType()) {
      case TYPE_ENUM:
        return getMessageJavaType(packageName, sourceMessageDesc, field);
      case TYPE_MESSAGE:
        String javaType = getMessageJavaType(packageName, sourceMessageDesc, field);
        return javaType;
      case TYPE_GROUP:
        logger.info("group have not support yet");
        return null;
      case TYPE_STRING:
        return "String";
      case TYPE_INT64:
        return "Long";
      case TYPE_INT32:
        return "Integer";
      case TYPE_BOOL:
        return "Boolean";
      case TYPE_DOUBLE:
        return "Double";
      case TYPE_FLOAT:
        return "Float";
      default:
        logger.info("have not support this type " + field.getType()
            + ",please contact <EMAIL> for support");
        return null;
    }
  }

  private String getMessageJavaType(String packageName, DescriptorProto sourceMessageDesc,
      FieldDescriptorProto field) {
    String fieldType = CommonUtils.findNotIncludePackageType(field.getTypeName());
    Map<String, Pair<DescriptorProto, List<FieldDescriptorProto>>> nestedFieldType =
        transform(sourceMessageDesc);
    // isMap
    if (nestedFieldType.containsKey(fieldType)) {
      Pair<DescriptorProto, List<FieldDescriptorProto>> nestedFieldPair =
          nestedFieldType.get(fieldType);
      if (nestedFieldPair.getRight().size() == 2) {
        DescriptorProto mapSourceMessageDesc = nestedFieldPair.getLeft();
        List<FieldDescriptorProto> mapFieldList = nestedFieldPair.getRight();
        String nestedJavaType =
            "java.util.Map<" + findJavaType(packageName, mapSourceMessageDesc, mapFieldList.get(0))
                + "," + findJavaType(packageName, mapSourceMessageDesc, mapFieldList.get(1)) + ">";
        return nestedJavaType;
      } else {
        return null;
      }
    } else {
      return CommonUtils.findPojoTypeFromCache(field.getTypeName(), pojoTypeCache);
    }
  }

  private Map<String, Pair<DescriptorProto, List<FieldDescriptorProto>>> transform(
      DescriptorProto sourceMessageDesc) {
    Map<String, Pair<DescriptorProto, List<FieldDescriptorProto>>> nestedFieldMap =
        Maps.newHashMap();
    sourceMessageDesc.getNestedTypeList().forEach(new Consumer<DescriptorProto>() {

      @Override
      public void accept(DescriptorProto t) {
        nestedFieldMap.put(t.getName(),
            new ImmutablePair<DescriptorProto, List<FieldDescriptorProto>>(t, t.getFieldList()));
      }

    });
    return nestedFieldMap;
  }

  private String captureName(String name) {
    char[] cs = name.toCharArray();
    cs[0] -= 32;
    return String.valueOf(cs);

  }
}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/exception/RpcErrorMsg.java<|end_filename|>
package io.github.saluki.grpc.exception;

import java.io.Serializable;


public class RpcErrorMsg implements Serializable {

  private static final long serialVersionUID = 4909459500370103048L;

  private int status;
  private int errorcode;
  private String message;

  public RpcErrorMsg(int status, int errorcode, String message) {
    this.status = status;
    this.errorcode = errorcode;
    this.message = message;
  }

  public int getStatus() {
    return status;
  }

  public int getErrorCode() {
    return errorcode;
  }

  public String getMessage() {
    return message;
  }

}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/exception/RpcValidatorException.java<|end_filename|>
package io.github.saluki.grpc.exception;

public class RpcValidatorException extends RpcAbstractException {

    private static final long serialVersionUID = -3491276058323309898L;

    public RpcValidatorException(){
        super(RpcErrorMsgConstant.REQUEST_ARG_VALIDATE_EXCEPTION);
    }

    public RpcValidatorException(RpcErrorMsg motanErrorMsg){
        super(motanErrorMsg);
    }

    public RpcValidatorException(String message){
        super(message, RpcErrorMsgConstant.REQUEST_ARG_VALIDATE_EXCEPTION);
    }

    public RpcValidatorException(String message, RpcErrorMsg motanErrorMsg){
        super(message, motanErrorMsg);
    }

    public RpcValidatorException(String message, Throwable cause){
        super(message, cause, RpcErrorMsgConstant.REQUEST_ARG_VALIDATE_EXCEPTION);
    }

    public RpcValidatorException(String message, Throwable cause, RpcErrorMsg motanErrorMsg){
        super(message, cause, motanErrorMsg);
    }

    public RpcValidatorException(Throwable cause){
        super(cause, RpcErrorMsgConstant.REQUEST_ARG_VALIDATE_EXCEPTION);
    }

    public RpcValidatorException(Throwable cause, RpcErrorMsg motanErrorMsg){
        super(cause, motanErrorMsg);
    }
}


<|start_filename|>saluki-ops/spring-boot-starter-salukiops/src/main/resources/META-INF/static/assets/css/saluki.css<|end_filename|>
/*
 * Fonts
 */

@import url('../fonts/fonts.css');

/*
 * Base structure
 */

/* Move down content because we have a fixed navbar that is 50px tall */
body {
  padding-top: 50px;
}


/*
 * Global add-ons
 */

.sub-header {
  padding-bottom: 10px;
  border-bottom: 1px solid #eee;
}

pre, code, kbd, var, samp, tt {
    color: inherit;
    background: none;
}

h1 {
  font-size: 150%;
}

h2 {
  font-size: 125%;
}

label {
  font-weight: inherit;
}

/*
 * Top navigation
 * Hide default border to remove 1px line.
 */
.navbar-fixed-top {
  border: 0;
}

/*
 * Sidebar
 */

.sidebar {
  position: fixed;
  top: 51px;
  bottom: 0;
  left: 0;
  z-index: 1000;
  display: block;
  padding: 0 20px;
  overflow-x: hidden;
  overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
  background-color: #f5f5f5;
  border-right: 1px solid #eee;
}

/* Hide on a small screen */
@media (max-width: 768px) {
  .sidebar {
    display: none;
  }
}

/* Sidebar navigation */
.nav-sidebar {
  margin-right: -21px; /* 20px padding + 1px border */
  margin-bottom: 20px;
  margin-left: -20px;
}

.nav-sidebar > li {
}

.nav-sidebar > li > a {
  padding: 0 20px 0 30px;
}

.nav-sidebar > .active > a,
.nav-sidebar > .active > a:hover,
.nav-sidebar > .active > a:focus {
  color: #fff;
  background-color: #428bca;
}


/*
 * Main content
 */

.main {
  padding: 20px;
}

@media (min-width: 768px) {
  .main {
    padding-right: 40px;
    padding-left: 40px;
  }
}

.main .page-header {
  margin-top: 0;
}

.main code.package-name {
  font-size: 60%;
}

.main div.description, .main td.description {
  font-size: 100%;
  text-align: justify;
}

.main td ul {
  list-style-type: none;
  padding-left: 0;
}

.main h2 ~ .table-responsive {
  /* Remove the spacing between a heading and its first table */
  margin-top: -0.75em;
  padding-top: 0;
}

.main tbody tr:first-child > td {
  border-top: none;
}

/*
 * Placeholder dashboard ideas
 */

.placeholders {
  margin-bottom: 30px;
  text-align: center;
}

.placeholders h4 {
  margin-bottom: 0;
}

.placeholder {
  margin-bottom: 20px;
}

.placeholder img {
  display: inline-block;
  border-radius: 50%;
}

.debug-textarea {
  width: 100%;
  max-width: 100%;
  font-size: 90%;
  min-height: 200px;
}

.debug-http-headers {
  width: 100%;
  max-width: 100%;
  font-size: 90%;
  min-height: 140px;
}

.debug-http-headers-collapser.opened:after {
  content: ': ';
}

.debug-submit {
  margin-top: 8px;
}

.debug-response {
  min-height: 256px;
}
div.jsoneditor,
div.jsoneditor-menu {
  border-color: #4b4b4b;
}
div.jsoneditor-menu {
  background-color: #4b4b4b;
}
div.jsoneditor-tree,
div.jsoneditor textarea.jsoneditor-text {
  background-color: #666666;
  color: #ffffff;
}
div.jsoneditor-field,
div.jsoneditor-value {
  color: #ffffff;
}
table.jsoneditor-search div.jsoneditor-frame {
  background: #808080;
}

tr.jsoneditor-highlight,
tr.jsoneditor-selected {
  background-color: #808080;
}

div.jsoneditor-field[contenteditable=true]:focus,
div.jsoneditor-field[contenteditable=true]:hover,
div.jsoneditor-value[contenteditable=true]:focus,
div.jsoneditor-value[contenteditable=true]:hover,
div.jsoneditor-field.jsoneditor-highlight,
div.jsoneditor-value.jsoneditor-highlight {
  background-color: #808080;
  border-color: #808080;
}

div.jsoneditor-field.highlight-active,
div.jsoneditor-field.highlight-active:focus,
div.jsoneditor-field.highlight-active:hover,
div.jsoneditor-value.highlight-active,
div.jsoneditor-value.highlight-active:focus,
div.jsoneditor-value.highlight-active:hover {
  background-color: #b1b1b1;
  border-color: #b1b1b1;
}

div.jsoneditor-tree button:focus {
  background-color: #868686;
}

/* coloring of JSON in tree mode */
div.jsoneditor-readonly {
  color: #acacac;
}
div.jsoneditor td.jsoneditor-separator {
  color: #acacac;
}
div.jsoneditor-value.jsoneditor-string {
  color: #00ff88;
}
div.jsoneditor-value.jsoneditor-object,
div.jsoneditor-value.jsoneditor-array {
  color: #bababa;
}
div.jsoneditor-value.jsoneditor-number {
  color: #ff4040;
}
div.jsoneditor-value.jsoneditor-boolean {
  color: #ff8048;
}
div.jsoneditor-value.jsoneditor-null {
  color: #49a7fc;
}
div.jsoneditor-value.jsoneditor-invalid {
  color: white;
}

<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/client/internal/unary/CompletionFuture.java<|end_filename|>
/*
 * Copyright 2014-2017 the original author or authors.
 *
 * 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 io.github.saluki.grpc.client.internal.unary;

import com.google.common.util.concurrent.AbstractFuture;

import io.grpc.ClientCall;

/**
 * @author liushiming
 * @version CompletionFuture.java, v 0.0.1 2017年7月14日 下午9:42:42 liushiming
 * @since JDK 1.8
 */
public class CompletionFuture<T> extends AbstractFuture<T> {

  private final ClientCall<?, T> call;

  CompletionFuture(ClientCall<?, T> call) {
    this.call = call;
  }

  @Override
  protected void interruptTask() {
    call.cancel("CompletionFuture was cancelled", null);
  }

  @Override
  protected boolean set(T resp) {
    return super.set(resp);
  }

  @Override
  protected boolean setException(Throwable throwable) {
    return super.setException(throwable);
  }

}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/util/GrpcUtil.java<|end_filename|>
/*
 * Copyright 2014-2017 the original author or authors.
 *
 * 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 io.github.saluki.grpc.util;

import java.lang.reflect.Method;

import com.google.common.base.Charsets;
import com.google.protobuf.Message;
import io.github.saluki.grpc.annotation.GrpcMethodType;
import io.github.saluki.utils.ReflectUtils;
import io.github.saluki.serializer.ProtobufEntity;

import io.grpc.Metadata;

/**
 * @author liushiming
 * @version GrpcUtil.java, v 0.0.1 2017年7月19日 下午7:04:32 liushiming
 * @since JDK 1.8
 */
@SuppressWarnings("unchecked")
public class GrpcUtil {

  private GrpcUtil() {}

  public static final Metadata.Key<String> GRPC_CONTEXT_ATTACHMENTS =
      Metadata.Key.of("grpc_header_attachments-bin", utf8Marshaller());

  public static final Metadata.Key<String> GRPC_CONTEXT_VALUES =
      Metadata.Key.of("grpc_header_values-bin", utf8Marshaller());

  private static Metadata.BinaryMarshaller<String> utf8Marshaller() {
    return new Metadata.BinaryMarshaller<String>() {

      @Override
      public byte[] toBytes(String value) {
        return value.getBytes(Charsets.UTF_8);
      }

      @Override
      public String parseBytes(byte[] serialized) {
        return new String(serialized, Charsets.UTF_8);
      }
    };
  }

  public static io.grpc.MethodDescriptor<Message, Message> createMethodDescriptor(Class<?> clzz,
      Method method) {
    String clzzName = clzz.getName();
    String methodName = method.getName();
    GrpcMethodType grpcMethodType = method.getAnnotation(GrpcMethodType.class);
    Message argsReq = createDefaultInstance(grpcMethodType.requestType());
    Message argsRep = createDefaultInstance(grpcMethodType.responseType());
    return io.grpc.MethodDescriptor.<Message, Message>newBuilder()
        .setType(grpcMethodType.methodType())//
        .setFullMethodName(io.grpc.MethodDescriptor.generateFullMethodName(clzzName, methodName))//
        .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(argsReq))//
        .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(argsRep))//
        .setSafe(false)//
        .setIdempotent(false)//
        .build();
  }

  public static io.grpc.MethodDescriptor<Message, Message> createMethodDescriptor(String clzzName,
      String methodName, GrpcMethodType grpcMethodType) {
    Message argsReq = createDefaultInstance(grpcMethodType.requestType());
    Message argsRep = createDefaultInstance(grpcMethodType.responseType());
    return io.grpc.MethodDescriptor.<Message, Message>newBuilder()
        .setType(grpcMethodType.methodType())//
        .setFullMethodName(io.grpc.MethodDescriptor.generateFullMethodName(clzzName, methodName))//
        .setRequestMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(argsReq))//
        .setResponseMarshaller(io.grpc.protobuf.ProtoUtils.marshaller(argsRep))//
        .setSafe(false)//
        .setIdempotent(false)//
        .build();

  }


  public static Message createDefaultInstance(Class<?> type) {
    Class<? extends Message> messageType;
    if (!Message.class.isAssignableFrom(type)) {
      ProtobufEntity entity =
          (ProtobufEntity) ReflectUtils.findAnnotationFromClass(type, ProtobufEntity.class);
      messageType = entity.value();
    } else {
      messageType = (Class<? extends Message>) type;
    }
    Object obj = ReflectUtils.classInstance(messageType);
    return (Message) obj;
  }
}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/server/GrpcProtocolExporter.java<|end_filename|>
/*
 * Copyright (c) 2016, Quancheng-ec.com All right reserved. This software is the
 * confidential and proprietary information of Quancheng-ec.com ("Confidential
 * Information"). You shall not disclose such Confidential Information and shall
 * use it only in accordance with the terms of the license agreement you entered
 * into with Quancheng-ec.com.
 */
package io.github.saluki.grpc.server;

import io.grpc.ServerServiceDefinition;

/**
 * @author shimingliu 2016年12月14日 下午10:08:24
 * @version GrpcProtocolExporter.java, v 0.0.1 2016年12月14日 下午10:08:24 shimingliu
 */
public interface GrpcProtocolExporter {

    public ServerServiceDefinition export(Class<?> protocol, Object protocolImpl);
}


<|start_filename|>saluki-core/src/main/java/io/github/saluki/grpc/service/MonitorService.java<|end_filename|>
package io.github.saluki.grpc.service;

import io.github.saluki.common.GrpcURL;

public interface MonitorService {

    String APPLICATION    = "application";

    String INTERFACE      = "interface";

    String METHOD         = "method";

    String GROUP          = "group";

    String VERSION        = "version";

    String CONSUMER       = "consumer";

    String PROVIDER       = "provider";

    String TIMESTAMP      = "timestamp";

    String SUCCESS        = "success";

    String FAILURE        = "failure";

    String ELAPSED        = "elapsed";

    String CONCURRENT     = "concurrent";

    String TRACEID        = "traceId";

    String INPUT          = "input";

    String OUTPUT         = "output";

    String MAX_INPUT      = "max.input";

    String MAX_OUTPUT     = "max.output";

    String MAX_ELAPSED    = "max.elapsed";

    String MAX_CONCURRENT = "max.concurrent";

    /**
     * 监控数据采集. 1.
     * 支持调用次数统计：count://host/interface?application=foo&method=foo&provider=10.20.153.11:20880&success=12&failure=2&elapsed=135423423
     * 1.1 host,application,interface,group,version,method 记录监控来源主机，应用，接口，方法信息。 1.2
     * 如果是消费者发送的数据，加上provider地址参数，反之，加上来源consumer地址参数。 1.3 success,faulure,elapsed
     * 记录距上次采集，调用的成功次数，失败次数，成功调用总耗时，平均时间将用总耗时除以成功次数。
     * 
     * @param statistics
     */
    void collect(GrpcURL statistics);

}


<|start_filename|>saluki-ops/saluki-ops-console/src/main/resources/static/sourse/src/vendor.js<|end_filename|>
// Theme
import './libs/theme/eliteadmin/bootstrap/dist/css/bootstrap.css'; 	//Bootstrap Core CSS
import './libs/theme/eliteadmin/css/animate.css'; 										//animation CSS
import './libs/theme/eliteadmin/css/style.css';										//Custom CSS
// import './libs/theme/eliteadmin/css/colors/default.css';				//color CSS
import './libs/theme/eliteadmin/css/colors/default-dark.css';				//color CSS
import './libs/theme/plugins/bower_components/sidebar-nav/dist/sidebar-nav.min.css';				//color CSS


<|start_filename|>saluki-ops/spring-boot-starter-salukiops/src/main/java/io/github/saluki/monitor/jaket/builder/DefaultTypeBuilder.java<|end_filename|>
package io.github.saluki.monitor.jaket.builder;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

import io.github.saluki.monitor.jaket.JaketTypeBuilder;
import io.github.saluki.monitor.jaket.model.TypeDefinition;
import io.github.saluki.monitor.jaket.util.ClassUtils;
import io.github.saluki.monitor.jaket.util.JaketConfigurationUtils;

/**
 * Created by huangsheng.hs on 2015/1/27.
 */
public final class DefaultTypeBuilder {

    public static TypeDefinition build(Class<?> clazz, Map<Class<?>, TypeDefinition> typeCache) {
        final String canonicalName = clazz.getCanonicalName();

        TypeDefinition td = new TypeDefinition(canonicalName);
        // Try to get a cached definition
        if (typeCache.containsKey(clazz)) {
            return typeCache.get(clazz);
        }

        // Primitive type
        if (!JaketConfigurationUtils.needAnalyzing(clazz)) {
            return td;
        }

        // Custom type
        TypeDefinition ref = new TypeDefinition(canonicalName);
        ref.set$ref(canonicalName);
        typeCache.put(clazz, ref);

        List<Field> fields = ClassUtils.getNonStaticFields(clazz);
        for (Field field : fields) {
            String name = field.getName();
            Class<?> fieldClass = field.getType();
            Type fieldType = field.getGenericType();

            TypeDefinition fieldTd = JaketTypeBuilder.build(fieldType,fieldClass, typeCache);
            td.getProperties().put(name, fieldTd);
        }

        typeCache.put(clazz, td);
        return td;
    }

    private DefaultTypeBuilder() {
    }
}


<|start_filename|>saluki-registry/saluki-registry-consul/src/main/java/io/github/saluki/registry/consul/model/ConsulServiceResp.java<|end_filename|>
package io.github.saluki.registry.consul.model;

import java.util.List;

public final class ConsulServiceResp {

    private final List<ConsulService> salukiConsulServices;
    private final Long                consulIndex;
    private final Boolean             consulKnownLeader;
    private final Long                consulLastContact;

    private ConsulServiceResp(Builder builder){
        this.salukiConsulServices = builder.salukiConsulServices;
        this.consulIndex = builder.consulIndex;
        this.consulKnownLeader = builder.consulKnownLeader;
        this.consulLastContact = builder.consulLastContact;
    }

    public List<ConsulService> getSalukiConsulServices() {
        return salukiConsulServices;
    }

    public Long getConsulIndex() {
        return consulIndex;
    }

    public Boolean getConsulKnownLeader() {
        return consulKnownLeader;
    }

    public Long getConsulLastContact() {
        return consulLastContact;
    }

    public static Builder newResponse() {
        return new Builder();
    }

    public static class Builder extends AbstractBuilder {

        private List<ConsulService> salukiConsulServices;
        private Long                consulIndex;
        private Boolean             consulKnownLeader;
        private Long                consulLastContact;

        public Builder withValue(List<ConsulService> value) {
            this.salukiConsulServices = value;
            return this;
        }

        public Builder withConsulIndex(Long consulIndex) {
            this.consulIndex = consulIndex;
            return this;
        }

        public Builder withConsulKnowLeader(Boolean consulKnownLeader) {
            this.consulKnownLeader = consulKnownLeader;
            return this;
        }

        public Builder withConsulLastContact(Long consulLastContact) {
            this.consulLastContact = consulLastContact;
            return this;
        }

        public ConsulServiceResp build() {
            return new ConsulServiceResp(this);
        }

    }
}


<|start_filename|>saluki-example/saluki-example-client/src/main/java/io/github/saluki/example/client/GenricServiceController.java<|end_filename|>
/*
 * Copyright 2014-2017 the original author or authors.
 *
 * 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 io.github.saluki.example.client;

import java.util.Arrays;
import java.util.HashSet;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.saluki.example.model.First;
import com.saluki.example.model.Second;

import io.github.examples.model.hello.HelloReply;
import io.github.examples.model.hello.HelloRequest;
import io.github.saluki.boot.SalukiReference;
import io.github.saluki.common.RpcContext;
import io.github.saluki.grpc.service.GenericService;
import io.grpc.stub.StreamObserver;

/**
 * @author liushiming
 * @version GenricServiceController.java, v 0.0.1 2017年7月15日 上午11:09:11 liushiming
 * @since JDK 1.8
 */
@RestController
@RequestMapping("/genric")
public class GenricServiceController {

  @SalukiReference
  private GenericService genricService;

  @RequestMapping("/hello")
  public HelloReply view(@RequestParam(value = "name", required = false) String name) {
    String serviceName = "io.github.examples.service.HelloService";
    String method = "sayHello";
    HelloRequest request = new HelloRequest();
    request.setName(name);
    Object[] args = new Object[] {request};
    HelloReply reply =
        (HelloReply) genricService.$invoke(serviceName, "example", "1.0.0", method, args);
    return reply;
  }

  @RequestMapping("/hellostream")
  public HelloReply hellostream(@RequestParam(value = "name", required = false) String name) {
    String serviceName = "io.github.examples.service.HelloService";
    String method = "sayHelloServerStream";
    HelloRequest request = new HelloRequest();
    request.setName(name);
    Object[] args = new Object[] {request, responseObserver()};
    HelloReply reply =
        (HelloReply) genricService.$invoke(serviceName, "example", "1.0.0", method, args);
    return reply;
  }

  private StreamObserver<io.github.examples.model.hello.HelloReply> responseObserver() {
    StreamObserver<io.github.examples.model.hello.HelloReply> responseObserver =
        new StreamObserver<io.github.examples.model.hello.HelloReply>() {
          @Override
          public void onNext(io.github.examples.model.hello.HelloReply summary) {
            System.out.println(summary.getMessage());
          }

          @Override
          public void onError(Throwable t) {
            t.printStackTrace();
          }

          @Override
          public void onCompleted() {

        }
        };
    return responseObserver;
  }

  @RequestMapping("/hello_1")
  public HelloReply view1(@RequestParam(value = "name", required = false) String name) {
    String serviceName = "io.github.examples.service.HelloService";
    String method = "sayHello";
    HelloRequest request = new HelloRequest();
    request.setName(name);
    Object[] args = new Object[] {request};
    RpcContext.getContext().setHoldenGroups(new HashSet<>(Arrays.asList(First.class)));
    HelloReply reply =
        (HelloReply) genricService.$invoke(serviceName, "example", "1.0.0", method, args);
    return reply;
  }

  @RequestMapping("/hello_2")
  public HelloReply view2(@RequestParam(value = "name", required = false) String name) {
    String serviceName = "io.github.examples.service.HelloService";
    String method = "sayHello";
    HelloRequest request = new HelloRequest();
    request.setName(name);
    Object[] args = new Object[] {request};
    RpcContext.getContext().setHoldenGroups(new HashSet<>(Arrays.asList(Second.class)));
    HelloReply reply =
        (HelloReply) genricService.$invoke(serviceName, "example", "1.0.0", method, args);
    return reply;
  }
}
