stats

package module
Version: v0.0.0-...-f74b7e3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 11, 2018 License: MIT Imports: 8 Imported by: 0

README

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

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Data

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"`
	TotalVisitorCount      map[string]int `json:"total_visitor_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 serializable structure

type ResponseWriter

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))
}

func NewRecorderResponseWriter

func NewRecorderResponseWriter(w http.ResponseWriter, statusCode int) ResponseWriter

type StatItem

type StatItem struct {
	BeginTime time.Time
	Visitor   string
}

StatItem contains the request begin time and the visitor ip address

type Stats

type Stats struct {
	Uptime              time.Time
	Pid                 int
	ResponseCounts      map[string]int
	TotalResponseCounts map[string]int
	TotalVisitorCounts  map[string]int
	TotalResponseTime   time.Time
	// contains filtered or unexported fields
}

Stats data structure

func New

func New() *Stats

New constructs a new Stats structure

func (*Stats) Begin

Begin starts a recorder

func (*Stats) Data

func (mw *Stats) Data() *Data

Data returns the data serializable structure

func (*Stats) End

func (mw *Stats) End(st StatItem, recorder ResponseWriter)

End closes the recorder with the recorder status

func (*Stats) EndWithStatus

func (mw *Stats) EndWithStatus(st StatItem, recorder ResponseWriter)

EndWithStatus closes the recorder with a specific status

func (*Stats) Handler

func (mw *Stats) Handler(h http.Handler) http.Handler

Handler is a MiddlewareFunc makes Stats implement the Middleware interface.

func (*Stats) ResetResponseCounts

func (mw *Stats) ResetResponseCounts()

ResetResponseCounts reset the response counts

func (*Stats) ServeHTTP

func (mw *Stats) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)

Negroni compatible interface

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL