Пример #1
0
func prepareForCaching(r []reflect.Value, outputParams []string) []byte {

	var err error
	buf := new(bytes.Buffer)
	encd := json.NewEncoder(buf)

	for i, _ := range r {
		switch outputParams[i] {
		case "int":
			err = encd.Encode(r[i].Int())
			panik.On(err)
		case "map":
			err = encd.Encode(r[i].Interface().(map[string]interface{}))
			panik.On(err)
		case "string":
			err = encd.Encode(r[i].String())
			panik.On(err)
		case "*st:github.com/tolexo/aqua.Sac":
			err = encd.Encode(r[i].Elem().Interface().(Sac).Data)
		default:
			panic("Unknown type of output to be sent to endpoint cache: " + outputParams[i])
		}
	}

	return buf.Bytes()
}
Пример #2
0
func NewDebugCache(w string, r string, inner Cacher) Cacher {
	var err error
	var rf, wf *os.File

	if r != "" {
		rf, err = os.OpenFile(r, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
		panik.On(err)
	}
	if w != "" {
		wf, err = os.OpenFile(w, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)
		panik.On(err)
	}
	return debugCache{
		base: inner,
		w:    wf,
		r:    rf,
	}
}
Пример #3
0
func NewMemcache(host string, port int) Cacher {
	serv, err := gomemcache.Connect(host, port)
	panik.On(err)

	m := memCache{
		mc: serv,
	}
	return m
	// TODO: close port on destruction
}
Пример #4
0
func decomposeCachedValues(data []byte, outputParams []string) []reflect.Value {

	var err error
	buf := bytes.NewBuffer(data)
	decd := json.NewDecoder(buf)
	out := make([]reflect.Value, len(outputParams))

	for i, o := range outputParams {
		switch o {
		case "int":
			var j int
			err = decd.Decode(&j)
			panik.On(err)
			out[i] = reflect.ValueOf(j)
		case "map":
			var m map[string]interface{}
			err = decd.Decode(&m)
			panik.On(err)
			out[i] = reflect.ValueOf(m)
		case "string":
			var s string
			err = decd.Decode(&s)
			panik.On(err)
			out[i] = reflect.ValueOf(s)
		case "*st:github.com/tolexo/aqua.Sac":
			var m map[string]interface{}
			err = decd.Decode(&m)
			panik.On(err)
			s := NewSac()
			s.Data = m
			out[i] = reflect.ValueOf(s)
		default:
			panic("Unknown type of output to be decoded from endpoint cache:" + o)
		}
	}

	return out

}
Пример #5
0
func NewRedis(host string, port int, db int) Cacher {
	serv := redis.NewClient(&redis.Options{
		Addr: fmt.Sprintf("%s:%d", host, port),
		DB:   int64(db),
	})
	_, err := serv.Ping().Result()
	panik.On(err)

	return redisStore{
		r: serv,
	}
	// TODO: close port on destruction
}
Пример #6
0
func ModAccessLog(path string) func(http.Handler) http.Handler {

	f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	panik.On(err)
	l := log.New(f, "", log.LstdFlags)

	return func(next http.Handler) http.Handler {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			start := time.Now()
			next.ServeHTTP(w, r)
			l.Printf("%s %s %.3f", r.Method, r.RequestURI, time.Since(start).Seconds())
		})
	}
}
Пример #7
0
func MonitorMe(params MonitorParams) {
	if params.ServiceId != "" {
		dataDogAgent := GetDataDogAgent()

		dataDogAgent.Count("throughput", 1, nil, 1)
		dataDogAgent.Count(params.ServiceId, 1, nil, 1)

		dataDogAgent.Histogram("resptime", params.RespTime, nil, 1)
		dataDogAgent.Histogram(params.ServiceId+".resptime", params.RespTime, nil, 1)

		intervalTag := GetTimeIntervalTag(params.RespTime)
		dataDogAgent.Histogram("resptimeinterval", params.RespTime, intervalTag, 1)
		dataDogAgent.Histogram(params.ServiceId+".resptimeinterval", params.RespTime, intervalTag, 1)

		if params.CacheHit {
			dataDogAgent.Count("cachehit", 1, nil, 1)
			dataDogAgent.Count(params.ServiceId+".cachehit", 1, nil, 1)
			dataDogAgent.Histogram("resptime.c", params.RespTime, nil, 1)
			dataDogAgent.Histogram(params.ServiceId+".resptime.c", params.RespTime, nil, 1)
		} else {
			dataDogAgent.Histogram("resptime.nc", params.RespTime, nil, 1)
			dataDogAgent.Histogram(params.ServiceId+".resptime.nc", params.RespTime, nil, 1)

		}

		if params.ResponseCode > 0 {
			statusCode := FormatHttpStatusCode(int64(params.ResponseCode))
			dataDogAgent.Count(statusCode, 1, nil, 1)
			dataDogAgent.Count(params.ServiceId+"."+statusCode, 1, nil, 1)
		}

		enablelog := conf.Bool("monitor.enablelog", false)
		if enablelog {
			logfile := conf.String("monitor.filelog", "")
			if logfile != "" {
				t := time.Now()
				logfileSuffix := fmt.Sprintf("%d-%d-%d", t.Month(), t.Day(), t.Hour())
				f, err := os.OpenFile(logfile+logfileSuffix+".csv", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
				panik.On(err)
				l := log.New(f, "", log.LstdFlags)
				l.Printf("%s %f %s %d %t", params.ServiceId, params.RespTime, intervalTag, params.ResponseCode, params.CacheHit)
			}
		}
	}
}
Пример #8
0
func handleIncoming(e *endPoint) func(http.ResponseWriter, *http.Request) {

	// return stub
	if e.info.Stub != "" {
		return func(w http.ResponseWriter, r *http.Request) {
			d, err := getContent(e.info.Stub)
			if err == nil {
				fmt.Fprintf(w, "%s", d)
			} else {
				w.WriteHeader(400)
				fmt.Fprintf(w, "{ message: \"%s\"}", "Stub path not found")
			}
		}
	}

	return func(w http.ResponseWriter, r *http.Request) {

		cacheHit := false

		// TODO: create less local variables
		// TODO: move vars to closure level

		var out []reflect.Value
		//TODO: capture this using instrumentation handler
		defer func(reqStartTime time.Time) {
			go func() {
				if e.serviceId != "" {
					respTime := time.Since(reqStartTime).Seconds() * 1000
					var responseCode int64 = 200
					if out != nil && len(out) == 2 && e.caller.outParams[0] == "int" {
						responseCode = out[0].Int()
					}
					monitorParams := monit.MonitorParams{
						ServiceId:    e.serviceId,
						RespTime:     respTime,
						ResponseCode: responseCode,
						CacheHit:     cacheHit,
					}
					monit.MonitorMe(monitorParams)
				}
			}()
			if reqR := recover(); reqR != nil {
				monit.PanicLogger(reqR, e.serviceId, r.RequestURI, time.Now())
			}
		}(time.Now())

		//check authentication
		if e.info.Auth != "" {
			ok, errMsg := auth.AuthenticateRequest(r, e.info.Auth)
			if !ok { //print authentication error
				w.WriteHeader(401)
				w.Header().Set("Content-Type", "application/json")
				w.Header().Set("Content-Length", strconv.Itoa(len(errMsg)))
				fmt.Fprintf(w, "%s", errMsg)
				return
			}
		}

		var useCache bool = false
		var ttl time.Duration = 0 * time.Second
		var val []byte
		var err error

		if e.info.Ttl != "" {
			ttl, err = time.ParseDuration(e.info.Ttl)
			panik.On(err)
		}
		useCache = r.Method == "GET" && ttl > 0 && e.stash != nil

		muxVals := mux.Vars(r)
		params := make([]string, len(e.muxVars))
		for i, v := range e.muxVars {
			params[i] = muxVals[v]
		}

		if e.isStdHttpHandler {
			//TODO: caching of standard handler
			e.caller.Do([]reflect.Value{reflect.ValueOf(w), reflect.ValueOf(r)})
		} else {
			ref := convertToType(params, e.caller.inpParams)
			if e.needsJarInput {
				ref = append(ref, reflect.ValueOf(NewJar(r)))
			}

			if useCache {
				val, err = e.stash.Get(r.RequestURI)
				if err == nil {
					cacheHit = true
					// fmt.Print(".")
					out = decomposeCachedValues(val, e.caller.outParams)
				} else {
					out = e.caller.Do(ref)
					if len(out) == 2 && e.caller.outParams[0] == "int" {
						code := out[0].Int()
						if code < 200 || code > 299 {
							useCache = false
						}
					}
					if useCache {
						bytes := prepareForCaching(out, e.caller.outParams)
						e.stash.Set(r.RequestURI, bytes, ttl)
						// fmt.Print(":", len(bytes), r.RequestURI)
					}

				}
			} else {
				out = e.caller.Do(ref)
				// fmt.Print("!")
			}
			writeOutput(w, e.caller.outParams, out, e.info.Pretty)
		}
	}
}