func (l *Log) Fatalf(format string, args ...interface{}) {
	opts := getLoggerOpts(l.module, apilogging.CRITICAL)
	if l.loadCustomLogger() {
		l.customLogger.Fatalf(format, args...)
		return
	}
	l.logf(opts, apilogging.CRITICAL, format, args...)
	l.deflogger.Fatalf(format, args...)
}
Fatalf is CRITICAL log formatted followed by a call to os.Exit(1).
package modlog
import (
	"fmt"
	"log"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
	"io"
	"sync/atomic"
	"github.com/hyperledger/fabric-sdk-go/api/apilogging"
	"github.com/hyperledger/fabric-sdk-go/pkg/logging/decorator"
	"github.com/hyperledger/fabric-sdk-go/pkg/logging/utils"
)
var rwmutex = &sync.RWMutex{}
var moduleLevels = &decorator.ModuleLevels{}
var callerInfos = &decorator.CallerInfo{}
var useCustomLogger int32
var loggerProviderInstance apilogging.LoggerProvider
var loggerProviderOnce sync.Once
type Provider struct {
}
func (p *Provider) GetLogger(module string) apilogging.Logger {
	newDefLogger := log.New(os.Stdout, fmt.Sprintf(logPrefixFormatter, module), log.Ldate|log.Ltime|log.LUTC)
	return &Log{deflogger: newDefLogger, module: module}
}
func LoggerProvider() apilogging.LoggerProvider {
	return &Provider{}
}
func InitLogger(l apilogging.LoggerProvider) {
	loggerProviderOnce.Do(func() {
		loggerProviderInstance = l
		atomic.StoreInt32(&useCustomLogger, 1)
	})
}
type Log struct {
	deflogger    *log.Logger
	customLogger apilogging.Logger
	module       string
	custom       bool
	once         sync.Once
}
type loggerOpts struct {
	levelEnabled      bool
	callerInfoEnabled bool
}
const (
	logLevelFormatter   = "UTC %s-> %4.4s "
	logPrefixFormatter  = " [%s] "
	callerInfoFormatter = "- %s "
)
func SetLevel(module string, level apilogging.Level) {
	rwmutex.Lock()
	defer rwmutex.Unlock()
	moduleLevels.SetLevel(module, level)
}
func GetLevel(module string) apilogging.Level {
	rwmutex.RLock()
	defer rwmutex.RUnlock()
	return moduleLevels.GetLevel(module)
}
func IsEnabledFor(module string, level apilogging.Level) bool {
	rwmutex.RLock()
	defer rwmutex.RUnlock()
	return moduleLevels.IsEnabledFor(module, level)
}
func ShowCallerInfo(module string, level apilogging.Level) {
	rwmutex.Lock()
	defer rwmutex.Unlock()
	callerInfos.ShowCallerInfo(module, level)
}
func HideCallerInfo(module string, level apilogging.Level) {
	rwmutex.Lock()
	defer rwmutex.Unlock()
	callerInfos.HideCallerInfo(module, level)
}
func getLoggerOpts(module string, level apilogging.Level) *loggerOpts {
	rwmutex.RLock()
	defer rwmutex.RUnlock()
	return &loggerOpts{
		levelEnabled:      moduleLevels.IsEnabledFor(module, level),
		callerInfoEnabled: callerInfos.IsCallerInfoEnabled(module, level),
	}
}
func (l *Log) Fatal(args ...interface{}) {
	opts := getLoggerOpts(l.module, apilogging.CRITICAL)
	if l.loadCustomLogger() {
		l.customLogger.Fatal(args...)
		return
	}
	l.log(opts, apilogging.CRITICAL, args...)
	l.deflogger.Fatal(args...)
}