mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-31 21:28:11 +09:00 
			
		
		
		
	Added all required dependencies
This commit is contained in:
		
							
								
								
									
										191
									
								
								vendor/github.com/go-macaron/toolbox/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								vendor/github.com/go-macaron/toolbox/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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. | ||||
							
								
								
									
										110
									
								
								vendor/github.com/go-macaron/toolbox/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								vendor/github.com/go-macaron/toolbox/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | ||||
| toolbox | ||||
| ======= | ||||
|  | ||||
| Middleware toolbox provides health chcek, pprof, profile and statistic services for [Macaron](https://github.com/go-macaron/macaron). | ||||
|  | ||||
| [API Reference](https://gowalker.org/github.com/go-macaron/toolbox) | ||||
|  | ||||
| ### Installation | ||||
|  | ||||
| 	go get github.com/go-macaron/toolbox | ||||
| 	 | ||||
| ## Usage | ||||
|  | ||||
| ```go | ||||
| // main.go | ||||
| import ( | ||||
| 	"gopkg.in/macaron.v1" | ||||
| 	"github.com/go-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. | ||||
| 	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" | ||||
| 	//... | ||||
| 	"github.com/go-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. | ||||
							
								
								
									
										83
									
								
								vendor/github.com/go-macaron/toolbox/healthcheck.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								vendor/github.com/go-macaron/toolbox/healthcheck.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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() | ||||
| } | ||||
							
								
								
									
										163
									
								
								vendor/github.com/go-macaron/toolbox/profile.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								vendor/github.com/go-macaron/toolbox/profile.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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" | ||||
|  | ||||
| 	"github.com/Unknwon/com" | ||||
| 	"gopkg.in/macaron.v1" | ||||
| ) | ||||
|  | ||||
| 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 "" | ||||
| } | ||||
							
								
								
									
										138
									
								
								vendor/github.com/go-macaron/toolbox/statistic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								vendor/github.com/go-macaron/toolbox/statistic.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -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()) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										154
									
								
								vendor/github.com/go-macaron/toolbox/toolbox.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								vendor/github.com/go-macaron/toolbox/toolbox.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,154 @@ | ||||
| // 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" | ||||
|  | ||||
| 	"gopkg.in/macaron.v1" | ||||
| ) | ||||
|  | ||||
| const _VERSION = "0.1.2" | ||||
|  | ||||
| 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 | ||||
| 	// 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(ctx *macaron.Context) 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.Get(opt.HealthCheckURL, t.handleHealthCheck) | ||||
|  | ||||
| 	// URL map. | ||||
| 	m.Get(opt.URLMapPrefix, func(rw http.ResponseWriter) { | ||||
| 		t.JSON(rw) | ||||
| 	}) | ||||
|  | ||||
| 	// 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)) | ||||
| 	} | ||||
| } | ||||
		Reference in New Issue
	
	Block a user