summaryrefslogtreecommitdiffstats
path: root/vendor/gitea.com/macaron/toolbox
diff options
context:
space:
mode:
authorTamal Saha <tamal@appscode.com>2019-08-23 09:40:30 -0700
committertechknowlogick <techknowlogick@gitea.io>2019-08-23 12:40:29 -0400
commit171b3598778a1ecd0a921c71ed6755bfef68f7f0 (patch)
tree02857629ef9e8e26ee0ee559153f803f77b588b7 /vendor/gitea.com/macaron/toolbox
parentca6fb004ac50fc924861112403895d637c6a2d1d (diff)
downloadgitea-171b3598778a1ecd0a921c71ed6755bfef68f7f0.tar.gz
gitea-171b3598778a1ecd0a921c71ed6755bfef68f7f0.zip
Use gitea forked macaron (#7933)
Signed-off-by: Tamal Saha <tamal@appscode.com>
Diffstat (limited to 'vendor/gitea.com/macaron/toolbox')
-rw-r--r--vendor/gitea.com/macaron/toolbox/.drone.yml9
-rw-r--r--vendor/gitea.com/macaron/toolbox/.gitignore2
-rw-r--r--vendor/gitea.com/macaron/toolbox/LICENSE191
-rw-r--r--vendor/gitea.com/macaron/toolbox/README.md112
-rw-r--r--vendor/gitea.com/macaron/toolbox/go.mod9
-rw-r--r--vendor/gitea.com/macaron/toolbox/go.sum30
-rw-r--r--vendor/gitea.com/macaron/toolbox/healthcheck.go83
-rw-r--r--vendor/gitea.com/macaron/toolbox/profile.go163
-rw-r--r--vendor/gitea.com/macaron/toolbox/statistic.go138
-rw-r--r--vendor/gitea.com/macaron/toolbox/toolbox.go158
10 files changed, 895 insertions, 0 deletions
diff --git a/vendor/gitea.com/macaron/toolbox/.drone.yml b/vendor/gitea.com/macaron/toolbox/.drone.yml
new file mode 100644
index 0000000000..39499f444a
--- /dev/null
+++ b/vendor/gitea.com/macaron/toolbox/.drone.yml
@@ -0,0 +1,9 @@
+kind: pipeline
+name: default
+
+steps:
+- name: test
+ image: golang:1.11
+ commands:
+ - go build -v
+ - go test -v -race -coverprofile=coverage.txt -covermode=atomic
diff --git a/vendor/gitea.com/macaron/toolbox/.gitignore b/vendor/gitea.com/macaron/toolbox/.gitignore
new file mode 100644
index 0000000000..c3265c1186
--- /dev/null
+++ b/vendor/gitea.com/macaron/toolbox/.gitignore
@@ -0,0 +1,2 @@
+profile/
+/.idea
diff --git a/vendor/gitea.com/macaron/toolbox/LICENSE b/vendor/gitea.com/macaron/toolbox/LICENSE
new file mode 100644
index 0000000000..8405e89a0b
--- /dev/null
+++ b/vendor/gitea.com/macaron/toolbox/LICENSE
@@ -0,0 +1,191 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and
+distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright
+owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities
+that control, are controlled by, or are under common control with that entity.
+For the purposes of this definition, "control" means (i) the power, direct or
+indirect, to cause the direction or management of such entity, whether by
+contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
+outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising
+permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including
+but not limited to software source code, documentation source, and configuration
+files.
+
+"Object" form shall mean any form resulting from mechanical transformation or
+translation of a Source form, including but not limited to compiled object code,
+generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made
+available under the License, as indicated by a copyright notice that is included
+in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that
+is based on (or derived from) the Work and for which the editorial revisions,
+annotations, elaborations, or other modifications represent, as a whole, an
+original work of authorship. For the purposes of this License, Derivative Works
+shall not include works that remain separable from, or merely link (or bind by
+name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version
+of the Work and any modifications or additions to that Work or Derivative Works
+thereof, that is intentionally submitted to Licensor for inclusion in the Work
+by the copyright owner or by an individual or Legal Entity authorized to submit
+on behalf of the copyright owner. For the purposes of this definition,
+"submitted" means any form of electronic, verbal, or written communication sent
+to the Licensor or its representatives, including but not limited to
+communication on electronic mailing lists, source code control systems, and
+issue tracking systems that are managed by, or on behalf of, the Licensor for
+the purpose of discussing and improving the Work, but excluding communication
+that is conspicuously marked or otherwise designated in writing by the copyright
+owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
+of whom a Contribution has been received by Licensor and subsequently
+incorporated within the Work.
+
+2. Grant of Copyright License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable copyright license to reproduce, prepare Derivative Works of,
+publicly display, publicly perform, sublicense, and distribute the Work and such
+Derivative Works in Source or Object form.
+
+3. Grant of Patent License.
+
+Subject to the terms and conditions of this License, each Contributor hereby
+grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
+irrevocable (except as stated in this section) patent license to make, have
+made, use, offer to sell, sell, import, and otherwise transfer the Work, where
+such license applies only to those patent claims licensable by such Contributor
+that are necessarily infringed by their Contribution(s) alone or by combination
+of their Contribution(s) with the Work to which such Contribution(s) was
+submitted. If You institute patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Work or a
+Contribution incorporated within the Work constitutes direct or contributory
+patent infringement, then any patent licenses granted to You under this License
+for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution.
+
+You may reproduce and distribute copies of the Work or Derivative Works thereof
+in any medium, with or without modifications, and in Source or Object form,
+provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of
+this License; and
+You must cause any modified files to carry prominent notices stating that You
+changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute,
+all copyright, patent, trademark, and attribution notices from the Source form
+of the Work, excluding those notices that do not pertain to any part of the
+Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any
+Derivative Works that You distribute must include a readable copy of the
+attribution notices contained within such NOTICE file, excluding those notices
+that do not pertain to any part of the Derivative Works, in at least one of the
+following places: within a NOTICE text file distributed as part of the
+Derivative Works; within the Source form or documentation, if provided along
+with the Derivative Works; or, within a display generated by the Derivative
+Works, if and wherever such third-party notices normally appear. The contents of
+the NOTICE file are for informational purposes only and do not modify the
+License. You may add Your own attribution notices within Derivative Works that
+You distribute, alongside or as an addendum to the NOTICE text from the Work,
+provided that such additional attribution notices cannot be construed as
+modifying the License.
+You may add Your own copyright statement to Your modifications and may provide
+additional or different license terms and conditions for use, reproduction, or
+distribution of Your modifications, or for any such Derivative Works as a whole,
+provided Your use, reproduction, and distribution of the Work otherwise complies
+with the conditions stated in this License.
+
+5. Submission of Contributions.
+
+Unless You explicitly state otherwise, any Contribution intentionally submitted
+for inclusion in the Work by You to the Licensor shall be under the terms and
+conditions of this License, without any additional terms or conditions.
+Notwithstanding the above, nothing herein shall supersede or modify the terms of
+any separate license agreement you may have executed with Licensor regarding
+such Contributions.
+
+6. Trademarks.
+
+This License does not grant permission to use the trade names, trademarks,
+service marks, or product names of the Licensor, except as required for
+reasonable and customary use in describing the origin of the Work and
+reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty.
+
+Unless required by applicable law or agreed to in writing, Licensor provides the
+Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
+including, without limitation, any warranties or conditions of TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
+solely responsible for determining the appropriateness of using or
+redistributing the Work and assume any risks associated with Your exercise of
+permissions under this License.
+
+8. Limitation of Liability.
+
+In no event and under no legal theory, whether in tort (including negligence),
+contract, or otherwise, unless required by applicable law (such as deliberate
+and grossly negligent acts) or agreed to in writing, shall any Contributor be
+liable to You for damages, including any direct, indirect, special, incidental,
+or consequential damages of any character arising as a result of this License or
+out of the use or inability to use the Work (including but not limited to
+damages for loss of goodwill, work stoppage, computer failure or malfunction, or
+any and all other commercial damages or losses), even if such Contributor has
+been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability.
+
+While redistributing the Work or Derivative Works thereof, You may choose to
+offer, and charge a fee for, acceptance of support, warranty, indemnity, or
+other liability obligations and/or rights consistent with this License. However,
+in accepting such obligations, You may act only on Your own behalf and on Your
+sole responsibility, not on behalf of any other Contributor, and only if You
+agree to indemnify, defend, and hold each Contributor harmless for any liability
+incurred by, or claims asserted against, such Contributor by reason of your
+accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work
+
+To apply the Apache License to your work, attach the following boilerplate
+notice, with the fields enclosed by brackets "[]" replaced with your own
+identifying information. (Don't include the brackets!) The text should be
+enclosed in the appropriate comment syntax for the file format. We also
+recommend that a file or class name and description of purpose be included on
+the same "printed page" as the copyright notice for easier identification within
+third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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. \ No newline at end of file
diff --git a/vendor/gitea.com/macaron/toolbox/README.md b/vendor/gitea.com/macaron/toolbox/README.md
new file mode 100644
index 0000000000..75055d5f07
--- /dev/null
+++ b/vendor/gitea.com/macaron/toolbox/README.md
@@ -0,0 +1,112 @@
+toolbox
+=======
+
+Middleware toolbox provides health chcek, pprof, profile and statistic services for [Macaron](https://gitea.com/macaron/macaron).
+
+[![Build Status](https://drone.gitea.com/api/badges/macaron/toolbox/status.svg)](https://drone.gitea.com/macaron/toolbox)
+[API Reference](https://gowalker.org/gitea.com/macaron/toolbox)
+
+### Installation
+
+ go get gitea.com/macaron/toolbox
+
+## Usage
+
+```go
+// main.go
+import (
+ "gitea.com/macaron/macaron"
+ "gitea.com/macaron/toolbox"
+)
+
+func main() {
+ m := macaron.Classic()
+ m.Use(toolbox.Toolboxer(m))
+ m.Run()
+}
+```
+
+Open your browser and visit `http://localhost:4000/debug` to see the effects.
+
+## Options
+
+`toolbox.Toolboxer` comes with a variety of configuration options:
+
+```go
+type dummyChecker struct {
+}
+
+func (dc *dummyChecker) Desc() string {
+ return "Dummy checker"
+}
+
+func (dc *dummyChecker) Check() error {
+ return nil
+}
+
+// ...
+m.Use(toolbox.Toolboxer(m, toolbox.Options{
+ URLPrefix: "/debug", // URL prefix for toolbox dashboard
+ HealthCheckURL: "/healthcheck", // URL for health check request
+ HealthCheckers: []HealthChecker{
+ new(dummyChecker),
+ }, // Health checkers
+ HealthCheckFuncs: []*toolbox.HealthCheckFuncDesc{
+ &toolbox.HealthCheckFuncDesc{
+ Desc: "Database connection",
+ Func: func() error { return "OK" },
+ },
+ }, // Health check functions
+ DisableDebug: false, // Turns off all debug functionality when true
+ PprofURLPrefix: "/debug/pprof/", // URL prefix of pprof
+ ProfileURLPrefix: "/debug/profile/", // URL prefix of profile
+ ProfilePath: "profile", // Path store profile files
+}))
+// ...
+```
+
+## Route Statistic
+
+Toolbox also comes with a route call statistic functionality:
+
+```go
+import (
+ "os"
+ "time"
+ //...
+ "gitea.com/macaron/toolbox"
+)
+
+func main() {
+ //...
+ m.Get("/", func(t toolbox.Toolbox) {
+ start := time.Now()
+
+ // Other operations.
+
+ t.AddStatistics("GET", "/", time.Since(start))
+ })
+
+ m.Get("/dump", func(t toolbox.Toolbox) {
+ t.GetMap(os.Stdout)
+ })
+}
+```
+
+Output take from test:
+
+```
++---------------------------------------------------+------------+------------------+------------------+------------------+------------------+------------------+
+| Request URL | Method | Times | Total Used(s) | Max Used(μs) | Min Used(μs) | Avg Used(μs) |
++---------------------------------------------------+------------+------------------+------------------+------------------+------------------+------------------+
+| /api/user | POST | 2 | 0.000122 | 120.000000 | 2.000000 | 61.000000 |
+| /api/user | GET | 1 | 0.000013 | 13.000000 | 13.000000 | 13.000000 |
+| /api/user | DELETE | 1 | 0.000001 | 1.400000 | 1.400000 | 1.400000 |
+| /api/admin | POST | 1 | 0.000014 | 14.000000 | 14.000000 | 14.000000 |
+| /api/user/unknwon | POST | 1 | 0.000012 | 12.000000 | 12.000000 | 12.000000 |
++---------------------------------------------------+------------+------------------+------------------+------------------+------------------+------------------+
+```
+
+## License
+
+This project is under Apache v2 License. See the [LICENSE](LICENSE) file for the full license text. \ No newline at end of file
diff --git a/vendor/gitea.com/macaron/toolbox/go.mod b/vendor/gitea.com/macaron/toolbox/go.mod
new file mode 100644
index 0000000000..f54b8074ca
--- /dev/null
+++ b/vendor/gitea.com/macaron/toolbox/go.mod
@@ -0,0 +1,9 @@
+module gitea.com/macaron/toolbox
+
+go 1.11
+
+require (
+ gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb
+ github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337
+ github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e
+)
diff --git a/vendor/gitea.com/macaron/toolbox/go.sum b/vendor/gitea.com/macaron/toolbox/go.sum
new file mode 100644
index 0000000000..56302b6a5f
--- /dev/null
+++ b/vendor/gitea.com/macaron/toolbox/go.sum
@@ -0,0 +1,30 @@
+gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591 h1:UbCTjPcLrNxR9LzKDjQBMT2zoxZuEnca1pZCpgeMuhQ=
+gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591/go.mod h1:h6E4kLao1Yko6DOU6QDnQPcuoNzvbZqzj2mtPcEn1aM=
+gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb h1:amL0md6orTj1tXY16ANzVU9FmzQB+W7aJwp8pVDbrmA=
+gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb/go.mod h1:0coI+mSPSwbsyAbOuFllVS38awuk9mevhLD52l50Gjs=
+github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
+github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
+github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 h1:Jpy1PXuP99tXNrhbq2BaPz9B+jNAvH1JPQQpG/9GCXY=
+github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
+github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
+github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8=
+github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e h1:GSGeB9EAKY2spCABz6xOX5DbxZEXolK+nBSvmsQwRjM=
+github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
+golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+gopkg.in/ini.v1 v1.44.0 h1:YRJzTUp0kSYWUVFF5XAbDFfyiqwsl0Vb9R8TVP5eRi0=
+gopkg.in/ini.v1 v1.44.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
diff --git a/vendor/gitea.com/macaron/toolbox/healthcheck.go b/vendor/gitea.com/macaron/toolbox/healthcheck.go
new file mode 100644
index 0000000000..25b5bdfe26
--- /dev/null
+++ b/vendor/gitea.com/macaron/toolbox/healthcheck.go
@@ -0,0 +1,83 @@
+// Copyright 2013 Beego Authors
+// Copyright 2014 The Macaron 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 toolbox
+
+import (
+ "bytes"
+)
+
+// HealthChecker represents a health check instance.
+type HealthChecker interface {
+ Desc() string
+ Check() error
+}
+
+// HealthCheckFunc represents a callable function for health check.
+type HealthCheckFunc func() error
+
+// HealthCheckFunc represents a callable function for health check with description.
+type HealthCheckFuncDesc struct {
+ Desc string
+ Func HealthCheckFunc
+}
+
+type healthCheck struct {
+ desc string
+ HealthChecker
+ check HealthCheckFunc // Not nil if add job as a function.
+}
+
+// AddHealthCheck adds new health check job.
+func (t *toolbox) AddHealthCheck(hc HealthChecker) {
+ t.healthCheckJobs = append(t.healthCheckJobs, &healthCheck{
+ HealthChecker: hc,
+ })
+}
+
+// AddHealthCheckFunc adds a function as a new health check job.
+func (t *toolbox) AddHealthCheckFunc(desc string, fn HealthCheckFunc) {
+ t.healthCheckJobs = append(t.healthCheckJobs, &healthCheck{
+ desc: desc,
+ check: fn,
+ })
+}
+
+func (t *toolbox) handleHealthCheck() string {
+ if len(t.healthCheckJobs) == 0 {
+ return "no health check jobs"
+ }
+
+ var buf bytes.Buffer
+ var err error
+ for _, job := range t.healthCheckJobs {
+ buf.WriteString("* ")
+ if job.check != nil {
+ buf.WriteString(job.desc)
+ err = job.check()
+ } else {
+ buf.WriteString(job.Desc())
+ err = job.Check()
+ }
+ buf.WriteString(": ")
+ if err == nil {
+ buf.WriteString("OK")
+ } else {
+ buf.WriteString(err.Error())
+ }
+ buf.WriteString("\n")
+ }
+ return buf.String()
+}
diff --git a/vendor/gitea.com/macaron/toolbox/profile.go b/vendor/gitea.com/macaron/toolbox/profile.go
new file mode 100644
index 0000000000..359a87fde4
--- /dev/null
+++ b/vendor/gitea.com/macaron/toolbox/profile.go
@@ -0,0 +1,163 @@
+// Copyright 2013 Beego Authors
+// Copyright 2014 The Macaron 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 toolbox
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "os"
+ "path"
+ "runtime"
+ "runtime/debug"
+ "runtime/pprof"
+ "time"
+
+ "gitea.com/macaron/macaron"
+ "github.com/unknwon/com"
+)
+
+var (
+ profilePath string
+ pid int
+ startTime = time.Now()
+ inCPUProfile bool
+)
+
+// StartCPUProfile starts CPU profile monitor.
+func StartCPUProfile() error {
+ if inCPUProfile {
+ return errors.New("CPU profile has alreday been started!")
+ }
+ inCPUProfile = true
+
+ os.MkdirAll(profilePath, os.ModePerm)
+ f, err := os.Create(path.Join(profilePath, "cpu-"+com.ToStr(pid)+".pprof"))
+ if err != nil {
+ panic("fail to record CPU profile: " + err.Error())
+ }
+ pprof.StartCPUProfile(f)
+ return nil
+}
+
+// StopCPUProfile stops CPU profile monitor.
+func StopCPUProfile() error {
+ if !inCPUProfile {
+ return errors.New("CPU profile hasn't been started!")
+ }
+ pprof.StopCPUProfile()
+ inCPUProfile = false
+ return nil
+}
+
+func init() {
+ pid = os.Getpid()
+}
+
+// DumpMemProf dumps memory profile in pprof.
+func DumpMemProf(w io.Writer) {
+ pprof.WriteHeapProfile(w)
+}
+
+func dumpMemProf() {
+ os.MkdirAll(profilePath, os.ModePerm)
+ f, err := os.Create(path.Join(profilePath, "mem-"+com.ToStr(pid)+".memprof"))
+ if err != nil {
+ panic("fail to record memory profile: " + err.Error())
+ }
+ runtime.GC()
+ DumpMemProf(f)
+ f.Close()
+}
+
+func avg(items []time.Duration) time.Duration {
+ var sum time.Duration
+ for _, item := range items {
+ sum += item
+ }
+ return time.Duration(int64(sum) / int64(len(items)))
+}
+
+func dumpGC(memStats *runtime.MemStats, gcstats *debug.GCStats, w io.Writer) {
+
+ if gcstats.NumGC > 0 {
+ lastPause := gcstats.Pause[0]
+ elapsed := time.Now().Sub(startTime)
+ overhead := float64(gcstats.PauseTotal) / float64(elapsed) * 100
+ allocatedRate := float64(memStats.TotalAlloc) / elapsed.Seconds()
+
+ fmt.Fprintf(w, "NumGC:%d Pause:%s Pause(Avg):%s Overhead:%3.2f%% Alloc:%s Sys:%s Alloc(Rate):%s/s Histogram:%s %s %s \n",
+ gcstats.NumGC,
+ com.ToStr(lastPause),
+ com.ToStr(avg(gcstats.Pause)),
+ overhead,
+ com.HumaneFileSize(memStats.Alloc),
+ com.HumaneFileSize(memStats.Sys),
+ com.HumaneFileSize(uint64(allocatedRate)),
+ com.ToStr(gcstats.PauseQuantiles[94]),
+ com.ToStr(gcstats.PauseQuantiles[98]),
+ com.ToStr(gcstats.PauseQuantiles[99]))
+ } else {
+ // while GC has disabled
+ elapsed := time.Now().Sub(startTime)
+ allocatedRate := float64(memStats.TotalAlloc) / elapsed.Seconds()
+
+ fmt.Fprintf(w, "Alloc:%s Sys:%s Alloc(Rate):%s/s\n",
+ com.HumaneFileSize(memStats.Alloc),
+ com.HumaneFileSize(memStats.Sys),
+ com.HumaneFileSize(uint64(allocatedRate)))
+ }
+}
+
+// DumpGCSummary dumps GC information to io.Writer
+func DumpGCSummary(w io.Writer) {
+ memStats := &runtime.MemStats{}
+ runtime.ReadMemStats(memStats)
+ gcstats := &debug.GCStats{PauseQuantiles: make([]time.Duration, 100)}
+ debug.ReadGCStats(gcstats)
+
+ dumpGC(memStats, gcstats, w)
+}
+
+func handleProfile(ctx *macaron.Context) string {
+ switch ctx.Query("op") {
+ case "startcpu":
+ if err := StartCPUProfile(); err != nil {
+ return err.Error()
+ }
+ case "stopcpu":
+ if err := StopCPUProfile(); err != nil {
+ return err.Error()
+ }
+ case "mem":
+ dumpMemProf()
+ case "gc":
+ var buf bytes.Buffer
+ DumpGCSummary(&buf)
+ return string(buf.Bytes())
+ default:
+ return fmt.Sprintf(`<p>Available operations:</p>
+<ol>
+ <li><a href="%[1]s?op=startcpu">Start CPU profile</a></li>
+ <li><a href="%[1]s?op=stopcpu">Stop CPU profile</a></li>
+ <li><a href="%[1]s?op=mem">Dump memory profile</a></li>
+ <li><a href="%[1]s?op=gc">Dump GC summary</a></li>
+</ol>`, opt.ProfileURLPrefix)
+ }
+ ctx.Redirect(opt.ProfileURLPrefix)
+ return ""
+}
diff --git a/vendor/gitea.com/macaron/toolbox/statistic.go b/vendor/gitea.com/macaron/toolbox/statistic.go
new file mode 100644
index 0000000000..47e6ab23ee
--- /dev/null
+++ b/vendor/gitea.com/macaron/toolbox/statistic.go
@@ -0,0 +1,138 @@
+// Copyright 2013 Beego Authors
+// Copyright 2014 The Macaron 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 toolbox
+
+import (
+ "encoding/json"
+ "fmt"
+ "io"
+ "strings"
+ "sync"
+ "time"
+)
+
+// Statistics struct
+type Statistics struct {
+ RequestUrl string
+ RequestNum int64
+ MinTime time.Duration
+ MaxTime time.Duration
+ TotalTime time.Duration
+}
+
+// UrlMap contains several statistics struct to log different data
+type UrlMap struct {
+ lock sync.RWMutex
+ LengthLimit int // limit the urlmap's length if it's equal to 0 there's no limit
+ urlmap map[string]map[string]*Statistics
+}
+
+// add statistics task.
+// it needs request method, request url and statistics time duration
+func (m *UrlMap) AddStatistics(requestMethod, requestUrl string, requesttime time.Duration) {
+ m.lock.Lock()
+ defer m.lock.Unlock()
+
+ if method, ok := m.urlmap[requestUrl]; ok {
+ if s, ok := method[requestMethod]; ok {
+ s.RequestNum += 1
+ if s.MaxTime < requesttime {
+ s.MaxTime = requesttime
+ }
+ if s.MinTime > requesttime {
+ s.MinTime = requesttime
+ }
+ s.TotalTime += requesttime
+ } else {
+ nb := &Statistics{
+ RequestUrl: requestUrl,
+ RequestNum: 1,
+ MinTime: requesttime,
+ MaxTime: requesttime,
+ TotalTime: requesttime,
+ }
+ m.urlmap[requestUrl][requestMethod] = nb
+ }
+
+ } else {
+ if m.LengthLimit > 0 && m.LengthLimit <= len(m.urlmap) {
+ return
+ }
+ methodmap := make(map[string]*Statistics)
+ nb := &Statistics{
+ RequestUrl: requestUrl,
+ RequestNum: 1,
+ MinTime: requesttime,
+ MaxTime: requesttime,
+ TotalTime: requesttime,
+ }
+ methodmap[requestMethod] = nb
+ m.urlmap[requestUrl] = methodmap
+ }
+}
+
+// put url statistics result in io.Writer
+func (m *UrlMap) GetMap(w io.Writer) {
+ m.lock.RLock()
+ defer m.lock.RUnlock()
+
+ sep := fmt.Sprintf("+%s+%s+%s+%s+%s+%s+%s+\n", strings.Repeat("-", 51), strings.Repeat("-", 12),
+ strings.Repeat("-", 18), strings.Repeat("-", 18), strings.Repeat("-", 18), strings.Repeat("-", 18), strings.Repeat("-", 18))
+ fmt.Fprintf(w, sep)
+ fmt.Fprintf(w, "| % -50s| % -10s | % -16s | % -16s | % -16s | % -16s | % -16s |\n", "Request URL", "Method", "Times", "Total Used(s)", "Max Used(μs)", "Min Used(μs)", "Avg Used(μs)")
+ fmt.Fprintf(w, sep)
+
+ for k, v := range m.urlmap {
+ for kk, vv := range v {
+ fmt.Fprintf(w, "| % -50s| % -10s | % 16d | % 16f | % 16.6f | % 16.6f | % 16.6f |\n", k,
+ kk, vv.RequestNum, vv.TotalTime.Seconds(), float64(vv.MaxTime.Nanoseconds())/1000,
+ float64(vv.MinTime.Nanoseconds())/1000, float64(time.Duration(int64(vv.TotalTime)/vv.RequestNum).Nanoseconds())/1000,
+ )
+ }
+ }
+ fmt.Fprintf(w, sep)
+}
+
+type URLMapInfo struct {
+ URL string `json:"url"`
+ Method string `json:"method"`
+ Times int64 `json:"times"`
+ TotalUsed float64 `json:"total_used"`
+ MaxUsed float64 `json:"max_used"`
+ MinUsed float64 `json:"min_used"`
+ AvgUsed float64 `json:"avg_used"`
+}
+
+func (m *UrlMap) JSON(w io.Writer) {
+ infos := make([]*URLMapInfo, 0, len(m.urlmap))
+ for k, v := range m.urlmap {
+ for kk, vv := range v {
+ infos = append(infos, &URLMapInfo{
+ URL: k,
+ Method: kk,
+ Times: vv.RequestNum,
+ TotalUsed: vv.TotalTime.Seconds(),
+ MaxUsed: float64(vv.MaxTime.Nanoseconds()) / 1000,
+ MinUsed: float64(vv.MinTime.Nanoseconds()) / 1000,
+ AvgUsed: float64(time.Duration(int64(vv.TotalTime)/vv.RequestNum).Nanoseconds()) / 1000,
+ })
+ }
+ }
+
+ if err := json.NewEncoder(w).Encode(infos); err != nil {
+ panic("URLMap.JSON: " + err.Error())
+ }
+}
diff --git a/vendor/gitea.com/macaron/toolbox/toolbox.go b/vendor/gitea.com/macaron/toolbox/toolbox.go
new file mode 100644
index 0000000000..42e565e45b
--- /dev/null
+++ b/vendor/gitea.com/macaron/toolbox/toolbox.go
@@ -0,0 +1,158 @@
+// Copyright 2014 The Macaron 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 toolbox is a middleware that provides health check, pprof, profile and statistic services for Macaron.
+package toolbox
+
+import (
+ "fmt"
+ "io"
+ "net/http"
+ "net/http/pprof"
+ "path"
+ "time"
+
+ "gitea.com/macaron/macaron"
+)
+
+const _VERSION = "0.1.4"
+
+func Version() string {
+ return _VERSION
+}
+
+// Toolbox represents a tool box service for Macaron instance.
+type Toolbox interface {
+ AddHealthCheck(HealthChecker)
+ AddHealthCheckFunc(string, HealthCheckFunc)
+ AddStatistics(string, string, time.Duration)
+ GetMap(io.Writer)
+ JSON(io.Writer)
+}
+
+type toolbox struct {
+ *UrlMap
+ healthCheckJobs []*healthCheck
+}
+
+// Options represents a struct for specifying configuration options for the Toolbox middleware.
+type Options struct {
+ // URL prefix for toolbox dashboard. Default is "/debug".
+ URLPrefix string
+ // URL for health check request. Default is "/healthcheck".
+ HealthCheckURL string
+ // Health checkers.
+ HealthCheckers []HealthChecker
+ // Health check functions.
+ HealthCheckFuncs []*HealthCheckFuncDesc
+ // URL for URL map json. Default is "/urlmap.json".
+ URLMapPrefix string
+ // DisableDebug turns off all debug functionality.
+ DisableDebug bool
+ // URL prefix of pprof. Default is "/debug/pprof/".
+ PprofURLPrefix string
+ // URL prefix of profile. Default is "/debug/profile/".
+ ProfileURLPrefix string
+ // Path store profile files. Default is "profile".
+ ProfilePath string
+}
+
+var opt Options
+
+func prepareOptions(options []Options) {
+ if len(options) > 0 {
+ opt = options[0]
+ }
+
+ // Defaults.
+ if len(opt.URLPrefix) == 0 {
+ opt.URLPrefix = "/debug"
+ }
+ if len(opt.HealthCheckURL) == 0 {
+ opt.HealthCheckURL = "/healthcheck"
+ }
+ if len(opt.URLMapPrefix) == 0 {
+ opt.URLMapPrefix = "/urlmap.json"
+ }
+ if len(opt.PprofURLPrefix) == 0 {
+ opt.PprofURLPrefix = "/debug/pprof/"
+ } else if opt.PprofURLPrefix[len(opt.PprofURLPrefix)-1] != '/' {
+ opt.PprofURLPrefix += "/"
+ }
+ if len(opt.ProfileURLPrefix) == 0 {
+ opt.ProfileURLPrefix = "/debug/profile/"
+ } else if opt.ProfileURLPrefix[len(opt.ProfileURLPrefix)-1] != '/' {
+ opt.ProfileURLPrefix += "/"
+ }
+ if len(opt.ProfilePath) == 0 {
+ opt.ProfilePath = path.Join(macaron.Root, "profile")
+ }
+}
+
+func dashboard() string {
+ return fmt.Sprintf(`<p>Toolbox Index:</p>
+ <ol>
+ <li><a href="%s">Pprof Information</a></li>
+ <li><a href="%s">Profile Operations</a></li>
+ </ol>`, opt.PprofURLPrefix, opt.ProfileURLPrefix)
+}
+
+var _ Toolbox = &toolbox{}
+
+// Toolboxer is a middleware provides health check, pprof, profile and statistic services for your application.
+func Toolboxer(m *macaron.Macaron, options ...Options) macaron.Handler {
+ prepareOptions(options)
+ t := &toolbox{
+ healthCheckJobs: make([]*healthCheck, 0, len(opt.HealthCheckers)+len(opt.HealthCheckFuncs)),
+ }
+
+ // Dashboard.
+ m.Get(opt.URLPrefix, dashboard)
+
+ // Health check.
+ for _, hc := range opt.HealthCheckers {
+ t.AddHealthCheck(hc)
+ }
+ for _, fd := range opt.HealthCheckFuncs {
+ t.AddHealthCheckFunc(fd.Desc, fd.Func)
+ }
+ m.Route(opt.HealthCheckURL, "HEAD,GET", t.handleHealthCheck)
+
+ // URL map.
+ m.Get(opt.URLMapPrefix, func(rw http.ResponseWriter) {
+ t.JSON(rw)
+ })
+
+ if !opt.DisableDebug {
+ // Pprof
+ m.Any(path.Join(opt.PprofURLPrefix, "cmdline"), pprof.Cmdline)
+ m.Any(path.Join(opt.PprofURLPrefix, "profile"), pprof.Profile)
+ m.Any(path.Join(opt.PprofURLPrefix, "symbol"), pprof.Symbol)
+ m.Any(opt.PprofURLPrefix, pprof.Index)
+ m.Any(path.Join(opt.PprofURLPrefix, "*"), pprof.Index)
+
+ // Profile
+ profilePath = opt.ProfilePath
+ m.Get(opt.ProfileURLPrefix, handleProfile)
+ }
+
+ // Routes statistic.
+ t.UrlMap = &UrlMap{
+ urlmap: make(map[string]map[string]*Statistics),
+ }
+
+ return func(ctx *macaron.Context) {
+ ctx.MapTo(t, (*Toolbox)(nil))
+ }
+}