Apply .gitignore rules
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
DefaultLogPath/
|
||||
|
||||
/test_*/
|
||||
@@ -0,0 +1,103 @@
|
||||
package ini_config
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ParseFile
|
||||
// @description: 从文件读取配置文件,并转化为map对象
|
||||
// parameter:
|
||||
// @filePath:文件路径
|
||||
// return:
|
||||
// @map[string]string: 配置信息
|
||||
// @error:错误信息
|
||||
func ParseFile(filePath string) (map[string]string, error) {
|
||||
fn, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer fn.Close()
|
||||
|
||||
kvMap := make(map[string]string)
|
||||
rd := bufio.NewReader(fn)
|
||||
for {
|
||||
data, _, err := rd.ReadLine()
|
||||
if err != nil || io.EOF == err {
|
||||
break
|
||||
}
|
||||
|
||||
line := strings.TrimSpace(string(data))
|
||||
if line == "" || line[0:1] == "#" {
|
||||
continue
|
||||
}
|
||||
|
||||
var k string
|
||||
var v string
|
||||
k, v, err = Parse(line)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
kvMap[k] = v
|
||||
}
|
||||
|
||||
return kvMap, nil
|
||||
}
|
||||
|
||||
// Parse
|
||||
// @description: 转换单行字符串为配置对象
|
||||
// parameter:
|
||||
// @line:单行内容
|
||||
// return:
|
||||
// @string:key
|
||||
// @string:value
|
||||
// @error:错误信息
|
||||
func Parse(line string) (string, string, error) {
|
||||
ls := strings.SplitN(line, "=", 2)
|
||||
if len(ls) != 2 {
|
||||
return "", "", errors.New(fmt.Sprintf("配置%s中未找到=分隔符", line))
|
||||
}
|
||||
|
||||
var key = strings.TrimSpace(ls[0])
|
||||
var value string
|
||||
|
||||
i := strings.LastIndex(ls[1], "#")
|
||||
if i < 0 {
|
||||
value = strings.TrimSpace(ls[1])
|
||||
} else {
|
||||
s := ls[1][:i]
|
||||
value = strings.TrimSpace(s)
|
||||
}
|
||||
|
||||
return key, value, nil
|
||||
}
|
||||
|
||||
// ParseMultipleLines
|
||||
// @description: 转换多行字符串为配置对象
|
||||
// parameter:
|
||||
// @content:多行内容(通过\n换行)
|
||||
// return:
|
||||
// @map[string]string:配置信息
|
||||
// @error:错误信息
|
||||
func ParseMultipleLines(content string) (map[string]string, error) {
|
||||
lines := strings.Split(content, "\n")
|
||||
kvMap := make(map[string]string)
|
||||
for _, line := range lines {
|
||||
if line == "" || line[0:1] == "#" {
|
||||
continue
|
||||
}
|
||||
|
||||
k, v, err := Parse(line)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kvMap[k] = v
|
||||
}
|
||||
|
||||
return kvMap, nil
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package timeUtil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 将字符串转换为标准的时间格式
|
||||
// str:输入,格式为:2015-10-25T17:07:30
|
||||
// 返回值:
|
||||
// 标准时间格式对象
|
||||
// 错误对象
|
||||
func ConverToStandardFormat(str string) (result time.Time, err error) {
|
||||
newStr := strings.Replace(str, "T", ":", -1)
|
||||
newStr = strings.Replace(newStr, "-", ":", -1)
|
||||
newStr = strings.Replace(newStr, ".", ":", -1)
|
||||
|
||||
slice := strings.Split(newStr, ":")
|
||||
slice = slice[:6] // 只取前6位(表示年-月-日 时:分:秒)
|
||||
|
||||
intSlice := make([]int, len(slice))
|
||||
for index, item := range slice {
|
||||
if intItem, err1 := strconv.Atoi(item); err1 != nil {
|
||||
err = fmt.Errorf("输入字符串的格式错误:%s,转换后的格式为:%s", str, newStr)
|
||||
return
|
||||
} else {
|
||||
intSlice[index] = intItem
|
||||
}
|
||||
}
|
||||
|
||||
result = time.Date(intSlice[0], time.Month(intSlice[1]), intSlice[2], intSlice[3], intSlice[4], intSlice[5], 0, time.Local)
|
||||
return
|
||||
}
|
||||
|
||||
// 将时间转换为int类型(20160120,共8位)
|
||||
// t:时间
|
||||
// 返回值:
|
||||
// int类型的数字
|
||||
func ConvertToInt(t time.Time) int {
|
||||
year := int(t.Year())
|
||||
month := int(t.Month())
|
||||
day := int(t.Day())
|
||||
|
||||
return year*10e3 + month*10e1 + day
|
||||
}
|
||||
|
||||
// 计算两个时间的日期差值
|
||||
func SubDay(time1, time2 time.Time) int {
|
||||
// 当前时间距离00:00:00的秒数
|
||||
awayFromZero := func(val time.Time) int64 {
|
||||
hour := val.Hour()
|
||||
minute := val.Minute()
|
||||
second := val.Second()
|
||||
return int64(hour*3600 + minute*60 + second)
|
||||
}
|
||||
|
||||
// 每天对应的秒数
|
||||
var eachDaySecond int64 = 24 * 3600
|
||||
|
||||
// 计算出两个时间对应的00:00:00时的时间戳
|
||||
unix1 := time1.Unix() - awayFromZero(time1)
|
||||
unix2 := time2.Unix() - awayFromZero(time2)
|
||||
|
||||
if unix1 < unix2 {
|
||||
return int((unix2 - unix1) / eachDaySecond)
|
||||
} else {
|
||||
return int((unix1 - unix2) / eachDaySecond)
|
||||
}
|
||||
}
|
||||
|
||||
// 解析时间字符串,要求时间格式形式为:12:59:59 这种形式
|
||||
// timeStr:时间字符串
|
||||
// 返回值:
|
||||
// err:错误信息
|
||||
// hour:小时值
|
||||
// minute:分钟值
|
||||
// second:秒数
|
||||
func ParseTimeString(timeStr string) (err error, hour int, minute int, second int) {
|
||||
timeSlice := strings.Split(timeStr, ":")
|
||||
if len(timeSlice) != 3 {
|
||||
err = fmt.Errorf("时间字符串格式不正确:%v", timeStr)
|
||||
return
|
||||
}
|
||||
|
||||
hour, _ = strconv.Atoi(timeSlice[0])
|
||||
minute, _ = strconv.Atoi(timeSlice[1])
|
||||
second, _ = strconv.Atoi(timeSlice[2])
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 获取时间的日期值
|
||||
// timeVal:时间值
|
||||
// 返回值:
|
||||
// time.Time:日期值
|
||||
func GetDate(timeVal time.Time) time.Time {
|
||||
year, month, day := timeVal.Date()
|
||||
|
||||
return time.Date(year, month, day, 0, 0, 0, 0, timeVal.Location())
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
package monitorMgr
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"goutil/debugUtil"
|
||||
"goutil/logUtil"
|
||||
"goutil/webUtil"
|
||||
)
|
||||
|
||||
var (
|
||||
// 报告监控信息的URL
|
||||
remoteURL = "http://maintenance.7qule.com/Manage/Monitor.ashx"
|
||||
|
||||
// 服务器IP
|
||||
serverIP string
|
||||
|
||||
// 服务器名称
|
||||
serverName string
|
||||
|
||||
// 监控时间间隔(单位:分钟)
|
||||
monitorInterval = 5
|
||||
|
||||
// 重复消息发送的时间间隔(单位:分钟)
|
||||
duplicateInterval = 5
|
||||
|
||||
// 已经发送的消息
|
||||
sentMessageMap = make(map[string]int64)
|
||||
|
||||
// 已经发送消息的锁对象
|
||||
sentMessageMutex sync.Mutex
|
||||
|
||||
// 监控方法列表
|
||||
monitorFuncList = make([]func() error, 0, 4)
|
||||
|
||||
// 监控方法锁对象
|
||||
monitorFuncMutex sync.Mutex
|
||||
)
|
||||
|
||||
// SetURL ...设置监控信息发送的URL
|
||||
// url:监控信息发送的URL
|
||||
func SetURL(url string) {
|
||||
remoteURL = url
|
||||
}
|
||||
|
||||
// SetDuplicateInterval ...设置重复消息发送的时间间隔(单位:分钟)
|
||||
// _duplicateInterval:重复消息发送的时间间隔(单位:分钟)
|
||||
func SetDuplicateInterval(_duplicateInterval int) {
|
||||
duplicateInterval = _duplicateInterval
|
||||
}
|
||||
|
||||
// SetParam ...设置参数
|
||||
// _serverIP:服务器IP
|
||||
// _serverName:服务器名称
|
||||
// _monitorInterval:监控时间间隔(单位:分钟)
|
||||
func SetParam(_serverIP, _serverName string, _monitorInterval int) {
|
||||
serverIP = _serverIP
|
||||
serverName = _serverName
|
||||
monitorInterval = _monitorInterval
|
||||
}
|
||||
|
||||
// RegisterMonitorFunc ...注册监控方法
|
||||
// f:监控方法
|
||||
func RegisterMonitorFunc(f func() error) {
|
||||
monitorFuncMutex.Lock()
|
||||
defer monitorFuncMutex.Unlock()
|
||||
|
||||
monitorFuncList = append(monitorFuncList, f)
|
||||
}
|
||||
|
||||
// Start ...启动监控服务(obsolete,建议使用Start2)
|
||||
// serverIp:服务器IP
|
||||
// serverName:服务器名称
|
||||
// monitorInterval:监控时间间隔(单位:分钟)
|
||||
func Start(serverIp, serverName string, monitorInterval int) {
|
||||
monitorConfig := NewMonitorConfig(serverIp, serverName, monitorInterval)
|
||||
Start2(monitorConfig)
|
||||
}
|
||||
|
||||
// Start ...启动监控服务2
|
||||
// monitorConfig:监控配置对象
|
||||
func Start2(monitorConfig *MonitorConfig) {
|
||||
// 设置参数
|
||||
SetParam(monitorConfig.ServerIp, monitorConfig.ServerName, monitorConfig.Interval)
|
||||
|
||||
// 实际的监控方法调用
|
||||
monitorFunc := func() {
|
||||
monitorFuncMutex.Lock()
|
||||
defer monitorFuncMutex.Unlock()
|
||||
|
||||
for _, item := range monitorFuncList {
|
||||
if err := item(); err != nil {
|
||||
Report(err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
go func() {
|
||||
// 处理内部未处理的异常,以免导致主线程退出,从而导致系统崩溃
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
logUtil.LogUnknownError(r)
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
// 先休眠,避免系统启动时就进行报警
|
||||
time.Sleep(time.Minute * time.Duration(monitorInterval))
|
||||
|
||||
// 实际的监控方法调用
|
||||
monitorFunc()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// 判断指定时间内是否已经处理过
|
||||
// conent:报告内容
|
||||
func isDuplicate(content string) bool {
|
||||
if ts, exists := sentMessageMap[content]; exists && time.Now().Unix()-ts < int64(60*duplicateInterval) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// 添加到已发送集合中
|
||||
// conent:报告内容
|
||||
func addToMap(content string) {
|
||||
sentMessageMap[content] = time.Now().Unix()
|
||||
}
|
||||
|
||||
// Report ...报告异常信息
|
||||
// format:报告内容格式
|
||||
// args:具体参数
|
||||
func Report(format string, args ...interface{}) {
|
||||
if len(args) <= 0 {
|
||||
Report2(format, "")
|
||||
} else {
|
||||
Report2(fmt.Sprintf(format, args...), "")
|
||||
}
|
||||
}
|
||||
|
||||
// Report ...报告异常信息
|
||||
// title:上报的标题
|
||||
// contentFmt:报告内容
|
||||
// args:参数列表
|
||||
func Report2(title, contentFmt string, args ...interface{}) {
|
||||
content := contentFmt
|
||||
if len(args) > 0 {
|
||||
content = fmt.Sprintf(contentFmt, args...)
|
||||
}
|
||||
|
||||
sentMessageMutex.Lock()
|
||||
defer sentMessageMutex.Unlock()
|
||||
|
||||
// 判断指定时间内是否已经处理过
|
||||
if isDuplicate(title) {
|
||||
return
|
||||
}
|
||||
|
||||
logUtil.WarnLog(fmt.Sprintf("MonitorReport:ServerIP:%s,ServerName:%s,Title:%s Content:%s", serverIP, serverName, title, content))
|
||||
|
||||
// 判断是否是DEBUG模式
|
||||
if debugUtil.IsDebug() {
|
||||
return
|
||||
}
|
||||
|
||||
detailMsg := title
|
||||
if len(content) > 0 {
|
||||
detailMsg = fmt.Sprintf("Title:%s Content:%s", title, content)
|
||||
}
|
||||
|
||||
// 定义请求参数
|
||||
postDict := make(map[string]string)
|
||||
postDict["ServerIp"] = serverIP
|
||||
postDict["ServerName"] = serverName
|
||||
postDict["Content"] = detailMsg
|
||||
|
||||
//请求url,请求头
|
||||
header := webUtil.GetFormHeader()
|
||||
transport := webUtil.NewTransport()
|
||||
transport.DisableKeepAlives = true
|
||||
transport = webUtil.GetTimeoutTransport(transport, 30)
|
||||
|
||||
statusCode, returnBytes, err := webUtil.PostMapData(remoteURL, postDict, header, transport)
|
||||
// 连接服务器,以获取数据
|
||||
//returnBytes, err := webUtil.PostWebData(remoteURL, postDict, nil)
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("MonitorReport:,错误信息为:%s", err))
|
||||
return
|
||||
}
|
||||
if statusCode != 200 {
|
||||
logUtil.ErrorLog(fmt.Sprintf("MonitorReport:,状态吗为:%d", statusCode))
|
||||
return
|
||||
}
|
||||
|
||||
result := string(returnBytes)
|
||||
logUtil.WarnLog(fmt.Sprintf("MonitorReport:Result:%s", result))
|
||||
|
||||
if result != "200" {
|
||||
logUtil.ErrorLog(fmt.Sprintf("返回值不正确,当前返回值为:%s", result))
|
||||
}
|
||||
|
||||
// 添加到已发送集合中
|
||||
addToMap(title)
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
package logSqlSync
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"goutil/logUtil"
|
||||
)
|
||||
|
||||
// 同步信息表是否已经被初始化
|
||||
var ifSyncingTableInited bool = false
|
||||
|
||||
// 同步信息项,保存已经处理过的文件的信息
|
||||
type syncingModel struct {
|
||||
// 服务器组Id
|
||||
ServerGroupId int32
|
||||
|
||||
// 待处理文件的绝对路径
|
||||
FilePath string
|
||||
|
||||
// 待处理文件的偏移量
|
||||
FileOffset int64
|
||||
|
||||
// 更新时间
|
||||
UpdateTime time.Time
|
||||
}
|
||||
|
||||
// 同步信息对象
|
||||
type syncingInfo struct {
|
||||
// 服务器组Id
|
||||
ServerGroupId int32
|
||||
|
||||
// 同步信息项
|
||||
item *syncingModel
|
||||
|
||||
// 数据库连接对象
|
||||
db *sql.DB
|
||||
}
|
||||
|
||||
// 获取同步信息
|
||||
// filePath:正在同步的文件
|
||||
// fileOffset:同步到的位置
|
||||
func (this *syncingInfo) GetSyncingInfo() (filePath string, fileOffset int64) {
|
||||
return this.item.FilePath, this.item.FileOffset
|
||||
}
|
||||
|
||||
// 更新正在同步的位置和文件信息
|
||||
// filePath:文件路径
|
||||
// offset:当前同步到的位置
|
||||
// tran:事务对象,可以为nil
|
||||
// 返回值:
|
||||
// error:处理的错误信息
|
||||
func (this *syncingInfo) Update(filePath string, offset int64, tran *sql.Tx) error {
|
||||
this.item.FilePath = filePath
|
||||
this.item.FileOffset = offset
|
||||
this.item.UpdateTime = time.Now()
|
||||
|
||||
// 更新到数据库
|
||||
return this.update(this.item, tran)
|
||||
}
|
||||
|
||||
// 初始化同步信息
|
||||
// 返回值:
|
||||
// error:错误信息
|
||||
func (this *syncingInfo) init() error {
|
||||
// 数据表初始化
|
||||
if ifSyncingTableInited == false {
|
||||
if err := this.initSyncingInfoTable(this.db); err == nil {
|
||||
ifSyncingTableInited = true
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 获取此表的同步信息
|
||||
data, exist, err := this.get()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 2. 如果同步信息不存在,则初始化一条到此表
|
||||
if exist == false {
|
||||
data = &syncingModel{
|
||||
ServerGroupId: this.ServerGroupId,
|
||||
FilePath: "",
|
||||
FileOffset: 0,
|
||||
UpdateTime: time.Now(),
|
||||
}
|
||||
}
|
||||
|
||||
this.item = data
|
||||
return nil
|
||||
}
|
||||
|
||||
// 初始化同步信息表结构
|
||||
// db:数据库连接对象
|
||||
func (this *syncingInfo) initSyncingInfoTable(db *sql.DB) error {
|
||||
// 创建同步信息表
|
||||
createTableSql := `CREATE TABLE IF NOT EXISTS syncing_info (
|
||||
ServerGroupId int NOT NULL COMMENT '服务器组Id',
|
||||
FilePath varchar(500) NOT NULL COMMENT '正在同步的文件路径',
|
||||
FileOffset bigint(20) NOT NULL COMMENT '偏移量',
|
||||
UpdateTime datetime NOT NULL COMMENT '最后一次更新时间',
|
||||
PRIMARY KEY (ServerGroupId)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='正在同步的文件信息';`
|
||||
if _, err := db.Exec(createTableSql); err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("logSqlSync/syncingInfo.initSyncingInfoTable Error:%s", err.Error()))
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 从数据库获取数据
|
||||
// 返回值:
|
||||
// data:获取到的数据
|
||||
// exist:是否存在此数据
|
||||
// err:错误信息
|
||||
func (this *syncingInfo) get() (data *syncingModel, exist bool, err error) {
|
||||
//// 从数据库查询
|
||||
querySql := fmt.Sprintf("SELECT FilePath,FileOffset,UpdateTime FROM syncing_info WHERE ServerGroupId ='%v'", this.ServerGroupId)
|
||||
var rows *sql.Rows
|
||||
rows, err = this.db.Query(querySql)
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("logSqlSync/syncingInfo.get.Query ServerGroupId:%v error:%s", this.ServerGroupId, err.Error()))
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
if rows.Next() == false {
|
||||
exist = false
|
||||
return
|
||||
}
|
||||
exist = true
|
||||
|
||||
// 读取数据
|
||||
data = &syncingModel{
|
||||
ServerGroupId: this.ServerGroupId,
|
||||
}
|
||||
err = rows.Scan(&data.FilePath, &data.FileOffset, &data.UpdateTime)
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("logSqlSync/syncingInfo.get.Query ServerGroupId:%v error:%s", this.ServerGroupId, err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 把同步信息更新到数据库
|
||||
// data:待更新的数据
|
||||
// tran:事务处理对象
|
||||
// 返回值:
|
||||
// error:错误信息
|
||||
func (this *syncingInfo) update(data *syncingModel, tran *sql.Tx) error {
|
||||
updateSql := "REPLACE INTO `syncing_info` SET `ServerGroupId` = ?, `FilePath` = ?,`FileOffset` = ?, `UpdateTime` = ?;"
|
||||
var err error
|
||||
if tran != nil {
|
||||
_, err = tran.Exec(updateSql, data.ServerGroupId, data.FilePath, data.FileOffset, data.UpdateTime)
|
||||
} else {
|
||||
_, err = this.db.Exec(updateSql, data.ServerGroupId, data.FilePath, data.FileOffset, data.UpdateTime)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
logUtil.ErrorLog(fmt.Sprintf("logSqlSync/syncingInfo.update ServerGroupId:%v error:%s", this.ServerGroupId, err.Error()))
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// 创建同步信息对象
|
||||
// _dirPath:目录的路径
|
||||
// _identifier:当前数据的唯一标识(可以使用数据库表名)
|
||||
// _db:数据库连接对象
|
||||
// 返回值:
|
||||
// 同步信息对象
|
||||
func newSyncingInfoObject(serverGroupId int32, _db *sql.DB) (result *syncingInfo, err error) {
|
||||
result = &syncingInfo{
|
||||
ServerGroupId: serverGroupId,
|
||||
db: _db,
|
||||
}
|
||||
|
||||
err = result.init()
|
||||
|
||||
return result, err
|
||||
}
|
||||
Reference in New Issue
Block a user