package blog4go

import (
"bytes"
"fmt"
"net"
"sync"
)

// SocketWriter 是一个socket日志结构体
type SocketWriter struct {
level LevelType  //日志级别

closed bool   //链接是否关闭

// log hook
hook      Hook  //回调函数
hookLevel LevelType  //回调函数 对应的日志级别
hookAsync bool   //日志是否异步记录

// socket
writer net.Conn  //网络链接

lock *sync.Mutex  //读写锁
}

// NewSocketWriter  创建一个单例线程写
func NewSocketWriter(network string, address string) (err error) {
singltonLock.Lock()
defer singltonLock.Unlock()
if nil != blog {
return ErrAlreadyInit
}

socketWriter, err := newSocketWriter(network, address)
if nil != err {
return err
}

blog = socketWriter
return nil
}

// newSocketWriter 创建一个写socket  但是不是单例
func newSocketWriter(network string, address string) (socketWriter *SocketWriter, err error) {
socketWriter = new(SocketWriter)
socketWriter.level = DEBUG
socketWriter.closed = false
socketWriter.lock = new(sync.Mutex)

// log hook
socketWriter.hook = nil
socketWriter.hookLevel = DEBUG

conn, err := net.Dial(network, address)
if nil != err {
return nil, err
}
socketWriter.writer = conn

blog = socketWriter
return socketWriter, nil
}
//写日志   并设置日志级别  如果链接是关闭的 直接返回
func (writer *SocketWriter) write(level LevelType, args ...interface{}) {
writer.lock.Lock()
defer writer.lock.Unlock()

if writer.closed {
return
}

defer func() {
// call log hook
if nil != writer.hook && !(level < writer.hookLevel) {
if writer.hookAsync {
go func(level LevelType, args ...interface{}) {
writer.hook.Fire(level, args...)
}(level, args...)

} else {
writer.hook.Fire(level, args...)

}
}
}()

buffer := bytes.NewBuffer(timeCache.Format())
buffer.WriteString(level.prefix())
buffer.WriteString(fmt.Sprint(args...))
writer.writer.Write(buffer.Bytes())
}
//写日志
func (writer *SocketWriter) writef(level LevelType, format string, args ...interface{}) {
writer.lock.Lock()
defer writer.lock.Unlock()

if writer.closed {
return
}

defer func() {

// call log hook
if nil != writer.hook && !(level < writer.hookLevel) {
if writer.hookAsync {
go func(level LevelType, format string, args ...interface{}) {
writer.hook.Fire(level, fmt.Sprintf(format, args...))
}(level, format, args...)

} else {
writer.hook.Fire(level, fmt.Sprintf(format, args...))
}
}
}()

buffer := bytes.NewBuffer(timeCache.Format())
buffer.WriteString(level.prefix())
buffer.WriteString(fmt.Sprintf(format, args...))
writer.writer.Write(buffer.Bytes())
}

// 获取日志级别
func (writer *SocketWriter) Level() LevelType {
return writer.level
}

//设置日志级别
func (writer *SocketWriter) SetLevel(level LevelType) {
writer.level = level
}

//设置回调函数
func (writer *SocketWriter) SetHook(hook Hook) {
writer.hook = hook
}

//设置同步书写文件  如果为真的话
func (writer *SocketWriter) SetHookAsync(async bool) {
writer.hookAsync = async
}

//设置回调函数对应日志级别
func (writer *SocketWriter) SetHookLevel(level LevelType) {
writer.hookLevel = level
}

// TimeRotated暂时什么都不做
func (writer *SocketWriter) TimeRotated() bool {
return false
}

// SetTimeRotated暂时什么都不做
func (writer *SocketWriter) SetTimeRotated(timeRotated bool) {
return
}

// Retentions暂时什么都不做
func (writer *SocketWriter) Retentions() int64 {
return 0
}

// SetRetentions暂时什么都不做
func (writer *SocketWriter) SetRetentions(retentions int64) {
return
}

// RotateSize暂时什么都不做
func (writer *SocketWriter) RotateSize() int64 {
return 0
}

// SetRotateSize暂时什么都不做
func (writer *SocketWriter) SetRotateSize(rotateSize int64) {
return
}

// RotateLines暂时什么都不做
func (writer *SocketWriter) RotateLines() int {
return 0
}

// SetRotateLines暂时什么都不做
func (writer *SocketWriter) SetRotateLines(rotateLines int) {
return
}

// Colored 暂时什么都不做
func (writer *SocketWriter) Colored() bool {
return false
}

// SetColored 暂时什么都不做
func (writer *SocketWriter) SetColored(colored bool) {
return
}

// Close将关闭写流
func (writer *SocketWriter) Close() {
writer.lock.Lock()
defer writer.lock.Unlock()
if writer.closed {
return
}

writer.writer.Close()
writer.writer = nil
writer.closed = true
}

// flush暂时什么都不做
func (writer *SocketWriter) flush() {
return
}

// Trace  日志级别
func (writer *SocketWriter) Trace(args ...interface{}) {
if nil == writer.writer || TRACE < writer.level {
return
}

writer.write(TRACE, args...)
}

// Trac  日志级别
func (writer *SocketWriter) Tracef(format string, args ...interface{}) {
if nil == writer.writer || TRACE < writer.level {
return
}

writer.writef(TRACE, format, args...)
}

// Debug日志级别
func (writer *SocketWriter) Debug(args ...interface{}) {
if nil == writer.writer || DEBUG < writer.level {
return
}

writer.write(DEBUG, args...)
}

// Debugf日志级别
func (writer *SocketWriter) Debugf(format string, args ...interface{}) {
if nil == writer.writer || DEBUG < writer.level {
return
}

writer.writef(DEBUG, format, args...)
}

// Info日志级别
func (writer *SocketWriter) Info(args ...interface{}) {
if nil == writer.writer || INFO < writer.level {
return
}

writer.write(INFO, args...)
}

// Infof日志级别
func (writer *SocketWriter) Infof(format string, args ...interface{}) {
if nil == writer.writer || INFO < writer.level {
return
}

writer.writef(INFO, format, args...)
}

// Warn日志级别
func (writer *SocketWriter) Warn(args ...interface{}) {
if nil == writer.writer || WARNING < writer.level {
return
}

writer.write(WARNING, args...)
}

// Warnf日志级别
func (writer *SocketWriter) Warnf(format string, args ...interface{}) {
if nil == writer.writer || WARNING < writer.level {
return
}

writer.writef(WARNING, format, args...)
}

// Error 日志级别
func (writer *SocketWriter) Error(args ...interface{}) {
if nil == writer.writer || ERROR < writer.level {
return
}

writer.write(ERROR, args...)
}

// Errorf日志级别
func (writer *SocketWriter) Errorf(format string, args ...interface{}) {
if nil == writer.writer || ERROR < writer.level {
return
}

writer.writef(ERROR, format, args...)
}

// Critical日志级别
func (writer *SocketWriter) Critical(args ...interface{}) {
if nil == writer.writer || CRITICAL < writer.level {
return
}

writer.write(CRITICAL, args...)
}

// Criticalf 日志级别
func (writer *SocketWriter) Criticalf(format string, args ...interface{}) {
if nil == writer.writer || CRITICAL < writer.level {
return
}

writer.writef(CRITICAL, format, args...)
}

socketWriter.go的更多相关文章

  1. Java使用POS打印机(无驱)

    使用原因:应项目要求,需要使用打印机,但是如果使用Windows驱动来实现打印,在某些条件下会发生网络堵塞等,而且没有提示,所以为了确保信息的完整,避免数据丢失.我们使用无驱打印(直接写端口的方法), ...

  2. 【转】Kettle集群

    本文转自:http://blog.csdn.net/dqswuyundong/article/details/5952009 Kettle集群 Kettle是一款开源的ETL工具,以其高效和可扩展性而 ...

  3. kettle用mysql创建资源库执行sql代码报错

    一.原因:  sql语句里边使用 'Y' 'N'  给boolean类型的赋值产生sql失败    二.解决方法:将insert语句中‘Y’或‘N’ 改成TRUE或FALSE即可,共两张表3个地方  ...

  4. Go第七篇之规范的接口

    接口本身是调用方和实现方均需要遵守的一种协议,大家按照统一的方法命名参数类型和数量来协调逻辑处理的过程. Go 语言中使用组合实现对象特性的描述.对象的内部使用结构体内嵌组合对象应该具有的特性,对外通 ...

  5. 07. Go 语言接口

    Go 语言接口 接口本身是调用方和实现方均需要遵守的一种协议,大家按照统一的方法命名参数类型和数量来协调逻辑处理的过程. Go 语言中使用组合实现对象特性的描述.对象的内部使用结构体内嵌组合对象应该具 ...

  6. (转)JAVA socket 进行十六进制报文交互测试

    import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io. ...

  7. django正常运行确报错的解决方法

    django正常运行却报错的处理方法 出处 : https://www.infvie.com/ops-notes/django-normal-operation-error 报错一:self._soc ...

  8. Java 实现 POS 打印机无驱打印

    来源:https://www.ibm.com/developerworks/cn/java/j-lo-pos/index.html 行业需求 我们是一家专业做酒店餐饮软件的公司,餐饮软件一个重要的功能 ...

  9. 【源码解析】阿里在线诊断工具greys源码

    撸起袖子加油干!开门见山! 一.源码下载 下载代码: git clone https://github.com/oldmanpushcart/greys-anatomy.git 二.源码分析 2.1 ...

随机推荐

  1. OpenLayers3的WMS空间查询实现多个图层

    空间查询前面的帖子写过,但是在一次性查询多个图层的时候卡了一下,再次记录下. 1.WMS数据源: var wmsSource = new ol.source.TileWMS({ url:'http:/ ...

  2. 负载均衡之让nginx跑起来

    一个简单的原因,我不得不考虑负载 小源做了个网站,很简单,传统的java开放框架,和一个tomcat搞定,让人没想到的是网站既然火起来了,很快一个tomcat就搞不定了,怎么办? 网站访问量很大,既然 ...

  3. Java IO学习--(三)通道

    Java IO中的管道为运行在同一个JVM中的两个线程提供了通信的能力.所以管道也可以作为数据源以及目标媒介. 你不能利用管道与不同的JVM中的线程通信(不同的进程).在概念上,Java的管道不同于U ...

  4. mongodb3.6 (四)net 客户端如何连接、访问mongodb集群

    前言 在是一篇文章mongodb如何做数据备灾 中已经介绍mongodb集群是如何工作,可能很多人都有这样一个疑问:客户端如何知道主服务挂了呢?这一篇文章将介绍如何在net中访问这个集群. 第一步.安 ...

  5. IT轮子系列(六)——Excel上传与解析,一套代码解决所有Excel业务上传,你Get到了吗

    前言 在日常开发当中,excel的上传与解析是很常见的.根据业务不同,解析的数据模型也都不一样.不同的数据模型也就需要不同的校验逻辑,这往往需要写多套的代码进行字段的检验,如必填项,数据格式.为了避免 ...

  6. Spring中事务管理

    spring事务管理两种方式 第一种 编程式事务管理(不用) 第二种 声明式事务管理 (1)      基于xml配置文件实现 (2)      基于注解实现 一:声明式事务管理(xml配置) 第一步 ...

  7. sqlplus 分析执行计划

    转载 http://xm-koma.iteye.com/blog/1048451 对于oracle9i,需要手工设置plustrace角色,步骤如下: 1.在SQL>connect sys/密码 ...

  8. AngularJs 学习笔记(三)依赖注入

    一个对象可以通过三种方式来获取对依赖对象的控制权: 1.在内部创建依赖的对象 2.通过全局变量引用这个依赖对象 3.通过参数进行传递(在这里是通过函数参数) AngularJs通过$injector注 ...

  9. Web安全工具大汇聚

    http://www.owasp.org/index.PHP/Phoenix/Tools http://sebug.net/paper/other/Web安全工具大汇聚.txt =========== ...

  10. 数据库导入Excel数据的简易方法

    当然,最糙猛的方式就是自己写程序读取Excel程序然后插进数据库,但那种方式要求太高.说个简单方法,主流数据库的管理工具支持CSV文件格式数据向表导入,而Excel可以另存外CSV文件,这种导入就手工 ...