Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: CI

on:
push:
branches: [master, develop, aicode]
pull_request:
branches: [aicode]

jobs:
test:
name: Test
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.18'
cache: true

- name: Download dependencies
run: go mod download

- name: Build
run: go build -v ./...

- name: Run tests
run: go test -v -race -coverprofile=coverage.out ./...

- name: Upload coverage
uses: actions/upload-artifact@v4
with:
name: coverage
path: coverage.out

lint:
name: Lint
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: '1.18'
cache: true

- name: Run golangci-lint
uses: golangci/golangci-lint-action@v6
with:
version: latest
75 changes: 75 additions & 0 deletions config/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# dotlog YAML 配置文件示例
# 使用说明: 将文件名传递给 StartLogService("config.yaml") 即可

global:
isLog: true
chanSize: 1000
innerLogPath: "./"
innerLogEncode: "utf-8"

# 自定义变量
variables:
- name: LogDir
value: "./logs/"
- name: LogDateDir
value: "./logs/{year}/{month}/{day}/"

# 日志输出目标
targets:
# 文件输出
file:
- name: FileLogger
isLog: true
layout: "{datetime} - {message}"
encode: "utf-8"
fileMaxSize: 10240 # KB
fileName: "./logs/app.log"

# 标准输出
fmt:
- name: StdoutLogger
isLog: true
layout: "[{level}] {datetime} - {message}"
encode: "utf-8"

# UDP 输出 (可选)
# udp:
# - name: UdpLogger
# isLog: true
# layout: "{message}"
# encode: "utf-8"
# remoteIP: "127.0.0.1:9000"

# HTTP 输出 (可选)
# http:
# - name: HttpLogger
# isLog: true
# layout: "{message}"
# encode: "utf-8"
# httpUrl: "http://localhost:8080/log"

# 日志记录器配置
loggers:
- name: FileLogger
isLog: true
layout: "{datetime} - {message}"
configMode: "file"
levels:
- level: info
targets: "FileLogger"
isLog: true
- level: error
targets: "FileLogger"
isLog: true

- name: StdoutLogger
isLog: true
layout: "[{level}] {datetime} - {message}"
configMode: "fmt"
levels:
- level: debug
targets: "StdoutLogger"
isLog: true
- level: info
targets: "StdoutLogger"
isLog: true
213 changes: 213 additions & 0 deletions config/yaml.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
package config

import (
"fmt"
"os"

"gopkg.in/yaml.v3"
)

// yamlConfig YAML 配置结构
type yamlConfig struct {
Global globalConfig `yaml:"global"`
Variables []variableConfig `yaml:"variables"`
Targets targetList `yaml:"targets"`
Loggers []loggerConfig `yaml:"loggers"`
}

type globalConfig struct {
IsLog bool `yaml:"isLog"`
ChanSize int `yaml:"chanSize"`
InnerLogPath string `yaml:"innerLogPath"`
InnerLogEncode string `yaml:"innerLogEncode"`
}

type variableConfig struct {
Name string `yaml:"name"`
Value string `yaml:"value"`
}

type targetList struct {
File []fileTargetConfig `yaml:"file"`
Udp []udpTargetConfig `yaml:"udp"`
Http []httpTargetConfig `yaml:"http"`
EMail []emailTargetConfig `yaml:"email"`
Fmt []fmtTargetConfig `yaml:"fmt"`
}

type fileTargetConfig struct {
Name string `yaml:"name"`
IsLog bool `yaml:"isLog"`
Layout string `yaml:"layout"`
Encode string `yaml:"encode"`
FileMaxSize int64 `yaml:"fileMaxSize"`
FileName string `yaml:"fileName"`
}

type udpTargetConfig struct {
Name string `yaml:"name"`
IsLog bool `yaml:"isLog"`
Layout string `yaml:"layout"`
Encode string `yaml:"encode"`
RemoteIP string `yaml:"remoteIP"`
}

type httpTargetConfig struct {
Name string `yaml:"name"`
IsLog bool `yaml:"isLog"`
Layout string `yaml:"layout"`
Encode string `yaml:"encode"`
HttpUrl string `yaml:"httpUrl"`
}

type emailTargetConfig struct {
Name string `yaml:"name"`
IsLog bool `yaml:"isLog"`
Layout string `yaml:"layout"`
Encode string `yaml:"encode"`
MailServer string `yaml:"mailServer"`
MailAccount string `yaml:"mailAccount"`
MailNickName string `yaml:"mailNickName"`
MailPassword string `yaml:"mailPassword"`
ToMail string `yaml:"toMail"`
Subject string `yaml:"subject"`
}

type fmtTargetConfig struct {
Name string `yaml:"name"`
IsLog bool `yaml:"isLog"`
Layout string `yaml:"layout"`
Encode string `yaml:"encode"`
}

type loggerConfig struct {
Name string `yaml:"name"`
IsLog bool `yaml:"isLog"`
Layout string `yaml:"layout"`
ConfigMode string `yaml:"configMode"`
Levels []loggerLevelConfig `yaml:"levels"`
}

type loggerLevelConfig struct {
Level string `yaml:"level"`
Targets string `yaml:"targets"`
IsLog bool `yaml:"isLog"`
}

// LoadYamlConfig loads configuration from YAML file
func LoadYamlConfig(configFile string) (*AppConfig, error) {
data, err := os.ReadFile(configFile)
if err != nil {
return nil, fmt.Errorf("failed to read config file: %w", err)
}

var yc yamlConfig
if err := yaml.Unmarshal(data, &yc); err != nil {
return nil, fmt.Errorf("failed to parse YAML config: %w", err)
}

// Convert YAML config to AppConfig
appConfig := &AppConfig{
Global: &GlobalConfig{
IsLog: yc.Global.IsLog,
ChanSize: yc.Global.ChanSize,
InnerLogPath: yc.Global.InnerLogPath,
InnerLogEncode: yc.Global.InnerLogEncode,
},
Variables: make([]*VariableConfig, len(yc.Variables)),
Loggers: make([]*LoggerConfig, len(yc.Loggers)),
Targets: &TargetList{
FileTargets: make([]*FileTargetConfig, len(yc.Targets.File)),
UdpTargets: make([]*UdpTargetConfig, len(yc.Targets.Udp)),
HttpTargets: make([]*HttpTargetConfig, len(yc.Targets.Http)),
EMailTargets: make([]*EMailTargetConfig, len(yc.Targets.EMail)),
FmtTargets: make([]*FmtTargetConfig, len(yc.Targets.Fmt)),
},
}

// Convert variables
for i, v := range yc.Variables {
appConfig.Variables[i] = &VariableConfig{Name: v.Name, Value: v.Value}
}

// Convert loggers
for i, l := range yc.Loggers {
levels := make([]*LoggerLevelConfig, len(l.Levels))
for j, level := range l.Levels {
levels[j] = &LoggerLevelConfig{
Level: level.Level,
Targets: level.Targets,
IsLog: level.IsLog,
}
}
appConfig.Loggers[i] = &LoggerConfig{
Name: l.Name,
IsLog: l.IsLog,
Layout: l.Layout,
ConfigMode: l.ConfigMode,
Levels: levels,
}
}

// Convert file targets
for i, t := range yc.Targets.File {
appConfig.Targets.FileTargets[i] = &FileTargetConfig{
Name: t.Name,
IsLog: t.IsLog,
Layout: t.Layout,
Encode: t.Encode,
FileMaxSize: t.FileMaxSize,
FileName: t.FileName,
}
}

// Convert UDP targets
for i, t := range yc.Targets.Udp {
appConfig.Targets.UdpTargets[i] = &UdpTargetConfig{
Name: t.Name,
IsLog: t.IsLog,
Layout: t.Layout,
Encode: t.Encode,
RemoteIP: t.RemoteIP,
}
}

// Convert HTTP targets
for i, t := range yc.Targets.Http {
appConfig.Targets.HttpTargets[i] = &HttpTargetConfig{
Name: t.Name,
IsLog: t.IsLog,
Layout: t.Layout,
Encode: t.Encode,
HttpUrl: t.HttpUrl,
}
}

// Convert Email targets
for i, t := range yc.Targets.EMail {
appConfig.Targets.EMailTargets[i] = &EMailTargetConfig{
Name: t.Name,
IsLog: t.IsLog,
Layout: t.Layout,
Encode: t.Encode,
MailServer: t.MailServer,
MailAccount: t.MailAccount,
MailNickName: t.MailNickName,
MailPassword: t.MailPassword,
ToMail: t.ToMail,
Subject: t.Subject,
}
}

// Convert Fmt targets
for i, t := range yc.Targets.Fmt {
appConfig.Targets.FmtTargets[i] = &FmtTargetConfig{
Name: t.Name,
IsLog: t.IsLog,
Layout: t.Layout,
Encode: t.Encode,
}
}

return appConfig, nil
}
Loading
Loading