overdue
This commit is contained in:
202
.rclone_repo/vendor/github.com/pengsrc/go-shared/LICENSE
generated
vendored
Executable file
202
.rclone_repo/vendor/github.com/pengsrc/go-shared/LICENSE
generated
vendored
Executable file
@@ -0,0 +1,202 @@
|
||||
|
||||
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:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) 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
|
||||
|
||||
(d) 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 2017 Jingwen Peng
|
||||
|
||||
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.
|
||||
102
.rclone_repo/vendor/github.com/pengsrc/go-shared/buffer/bytes.go
generated
vendored
Executable file
102
.rclone_repo/vendor/github.com/pengsrc/go-shared/buffer/bytes.go
generated
vendored
Executable file
@@ -0,0 +1,102 @@
|
||||
// Package buffer provides a thin wrapper around a byte slice. Unlike the
|
||||
// standard library's bytes.BytesBuffer, it supports a portion of the strconv
|
||||
// package's zero-allocation formatters.
|
||||
package buffer
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// BytesBuffer is a thin wrapper around a byte slice. It's intended to be
|
||||
// pooled, so the only way to construct one is via a BytesBufferPool.
|
||||
type BytesBuffer struct {
|
||||
bs []byte
|
||||
pool BytesBufferPool
|
||||
}
|
||||
|
||||
// Free returns the BytesBuffer to its BytesBufferPool.
|
||||
// Callers must not retain references to the BytesBuffer after calling Free.
|
||||
func (b *BytesBuffer) Free() {
|
||||
b.pool.put(b)
|
||||
}
|
||||
|
||||
// Len returns the length of the underlying byte slice.
|
||||
func (b *BytesBuffer) Len() int {
|
||||
return len(b.bs)
|
||||
}
|
||||
|
||||
// Cap returns the capacity of the underlying byte slice.
|
||||
func (b *BytesBuffer) Cap() int {
|
||||
return cap(b.bs)
|
||||
}
|
||||
|
||||
// Bytes returns a mutable reference to the underlying byte slice.
|
||||
func (b *BytesBuffer) Bytes() []byte {
|
||||
return b.bs
|
||||
}
|
||||
|
||||
// String returns a string copy of the underlying byte slice.
|
||||
func (b *BytesBuffer) String() string {
|
||||
return string(b.bs)
|
||||
}
|
||||
|
||||
// Reset resets the underlying byte slice. Subsequent writes re-use the slice's
|
||||
// backing array.
|
||||
func (b *BytesBuffer) Reset() {
|
||||
b.bs = b.bs[:0]
|
||||
}
|
||||
|
||||
// Write implements io.Writer.
|
||||
func (b *BytesBuffer) Write(bs []byte) (int, error) {
|
||||
b.bs = append(b.bs, bs...)
|
||||
return len(bs), nil
|
||||
}
|
||||
|
||||
// AppendByte writes a single byte to the BytesBuffer.
|
||||
func (b *BytesBuffer) AppendByte(v byte) {
|
||||
b.bs = append(b.bs, v)
|
||||
}
|
||||
|
||||
// AppendBytes writes bytes to the BytesBuffer.
|
||||
func (b *BytesBuffer) AppendBytes(bs []byte) {
|
||||
b.bs = append(b.bs, bs...)
|
||||
}
|
||||
|
||||
// AppendString writes a string to the BytesBuffer.
|
||||
func (b *BytesBuffer) AppendString(s string) {
|
||||
b.bs = append(b.bs, s...)
|
||||
}
|
||||
|
||||
// AppendInt appends an integer to the underlying buffer (assuming base 10).
|
||||
func (b *BytesBuffer) AppendInt(i int64) {
|
||||
b.bs = strconv.AppendInt(b.bs, i, 10)
|
||||
}
|
||||
|
||||
// AppendUint appends an unsigned integer to the underlying buffer (assuming
|
||||
// base 10).
|
||||
func (b *BytesBuffer) AppendUint(i uint64) {
|
||||
b.bs = strconv.AppendUint(b.bs, i, 10)
|
||||
}
|
||||
|
||||
// AppendFloat appends a float to the underlying buffer. It doesn't quote NaN
|
||||
// or +/- Inf.
|
||||
func (b *BytesBuffer) AppendFloat(f float64, bitSize int) {
|
||||
b.bs = strconv.AppendFloat(b.bs, f, 'f', -1, bitSize)
|
||||
}
|
||||
|
||||
// AppendBool appends a bool to the underlying buffer.
|
||||
func (b *BytesBuffer) AppendBool(v bool) {
|
||||
b.bs = strconv.AppendBool(b.bs, v)
|
||||
}
|
||||
|
||||
// AppendTime appends a time to the underlying buffer.
|
||||
func (b *BytesBuffer) AppendTime(t time.Time, format string) {
|
||||
if format == "" {
|
||||
b.bs = strconv.AppendInt(b.bs, t.Unix(), 10)
|
||||
} else {
|
||||
b.bs = t.AppendFormat(b.bs, format)
|
||||
}
|
||||
}
|
||||
|
||||
const defaultSize = 1024 // Create 1 KiB buffers by default
|
||||
39
.rclone_repo/vendor/github.com/pengsrc/go-shared/buffer/bytes_pool.go
generated
vendored
Executable file
39
.rclone_repo/vendor/github.com/pengsrc/go-shared/buffer/bytes_pool.go
generated
vendored
Executable file
@@ -0,0 +1,39 @@
|
||||
package buffer
|
||||
|
||||
import "sync"
|
||||
|
||||
// A BytesBufferPool is a type-safe wrapper around a sync.BytesBufferPool.
|
||||
type BytesBufferPool struct {
|
||||
p *sync.Pool
|
||||
}
|
||||
|
||||
// NewBytesPool constructs a new BytesBufferPool.
|
||||
func NewBytesPool() BytesBufferPool {
|
||||
return BytesBufferPool{
|
||||
p: &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &BytesBuffer{bs: make([]byte, 0, defaultSize)}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Get retrieves a BytesBuffer from the pool, creating one if necessary.
|
||||
func (p BytesBufferPool) Get() *BytesBuffer {
|
||||
buf := p.p.Get().(*BytesBuffer)
|
||||
buf.Reset()
|
||||
buf.pool = p
|
||||
return buf
|
||||
}
|
||||
|
||||
func (p BytesBufferPool) put(buf *BytesBuffer) {
|
||||
p.p.Put(buf)
|
||||
}
|
||||
|
||||
// GlobalBytesPool returns the global buffer pool.
|
||||
func GlobalBytesPool() *BytesBufferPool {
|
||||
return &bytesPool
|
||||
}
|
||||
|
||||
// bytesPool is a pool of buffer bytes.
|
||||
var bytesPool = NewBytesPool()
|
||||
17
.rclone_repo/vendor/github.com/pengsrc/go-shared/check/dir.go
generated
vendored
Executable file
17
.rclone_repo/vendor/github.com/pengsrc/go-shared/check/dir.go
generated
vendored
Executable file
@@ -0,0 +1,17 @@
|
||||
package check
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// Dir checks the given path, will return error if path not exists or path
|
||||
// is not directory.
|
||||
func Dir(path string) error {
|
||||
if info, err := os.Stat(path); err != nil {
|
||||
return fmt.Errorf(`directory not exists: %s`, path)
|
||||
} else if !info.IsDir() {
|
||||
return fmt.Errorf(`path is not directory: %s`, path)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
37
.rclone_repo/vendor/github.com/pengsrc/go-shared/check/error.go
generated
vendored
Executable file
37
.rclone_repo/vendor/github.com/pengsrc/go-shared/check/error.go
generated
vendored
Executable file
@@ -0,0 +1,37 @@
|
||||
package check
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// ReadableError is just a structure contains readable message that can be
|
||||
// returned directly to end user.
|
||||
type ReadableError struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
// Error returns the description of ReadableError.
|
||||
func (e ReadableError) Error() string {
|
||||
return e.Message
|
||||
}
|
||||
|
||||
// NewReadableError creates a ReadableError{} from given message.
|
||||
func NewReadableError(message string) ReadableError {
|
||||
return ReadableError{Message: message}
|
||||
}
|
||||
|
||||
// ErrorForExit check the error.
|
||||
// If error is not nil, print the error message and exit the application.
|
||||
// If error is nil, do nothing.
|
||||
func ErrorForExit(name string, err error, code ...int) {
|
||||
if err != nil {
|
||||
exitCode := 1
|
||||
if len(code) > 0 {
|
||||
exitCode = code[0]
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "%s: %s (%d)\n", name, err.Error(), exitCode)
|
||||
fmt.Fprintf(os.Stderr, "See \"%s --help\".\n", name)
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
}
|
||||
11
.rclone_repo/vendor/github.com/pengsrc/go-shared/check/host.go
generated
vendored
Executable file
11
.rclone_repo/vendor/github.com/pengsrc/go-shared/check/host.go
generated
vendored
Executable file
@@ -0,0 +1,11 @@
|
||||
package check
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// HostAndPort checks whether a string contains host and port.
|
||||
// It returns true if matched.
|
||||
func HostAndPort(hostAndPort string) bool {
|
||||
return regexp.MustCompile(`^[^:]+:[0-9]+$`).MatchString(hostAndPort)
|
||||
}
|
||||
41
.rclone_repo/vendor/github.com/pengsrc/go-shared/check/slice.go
generated
vendored
Executable file
41
.rclone_repo/vendor/github.com/pengsrc/go-shared/check/slice.go
generated
vendored
Executable file
@@ -0,0 +1,41 @@
|
||||
package check
|
||||
|
||||
// StringSliceContains iterates over the slice to find the target.
|
||||
func StringSliceContains(slice []string, target string) bool {
|
||||
for _, v := range slice {
|
||||
if v == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IntSliceContains iterates over the slice to find the target.
|
||||
func IntSliceContains(slice []int, target int) bool {
|
||||
for _, v := range slice {
|
||||
if v == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Int32SliceContains iterates over the slice to find the target.
|
||||
func Int32SliceContains(slice []int32, target int32) bool {
|
||||
for _, v := range slice {
|
||||
if v == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Int64SliceContains iterates over the slice to find the target.
|
||||
func Int64SliceContains(slice []int64, target int64) bool {
|
||||
for _, v := range slice {
|
||||
if v == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
10
.rclone_repo/vendor/github.com/pengsrc/go-shared/convert/string.go
generated
vendored
Executable file
10
.rclone_repo/vendor/github.com/pengsrc/go-shared/convert/string.go
generated
vendored
Executable file
@@ -0,0 +1,10 @@
|
||||
package convert
|
||||
|
||||
// StringSliceWithConverter converts a list of string using the passed converter function
|
||||
func StringSliceWithConverter(s []string, c func(string) string) []string {
|
||||
out := []string{}
|
||||
for _, i := range s {
|
||||
out = append(out, c(i))
|
||||
}
|
||||
return out
|
||||
}
|
||||
82
.rclone_repo/vendor/github.com/pengsrc/go-shared/convert/time.go
generated
vendored
Executable file
82
.rclone_repo/vendor/github.com/pengsrc/go-shared/convert/time.go
generated
vendored
Executable file
@@ -0,0 +1,82 @@
|
||||
package convert
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pengsrc/go-shared/check"
|
||||
)
|
||||
|
||||
// Supported time layouts
|
||||
const (
|
||||
RFC822 = "Mon, 02 Jan 2006 15:04:05 GMT"
|
||||
ISO8601 = "2006-01-02T15:04:05Z"
|
||||
ISO8601Milli = "2006-01-02T15:04:05.000Z"
|
||||
NGINXTime = "02/Jan/2006:15:04:05 -0700"
|
||||
)
|
||||
|
||||
// TimeToString transforms given time to string.
|
||||
func TimeToString(timeValue time.Time, format string) string {
|
||||
if check.StringSliceContains([]string{RFC822, ISO8601, ISO8601Milli}, format) {
|
||||
timeValue = timeValue.UTC()
|
||||
}
|
||||
return timeValue.Format(format)
|
||||
}
|
||||
|
||||
// StringToTime transforms given string to time.
|
||||
func StringToTime(timeString string, format string) (time.Time, error) {
|
||||
result, err := time.Parse(format, timeString)
|
||||
if timeString != "0001-01-01T00:00:00Z" {
|
||||
zero := time.Time{}
|
||||
if result == zero {
|
||||
err = fmt.Errorf(`failed to parse "%s" like "%s"`, timeString, format)
|
||||
}
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
// TimeToTimestamp transforms given time to unix time int.
|
||||
func TimeToTimestamp(t time.Time) int64 {
|
||||
zero := time.Time{}
|
||||
if t == zero {
|
||||
t = time.Unix(0, 0).UTC()
|
||||
}
|
||||
return t.Unix()
|
||||
}
|
||||
|
||||
// TimestampToTime transforms given unix time int64 to time in UTC.
|
||||
func TimestampToTime(unix int64) time.Time {
|
||||
return time.Unix(unix, 0).UTC()
|
||||
}
|
||||
|
||||
// TimestampToTimePointer transforms given unix time int64 to time pointer in UTC.
|
||||
func TimestampToTimePointer(unix int64) *time.Time {
|
||||
if unix == 0 {
|
||||
return nil
|
||||
}
|
||||
t := time.Unix(unix, 0).UTC()
|
||||
return &t
|
||||
}
|
||||
|
||||
// TimePointerToTimestamp transforms given time pointer to unix time int64.
|
||||
func TimePointerToTimestamp(t *time.Time) int64 {
|
||||
if t == nil {
|
||||
return 0
|
||||
}
|
||||
return t.Unix()
|
||||
}
|
||||
|
||||
// StringToTimestamp transforms given string to unix time int64. It will
|
||||
// return -1 when time string parse error.
|
||||
func StringToTimestamp(timeString string, format string) int64 {
|
||||
t, err := StringToTime(timeString, format)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return t.Unix()
|
||||
}
|
||||
|
||||
// TimestampToString converts unix timestamp to formatted string.
|
||||
func TimestampToString(unix int64, format string) string {
|
||||
return TimeToString(time.Unix(unix, 0).UTC(), format)
|
||||
}
|
||||
550
.rclone_repo/vendor/github.com/pengsrc/go-shared/convert/types.go
generated
vendored
Executable file
550
.rclone_repo/vendor/github.com/pengsrc/go-shared/convert/types.go
generated
vendored
Executable file
@@ -0,0 +1,550 @@
|
||||
package convert
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// String returns a pointer to the given string value.
|
||||
func String(v string) *string {
|
||||
return &v
|
||||
}
|
||||
|
||||
// StringValue returns the value of the given string pointer or
|
||||
// "" if the pointer is nil.
|
||||
func StringValue(v *string) string {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// StringSlice converts a slice of string values into a slice of
|
||||
// string pointers.
|
||||
func StringSlice(src []string) []*string {
|
||||
dst := make([]*string, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// StringValueSlice converts a slice of string pointers into a slice of
|
||||
// string values.
|
||||
func StringValueSlice(src []*string) []string {
|
||||
dst := make([]string, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// StringMap converts a string map of string values into a string
|
||||
// map of string pointers.
|
||||
func StringMap(src map[string]string) map[string]*string {
|
||||
dst := make(map[string]*string)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// StringValueMap converts a string map of string pointers into a string
|
||||
// map of string values.
|
||||
func StringValueMap(src map[string]*string) map[string]string {
|
||||
dst := make(map[string]string)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Bool returns a pointer to the given bool value.
|
||||
func Bool(v bool) *bool {
|
||||
return &v
|
||||
}
|
||||
|
||||
// BoolValue returns the value of the given bool pointer or
|
||||
// false if the pointer is nil.
|
||||
func BoolValue(v *bool) bool {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// BoolSlice converts a slice of bool values into a slice of
|
||||
// bool pointers.
|
||||
func BoolSlice(src []bool) []*bool {
|
||||
dst := make([]*bool, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// BoolValueSlice converts a slice of bool pointers into a slice of
|
||||
// bool values.
|
||||
func BoolValueSlice(src []*bool) []bool {
|
||||
dst := make([]bool, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// BoolMap converts a string map of bool values into a string
|
||||
// map of bool pointers.
|
||||
func BoolMap(src map[string]bool) map[string]*bool {
|
||||
dst := make(map[string]*bool)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// BoolValueMap converts a string map of bool pointers into a string
|
||||
// map of bool values.
|
||||
func BoolValueMap(src map[string]*bool) map[string]bool {
|
||||
dst := make(map[string]bool)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int returns a pointer to the given int value.
|
||||
func Int(v int) *int {
|
||||
return &v
|
||||
}
|
||||
|
||||
// IntValue returns the value of the given int pointer or
|
||||
// 0 if the pointer is nil.
|
||||
func IntValue(v *int) int {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// IntSlice converts a slice of int values into a slice of
|
||||
// int pointers.
|
||||
func IntSlice(src []int) []*int {
|
||||
dst := make([]*int, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// IntValueSlice converts a slice of int pointers into a slice of
|
||||
// int values.
|
||||
func IntValueSlice(src []*int) []int {
|
||||
dst := make([]int, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// IntMap converts a string map of int values into a string
|
||||
// map of int pointers.
|
||||
func IntMap(src map[string]int) map[string]*int {
|
||||
dst := make(map[string]*int)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// IntValueMap converts a string map of int pointers into a string
|
||||
// map of int values.
|
||||
func IntValueMap(src map[string]*int) map[string]int {
|
||||
dst := make(map[string]int)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int32 returns a pointer to the given int32 value.
|
||||
func Int32(v int32) *int32 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Int32Value returns the value of the given int32 pointer or
|
||||
// 0 if the pointer is nil.
|
||||
func Int32Value(v *int32) int32 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Int32Slice converts a slice of int32 values into a slice of
|
||||
// int32 pointers.
|
||||
func Int32Slice(src []int32) []*int32 {
|
||||
dst := make([]*int32, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int32ValueSlice converts a slice of int32 pointers into a slice of
|
||||
// int32 values.
|
||||
func Int32ValueSlice(src []*int32) []int32 {
|
||||
dst := make([]int32, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int32Map converts a string map of int32 values into a string
|
||||
// map of int32 pointers.
|
||||
func Int32Map(src map[string]int32) map[string]*int32 {
|
||||
dst := make(map[string]*int32)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int32ValueMap converts a string map of int32 pointers into a string
|
||||
// map of int32 values.
|
||||
func Int32ValueMap(src map[string]*int32) map[string]int32 {
|
||||
dst := make(map[string]int32)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int64 returns a pointer to the given int64 value.
|
||||
func Int64(v int64) *int64 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Int64Value returns the value of the given int64 pointer or
|
||||
// 0 if the pointer is nil.
|
||||
func Int64Value(v *int64) int64 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Int64Slice converts a slice of int64 values into a slice of
|
||||
// int64 pointers.
|
||||
func Int64Slice(src []int64) []*int64 {
|
||||
dst := make([]*int64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int64ValueSlice converts a slice of int64 pointers into a slice of
|
||||
// int64 values.
|
||||
func Int64ValueSlice(src []*int64) []int64 {
|
||||
dst := make([]int64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int64Map converts a string map of int64 values into a string
|
||||
// map of int64 pointers.
|
||||
func Int64Map(src map[string]int64) map[string]*int64 {
|
||||
dst := make(map[string]*int64)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int64ValueMap converts a string map of int64 pointers into a string
|
||||
// map of int64 values.
|
||||
func Int64ValueMap(src map[string]*int64) map[string]int64 {
|
||||
dst := make(map[string]int64)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int64Uint returns a uint pointer to the given int64 value.
|
||||
func Int64Uint(src int64) *uint {
|
||||
dst := uint(src)
|
||||
return &dst
|
||||
}
|
||||
|
||||
// Uint8 return a uint8 pointer to the given uint8 value.
|
||||
func Uint8(src uint8) *uint8 {
|
||||
dst := uint8(src)
|
||||
return &dst
|
||||
}
|
||||
|
||||
// Uint8Value returns the value of the given uint8 pointer or
|
||||
// 0 if the pointer is nil.
|
||||
func Uint8Value(v *uint8) uint8 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Uint32 return a uint32 pointer to the given uint32 value.
|
||||
func Uint32(src uint32) *uint32 {
|
||||
dst := uint32(src)
|
||||
return &dst
|
||||
}
|
||||
|
||||
// Uint32Value returns the value of the given uint32 pointer or
|
||||
// 0 if the pointer is nil.
|
||||
func Uint32Value(v *uint32) uint32 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Uint64 return a uint64 pointer to the given uint64 value.
|
||||
func Uint64(src uint64) *uint64 {
|
||||
dst := uint64(src)
|
||||
return &dst
|
||||
}
|
||||
|
||||
// Uint64Value returns the value of the given uint64 pointer or
|
||||
// 0 if the pointer is nil.
|
||||
func Uint64Value(v *uint64) uint64 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Uint64Slice converts a slice of uint64 values into a slice of
|
||||
// uint64 pointers.
|
||||
func Uint64Slice(src []uint64) []*uint64 {
|
||||
dst := make([]*uint64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Uint64ValueSlice converts a slice of uint64 pointers into a slice of
|
||||
// uint64 values.
|
||||
func Uint64ValueSlice(src []*uint64) []uint64 {
|
||||
dst := make([]uint64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float32 returns a pointer to the given float32 value.
|
||||
func Float32(v float32) *float32 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Float32Value returns the value of the given float32 pointer or
|
||||
// 0 if the pointer is nil.
|
||||
func Float32Value(v *float32) float32 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Float32Slice converts a slice of float32 values into a slice of
|
||||
// float32 pointers.
|
||||
func Float32Slice(src []float32) []*float32 {
|
||||
dst := make([]*float32, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float32ValueSlice converts a slice of float32 pointers into a slice of
|
||||
// float32 values.
|
||||
func Float32ValueSlice(src []*float32) []float32 {
|
||||
dst := make([]float32, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float32Map converts a string map of float32 values into a string
|
||||
// map of float32 pointers.
|
||||
func Float32Map(src map[string]float32) map[string]*float32 {
|
||||
dst := make(map[string]*float32)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float32ValueMap converts a string map of float32 pointers into a string
|
||||
// map of float32 values.
|
||||
func Float32ValueMap(src map[string]*float32) map[string]float32 {
|
||||
dst := make(map[string]float32)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float64 returns a pointer to the given float64 value.
|
||||
func Float64(v float64) *float64 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Float64Value returns the value of the given float64 pointer or
|
||||
// 0 if the pointer is nil.
|
||||
func Float64Value(v *float64) float64 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Float64Slice converts a slice of float64 values into a slice of
|
||||
// float64 pointers.
|
||||
func Float64Slice(src []float64) []*float64 {
|
||||
dst := make([]*float64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float64ValueSlice converts a slice of float64 pointers into a slice of
|
||||
// float64 values.
|
||||
func Float64ValueSlice(src []*float64) []float64 {
|
||||
dst := make([]float64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float64Map converts a string map of float64 values into a string
|
||||
// map of float64 pointers.
|
||||
func Float64Map(src map[string]float64) map[string]*float64 {
|
||||
dst := make(map[string]*float64)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float64ValueMap converts a string map of float64 pointers into a string
|
||||
// map of float64 values.
|
||||
func Float64ValueMap(src map[string]*float64) map[string]float64 {
|
||||
dst := make(map[string]float64)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Time returns a pointer to the given time.Time value.
|
||||
func Time(v time.Time) *time.Time {
|
||||
return &v
|
||||
}
|
||||
|
||||
// TimeValue returns the value of the given time.Time pointer or
|
||||
// time.Time{} if the pointer is nil.
|
||||
func TimeValue(v *time.Time) time.Time {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
// TimeSlice converts a slice of time.Time values into a slice of
|
||||
// time.Time pointers.
|
||||
func TimeSlice(src []time.Time) []*time.Time {
|
||||
dst := make([]*time.Time, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// TimeValueSlice converts a slice of time.Time pointers into a slice of
|
||||
// time.Time values.
|
||||
func TimeValueSlice(src []*time.Time) []time.Time {
|
||||
dst := make([]time.Time, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// TimeMap converts a string map of time.Time values into a string
|
||||
// map of time.Time pointers.
|
||||
func TimeMap(src map[string]time.Time) map[string]*time.Time {
|
||||
dst := make(map[string]*time.Time)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// TimeValueMap converts a string map of time.Time pointers into a string
|
||||
// map of time.Time values.
|
||||
func TimeValueMap(src map[string]*time.Time) map[string]time.Time {
|
||||
dst := make(map[string]time.Time)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
460
.rclone_repo/vendor/github.com/pengsrc/go-shared/log/event.go
generated
vendored
Executable file
460
.rclone_repo/vendor/github.com/pengsrc/go-shared/log/event.go
generated
vendored
Executable file
@@ -0,0 +1,460 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/pengsrc/go-shared/buffer"
|
||||
"github.com/pengsrc/go-shared/convert"
|
||||
)
|
||||
|
||||
// A EventCallerPool is a type-safe wrapper around a sync.BytesBufferPool.
|
||||
type EventCallerPool struct {
|
||||
p *sync.Pool
|
||||
}
|
||||
|
||||
// NewEventCallerPool constructs a new BytesBufferPool.
|
||||
func NewEventCallerPool() EventCallerPool {
|
||||
return EventCallerPool{
|
||||
p: &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &EventCaller{}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Get retrieves a EventCaller from the pool, creating one if necessary.
|
||||
func (p EventCallerPool) Get() *EventCaller {
|
||||
e := p.p.Get().(*EventCaller)
|
||||
|
||||
e.pool = p
|
||||
|
||||
e.Defined = false
|
||||
e.PC = 0
|
||||
e.File = ""
|
||||
e.Line = 0
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
func (p EventCallerPool) put(caller *EventCaller) {
|
||||
p.p.Put(caller)
|
||||
}
|
||||
|
||||
// EventCaller represents the caller of a logging function.
|
||||
type EventCaller struct {
|
||||
pool EventCallerPool
|
||||
|
||||
Defined bool
|
||||
PC uintptr
|
||||
File string
|
||||
Line int
|
||||
}
|
||||
|
||||
// Free returns the EventCaller to its EventCallerPool.
|
||||
// Callers must not retain references to the EventCaller after calling Free.
|
||||
func (ec *EventCaller) Free() {
|
||||
ec.pool.put(ec)
|
||||
}
|
||||
|
||||
// String returns the full path and line number of the caller.
|
||||
func (ec EventCaller) String() string {
|
||||
return ec.FullPath()
|
||||
}
|
||||
|
||||
// FullPath returns a /full/path/to/package/file:line description of the
|
||||
// caller.
|
||||
func (ec EventCaller) FullPath() string {
|
||||
if !ec.Defined {
|
||||
return "undefined"
|
||||
}
|
||||
buf := buffer.GlobalBytesPool().Get()
|
||||
defer buf.Free()
|
||||
buf.AppendString(ec.File)
|
||||
buf.AppendByte(':')
|
||||
buf.AppendInt(int64(ec.Line))
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// TrimmedPath returns a package/file:line description of the caller,
|
||||
// preserving only the leaf directory name and file name.
|
||||
func (ec EventCaller) TrimmedPath() string {
|
||||
if !ec.Defined {
|
||||
return "undefined"
|
||||
}
|
||||
// nb. To make sure we trim the path correctly on Windows too, we
|
||||
// counter-intuitively need to use '/' and *not* os.PathSeparator here,
|
||||
// because the path given originates from Go stdlib, specifically
|
||||
// runtime.Caller() which (as of Mar/17) returns forward slashes even on
|
||||
// Windows.
|
||||
//
|
||||
// See https://github.com/golang/go/issues/3335
|
||||
// and https://github.com/golang/go/issues/18151
|
||||
//
|
||||
// for discussion on the issue on Go side.
|
||||
//
|
||||
// Find the last separator.
|
||||
//
|
||||
idx := strings.LastIndexByte(ec.File, '/')
|
||||
if idx == -1 {
|
||||
return ec.FullPath()
|
||||
}
|
||||
// Find the penultimate separator.
|
||||
idx = strings.LastIndexByte(ec.File[:idx], '/')
|
||||
if idx == -1 {
|
||||
return ec.FullPath()
|
||||
}
|
||||
buf := buffer.GlobalBytesPool().Get()
|
||||
defer buf.Free()
|
||||
// Keep everything after the penultimate separator.
|
||||
buf.AppendString(ec.File[idx+1:])
|
||||
buf.AppendByte(':')
|
||||
buf.AppendInt(int64(ec.Line))
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// A EventPool is a type-safe wrapper around a sync.BytesBufferPool.
|
||||
type EventPool struct {
|
||||
p *sync.Pool
|
||||
}
|
||||
|
||||
// NewEventPool constructs a new BytesBufferPool.
|
||||
func NewEventPool() EventPool {
|
||||
return EventPool{
|
||||
p: &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return &Event{}
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Get retrieves a Event from the pool, creating one if necessary.
|
||||
func (p EventPool) Get() *Event {
|
||||
e := p.p.Get().(*Event)
|
||||
|
||||
e.buffer = buffer.GlobalBytesPool().Get()
|
||||
e.pool = p
|
||||
|
||||
e.level = MuteLevel
|
||||
e.lw = nil
|
||||
|
||||
e.ctx = nil
|
||||
e.ctxKeys = nil
|
||||
|
||||
e.isEnabled = false
|
||||
e.isCallerEnabled = false
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
func (p EventPool) put(event *Event) {
|
||||
event.buffer.Free()
|
||||
|
||||
event.ctx = nil
|
||||
event.ctxKeys = nil
|
||||
|
||||
p.p.Put(event)
|
||||
}
|
||||
|
||||
// Event represents a log event. It is instanced by one of the with method of
|
||||
// logger and finalized by the log method such as Debug().
|
||||
type Event struct {
|
||||
buffer *buffer.BytesBuffer
|
||||
pool EventPool
|
||||
|
||||
level Level
|
||||
lw LevelWriter
|
||||
|
||||
ctx context.Context
|
||||
ctxKeys *[]interface{}
|
||||
ctxKeysMap *map[interface{}]string
|
||||
|
||||
isEnabled bool
|
||||
isCallerEnabled bool
|
||||
}
|
||||
|
||||
// Free returns the Event to its EventPool.
|
||||
// Callers must not retain references to the Event after calling Free.
|
||||
func (e *Event) Free() {
|
||||
e.pool.put(e)
|
||||
}
|
||||
|
||||
// Message writes the *Event to level writer.
|
||||
//
|
||||
// NOTICE: Once this method is called, the *Event should be disposed.
|
||||
// Calling twice can have unexpected result.
|
||||
func (e *Event) Message(message string) {
|
||||
if !e.isEnabled {
|
||||
return
|
||||
}
|
||||
e.write(message)
|
||||
}
|
||||
|
||||
// Messagef writes the *Event to level writer.
|
||||
//
|
||||
// NOTICE: Once this method is called, the *Event should be disposed.
|
||||
// Calling twice can have unexpected result.
|
||||
func (e *Event) Messagef(format string, v ...interface{}) {
|
||||
if !e.isEnabled {
|
||||
return
|
||||
}
|
||||
e.write(format, v...)
|
||||
}
|
||||
|
||||
// Byte appends string key and byte value to event.
|
||||
func (e *Event) Byte(key string, value byte) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendByte(value) })
|
||||
}
|
||||
|
||||
// Bytes appends string key and bytes value to event.
|
||||
func (e *Event) Bytes(key string, value []byte) *Event {
|
||||
return e.appendField(key, func() {
|
||||
if needsQuote(string(value)) {
|
||||
e.buffer.AppendString(strconv.Quote(string(value)))
|
||||
} else {
|
||||
e.buffer.AppendBytes(value)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// String appends string key and string value to event.
|
||||
func (e *Event) String(key string, value string) *Event {
|
||||
return e.appendField(key, func() {
|
||||
if needsQuote(string(value)) {
|
||||
e.buffer.AppendString(strconv.Quote(value))
|
||||
} else {
|
||||
e.buffer.AppendString(value)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Int appends string key and int value to event.
|
||||
func (e *Event) Int(key string, value int) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendInt(int64(value)) })
|
||||
}
|
||||
|
||||
// Int32 appends string key and int32 value to event.
|
||||
func (e *Event) Int32(key string, value int32) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendInt(int64(value)) })
|
||||
}
|
||||
|
||||
// Int64 appends string key and int64 value to event.
|
||||
func (e *Event) Int64(key string, value int64) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendInt(value) })
|
||||
}
|
||||
|
||||
// Uint appends string key and uint value to event.
|
||||
func (e *Event) Uint(key string, value uint) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendUint(uint64(value)) })
|
||||
}
|
||||
|
||||
// Uint32 appends string key and uint32 value to event.
|
||||
func (e *Event) Uint32(key string, value uint32) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendUint(uint64(value)) })
|
||||
}
|
||||
|
||||
// Uint64 appends string key and uint64 value to event.
|
||||
func (e *Event) Uint64(key string, value uint64) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendUint(value) })
|
||||
}
|
||||
|
||||
// Float32 appends string key and float32 value to event.
|
||||
func (e *Event) Float32(key string, value float32) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendFloat(float64(value), 32) })
|
||||
}
|
||||
|
||||
// Float64 appends string key and float value to event.
|
||||
func (e *Event) Float64(key string, value float64) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendFloat(value, 64) })
|
||||
}
|
||||
|
||||
// Bool appends string key and bool value to event.
|
||||
func (e *Event) Bool(key string, value bool) *Event {
|
||||
return e.appendField(key, func() { e.buffer.AppendBool(value) })
|
||||
}
|
||||
|
||||
// Time appends string key and time value to event.
|
||||
func (e *Event) Time(key string, value time.Time, format string) *Event {
|
||||
buf := buffer.GlobalBytesPool().Get()
|
||||
defer buf.Free()
|
||||
|
||||
buf.AppendTime(value, format)
|
||||
return e.Bytes(key, buf.Bytes())
|
||||
}
|
||||
|
||||
// Error appends string key and error value to event.
|
||||
func (e *Event) Error(key string, err error) *Event {
|
||||
return e.String(key, err.Error())
|
||||
}
|
||||
|
||||
// Interface appends string key and interface value to event.
|
||||
func (e *Event) Interface(key string, value interface{}) *Event {
|
||||
switch v := value.(type) {
|
||||
case byte:
|
||||
e.Byte(key, v)
|
||||
case []byte:
|
||||
e.Bytes(key, v)
|
||||
case string:
|
||||
e.String(key, v)
|
||||
case int:
|
||||
e.Int(key, v)
|
||||
case int32:
|
||||
e.Int32(key, v)
|
||||
case int64:
|
||||
e.Int64(key, v)
|
||||
case uint:
|
||||
e.Uint(key, v)
|
||||
case uint32:
|
||||
e.Uint32(key, v)
|
||||
case uint64:
|
||||
e.Uint64(key, v)
|
||||
case float32:
|
||||
e.Float32(key, v)
|
||||
case float64:
|
||||
e.Float64(key, v)
|
||||
case bool:
|
||||
e.Bool(key, v)
|
||||
case time.Time:
|
||||
e.Time(key, v, convert.ISO8601Milli)
|
||||
case error:
|
||||
e.Error(key, v)
|
||||
case nil:
|
||||
e.String(key, "nil")
|
||||
default:
|
||||
panic(fmt.Sprintf("unknown field type: %v", value))
|
||||
}
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Event) appendField(key string, appendFunc func()) *Event {
|
||||
if !e.isEnabled {
|
||||
return e
|
||||
}
|
||||
|
||||
// Ignore field with empty key.
|
||||
if len(key) <= 0 {
|
||||
return e
|
||||
}
|
||||
|
||||
// Append space if event field not empty.
|
||||
if e.buffer.Len() != 0 {
|
||||
e.buffer.AppendByte(' ')
|
||||
}
|
||||
|
||||
e.buffer.AppendString(key)
|
||||
e.buffer.AppendString("=")
|
||||
|
||||
appendFunc()
|
||||
return e
|
||||
}
|
||||
|
||||
func (e *Event) write(format string, v ...interface{}) {
|
||||
defer e.Free()
|
||||
|
||||
if !e.isEnabled {
|
||||
return
|
||||
}
|
||||
|
||||
// Append interested contexts.
|
||||
if e.ctx != nil && e.ctxKeys != nil && e.ctxKeysMap != nil {
|
||||
for _, key := range *e.ctxKeys {
|
||||
if value := e.ctx.Value(key); value != nil {
|
||||
e.Interface((*e.ctxKeysMap)[key], e.ctx.Value(key))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Append caller.
|
||||
if e.isCallerEnabled {
|
||||
ec := newEventCaller(runtime.Caller(callerSkipOffset))
|
||||
e.String("source", ec.TrimmedPath())
|
||||
}
|
||||
|
||||
// Compose and store current log.
|
||||
buf := buffer.GlobalBytesPool().Get()
|
||||
defer buf.Free()
|
||||
|
||||
// Format print message.
|
||||
if format != "" {
|
||||
if len(v) == 0 {
|
||||
fmt.Fprint(buf, format)
|
||||
} else {
|
||||
fmt.Fprintf(buf, format, v...)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprint(buf, v...)
|
||||
}
|
||||
|
||||
// Append filed.
|
||||
buf.AppendByte(' ')
|
||||
buf.AppendBytes(e.buffer.Bytes())
|
||||
|
||||
// Finally write.
|
||||
if _, err := e.lw.WriteLevel(e.level, buf.Bytes()); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "log: could not write event: %v", err)
|
||||
}
|
||||
|
||||
switch e.level {
|
||||
case PanicLevel:
|
||||
panic(buf.String())
|
||||
case FatalLevel:
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func newEventCaller(pc uintptr, file string, line int, ok bool) (ec *EventCaller) {
|
||||
ec = eventCallerPool.Get()
|
||||
|
||||
if ok {
|
||||
ec.PC = pc
|
||||
ec.File = file
|
||||
ec.Line = line
|
||||
ec.Defined = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func newEvent(
|
||||
ctx context.Context,
|
||||
ctxKeys *[]interface{}, ctxKeysMap *map[interface{}]string,
|
||||
level Level, lw LevelWriter,
|
||||
isEnabled bool, isCallerEnabled bool,
|
||||
) (e *Event) {
|
||||
e = eventPool.Get()
|
||||
|
||||
e.level = level
|
||||
e.lw = lw
|
||||
|
||||
e.ctx = ctx
|
||||
e.ctxKeys = ctxKeys
|
||||
e.ctxKeysMap = ctxKeysMap
|
||||
|
||||
e.isEnabled = isEnabled
|
||||
e.isCallerEnabled = isCallerEnabled
|
||||
return
|
||||
}
|
||||
|
||||
func needsQuote(s string) bool {
|
||||
for i := range s {
|
||||
if s[i] < 0x20 || s[i] > 0x7e || s[i] == ' ' || s[i] == '\\' || s[i] == '"' {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const callerSkipOffset = 2
|
||||
|
||||
// eventCallerPool is a pool of newEvent callers.
|
||||
var eventCallerPool = NewEventCallerPool()
|
||||
|
||||
// eventPool is a pool of events.
|
||||
var eventPool = NewEventPool()
|
||||
151
.rclone_repo/vendor/github.com/pengsrc/go-shared/log/exported.go
generated
vendored
Executable file
151
.rclone_repo/vendor/github.com/pengsrc/go-shared/log/exported.go
generated
vendored
Executable file
@@ -0,0 +1,151 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// Fatal logs a message with severity FATAL followed by a call to os.Exit(1).
|
||||
func Fatal(ctx context.Context, v ...interface{}) {
|
||||
if globalLogger != nil {
|
||||
globalLogger.event(ctx, FatalLevel).write("", v...)
|
||||
}
|
||||
}
|
||||
|
||||
// Panic logs a message with severity PANIC followed by a call to panic().
|
||||
func Panic(ctx context.Context, v ...interface{}) {
|
||||
if globalLogger != nil {
|
||||
globalLogger.event(ctx, PanicLevel).write("", v...)
|
||||
}
|
||||
}
|
||||
|
||||
// Error logs a message with severity ERROR.
|
||||
func Error(ctx context.Context, v ...interface{}) {
|
||||
if globalLogger != nil {
|
||||
globalLogger.event(ctx, ErrorLevel).write("", v...)
|
||||
}
|
||||
}
|
||||
|
||||
// Warn logs a message with severity WARN.
|
||||
func Warn(ctx context.Context, v ...interface{}) {
|
||||
if globalLogger != nil {
|
||||
globalLogger.event(ctx, WarnLevel).write("", v...)
|
||||
}
|
||||
}
|
||||
|
||||
// Info logs a message with severity INFO.
|
||||
func Info(ctx context.Context, v ...interface{}) {
|
||||
if globalLogger != nil {
|
||||
globalLogger.event(ctx, InfoLevel).write("", v...)
|
||||
}
|
||||
}
|
||||
|
||||
// Debug logs a message with severity DEBUG.
|
||||
func Debug(ctx context.Context, v ...interface{}) {
|
||||
if globalLogger != nil {
|
||||
globalLogger.event(ctx, DebugLevel).write("", v...)
|
||||
}
|
||||
}
|
||||
|
||||
// Fatalf logs a message with severity FATAL in format followed by a call to
|
||||
// os.Exit(1).
|
||||
func Fatalf(ctx context.Context, format string, v ...interface{}) {
|
||||
if globalLogger != nil {
|
||||
globalLogger.event(ctx, FatalLevel).write(format, v...)
|
||||
}
|
||||
}
|
||||
|
||||
// Panicf logs a message with severity PANIC in format followed by a call to
|
||||
// panic().
|
||||
func Panicf(ctx context.Context, format string, v ...interface{}) {
|
||||
if globalLogger != nil {
|
||||
globalLogger.event(ctx, PanicLevel).write(format, v...)
|
||||
}
|
||||
}
|
||||
|
||||
// Errorf logs a message with severity ERROR in format.
|
||||
func Errorf(ctx context.Context, format string, v ...interface{}) {
|
||||
if globalLogger != nil {
|
||||
globalLogger.event(ctx, ErrorLevel).write(format, v...)
|
||||
}
|
||||
}
|
||||
|
||||
// Warnf logs a message with severity WARN in format.
|
||||
func Warnf(ctx context.Context, format string, v ...interface{}) {
|
||||
if globalLogger != nil {
|
||||
globalLogger.event(ctx, WarnLevel).write(format, v...)
|
||||
}
|
||||
}
|
||||
|
||||
// Infof logs a message with severity INFO in format.
|
||||
func Infof(ctx context.Context, format string, v ...interface{}) {
|
||||
if globalLogger != nil {
|
||||
globalLogger.event(ctx, InfoLevel).write(format, v...)
|
||||
}
|
||||
}
|
||||
|
||||
// Debugf logs a message with severity DEBUG in format.
|
||||
func Debugf(ctx context.Context, format string, v ...interface{}) {
|
||||
if globalLogger != nil {
|
||||
globalLogger.event(ctx, DebugLevel).write(format, v...)
|
||||
}
|
||||
}
|
||||
|
||||
// FatalEvent returns a log event with severity FATAL.
|
||||
func FatalEvent(ctx context.Context) *Event {
|
||||
if globalLogger != nil {
|
||||
return globalLogger.event(ctx, FatalLevel)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PanicEvent returns a log event with severity PANIC.
|
||||
func PanicEvent(ctx context.Context) *Event {
|
||||
if globalLogger != nil {
|
||||
return globalLogger.event(ctx, PanicLevel)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ErrorEvent returns a log event with severity ERROR.
|
||||
func ErrorEvent(ctx context.Context) *Event {
|
||||
if globalLogger != nil {
|
||||
return globalLogger.event(ctx, ErrorLevel)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WarnEvent returns a log event with severity WARN.
|
||||
func WarnEvent(ctx context.Context) *Event {
|
||||
if globalLogger != nil {
|
||||
return globalLogger.event(ctx, WarnLevel)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// InfoEvent returns a log event with severity INFO.
|
||||
func InfoEvent(ctx context.Context) *Event {
|
||||
if globalLogger != nil {
|
||||
return globalLogger.event(ctx, InfoLevel)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DebugEvent returns a log event with severity DEBUG.
|
||||
func DebugEvent(ctx context.Context) *Event {
|
||||
if globalLogger != nil {
|
||||
return globalLogger.event(ctx, DebugLevel)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetGlobalLogger sets a logger as global logger.
|
||||
func SetGlobalLogger(l *Logger) {
|
||||
globalLogger = l
|
||||
}
|
||||
|
||||
// GlobalLogger returns the global logger.
|
||||
func GlobalLogger() *Logger {
|
||||
return globalLogger
|
||||
}
|
||||
|
||||
var globalLogger *Logger
|
||||
67
.rclone_repo/vendor/github.com/pengsrc/go-shared/log/level.go
generated
vendored
Executable file
67
.rclone_repo/vendor/github.com/pengsrc/go-shared/log/level.go
generated
vendored
Executable file
@@ -0,0 +1,67 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Level defines log levels.
|
||||
type Level uint8
|
||||
|
||||
// String returns name of the level.
|
||||
func (l Level) String() string {
|
||||
switch l {
|
||||
case MuteLevel:
|
||||
return "MUTE"
|
||||
case FatalLevel:
|
||||
return "FATAL"
|
||||
case PanicLevel:
|
||||
return "PANIC"
|
||||
case ErrorLevel:
|
||||
return "ERROR"
|
||||
case WarnLevel:
|
||||
return "WARN"
|
||||
case InfoLevel:
|
||||
return "INFO"
|
||||
case DebugLevel:
|
||||
return "DEBUG"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
const (
|
||||
// MuteLevel disables the logger.
|
||||
MuteLevel Level = iota
|
||||
// FatalLevel defines fatal log level.
|
||||
FatalLevel
|
||||
// PanicLevel defines panic log level.
|
||||
PanicLevel
|
||||
// ErrorLevel defines error log level.
|
||||
ErrorLevel
|
||||
// WarnLevel defines warn log level.
|
||||
WarnLevel
|
||||
// InfoLevel defines info log level.
|
||||
InfoLevel
|
||||
// DebugLevel defines debug log level.
|
||||
DebugLevel
|
||||
)
|
||||
|
||||
// ParseLevel takes a string level and returns the log level constant.
|
||||
func ParseLevel(level string) (Level, error) {
|
||||
switch strings.ToUpper(level) {
|
||||
case "FATAL":
|
||||
return FatalLevel, nil
|
||||
case "PANIC":
|
||||
return PanicLevel, nil
|
||||
case "ERROR":
|
||||
return ErrorLevel, nil
|
||||
case "WARN":
|
||||
return WarnLevel, nil
|
||||
case "INFO":
|
||||
return InfoLevel, nil
|
||||
case "DEBUG":
|
||||
return DebugLevel, nil
|
||||
}
|
||||
|
||||
return MuteLevel, fmt.Errorf(`"%q" is not a valid log Level`, level)
|
||||
}
|
||||
327
.rclone_repo/vendor/github.com/pengsrc/go-shared/log/logger.go
generated
vendored
Executable file
327
.rclone_repo/vendor/github.com/pengsrc/go-shared/log/logger.go
generated
vendored
Executable file
@@ -0,0 +1,327 @@
|
||||
// Package log provides support for logging to stdout, stderr and file.
|
||||
package log
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/pengsrc/go-shared/check"
|
||||
"github.com/pengsrc/go-shared/reopen"
|
||||
)
|
||||
|
||||
// Logger presents a logger.
|
||||
// The only way to initialize a logger is using the convention construct
|
||||
// functions like NewLogger().
|
||||
type Logger struct {
|
||||
level Level
|
||||
lw LevelWriter
|
||||
|
||||
// Interested context keys.
|
||||
ctxKeys []interface{}
|
||||
ctxKeysMap map[interface{}]string
|
||||
|
||||
// isCallerEnabled sets whether to annotating logs with the calling
|
||||
// function's file name and line number. By default, all logs are annotated.
|
||||
isCallerEnabled bool
|
||||
}
|
||||
|
||||
// GetLevel get the log level string.
|
||||
func (l *Logger) GetLevel() string {
|
||||
return l.level.String()
|
||||
}
|
||||
|
||||
// SetLevel sets the log level.
|
||||
// Valid levels are "debug", "info", "warn", "error", and "fatal".
|
||||
func (l *Logger) SetLevel(level string) (err error) {
|
||||
levelFlag, err := ParseLevel(level)
|
||||
if err == nil {
|
||||
l.level = levelFlag
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SetInterestContextKeys sets the contexts keys that the logger should be
|
||||
// interested in. Value of the interested context key will extract and print as
|
||||
// newEvent filed.
|
||||
func (l *Logger) SetInterestContextKeys(keys []interface{}) {
|
||||
l.ctxKeys = keys
|
||||
|
||||
l.ctxKeysMap = make(map[interface{}]string)
|
||||
for _, key := range l.ctxKeys {
|
||||
l.ctxKeysMap[key] = fmt.Sprintf("%v", key)
|
||||
}
|
||||
}
|
||||
|
||||
// SetCallerFlag sets whether to annotating logs with the caller.
|
||||
func (l *Logger) SetCallerFlag(isEnabled bool) {
|
||||
l.isCallerEnabled = isEnabled
|
||||
}
|
||||
|
||||
// Flush writes buffered logs.
|
||||
func (l *Logger) Flush() {
|
||||
if flusher, ok := l.lw.(Flusher); ok {
|
||||
flusher.Flush()
|
||||
}
|
||||
}
|
||||
|
||||
// Fatal logs a message with severity FATAL followed by a call to os.Exit(1).
|
||||
func (l *Logger) Fatal(ctx context.Context, v ...interface{}) {
|
||||
l.event(ctx, FatalLevel).write("", v...)
|
||||
}
|
||||
|
||||
// Panic logs a message with severity PANIC followed by a call to panic().
|
||||
func (l *Logger) Panic(ctx context.Context, v ...interface{}) {
|
||||
l.event(ctx, PanicLevel).write("", v...)
|
||||
}
|
||||
|
||||
// Error logs a message with severity ERROR.
|
||||
func (l *Logger) Error(ctx context.Context, v ...interface{}) {
|
||||
l.event(ctx, ErrorLevel).write("", v...)
|
||||
}
|
||||
|
||||
// Warn logs a message with severity WARN.
|
||||
func (l *Logger) Warn(ctx context.Context, v ...interface{}) {
|
||||
l.event(ctx, WarnLevel).write("", v...)
|
||||
}
|
||||
|
||||
// Info logs a message with severity INFO.
|
||||
func (l *Logger) Info(ctx context.Context, v ...interface{}) {
|
||||
l.event(ctx, InfoLevel).write("", v...)
|
||||
}
|
||||
|
||||
// Debug logs a message with severity DEBUG.
|
||||
func (l *Logger) Debug(ctx context.Context, v ...interface{}) {
|
||||
l.event(ctx, DebugLevel).write("", v...)
|
||||
}
|
||||
|
||||
// Fatalf logs a message with severity FATAL in format followed by a call to
|
||||
// os.Exit(1).
|
||||
func (l *Logger) Fatalf(ctx context.Context, format string, v ...interface{}) {
|
||||
l.event(ctx, FatalLevel).write(format, v...)
|
||||
}
|
||||
|
||||
// Panicf logs a message with severity PANIC in format followed by a call to
|
||||
// panic().
|
||||
func (l *Logger) Panicf(ctx context.Context, format string, v ...interface{}) {
|
||||
l.event(ctx, PanicLevel).write(format, v...)
|
||||
}
|
||||
|
||||
// Errorf logs a message with severity ERROR in format.
|
||||
func (l *Logger) Errorf(ctx context.Context, format string, v ...interface{}) {
|
||||
l.event(ctx, ErrorLevel).write(format, v...)
|
||||
}
|
||||
|
||||
// Warnf logs a message with severity WARN in format.
|
||||
func (l *Logger) Warnf(ctx context.Context, format string, v ...interface{}) {
|
||||
l.event(ctx, WarnLevel).write(format, v...)
|
||||
}
|
||||
|
||||
// Infof logs a message with severity INFO in format.
|
||||
func (l *Logger) Infof(ctx context.Context, format string, v ...interface{}) {
|
||||
l.event(ctx, InfoLevel).write(format, v...)
|
||||
}
|
||||
|
||||
// Debugf logs a message with severity DEBUG in format.
|
||||
func (l *Logger) Debugf(ctx context.Context, format string, v ...interface{}) {
|
||||
l.event(ctx, DebugLevel).write(format, v...)
|
||||
}
|
||||
|
||||
// FatalEvent returns a log event with severity FATAL.
|
||||
func (l *Logger) FatalEvent(ctx context.Context) *Event {
|
||||
return l.event(ctx, FatalLevel)
|
||||
}
|
||||
|
||||
// PanicEvent returns a log event with severity PANIC.
|
||||
func (l *Logger) PanicEvent(ctx context.Context) *Event {
|
||||
return l.event(ctx, PanicLevel)
|
||||
}
|
||||
|
||||
// ErrorEvent returns a log event with severity ERROR.
|
||||
func (l *Logger) ErrorEvent(ctx context.Context) *Event {
|
||||
return l.event(ctx, ErrorLevel)
|
||||
}
|
||||
|
||||
// WarnEvent returns a log event with severity WARN.
|
||||
func (l *Logger) WarnEvent(ctx context.Context) *Event {
|
||||
return l.event(ctx, WarnLevel)
|
||||
}
|
||||
|
||||
// InfoEvent returns a log event with severity INFO.
|
||||
func (l *Logger) InfoEvent(ctx context.Context) *Event {
|
||||
return l.event(ctx, InfoLevel)
|
||||
}
|
||||
|
||||
// DebugEvent returns a log event with severity DEBUG.
|
||||
func (l *Logger) DebugEvent(ctx context.Context) *Event {
|
||||
return l.event(ctx, DebugLevel)
|
||||
}
|
||||
|
||||
func (l *Logger) event(ctx context.Context, level Level) (e *Event) {
|
||||
var ctxKeys *[]interface{}
|
||||
var ctxKeysMap *map[interface{}]string
|
||||
|
||||
if len(l.ctxKeys) > 0 {
|
||||
ctxKeys = &l.ctxKeys
|
||||
}
|
||||
if len(l.ctxKeysMap) > 0 {
|
||||
ctxKeysMap = &l.ctxKeysMap
|
||||
}
|
||||
|
||||
return newEvent(ctx, ctxKeys, ctxKeysMap, level, l.lw, level <= l.level, l.isCallerEnabled)
|
||||
}
|
||||
|
||||
// NewLogger creates a new logger for given out and level, and the level is
|
||||
// optional.
|
||||
func NewLogger(out io.Writer, level ...string) (*Logger, error) {
|
||||
return NewLoggerWithError(out, nil, level...)
|
||||
}
|
||||
|
||||
// NewLoggerWithError creates a new logger for given out, err out, level, and the
|
||||
// err out can be nil, and the level is optional.
|
||||
func NewLoggerWithError(out, errOut io.Writer, level ...string) (l *Logger, err error) {
|
||||
if out == nil {
|
||||
return nil, errors.New("logger output must specified")
|
||||
}
|
||||
|
||||
sw := &StandardWriter{w: out, ew: errOut, pid: os.Getpid()}
|
||||
l = &Logger{lw: sw}
|
||||
|
||||
if len(level) == 1 {
|
||||
if err = l.SetLevel(level[0]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return l, nil
|
||||
}
|
||||
|
||||
// NewTerminalLogger creates a logger that write into terminal.
|
||||
func NewTerminalLogger(level ...string) (*Logger, error) {
|
||||
return NewLogger(os.Stdout, level...)
|
||||
}
|
||||
|
||||
// NewBufferedTerminalLogger creates a buffered logger that write into terminal.
|
||||
func NewBufferedTerminalLogger(level ...string) (*Logger, error) {
|
||||
return NewLogger(bufio.NewWriter(os.Stdout), level...)
|
||||
}
|
||||
|
||||
// NewFileLogger creates a logger that write into file.
|
||||
func NewFileLogger(filePath string, level ...string) (*Logger, error) {
|
||||
return NewFileLoggerWithError(filePath, "", level...)
|
||||
}
|
||||
|
||||
// NewFileLoggerWithError creates a logger that write into files.
|
||||
func NewFileLoggerWithError(filePath, errFilePath string, level ...string) (*Logger, error) {
|
||||
if err := check.Dir(path.Dir(filePath)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if errFilePath != "" {
|
||||
if err := check.Dir(path.Dir(errFilePath)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
out, err := reopen.NewFileWriter(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var errOut *reopen.FileWriter
|
||||
if errFilePath != "" {
|
||||
errOut, err = reopen.NewFileWriter(errFilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
c := make(chan os.Signal)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-c:
|
||||
out.Reopen()
|
||||
if errOut != nil {
|
||||
errOut.Reopen()
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
signal.Notify(c, syscall.SIGHUP)
|
||||
|
||||
if errOut == nil {
|
||||
return NewLoggerWithError(out, nil, level...)
|
||||
}
|
||||
return NewLoggerWithError(out, errOut, level...)
|
||||
}
|
||||
|
||||
// NewBufferedFileLogger creates a logger that write into file with buffer.
|
||||
// The flushSeconds's unit is second.
|
||||
func NewBufferedFileLogger(filePath string, flushInterval int, level ...string) (*Logger, error) {
|
||||
return NewBufferedFileLoggerWithError(filePath, "", flushInterval, level...)
|
||||
}
|
||||
|
||||
// NewBufferedFileLoggerWithError creates a logger that write into files with buffer.
|
||||
// The flushSeconds's unit is second.
|
||||
func NewBufferedFileLoggerWithError(filePath, errFilePath string, flushInterval int, level ...string) (*Logger, error) {
|
||||
if err := check.Dir(path.Dir(filePath)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if errFilePath != "" {
|
||||
if err := check.Dir(path.Dir(errFilePath)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if flushInterval == 0 {
|
||||
flushInterval = 10
|
||||
}
|
||||
|
||||
out, err := reopen.NewFileWriter(filePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var errOut *reopen.FileWriter
|
||||
if errFilePath != "" {
|
||||
errOut, err = reopen.NewFileWriter(errFilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
bufferedOut := reopen.NewBufferedFileWriter(out)
|
||||
var bufferedErrOut *reopen.BufferedFileWriter
|
||||
if errOut != nil {
|
||||
bufferedErrOut = reopen.NewBufferedFileWriter(errOut)
|
||||
}
|
||||
|
||||
c := make(chan os.Signal)
|
||||
go func() {
|
||||
for {
|
||||
select {
|
||||
case <-c:
|
||||
bufferedOut.Reopen()
|
||||
if bufferedErrOut != nil {
|
||||
bufferedErrOut.Reopen()
|
||||
}
|
||||
case <-time.After(time.Duration(flushInterval) * time.Second):
|
||||
bufferedOut.Flush()
|
||||
if bufferedErrOut != nil {
|
||||
bufferedErrOut.Flush()
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
signal.Notify(c, syscall.SIGHUP)
|
||||
|
||||
if bufferedErrOut == nil {
|
||||
return NewLoggerWithError(bufferedOut, nil, level...)
|
||||
}
|
||||
return NewLoggerWithError(bufferedOut, bufferedErrOut, level...)
|
||||
}
|
||||
83
.rclone_repo/vendor/github.com/pengsrc/go-shared/log/writer.go
generated
vendored
Executable file
83
.rclone_repo/vendor/github.com/pengsrc/go-shared/log/writer.go
generated
vendored
Executable file
@@ -0,0 +1,83 @@
|
||||
package log
|
||||
|
||||
import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/pengsrc/go-shared/buffer"
|
||||
"github.com/pengsrc/go-shared/convert"
|
||||
)
|
||||
|
||||
// LevelWriter defines as interface a writer may implement in order
|
||||
// to receive level information with payload.
|
||||
type LevelWriter interface {
|
||||
io.Writer
|
||||
WriteLevel(level Level, message []byte) (n int, err error)
|
||||
}
|
||||
|
||||
// Flusher defines a interface with Flush() method.
|
||||
type Flusher interface {
|
||||
Flush() error
|
||||
}
|
||||
|
||||
// StandardWriter implements io.Writer{} and LevelWriter{} interface.
|
||||
type StandardWriter struct {
|
||||
w io.Writer
|
||||
ew io.Writer // Writer for WARN, ERROR, FATAL, PANIC
|
||||
|
||||
dl Level // Default level
|
||||
pid int
|
||||
}
|
||||
|
||||
// Write implements the io.Writer{} interface.
|
||||
func (sw *StandardWriter) Write(p []byte) (n int, err error) {
|
||||
return sw.WriteLevel(sw.dl, p)
|
||||
}
|
||||
|
||||
// WriteLevel implements the LevelWriter{} interface.
|
||||
func (sw *StandardWriter) WriteLevel(level Level, message []byte) (n int, err error) {
|
||||
levelString := level.String()
|
||||
if len(levelString) == 4 {
|
||||
levelString = " " + levelString
|
||||
}
|
||||
|
||||
buf := buffer.GlobalBytesPool().Get()
|
||||
defer buf.Free()
|
||||
|
||||
buf.AppendString("[")
|
||||
buf.AppendTime(time.Now().UTC(), convert.ISO8601Milli)
|
||||
buf.AppendString(" #")
|
||||
buf.AppendInt(int64(sw.pid))
|
||||
buf.AppendString("] ")
|
||||
buf.AppendString(levelString)
|
||||
buf.AppendString(" -- : ")
|
||||
buf.AppendBytes(message)
|
||||
buf.AppendString("\n")
|
||||
|
||||
if sw.ew != nil {
|
||||
if level > MuteLevel && level <= WarnLevel {
|
||||
n, err = sw.ew.Write(buf.Bytes())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return sw.w.Write(buf.Bytes())
|
||||
}
|
||||
|
||||
// Flush implements the Flusher{} interface.
|
||||
func (sw *StandardWriter) Flush() (err error) {
|
||||
if flusher, ok := sw.w.(Flusher); ok {
|
||||
err = flusher.Flush()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if sw.ew != nil {
|
||||
if flusher, ok := sw.ew.(Flusher); ok {
|
||||
err = flusher.Flush()
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
182
.rclone_repo/vendor/github.com/pengsrc/go-shared/reopen/reopen.go
generated
vendored
Executable file
182
.rclone_repo/vendor/github.com/pengsrc/go-shared/reopen/reopen.go
generated
vendored
Executable file
@@ -0,0 +1,182 @@
|
||||
package reopen
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Reopener interface defines something that can be reopened.
|
||||
type Reopener interface {
|
||||
Reopen() error
|
||||
}
|
||||
|
||||
// Writer is a writer that also can be reopened.
|
||||
type Writer interface {
|
||||
Reopener
|
||||
io.Writer
|
||||
}
|
||||
|
||||
// WriteCloser is a io.WriteCloser that can also be reopened.
|
||||
type WriteCloser interface {
|
||||
Reopener
|
||||
io.WriteCloser
|
||||
}
|
||||
|
||||
// FileWriter that can also be reopened.
|
||||
type FileWriter struct {
|
||||
// Ensures close/reopen/write are not called at the same time, protects f
|
||||
mu sync.Mutex
|
||||
f *os.File
|
||||
mode os.FileMode
|
||||
name string
|
||||
}
|
||||
|
||||
// Close calls the under lying File.Close().
|
||||
func (f *FileWriter) Close() error {
|
||||
f.mu.Lock()
|
||||
err := f.f.Close()
|
||||
f.mu.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
// Reopen the file.
|
||||
func (f *FileWriter) Reopen() error {
|
||||
f.mu.Lock()
|
||||
err := f.reopen()
|
||||
f.mu.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
// Write implements the stander io.Writer interface.
|
||||
func (f *FileWriter) Write(p []byte) (int, error) {
|
||||
f.mu.Lock()
|
||||
n, err := f.f.Write(p)
|
||||
f.mu.Unlock()
|
||||
return n, err
|
||||
}
|
||||
|
||||
// reopen with mutex free.
|
||||
func (f *FileWriter) reopen() error {
|
||||
if f.f != nil {
|
||||
f.f.Close()
|
||||
f.f = nil
|
||||
}
|
||||
ff, err := os.OpenFile(f.name, os.O_WRONLY|os.O_APPEND|os.O_CREATE, f.mode)
|
||||
if err != nil {
|
||||
f.f = nil
|
||||
return err
|
||||
}
|
||||
f.f = ff
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewFileWriter opens a file for appending and writing and can be reopened.
|
||||
// It is a ReopenWriteCloser...
|
||||
func NewFileWriter(name string) (*FileWriter, error) {
|
||||
// Standard default mode
|
||||
return NewFileWriterMode(name, 0644)
|
||||
}
|
||||
|
||||
// NewFileWriterMode opens a Reopener file with a specific permission.
|
||||
func NewFileWriterMode(name string, mode os.FileMode) (*FileWriter, error) {
|
||||
writer := FileWriter{
|
||||
f: nil,
|
||||
name: name,
|
||||
mode: mode,
|
||||
}
|
||||
err := writer.reopen()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &writer, nil
|
||||
}
|
||||
|
||||
// BufferedFileWriter is buffer writer than can be reopened.
|
||||
type BufferedFileWriter struct {
|
||||
mu sync.Mutex
|
||||
OrigWriter *FileWriter
|
||||
BufWriter *bufio.Writer
|
||||
}
|
||||
|
||||
// Reopen implement Reopener.
|
||||
func (bw *BufferedFileWriter) Reopen() error {
|
||||
bw.mu.Lock()
|
||||
bw.BufWriter.Flush()
|
||||
|
||||
// Use non-mutex version since we are using this one.
|
||||
err := bw.OrigWriter.reopen()
|
||||
|
||||
bw.BufWriter.Reset(io.Writer(bw.OrigWriter))
|
||||
bw.mu.Unlock()
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// Close flushes the internal buffer and closes the destination file.
|
||||
func (bw *BufferedFileWriter) Close() error {
|
||||
bw.mu.Lock()
|
||||
bw.BufWriter.Flush()
|
||||
bw.OrigWriter.f.Close()
|
||||
bw.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write implements io.Writer (and reopen.Writer).
|
||||
func (bw *BufferedFileWriter) Write(p []byte) (int, error) {
|
||||
bw.mu.Lock()
|
||||
n, err := bw.BufWriter.Write(p)
|
||||
|
||||
// Special Case... if the used space in the buffer is LESS than
|
||||
// the input, then we did a flush in the middle of the line
|
||||
// and the full log line was not sent on its way.
|
||||
if bw.BufWriter.Buffered() < len(p) {
|
||||
bw.BufWriter.Flush()
|
||||
}
|
||||
|
||||
bw.mu.Unlock()
|
||||
return n, err
|
||||
}
|
||||
|
||||
// Flush flushes the buffer.
|
||||
func (bw *BufferedFileWriter) Flush() (err error) {
|
||||
bw.mu.Lock()
|
||||
defer bw.mu.Unlock()
|
||||
|
||||
if err = bw.BufWriter.Flush(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = bw.OrigWriter.f.Sync(); err != nil {
|
||||
return err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// flushDaemon periodically flushes the log file buffers.
|
||||
func (bw *BufferedFileWriter) flushDaemon(interval time.Duration) {
|
||||
for range time.NewTicker(interval).C {
|
||||
bw.Flush()
|
||||
}
|
||||
}
|
||||
|
||||
// NewBufferedFileWriter opens a buffered file that is periodically flushed.
|
||||
func NewBufferedFileWriter(w *FileWriter) *BufferedFileWriter {
|
||||
return NewBufferedFileWriterSize(w, bufferSize, flushInterval)
|
||||
}
|
||||
|
||||
// NewBufferedFileWriterSize opens a buffered file with the given size that is periodically
|
||||
// flushed on the given interval.
|
||||
func NewBufferedFileWriterSize(w *FileWriter, size int, flush time.Duration) *BufferedFileWriter {
|
||||
bw := BufferedFileWriter{
|
||||
OrigWriter: w,
|
||||
BufWriter: bufio.NewWriterSize(w, size),
|
||||
}
|
||||
go bw.flushDaemon(flush)
|
||||
return &bw
|
||||
}
|
||||
|
||||
const bufferSize = 256 * 1024
|
||||
const flushInterval = 30 * time.Second
|
||||
Reference in New Issue
Block a user