1
0
Fork 0

mnemonics 소스 추가

This commit is contained in:
tom.cat 2016-03-07 19:16:06 +09:00
parent 7fbf716eed
commit 96f8d6f794
13 changed files with 429 additions and 121 deletions

2
.gitignore vendored
View File

@ -121,4 +121,4 @@ $RECYCLE.BIN/
build/ build/
bind/ bind/
wiki mnemonics

7
Godeps/Godeps.json generated
View File

@ -1,5 +1,5 @@
{ {
"ImportPath": "amuz.es/go/wiki", "ImportPath": "amuz.es/go/mnemonics",
"GoVersion": "go1.5", "GoVersion": "go1.5",
"Deps": [ "Deps": [
{ {
@ -38,6 +38,11 @@
"ImportPath": "github.com/manucorporat/sse", "ImportPath": "github.com/manucorporat/sse",
"Rev": "ee05b128a739a0fb76c7ebd3ae4810c1de808d6d" "Rev": "ee05b128a739a0fb76c7ebd3ae4810c1de808d6d"
}, },
{
"ImportPath": "github.com/zalando-techmonkeys/gin-glog",
"Comment": "1.0.2-10-g3a91815",
"Rev": "3a9181566c628311ad5453b06d5f6934a1fec92c"
},
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "08f168e593b5aab61849054b77981de812666697" "Rev": "08f168e593b5aab61849054b77981de812666697"

View File

@ -0,0 +1,24 @@
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof

View File

@ -0,0 +1,12 @@
language: go
go:
- 1.4
- 1.4.2
- tip
before_install:
- go get github.com/axw/gocov/gocov
- go get github.com/mattn/goveralls
- if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
script:
- $HOME/gopath/bin/goveralls -service=travis-ci

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Zalando SE
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.

View File

@ -0,0 +1,3 @@
Sandor Szücs <sandor.szuecs@zalando.de>
Raffaele Di Fazio <raffaele.di.fazio@zalando.de>
Nick Jüttner <nick.juettner@zalando.de>

View File

@ -0,0 +1,141 @@
# Gin-Glog
[Gin](https://github.com/gin-gonic/gin) middleware for Logging with
[glog](https://github.com/golang/glog). It is meant as drop in
replacement for the default logger used in Gin.
[![Build Status](https://travis-ci.org/zalando-techmonkeys/gin-glog.svg?branch=master)](https://travis-ci.org/zalando-techmonkeys/gin-glog)
[![Coverage Status](https://coveralls.io/repos/zalando-techmonkeys/gin-glog/badge.svg?branch=master&service=github)](https://coveralls.io/github/zalando-techmonkeys/gin-glog?branch=master)
[![Go Report Card](http://goreportcard.com/badge/zalando-techmonkeys/gin-glog)](http://goreportcard.com/report/zalando-techmonkeys/gin-glog)
[![GoDoc](https://godoc.org/github.com/zalando-techmonkeys/gin-glog?status.svg)](http://godoc.org/github.com/zalando-techmonkeys/gin-glog)
## Project Context and Features
When it comes to choosing a Go framework, there's a lot of confusion
about what to use. The scene is very fragmented, and detailed
comparisons of different frameworks are still somewhat rare. Meantime,
how to handle dependencies and structure projects are big topics in
the Golang community. We've liked using Gin for its speed,
accessibility, and usefulness in developing microservice
architectures. In creating Gin-Glog, we wanted to take fuller
advantage of [Gin](https://github.com/gin-gonic/gin)'s capabilities
and help other devs do likewise.
Gin-Glog replaces the default logger of [Gin](https://github.com/gin-gonic/gin) to use
[Glog](https://github.com/golang/glog).
## How Glog is different compared to other loggers
Glog is an efficient pure Go implementation of leveled logs. If you
use Glog, you do not use blocking calls for writing logs. A goroutine
in the background will flush queued loglines into appropriate
logfiles. It provides logrotation, maintains symlinks to current files
and creates flags to your command line interface.
## Requirements
Gin-Glog uses the following [Go](https://golang.org/) packages as
dependencies:
- github.com/gin-gonic/gin
- github.com/golang/glog
## Installation
Assuming you've installed Go and Gin, run this:
go get github.com/zalando-techmonkeys/gin-glog
## Usage
### Example
Start your webapp to log to STDERR and /tmp:
% ./webapp -log_dir="/tmp" -alsologtostderr -v=2
```go
package main
import (
"flag"
"time"
"github.com/golang/glog"
"github.com/zalando-techmonkeys/gin-glog"
"github.com/gin-gonic/gin"
)
func main() {
flag.Parse()
router := gin.New()
router.Use(ginglog.Logger(3 * time.Second))
//..
router.Use(gin.Recovery())
glog.Warning("warning")
glog.Error("err")
glog.Info("info")
glog.V(2).Infoln("This line will be printed if you use -v=N with N >= 2.")
router.Run(":8080")
}
```
STDERR output of the example above. Lines with prefix "[Gin-Debug]"
are hardcoded output of Gin and will not appear in your logfile:
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
W0306 16:37:12.836001 367 main.go:18] warning
E0306 16:37:12.836335 367 main.go:19] err
I0306 16:37:12.836402 367 main.go:20] info
I0306 16:26:33.901278 32538 main.go:19] This line will be printed if you use -v=N with N >= 2.
[GIN-debug] Listening and serving HTTP on :8080
## Synopsis
Glog will add the following flags to your binary:
-alsologtostderr
log to standard error as well as files
-log_backtrace_at value
when logging hits line file:N, emit a stack trace (default :0)
-log_dir string
If non-empty, write log files in this directory
-logtostderr
log to standard error instead of files
-stderrthreshold value
logs at or above this threshold go to stderr
-v value
log level for V logs
-vmodule value
comma-separated list of pattern=N settings for file-filtered logging
## Contributing/TODO
We welcome contributions from the community; just submit a pull
request. To help you get started, here are some items that we'd love
help with:
- Remove hardcoded logs in [Gin](https://github.com/gin-gonic/gin)
- the code base
If you need to:
* create an issue: please create them on github
* get in contact: team-techmonkeys@zalando.de
* a list of [MAINTAINERS](MAINTAINERS)
## Contributors
Thanks to:
- &lt;your name&gt;
## License
See [LICENSE](LICENSE) file.

View File

@ -0,0 +1,168 @@
// Package ginglog provides a logging middleware to get
// https://github.com/golang/glog as logging library for
// https://github.com/gin-gonic/gin. It can be used as replacement for
// the internal logging middleware
// http://godoc.org/github.com/gin-gonic/gin#Logger.
//
// Example:
// package main
// import (
// "flag
// "time"
// "github.com/golang/glog"
// "github.com/zalando-techmonkeys/gin-glog"
// "github.com/gin-gonic/gin"
// )
// func main() {
// flag.Parse()
// router := gin.New()
// router.Use(ginglog.Logger(3 * time.Second))
// //..
// router.Use(gin.Recovery())
// glog.Info("bootstrapped application")
// router.Run(":8080")
// }
//
// Your service will get new command line parameters from
// https://github.com/golang/glog.
package ginglog
import (
"time"
"github.com/gin-gonic/gin"
"github.com/golang/glog"
)
func setupLogging(duration time.Duration) {
go func() {
for range time.Tick(duration) {
glog.Flush()
}
}()
}
var (
green = string([]byte{27, 91, 57, 55, 59, 52, 50, 109})
white = string([]byte{27, 91, 57, 48, 59, 52, 55, 109})
yellow = string([]byte{27, 91, 57, 55, 59, 52, 51, 109})
red = string([]byte{27, 91, 57, 55, 59, 52, 49, 109})
blue = string([]byte{27, 91, 57, 55, 59, 52, 52, 109})
magenta = string([]byte{27, 91, 57, 55, 59, 52, 53, 109})
cyan = string([]byte{27, 91, 57, 55, 59, 52, 54, 109})
reset = string([]byte{27, 91, 48, 109})
)
// ErrorLogger returns an ErrorLoggerT with parameter gin.ErrorTypeAny
func ErrorLogger() gin.HandlerFunc {
return ErrorLoggerT(gin.ErrorTypeAny)
}
// ErrorLoggerT returns an ErrorLoggerT middleware with the given
// type gin.ErrorType.
func ErrorLoggerT(typ gin.ErrorType) gin.HandlerFunc {
return func(c *gin.Context) {
c.Next()
if !c.Writer.Written() {
json := c.Errors.ByType(typ).JSON()
if json != nil {
c.JSON(-1, json)
}
}
}
}
// Logger prints a logline for each request and measures the time to
// process for a call. It formats the log entries similar to
// http://godoc.org/github.com/gin-gonic/gin#Logger does.
//
// Example:
// router := gin.New()
// router.Use(ginglog.Logger(3 * time.Second))
func Logger(duration time.Duration) gin.HandlerFunc {
setupLogging(duration)
return func(c *gin.Context) {
t := time.Now()
// process request
c.Next()
latency := time.Since(t)
clientIP := c.ClientIP()
method := c.Request.Method
statusCode := c.Writer.Status()
statusColor := colorForStatus(statusCode)
methodColor := colorForMethod(method)
path := c.Request.URL.Path
switch {
case statusCode >= 400 && statusCode <= 499:
{
glog.Warningf("[GIN] |%s %3d %s| %12v | %s |%s %s %-7s %s\n%s",
statusColor, statusCode, reset,
latency,
clientIP,
methodColor, reset, method,
path,
c.Errors.String(),
)
}
case statusCode >= 500:
{
glog.Errorf("[GIN] |%s %3d %s| %12v | %s |%s %s %-7s %s\n%s",
statusColor, statusCode, reset,
latency,
clientIP,
methodColor, reset, method,
path,
c.Errors.String(),
)
}
default:
glog.V(2).Infof("[GIN] |%s %3d %s| %12v | %s |%s %s %-7s %s\n%s",
statusColor, statusCode, reset,
latency,
clientIP,
methodColor, reset, method,
path,
c.Errors.String(),
)
}
}
}
func colorForStatus(code int) string {
switch {
case code >= 200 && code <= 299:
return green
case code >= 300 && code <= 399:
return white
case code >= 400 && code <= 499:
return yellow
default:
return red
}
}
func colorForMethod(method string) string {
switch {
case method == "GET":
return blue
case method == "POST":
return cyan
case method == "PUT":
return yellow
case method == "DELETE":
return red
case method == "PATCH":
return green
case method == "HEAD":
return magenta
case method == "OPTIONS":
return white
default:
return reset
}
}

View File

@ -6,7 +6,7 @@ CUR_DIR=$(shell pwd)
GOPATH=$(CUR_DIR)/build/ GOPATH=$(CUR_DIR)/build/
PARENT_PKG=amuz.es/go/ PARENT_PKG=amuz.es/go/
NAME=wiki NAME=mnemonics
PKG=$(PARENT_PKG)$(NAME) PKG=$(PARENT_PKG)$(NAME)
usage: usage:
@ -34,7 +34,7 @@ test-all:
assets-%: asset/%/ assets-%: asset/%/
@echo "serialize $*" @echo "serialize $*"
@go-bindata -o bind/$*/handler.go -pkg $* -prefix $* -ignore=[.]gitignore -ignore=[.]gitkeep -prefix asset/$*/ $(BINDATA_OPTS) $<... @$(GOPATH)bin/go-bindata -o bind/$*/handler.go -pkg $* -prefix $* -ignore=[.]gitignore -ignore=[.]gitkeep -prefix asset/$*/ $(BINDATA_OPTS) $<...
assets: $(addprefix assets-,${ASSETS}) assets: $(addprefix assets-,${ASSETS})
@ -52,7 +52,7 @@ dependency-restore:
godep restore godep restore
build: setup assets build: assets
godep go build godep go build
@echo "You can now execute ./$(NAME)" @echo "You can now execute ./$(NAME)"
@ -77,3 +77,4 @@ clean:
rm -f ./$(NAME) rm -f ./$(NAME)
rm -rf ./build rm -rf ./build
rm -rf ./bind/* rm -rf ./bind/*

View File

@ -17,10 +17,12 @@ package main
import ( import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/golang/glog" "github.com/golang/glog"
"github.com/zalando-techmonkeys/gin-glog"
"runtime" "runtime"
"time"
"flag" "flag"
"amuz.es/go/wiki/route" "amuz.es/go/mnemonics/route"
"amuz.es/go/wiki/util" "amuz.es/go/mnemonics/util"
"net/http" "net/http"
"github.com/flosch/pongo2" "github.com/flosch/pongo2"
) )
@ -30,9 +32,12 @@ var argPort = flag.Int("port", 8080, "port to listen")
var maxProcs = flag.Int("max_procs", 0, "max number of CPUs that can be used simultaneously. Less than 1 for default (number of cores).") var maxProcs = flag.Int("max_procs", 0, "max number of CPUs that can be used simultaneously. Less than 1 for default (number of cores).")
func main() { func main() {
flag.Parse()
setMaxProcs() setMaxProcs()
r := gin.Default() r := gin.Default()
r.Use(ginglog.Logger(3 * time.Second))
r.Use(gin.Recovery()) r.Use(gin.Recovery())
r.NoRoute(func(c *gin.Context) { r.NoRoute(func(c *gin.Context) {
@ -45,13 +50,16 @@ func main() {
r.GET("/page", route.Page) r.GET("/page", route.Page)
r.GET("/metric", route.Metric) r.GET("/metric", route.Metric)
r.GET("/health", func(c *gin.Context) { r.GET("/health", func(c *gin.Context) {
c.String(200, "OK! - wiki services are fully operational!") c.String(200, "OK! - mnemonics services are fully operational!")
}) })
// Use pongo2gin.Default() for default options or pongo2gin.New() // Use pongo2gin.Default() for default options or pongo2gin.New()
// if you need to use custom RenderOptions. // if you need to use custom RenderOptions.
r.HTMLRender = util.Default() r.HTMLRender = util.Default()
r.GET("/", route.Index) r.GET("/", route.Index)
glog.Info("bootstrapped application")
r.Run() // listen and server on 0.0.0.0:8080 r.Run() // listen and server on 0.0.0.0:8080
} }

View File

@ -4,132 +4,57 @@ import (
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"runtime" "runtime"
"time" "time"
"amuz.es/go/wiki/util" "amuz.es/go/mnemonics/util"
"fmt" "fmt"
) )
func Metric(c *gin.Context) {
updateSystemStatus()
metricInfo:=sysStatus
content := gin.H{
"uptime":metricInfo.Uptime,
"numGoroutine":metricInfo.NumGoroutine,
"memAllocated":metricInfo.MemAllocated,
"memTotal":metricInfo.MemTotal,
"memSys":metricInfo.MemSys,
"lookups":metricInfo.Lookups,
"memMallocs":metricInfo.MemMallocs,
"memFrees":metricInfo.MemFrees,
"heapAlloc":metricInfo.HeapAlloc,
"heapSys":metricInfo.HeapSys,
"heapIdle":metricInfo.HeapIdle,
"heapInuse":metricInfo.HeapInuse,
"heapReleased":metricInfo.HeapReleased,
"heapObjects":metricInfo.HeapObjects,
"stackInuse":metricInfo.StackInuse,
"stackSys":metricInfo.StackSys,
"mSpanInuse":metricInfo.MSpanInuse,
"mSpanSys":metricInfo.MSpanSys,
"mCacheInuse":metricInfo.MCacheInuse,
"mCacheSys":metricInfo.MCacheSys,
"buckHashSys":metricInfo.BuckHashSys,
"gCSys":metricInfo.GCSys,
"otherSys":metricInfo.OtherSys,
"nextGC":metricInfo.NextGC,
"lastGC":metricInfo.LastGC,
"pauseTotalNs":metricInfo.PauseTotalNs,
"pauseNs":metricInfo.PauseNs,
"numGC":metricInfo.NumGC}
c.JSON(200, content)
}
var ( var (
startTime = time.Now() startTime = time.Now()
) )
var sysStatus struct {
Uptime string
NumGoroutine int
// General statistics. func Metric(c *gin.Context) {
MemAllocated string // bytes allocated and still in use memory:=serializeMemoryStat()
MemTotal string // bytes allocated (even if freed) content := gin.H{"memory":memory}
MemSys string // bytes obtained from system (sum of XxxSys below) c.JSON(200, content)
Lookups uint64 // number of pointer lookups
MemMallocs uint64 // number of mallocs
MemFrees uint64 // number of frees
// Main allocation heap statistics.
HeapAlloc string // bytes allocated and still in use
HeapSys string // bytes obtained from system
HeapIdle string // bytes in idle spans
HeapInuse string // bytes in non-idle span
HeapReleased string // bytes released to the OS
HeapObjects uint64 // total number of allocated objects
// Low-level fixed-size structure allocator statistics.
// Inuse is bytes used now.
// Sys is bytes obtained from system.
StackInuse string // bootstrap stacks
StackSys string
MSpanInuse string // mspan structures
MSpanSys string
MCacheInuse string // mcache structures
MCacheSys string
BuckHashSys string // profiling bucket hash table
GCSys string // GC metadata
OtherSys string // other system allocations
// Garbage collector statistics.
NextGC string // next run in HeapAlloc time (bytes)
LastGC string // last run in absolute time (ns)
PauseTotalNs string
PauseNs string // circular buffer of recent GC pause times, most recent at [(NumGC+255)%256]
NumGC uint32
} }
func updateSystemStatus() { func serializeMemoryStat() map[string]interface{} {
sysStatus.Uptime = util.TimeSincePro(startTime)
m := new(runtime.MemStats) m := new(runtime.MemStats)
runtime.ReadMemStats(m) runtime.ReadMemStats(m)
sysStatus.NumGoroutine = runtime.NumGoroutine() return gin.H{
"uptime":util.TimeSincePro(startTime),
"numGoroutine":runtime.NumGoroutine(),
sysStatus.MemAllocated = util.FileSize(int64(m.Alloc)) "memAllocated":util.FileSize(int64(m.Alloc)),
sysStatus.MemTotal = util.FileSize(int64(m.TotalAlloc)) "memTotal":util.FileSize(int64(m.TotalAlloc)),
sysStatus.MemSys = util.FileSize(int64(m.Sys)) "memSys":util.FileSize(int64(m.Sys)),
sysStatus.Lookups = m.Lookups "lookups":m.Lookups,
sysStatus.MemMallocs = m.Mallocs "memMallocs":m.Mallocs,
sysStatus.MemFrees = m.Frees "memFrees":m.Frees,
sysStatus.HeapAlloc = util.FileSize(int64(m.HeapAlloc)) "heapAlloc":util.FileSize(int64(m.HeapAlloc)),
sysStatus.HeapSys = util.FileSize(int64(m.HeapSys)) "heapSys":util.FileSize(int64(m.HeapSys)),
sysStatus.HeapIdle = util.FileSize(int64(m.HeapIdle)) "heapIdle":util.FileSize(int64(m.HeapIdle)),
sysStatus.HeapInuse = util.FileSize(int64(m.HeapInuse)) "heapInuse":util.FileSize(int64(m.HeapInuse)),
sysStatus.HeapReleased = util.FileSize(int64(m.HeapReleased)) "heapReleased":util.FileSize(int64(m.HeapReleased)),
sysStatus.HeapObjects = m.HeapObjects "heapObjects":m.HeapObjects,
sysStatus.StackInuse = util.FileSize(int64(m.StackInuse))
sysStatus.StackSys = util.FileSize(int64(m.StackSys))
sysStatus.MSpanInuse = util.FileSize(int64(m.MSpanInuse))
sysStatus.MSpanSys = util.FileSize(int64(m.MSpanSys))
sysStatus.MCacheInuse = util.FileSize(int64(m.MCacheInuse))
sysStatus.MCacheSys = util.FileSize(int64(m.MCacheSys))
sysStatus.BuckHashSys = util.FileSize(int64(m.BuckHashSys))
sysStatus.GCSys = util.FileSize(int64(m.GCSys))
sysStatus.OtherSys = util.FileSize(int64(m.OtherSys))
sysStatus.NextGC = util.FileSize(int64(m.NextGC)) "stackInuse":util.FileSize(int64(m.StackInuse)),
sysStatus.LastGC = fmt.Sprintf("%.1fs", float64(time.Now().UnixNano()-int64(m.LastGC))/1000/1000/1000) "stackSys":util.FileSize(int64(m.StackSys)),
sysStatus.PauseTotalNs = fmt.Sprintf("%.1fs", float64(m.PauseTotalNs)/1000/1000/1000) "mSpanInuse":util.FileSize(int64(m.MSpanInuse)),
sysStatus.PauseNs = fmt.Sprintf("%.3fs", float64(m.PauseNs[(m.NumGC+255)%256])/1000/1000/1000) "mSpanSys":util.FileSize(int64(m.MSpanSys)),
sysStatus.NumGC = m.NumGC "mCacheInuse":util.FileSize(int64(m.MCacheInuse)),
"mCacheSys":util.FileSize(int64(m.MCacheSys)),
"buckHashSys":util.FileSize(int64(m.BuckHashSys)),
"gCSys":util.FileSize(int64(m.GCSys)),
"otherSys":util.FileSize(int64(m.OtherSys)),
"nextGC":util.FileSize(int64(m.NextGC)),
"lastGC":fmt.Sprintf("%.1fs", float64(time.Now().UnixNano() - int64(m.LastGC)) / 1000 / 1000 / 1000),
"pauseTotalNs":fmt.Sprintf("%.1fs", float64(m.PauseTotalNs) / 1000 / 1000 / 1000),
"pauseNs":fmt.Sprintf("%.3fs", float64(m.PauseNs[(m.NumGC + 255) % 256]) / 1000 / 1000 / 1000),
"numGC":m.NumGC}
} }

View File

@ -2,7 +2,7 @@ package route
import ( import (
assetfs "github.com/elazarl/go-bindata-assetfs" assetfs "github.com/elazarl/go-bindata-assetfs"
"amuz.es/go/wiki/bind/static" "amuz.es/go/mnemonics/bind/static"
"net/http" "net/http"
"strings" "strings"
) )

View File

@ -2,7 +2,7 @@ package util
import ( import (
"net/http" "net/http"
"amuz.es/go/wiki/bind/template" "amuz.es/go/mnemonics/bind/template"
"github.com/flosch/pongo2" "github.com/flosch/pongo2"
"github.com/gin-gonic/gin/render" "github.com/gin-gonic/gin/render"
) )