存档

2019年3月 的存档

go结构化日志库logrus

2019年3月5日 没有评论

日志无论在开发还是生产当中,都是很重要的部分,帮助我们快速定位和发现问题。logrus是一个可以格式化存储日志的golang库,而且它还兼容标准库中的logger。logrus目前在github的start数量已经快达到10k,可谓是一个非常受欢迎的golang第三方库了。

logrus特性

  • 完全兼容golang标准库日志模块:logrus拥有六种日志级别:debug、info、warn、error、fatal和panic,这是golang标准库日志模块的API的超集。如果您的项目使用标准库日志模块,完全可以以最低的代价迁移到logrus上。
  • 可扩展的Hook机制:允许使用者通过hook的方式将日志分发到任意地方,如本地文件系统、标准输出、logstash、elasticsearch或者mq等,或者通过hook定义日志内容和格式等。
  • 可选的日志输出格式:logrus内置了两种日志格式,JSONFormatter和TextFormatter,如果这两个格式不满足需求,可以自己动手实现接口Formatter,来定义自己的日志格式。
  • Field机制:logrus鼓励通过Field机制进行精细化的、结构化的日志记录,而不是通过冗长的消息来记录日志。
  • logrus是一个可插拔的、结构化的日志框架。

最简例子

下面是一个最简单的logrus例子:

package main

import (
	log "github.com/sirupsen/logrus"
)

func main() {
	
	log.Info("hello log")
}

分隔日志

分隔日志使用了logrus提供的hook机制,然后利用rotatelogs实现这些功能。

package main

import (
        "path"
	"time"
	"github.com/lestrrat-go/file-rotatelogs"
	"github.com/pkg/errors"
	"github.com/rifflock/lfshook"

	log "github.com/sirupsen/logrus"
)

func ConfigLocalFilesystemLogger(logPath string, logFileName string, maxAge time.Duration) {
	baseLogPaht := path.Join(logPath, logFileName)
	writer, err := rotatelogs.New(
		baseLogPaht+".%Y%m%d.log",
		rotatelogs.WithLinkName(baseLogPaht),      // 生成软链,指向最新日志文件
		rotatelogs.WithMaxAge(maxAge),             // 文件最大保存时间
		rotatelogs.WithRotationTime(time.Hour*24), // 日志切割时间间隔
	)
	if err != nil {
		log.Errorf("config local file system logger error. %+v", errors.WithStack(err))
	}
	lfHook := lfshook.NewHook(lfshook.WriterMap{
		log.DebugLevel: writer, // 为不同级别设置不同的输出目的
		log.InfoLevel:  writer,
		log.WarnLevel:  writer,
		log.ErrorLevel: writer,
		log.FatalLevel: writer,
		log.PanicLevel: writer,
	}, &log.JSONFormatter{
		TimestampFormat:"2006-01-02 15:04:05",
	})
	log.AddHook(lfHook)
}

func main() {
	//log.SetOutput(os.Stdout)
	ConfigLocalFilesystemLogger("./log/", "simple", time.Hour*24*60)
	log.Info("hello log")
	log.WithFields(log.Fields{
		"animal": "walrus",
		"size":   10,
	}).Info("A group of walrus emerges from the ocean")
}

参考资料:

《golang日志框架logrus》

分类: golang 标签:

angular组件数据双向绑定

2019年3月4日 没有评论

周末的时候给网站做一个后台,前端用的是阿里的antd的angular版本。其中有用到他们的上传组件,由于有多个地方使用到上传,就把它封装成了一个通用图片上传组件。这时候服务端返回的图片链接地址,如何返回给父组件里面的表单里面哪?

通用上传组件

下面是我图片上传组件的实现:

image-upload/image-upload.component.html

<nz-upload class="avatar-uploader"
           nzAction="{{serverUrl}}"
           nzName="avatar"
           nzListType="picture-card"
           [nzShowUploadList]="false"
           [nzHeaders]="headers"
           [nzBeforeUpload]="beforeUpload"
           (nzChange)="handleChange($event)">
  <ng-container *ngIf="!previewUrl">
    <div class="ant-upload-text">Upload</div>
  </ng-container>
  <img *ngIf="previewUrl" [src]="previewUrl" class="avatar">
</nz-upload>

image-upload/image-upload.component.ts

import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
import {BACKEND_BASE_HOST, UPLOAD_IMAGE_API} from '../../services/Apis.namespace';
import { NzMessageService, UploadFile } from 'ng-zorro-antd';
import {LocalStorageService} from '../../services/local-storage.service';

@Component({
  selector: 'app-image-upload',
  templateUrl: './image-upload.component.html',
  styleUrls: ['./image-upload.component.css']
})
export class ImageUploadComponent implements OnInit {
  @Input() uploadUrl: string;
  @Output() uploadUrlChange = new EventEmitter();

  previewUrl: string;
  serverUrl: string;
  loading: boolean;
  headers: {};

  constructor(private msg: NzMessageService,
              private store: LocalStorageService) { }

  ngOnInit() {
    console.log(UPLOAD_IMAGE_API);
    this.serverUrl = UPLOAD_IMAGE_API;
    this.loading = false;
    this.headers = {'Authorization': 'Bearer ' + this.store.get('user.token')};
    this.previewUrl = this.uploadUrl;
  }

  beforeUpload() {

  }

  handleChange(info: { file: UploadFile }): void {
    console.log('info: ' + info);
    switch (info.file.status) {
      case 'uploading':
        this.loading = true;
        break;
      case 'done':
        if (info.file.response.error === '200') {
          this.previewUrl = BACKEND_BASE_HOST + info.file.response.data;
          this.uploadUrlChange.emit(info.file.response.data);
        }
        this.loading = false;

        break;
      case 'error':
        this.msg.error('Network error');
        this.loading = false;
        break;
    }
  }
}

这里贴了一下代码的实现,原理可以查看官方的相关文档。我写的时候也参考了《Angular:实现组件间双向数据绑定》