xiao

package module
v0.4.3 Latest Latest
Warning

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

Go to latest
Published: Mar 26, 2026 License: MIT Imports: 18 Imported by: 0

README

Xiao

My personal basic golang package

Go Reference

import "github.com/cjey/xiao"

Context

Context在实现了官方的Context接口外,额外追加了环境变量和日志能力,主包在此基础上做了个应用封装

关键特性

兼容

实现了官方库的Context接口

WithX

一组操作,用于直接简单的执行Context派生

Fork

Context支持执行fork操作,将会copy当前的环境,生成新的子级环境,同时其name后会自动的被追加一个数字后缀(location保持)

一般使用场景:一次请求当中,需要开启并发操作,并发的任务当中使用fork的Context来执行操作,这样在日志输出上就可以简单的区分出子任务

如果本请求触发了一个异步任务,则需要谨慎对待,因为派生Context用于异步可能会存在副作用(常规现象,继承的Context很可能会在同步请求结束时被立即Cancel),解决的办法可以是根据情况创建一个新的NamedContext,手工继承源Context的Name和Location(按需)

At

此操作将会copy当前的环境,生成新的子级环境,同时会在原有的Location之上合并入一个新的location名称(name保持),Context支持在新的逻辑过程中自行指明一个位置名称,在日志输出时便会自动带上该位置,并且,此位置名称是会被继承的,这样在输出日志中便可以简单的查看到一定的逻辑调用层次关系

当然,这个是可选的,也不建议在大大小小所有的函数位置处使用此能力,否则跟每条日志都打印一次调用堆栈没了区别,应当根据情况用在合适的位置

Set/Get

这是一组快捷操作,等价于调用Context内的Env,用于提供类似环境变量的能力,每当有新的Context派生出来之时,即会同步派生出新的变量空间

Set操作将只针对自己当前的变量空间,不会影响上游空间,而Get操作则会优先访问当前的变量空间,如果没有找到,则会逐级向上游追溯

Debug/Info/...

这是一组快捷操作,等价于调用Context内的Logger,用于提供基本的日志操作,内部的logger选择了zap.SugaredLogger,日志格式也默认被重新调整过,如果想定制格式,可以直接自行执行全局替换

如果只是想要在默认风格上调整日志等级/日志文件/日志编码等配置,可以直接使用ReplaceZapLogger完成目标

默认:ReplaceZapLogger("debug", "stderr", "console", false)

info+json: ReplaceZapLogger("info", "stderr", "json", false)

NamedContext

Context可以支持自命名,一般用于伴随服务生命周期的任务,或者是定时执行类的任务

对于这样的用法,需要注意的是,Context创建时,其内部的logger已经固定,比如定时执行类的任务,如果在运行时需要动态调整logger,应当在每次执行时重新创建一个同名的Context

var ctx = gbase.NamedContext("ZookeeperMonitor")
ctx.Info("started")
// console encode
// 2020-04-11 21:24:45.361  info    ZookeeperMonitor started
// json encode
// {"L":"info","T":"2020-04-11 21:24:45.361","N":"ZookeeperMonitor","M":"started"}

ctx = ctx.At("GetID")
ctx.Set("id", "123")
ctx.Info("got it!", "id", ctx.GetString("id"))
// console encode
// 2020-04-11 21:24:45.361  info    ZookeeperMonitor got it! {"@": "GetID", "id": "123"}
// json encode
// {"L":"info","T":"2020-04-11 21:24:45.361","N":"ZookeeperMonitor","M":"got it!", "@": "GetID", "id": "123"}
SessionContext

还可以选择使用自动生成uuid风格名称的Context,适用于服务请求开始时,为本次请求创建一个SessionContext。

生成的Context的name即是一个带有一定规律的uuid(以BootID的前24位为前缀+12位10进制数字递增序列)

你还可以通过替换变量SessionNameGenerator的方式来实现定制session的生成规则

var ctx = gbase.SessionContext()
ctx.Info("started")
// console encode
// 2020-04-11 21:24:45.361  info    9b2119d3-7f37-4033-8c19-000000000001 started
// json encode
// {"L":"info","T":"2020-04-11 21:24:45.361","N":"9b2119d3-7f37-4033-8c19-000000000001","M":"started"}

ctx = ctx.ForkAt("AsyncGetID")
ctx.Info("show default session", "session", GetSesson(ctx))
// console encode
// 2020-04-11 21:24:45.361  info    9b2119d3-7f37-4033-8c19-000000000001.1 show default session {"@": "AsyncGetID", "session": "9b2119d3-7f37-4033-8c19-000000000001.1"}
// json encode
// {"L":"info","T":"2020-04-11 21:24:45.361","N":"9b2119d3-7f37-4033-8c19-000000000001.1","M":"show default session", "@": "AsyncGetID", "session": "9b2119d3-7f37-4033-8c19-000000000001.1"}

SetSession(ctx, "7ec17674-1360-4fb1-9245-bd8d8d5866c4")
ctx.Info("use my own session", "session", GetSession(ctx))
// console encode
// 2020-04-11 21:24:45.361  info    9b2119d3-7f37-4033-8c19-000000000001.1 use my own session {"@": "AsyncGetID", "session": "7ec17674-1360-4fb1-9245-bd8d8d5866c4"}
// json encode
// {"L":"info","T":"2020-04-11 21:24:45.361","N":"9b2119d3-7f37-4033-8c19-000000000001.1","M":"use my own session", "@": "AsyncGetID", "session": "7ec17674-1360-4fb1-9245-bd8d8d5866c4"}
ToContext

NamedContext和SessionContext都使用官方context的Background作为内部context,如果需要使用自定义的context或者将官方的context执行转换,则可以使用ToSessionContextToNamedContext

Documentation

Overview

Author: CJey Hou<cjey.hou@gmail.com>

Index

Constants

This section is empty.

Variables

View Source
var (
	Canceled         = gcontext.Canceled
	DeadlineExceeded = gcontext.DeadlineExceeded
)

variable alias

View Source
var (
	BootID   = uuid.NewString()
	BootTime = time.Now()
)

Functions

func GetRealSession

func GetRealSession(ctx Context) string

GetRealSession use to get real session name

func GetSession

func GetSession(ctx Context) string

GetSession use to get session name if it has real session, otherwise return context name instead

func Gunzip added in v0.4.3

func Gunzip(input []byte) ([]byte, error)

func Gzip added in v0.4.3

func Gzip(input []byte) ([]byte, error)

func Json added in v0.4.3

func Json(msg any) json.RawMessage

func JsonPretty added in v0.4.3

func JsonPretty(msg any, prefix ...string) string

func NewSimpleLogger

func NewSimpleLogger(level, outpath, encoding string, disableCaller bool) (*zap.Logger, error)

NewSimpleLogger 生成并返回一个简单的默认风格的zap.Logger

func ReplaceLogger

func ReplaceLogger(logger *zap.Logger) func()

ReplaceLogger 用给定的zap.Logger替换context内部的默认全局zap.Logger和zap.SugaredLogger

func SessionNameGenerator

func SessionNameGenerator(header string) func(...string) string

SessionNameGenerator 返回一个命名生成器,会自动在header后面追加12位长的自增字符串, 同时支持提供额外的前缀,会被附加在header之前。

func SetSession

func SetSession(ctx Context, session string)

SetSession use to set real session name

func UseDefaultLogger

func UseDefaultLogger() (func(), error)

UseDefaultLogger 使用预定义的简单zap.Logger替换全局默认zap.Logger。

func UseDevelopLogger

func UseDevelopLogger() (func(), error)

UseDevlopLogger 使用预定义的简单zap.Logger替换全局默认zap.Logger,适合于开发、测试、写简单的工具时用。

func UseSimpleLogger

func UseSimpleLogger(level, outpath, encoding string, disableCaller bool) (func(), error)

UseSimpleLogger 使用简单的默认风格logger替换掉全局的zap.Logger

Types

type CancelFunc

type CancelFunc = gcontext.CancelFunc

type alias

type Context

type Context interface {
	// composite
	gcontext.Context

	// Fork return a copied context, if there is a new goroutine generated
	// it will use my name with a sequential number suffix started from 1
	Fork() Context
	// At return a copied context, specify the current location where it is in,
	// it should chain all locations start from root
	At(location string) Context
	ForkAt(location string) Context
	// Reborn will use gcontext.Background() instead of internal context,
	// it used for escaping internal context's cancel request
	Reborn() Context
	// RebornWith will use specified context instead of internal context,
	// it used for escaping internal context's cancel request
	RebornWith(gcontext.Context) Context
	// Name return my logger's name
	Name() string
	// Location return my logger's location
	Location() string

	// integrated base official context action
	WithCancel() (Context, CancelFunc)
	WithDeadline(time.Time) (Context, CancelFunc)
	WithTimeout(time.Duration) (Context, CancelFunc)
	WithValue(key, value any) Context

	// Env return my env
	// WARN: env value and official context value are two diffrent things
	Env() Env
	// shortcut methods of my env
	Set(key, value any)
	Get(key any) (value any, ok bool)
	GetString(key any) string
	GetInt(key any) int
	GetUint(key any) uint
	GetFloat(key any) float64
	GetBool(key any) bool

	// mute/unmute my logger
	Mute()
	Unmute()
	// Logger return my logger
	Logger() Logger
	// shortcut methods of my logger
	Debug(msg string, kvs ...any)
	Debugf(template string, args ...any)
	Info(msg string, kvs ...any)
	Infof(template string, args ...any)
	Warn(msg string, kvs ...any)
	Warnf(template string, args ...any)
	Error(msg string, kvs ...any)
	Errorf(template string, args ...any)
	Panic(msg string, kvs ...any)
	Panicf(template string, args ...any)
	Fatal(msg string, kvs ...any)
	Fatalf(template string, args ...any)
}

Context extend default context package, make it better It should has name, location, environment and logger

func NamedContext

func NamedContext(name string) Context

NamedContext 返回一个简单的Context,Context的名称可以通过参数name实现自定义。

func NewContext

func NewContext(gctx gcontext.Context, env Env, log Logger) Context

NewContext use an official Context, an Env and a Logger to generate a new Context. It will use default value if not given.

func SessionalContext

func SessionalContext(prefix ...string) Context

SessinalContext 返回一个简单的Context,命名部分使用自动生成的uuid。

func SimpleContext

func SimpleContext() Context

SimpleContext return a very simple context, without name, without location, and use S() as internal logger

func ToNamedContext

func ToNamedContext(gctx gcontext.Context, name string) Context

ToNamedContext 使用给定的标准库Context和名称列表构建一个Context。

func ToSessionalContext

func ToSessionalContext(gctx gcontext.Context, prefix ...string) Context

ToSesionalContext 将给定的标准库Context对象对位Context的内部基础对象,并自动生成uuid作为name。

func ToSimpleContext

func ToSimpleContext(gctx gcontext.Context) Context

ToSimpleContext 将给定的标准库Context对象作为Context的内部基础对象。

type ContextGenerator

type ContextGenerator = func() Context

Generator 定义了一个Context的生成函数,每次调用都应当返回一个新的Context

type Env

type Env interface {
	// Fork return an inherited sub Env, and I am it's parent
	Fork() Env

	// Set always set key & value at local storage
	Set(key, value any)
	// Get always check local, if the key not exists, then check parent
	Get(key any) (value any, ok bool)
	Has(key any) (ok bool)
	Keys() []any

	GetInt(key any) int
	GetInt64(key any) int64
	GetUint(key any) uint
	GetUint64(key any) uint64
	GetBool(key any) bool
	GetFloat(key any) float64
	GetString(key any) string
	GetIP(key any) net.IP
	GetAddr(key any) net.Addr
	GetTime(key any) time.Time
	GetDuration(key any) time.Duration
}

Env should used as a map, but it has an inherited mode, overlay liked. If you set, the value should be store at local. If you get, the value should be get from local first, otherwise from parent

func NewEnv

func NewEnv() Env

NewEnv return a simple Env, use sync.Map as it's storage

type Event

type Event struct {
	Args []any // 触发事件时提供的关联数据
	// contains filtered or unexported fields
}

Event 提供一个简单的一次性事件订阅和管理功能

func NewEvent

func NewEvent() *Event

NewEvent 初始化并返回一个*Event

func (*Event) Done

func (evt *Event) Done() bool

事件是否已经结束

func (*Event) Emit

func (evt *Event) Emit(args ...any) bool

用于触发事件,支持提供可选的关联数据,只在首次触发时返回true

func (*Event) Yes

func (evt *Event) Yes() <-chan struct{}

type LocationJoiner

type LocationJoiner func(origin, given string) (field, location string)

LocationJoiner will generate a full location after joining the origin and given. Default logger use it to join location when invoking Fork()

type Logger

type Logger interface {
	// Fork return a new logger, with the given name and location,
	// but it's full name and full location should inhert from me.
	// It could just simplely join my name and location.
	// e.g. my name = ServiceMonitor, name = go1, then new name = ServiceMonitor.go1.
	// e.g. my location = CheckPort, location = CheckAlive, then new location = CheckPort/CheckAlive.
	// name will be print as zap logger's name, mostly it looks like a uuid
	// location will be print as a data field, field name is '@' mostly.
	Fork(name, location string) Logger

	// Name return my full name
	Name() string
	// Location return my full location
	Location() string

	// Debug("New user created", "name", "CJey", "sex", "male")
	Debug(msg string, kvs ...any)
	Debugf(template string, args ...any)
	Info(msg string, kvs ...any)
	Infof(template string, args ...any)
	Warn(msg string, kvs ...any)
	Warnf(template string, args ...any)
	Error(msg string, kvs ...any)
	Errorf(template string, args ...any)
	Panic(msg string, kvs ...any)
	Panicf(template string, args ...any)
	Fatal(msg string, kvs ...any)
	Fatalf(template string, args ...any)

	// With return a Logger with specified key/value pairs
	With(kvs ...any) Logger
	// Sync flush log buffers
	Sync() error

	// Mute
	Mute()
	// Unmute
	Unmute()
}

Logger is a logger, but it has name and location. When print message, it simulates zap's 'with' style, encourage print message and data seprately

func NewLogger

func NewLogger(name, location string, z0 *zap.SugaredLogger, nj NameJoiner, lj LocationJoiner) Logger

NewLogger return a Logger, with name and location. name and location are optional, empty string means no name, no location. z0, nj, lj are optional too, default nj is nameJoiner, default lj is locationJoiner, but no default z0. nj and lj will be used when Fork() invoked

type NameJoiner

type NameJoiner func(origin, given string) (name string)

NameJoiner will generate a full name after joining the origin and given. Default logger use it to join name when invoking Fork()

type TaskGroup added in v0.4.3

type TaskGroup struct {
	// contains filtered or unexported fields
}

func NewTaskGroup added in v0.4.3

func NewTaskGroup(evt *Event) *TaskGroup

func (*TaskGroup) Count added in v0.4.3

func (tg *TaskGroup) Count() int

func (*TaskGroup) Done added in v0.4.3

func (tg *TaskGroup) Done() <-chan struct{}

func (*TaskGroup) Go added in v0.4.3

func (tg *TaskGroup) Go(ctx Context, f func(Context))

func (*TaskGroup) Wait added in v0.4.3

func (tg *TaskGroup) Wait()

Directories

Path Synopsis
gerror提供用于编解码grpc错误的对象和方法,用于将业务错误编码在带外错误中, 从而让grpc的使用方式上更加符合go style
gerror提供用于编解码grpc错误的对象和方法,用于将业务错误编码在带外错误中, 从而让grpc的使用方式上更加符合go style

Jump to

Keyboard shortcuts

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