Skip to content

Migration from standard log package

Pavel Korotkov edited this page Oct 26, 2013 · 9 revisions

Migration from the log package to seelog is a common task for those who want to start using seelog in an application which already utilizes logging functionality via the standard pkg.

Incompatibility

Seelog concepts are different from the standard log concepts, and thus they are not compatible.

Example #1: log.Printf. There is no analogue of this function in seelog, because Printf doesn't carry any log level information, so if we are migrating, it is not clear what we should replace log.Printf with. It might be seelog.Infof or seelog.Debugf or any others.

Example #2: log.Panicf. It creates the message according to format and panics using the formatted message as the panic text. In seelog, a single call to any of the log functions may produce several messages with different formats (depending on the config), so it's unclear what to use as the panic text.

Example #3: log.SetPrefix. Seelog just cannot have any analogue of that, because a single call to any log function (e.g. Debug) may produce several messages with different formats, so it doesn't make sense to have one such global function. Also, one of the seelog core principles is to avoid configuration via code. All configuring is made via config files. So such a function would break the seelog concepts.

Conclusion

Currently (Go1.X), seelog is not compatible with standard log package and cannot have any of 'standard log pkg compatibility' features.

Migration note

Despite the fact that actually you cannot replace log with seelog and have the same behavior (they are just incompatible, as stated above), you may want to automate the migration from log to seelog. We recommend to create a replacement script for your projects.

Example migration script

Here is a Python script performing some replacements in multiple files for several log package funcs. It can be used as a stub to meet your own replacement needs.

import os, sys,shutil,re

changeDir= './test'
openFlags = 'rb'
writeFlags = 'r+b'
encoding = 'utf-8'
backupPostfix = '.backup'

goFilesRx = r'.+\.go$'

patterns = [

(re.compile(ur'''(?P<before>import[\s\S]*?)"log"''', re.U | re.M), 
            ur'''\g<before>log "github.com/cihub/seelog"'''), # change import

(re.compile(ur'''log.Print(?P<after>.*?)''', re.U), 
            ur'''log.Info\g<after>'''), # Print -> Info

(re.compile(ur'''log.Println(?P<after>.*?)''', re.U),
            ur'''log.Info\g<after>'''), # Println -> Info

(re.compile(ur'''log.Printf(?P<after>.*?)''', re.U),
            ur'''log.Infof\g<after>'''), # Printf -> Infof

(re.compile(ur'''(?P<ws>[\t ]*)log.Panic\((?P<values>.*?)\)''', re.U),
            ur'''\g<ws>log.Info(\g<values>)\n\g<ws>panic(fmt.Sprint(\g<values>))'''), # Panic -> Info + panic(...)

(re.compile(ur'''(?P<ws>[\t ]*)log.Panicf\((?P<values>.*?)\)''', re.U),
            ur'''\g<ws>log.Infof(\g<values>)\n\g<ws>panic(fmt.Sprint(\g<values>))'''), # Panicf -> Info + panic(...)

# ... and so on

]

def rewriteFile(fl, text):
   fl.read() # To preserve file creation date
   fl.seek(0)
   fl.write(text.encode(encoding))
   fl.truncate()

def replacePatterns(filePath, backup):
   # Open file and get its contents
   input = open(filePath, openFlags)
   fileText = unicode(input.read(), encoding)
   input.close()

   found = False
   # Make replacements for all patterns
   for pc in patterns:
      origRx = pc[0]
      replRx = pc[1]
      replacedText = re.sub(origRx, replRx, fileText)
      if fileText != replacedText:
         found = True
      fileText = replacedText

   # If any replacements were made, write the changed file
   if found:
      if backup:
         bckName = filePath + backupPostfix
         shutil.copy2(filePath, bckName)

      outF = open(filePath,writeFlags)
      rewriteFile(outF, fileText)
      outF.close()

def replaceFunc(a, dir, files):
   for f in files:
      fPath = dir + '/' + f
      if re.search(goFilesRx, f, re.U) and os.path.isfile(fPath):
         replacePatterns(fPath, True)

os.path.walk(changeDir, replaceFunc, 3)