feat: switch glide to govendor. (#186)

* feat: switch glide to govendor.

* fix: testing
This commit is contained in:
Bo-Yi Wu
2017-02-19 15:04:00 +08:00
committed by GitHub
parent 3f4485edf7
commit 23bd0d0c56
732 changed files with 252501 additions and 52 deletions

22
vendor/github.com/thoas/stats/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Florent Messa
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

4
vendor/github.com/thoas/stats/Makefile generated vendored Normal file
View File

@@ -0,0 +1,4 @@
test: unit
unit:
@(go test -v)

251
vendor/github.com/thoas/stats/README.rst generated vendored Normal file
View File

@@ -0,0 +1,251 @@
Go stats handler
================
.. image:: https://secure.travis-ci.org/thoas/stats.png?branch=master
:alt: Build Status
:target: http://travis-ci.org/thoas/stats
stats is a ``net/http`` handler in golang reporting various metrics about
your web application.
This middleware has been developed and required for the need of picfit_,
an image resizing server written in Go.
Compatibility
-------------
This handler supports the following frameworks at the moment:
* `negroni`_
* `martini`_
* `gocraft/web <https://github.com/gocraft/web>`_
* `Gin <https://github.com/gin-gonic/gin>`_
* `Goji <https://github.com/zenazn/goji>`_
* `Beego <https://github.com/astaxie/beego>`_
* `HTTPRouter <https://github.com/julienschmidt/httprouter>`_
We don't support your favorite Go framework? Send me a PR or
create a new `issue <https://github.com/thoas/stats/issues>`_ and
I will implement it :)
Installation
------------
1. Make sure you have a Go language compiler >= 1.3 (required) and git installed.
2. Make sure you have the following go system dependencies in your $PATH: bzr, svn, hg, git
3. Ensure your GOPATH_ is properly set.
4. Download it:
::
go get github.com/thoas/stats
Usage
-----
Basic net/http
..............
To use this handler directly with ``net/http``, you need to call the
middleware with the handler itself:
.. code-block:: go
package main
import (
"net/http"
"github.com/thoas/stats"
)
func main() {
h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{\"hello\": \"world\"}"))
})
handler := stats.New().Handler(h)
http.ListenAndServe(":8080", handler)
}
Negroni
.......
If you are using negroni_ you can implement the handler as
a simple middleware in ``server.go``:
.. code-block:: go
package main
import (
"net/http"
"github.com/codegangsta/negroni"
"github.com/thoas/stats"
"encoding/json"
)
func main() {
middleware := stats.New()
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{\"hello\": \"world\"}"))
})
mux.HandleFunc("/stats", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
stats := middleware.Data()
b, _ := json.Marshal(stats)
w.Write(b)
})
n := negroni.Classic()
n.Use(middleware)
n.UseHandler(mux)
n.Run(":3000")
}
HTTPRouter
.......
If you are using HTTPRouter_ you need to call the middleware with the handler itself:
.. code-block:: go
package main
import (
"encoding/json"
"github.com/julienschmidt/httprouter"
"github.com/thoas/stats"
"net/http"
)
func main() {
router := httprouter.New()
s := stats.New()
router.GET("/stats", func(w http.ResponseWriter, _ *http.Request, _ httprouter.Params) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
s, err := json.Marshal(s.Data())
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
w.Write(s)
})
http.ListenAndServe(":8080", s.Handler(router))
}
Martini
.......
If you are using martini_, you can implement the handler as a wrapper of
a ``Martini.Context`` in ``server.go``:
.. code-block:: go
package main
import (
"encoding/json"
"github.com/go-martini/martini"
"github.com/thoas/stats"
"net/http"
)
func main() {
middleware := stats.New()
m := martini.Classic()
m.Get("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.Write([]byte("{\"hello\": \"world\"}"))
})
m.Get("/stats", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
stats := middleware.Data()
b, _ := json.Marshal(stats)
w.Write(b)
})
m.Use(func(c martini.Context, w http.ResponseWriter, r *http.Request) {
beginning, recorder := middleware.Begin(w)
c.Next()
middleware.End(beginning, recorder)
})
m.Run()
}
Run it in a shell:
::
$ go run server.go
Then in another shell run:
::
$ curl http://localhost:3000/stats | python -m "json.tool"
Expect the following result:
.. code-block:: json
{
"total_response_time": "1.907382ms",
"average_response_time": "86.699\u00b5s",
"average_response_time_sec": 8.6699e-05,
"count": 1,
"pid": 99894,
"status_code_count": {
"200": 1
},
"time": "2015-03-06 17:23:27.000677896 +0100 CET",
"total_count": 22,
"total_response_time_sec": 0.0019073820000000002,
"total_status_code_count": {
"200": 22
},
"unixtime": 1425659007,
"uptime": "4m14.502271612s",
"uptime_sec": 254.502271612
}
See `examples <https://github.com/thoas/stats/blob/master/examples>`_ to
test them.
Inspiration
-----------
`Antoine Imbert <https://github.com/ant0ine>`_ is the original author
of this middleware.
Originally developed for `go-json-rest <https://github.com/ant0ine/go-json-rest>`_,
it had been ported as a simple Golang handler by `Florent Messa <https://github.com/thoas>`_
to be used in various frameworks.
This middleware implements a ticker which is launched every seconds to
reset requests/sec and will implement new features in a near future :)
.. _GOPATH: http://golang.org/doc/code.html#GOPATH
.. _StatusMiddleware: https://github.com/ant0ine/go-json-rest/blob/master/rest/status.go
.. _go-json-rest: https://github.com/ant0ine/go-json-rest
.. _negroni: https://github.com/codegangsta/negroni
.. _martini: https://github.com/go-martini/martini
.. _picfit: https://github.com/thoas/picfit
.. _HTTPRouter: https://github.com/julienschmidt/httprouter

90
vendor/github.com/thoas/stats/recorder.go generated vendored Normal file
View File

@@ -0,0 +1,90 @@
package stats
import (
"bufio"
"fmt"
"net"
"net/http"
)
type ResponseWriter interface {
http.ResponseWriter
http.Flusher
// Status returns the status code of the response or 0 if the response has not been written.
Status() int
// Written returns whether or not the ResponseWriter has been written.
Written() bool
// Size returns the size of the response body.
Size() int
// Before allows for a function to be called before the ResponseWriter has been written to. This is
// useful for setting headers or any other operations that must happen before a response has been written.
Before(func(ResponseWriter))
}
type beforeFunc func(ResponseWriter)
type recorderResponseWriter struct {
http.ResponseWriter
status int
size int
beforeFuncs []beforeFunc
}
func NewRecorderResponseWriter(w http.ResponseWriter, statusCode int) ResponseWriter {
return &recorderResponseWriter{w, statusCode, 0, nil}
}
func (r *recorderResponseWriter) WriteHeader(code int) {
r.ResponseWriter.WriteHeader(code)
r.status = code
}
func (r *recorderResponseWriter) Flush() {
flusher, ok := r.ResponseWriter.(http.Flusher)
if ok {
flusher.Flush()
}
}
func (r *recorderResponseWriter) Status() int {
return r.status
}
func (r *recorderResponseWriter) Write(b []byte) (int, error) {
if !r.Written() {
// The status will be StatusOK if WriteHeader has not been called yet
r.WriteHeader(http.StatusOK)
}
size, err := r.ResponseWriter.Write(b)
r.size += size
return size, err
}
// Proxy method to Status to add support for gocraft
func (r *recorderResponseWriter) StatusCode() int {
return r.Status()
}
func (r *recorderResponseWriter) Size() int {
return r.size
}
func (r *recorderResponseWriter) Written() bool {
return r.StatusCode() != 0
}
func (r *recorderResponseWriter) CloseNotify() <-chan bool {
return r.ResponseWriter.(http.CloseNotifier).CloseNotify()
}
func (r *recorderResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
hijacker, ok := r.ResponseWriter.(http.Hijacker)
if !ok {
return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface")
}
return hijacker.Hijack()
}
func (r *recorderResponseWriter) Before(before func(ResponseWriter)) {
r.beforeFuncs = append(r.beforeFuncs, before)
}

168
vendor/github.com/thoas/stats/stats.go generated vendored Normal file
View File

@@ -0,0 +1,168 @@
package stats
import (
"fmt"
"net/http"
"os"
"sync"
"time"
)
// Stats data structure
type Stats struct {
mu sync.RWMutex
Uptime time.Time
Pid int
ResponseCounts map[string]int
TotalResponseCounts map[string]int
TotalResponseTime time.Time
}
// New constructs a new Stats structure
func New() *Stats {
stats := &Stats{
Uptime: time.Now(),
Pid: os.Getpid(),
ResponseCounts: map[string]int{},
TotalResponseCounts: map[string]int{},
TotalResponseTime: time.Time{},
}
go func() {
for {
stats.ResetResponseCounts()
time.Sleep(time.Second * 1)
}
}()
return stats
}
// ResetResponseCounts reset the response counts
func (mw *Stats) ResetResponseCounts() {
mw.mu.Lock()
defer mw.mu.Unlock()
mw.ResponseCounts = map[string]int{}
}
// Handler is a MiddlewareFunc makes Stats implement the Middleware interface.
func (mw *Stats) Handler(h http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
beginning, recorder := mw.Begin(w)
h.ServeHTTP(recorder, r)
mw.End(beginning, recorder)
})
}
// Negroni compatible interface
func (mw *Stats) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
beginning, recorder := mw.Begin(w)
next(recorder, r)
mw.End(beginning, recorder)
}
// Begin starts a recorder
func (mw *Stats) Begin(w http.ResponseWriter) (time.Time, ResponseWriter) {
start := time.Now()
writer := NewRecorderResponseWriter(w, 200)
return start, writer
}
// EndWithStatus closes the recorder with a specific status
func (mw *Stats) EndWithStatus(start time.Time, status int) {
end := time.Now()
responseTime := end.Sub(start)
mw.mu.Lock()
defer mw.mu.Unlock()
statusCode := fmt.Sprintf("%d", status)
mw.ResponseCounts[statusCode]++
mw.TotalResponseCounts[statusCode]++
mw.TotalResponseTime = mw.TotalResponseTime.Add(responseTime)
}
// End closes the recorder with the recorder status
func (mw *Stats) End(start time.Time, recorder ResponseWriter) {
mw.EndWithStatus(start, recorder.Status())
}
// Data serializable structure
type Data struct {
Pid int `json:"pid"`
UpTime string `json:"uptime"`
UpTimeSec float64 `json:"uptime_sec"`
Time string `json:"time"`
TimeUnix int64 `json:"unixtime"`
StatusCodeCount map[string]int `json:"status_code_count"`
TotalStatusCodeCount map[string]int `json:"total_status_code_count"`
Count int `json:"count"`
TotalCount int `json:"total_count"`
TotalResponseTime string `json:"total_response_time"`
TotalResponseTimeSec float64 `json:"total_response_time_sec"`
AverageResponseTime string `json:"average_response_time"`
AverageResponseTimeSec float64 `json:"average_response_time_sec"`
}
// Data returns the data serializable structure
func (mw *Stats) Data() *Data {
mw.mu.RLock()
responseCounts := make(map[string]int, len(mw.ResponseCounts))
totalResponseCounts := make(map[string]int, len(mw.TotalResponseCounts))
now := time.Now()
uptime := now.Sub(mw.Uptime)
count := 0
for code, current := range mw.ResponseCounts {
responseCounts[code] = current
count += current
}
totalCount := 0
for code, count := range mw.TotalResponseCounts {
totalResponseCounts[code] = count
totalCount += count
}
totalResponseTime := mw.TotalResponseTime.Sub(time.Time{})
averageResponseTime := time.Duration(0)
if totalCount > 0 {
avgNs := int64(totalResponseTime) / int64(totalCount)
averageResponseTime = time.Duration(avgNs)
}
mw.mu.RUnlock()
r := &Data{
Pid: mw.Pid,
UpTime: uptime.String(),
UpTimeSec: uptime.Seconds(),
Time: now.String(),
TimeUnix: now.Unix(),
StatusCodeCount: responseCounts,
TotalStatusCodeCount: totalResponseCounts,
Count: count,
TotalCount: totalCount,
TotalResponseTime: totalResponseTime.String(),
TotalResponseTimeSec: totalResponseTime.Seconds(),
AverageResponseTime: averageResponseTime.String(),
AverageResponseTimeSec: averageResponseTime.Seconds(),
}
return r
}