func (p NamedLogProducer) Info(message string) {
	p.log(LogLevelInfo, message)
}
Info logs the given message with a INFO level
package logging
import (
	"fmt"
	"os"
	"strconv"
	"sync"
	"sync/atomic"
)
type LogLevel int
func (l LogLevel) String() string {
	return [...]string{"", "Debug", "Info", "Warning", "Error"}[l]
}
var defaultLogConsumer OptimizelyLogConsumer
var mutex = &sync.Mutex{}
var sdkKeyMappings = sync.Map{}
var count int32
const (
	LogLevelDebug LogLevel = iota + 1
	LogLevelInfo
	LogLevelWarning
	LogLevelError
)
func init() {
	mutex.Lock()
	defaultLogConsumer = NewFilteredLevelLogConsumer(LogLevelInfo, os.Stdout)
	mutex.Unlock()
}
func SetLogger(logger OptimizelyLogConsumer) {
	mutex.Lock()
	defaultLogConsumer = logger
	mutex.Unlock()
}
func SetLogLevel(logLevel LogLevel) {
	mutex.Lock()
	defaultLogConsumer.SetLogLevel(logLevel)
	mutex.Unlock()
}
func GetLogger(sdkKey, name string) OptimizelyLogProducer {
	fields := map[string]interface{}{
		"instance": GetSdkKeyLogMapping(sdkKey),
		"name":     name,
	}
	if shouldIncludeSDKKey {
		fields["sdkKey"] = sdkKey
	}
	return NamedLogProducer{
		fields: fields,
	}
}
func GetSdkKeyLogMapping(sdkKey string) string {
	if logMapping, _ := sdkKeyMappings.Load(sdkKey); logMapping != nil {
		if lm, ok := logMapping.(string); ok {
			return lm
		}
	} else if sdkKey != "" {
		mapping := "Instance-" + strconv.Itoa(int(atomic.AddInt32(&count, 1)))
		sdkKeyMappings.Store(sdkKey, mapping)
		return mapping
	}
	return ""
}
var shouldIncludeSDKKey = false
func IncludeSDKKeyInLogFields(include bool) {
	shouldIncludeSDKKey = include
}
type NamedLogProducer struct {
	fields map[string]interface{}
}
func (p NamedLogProducer) Debug(message string) {
	p.log(LogLevelDebug, message)
}