func Prettify(logMessage *events.LogMessage) string { entry := chug.ChugLogMessage(logMessage) var sourceType, sourceTypeColorized, sourceInstance, sourceInstanceColorized string sourceType = path.Base(entry.LogMessage.GetSourceType()) sourceInstance = entry.LogMessage.GetSourceInstance() // TODO: Or, do we use GetSourceType() for raw and Json source for pretty? color, ok := colorLookup[path.Base(strings.Split(sourceType, ":")[0])] if ok { sourceTypeColorized = colors.Colorize(color, sourceType) sourceInstanceColorized = colors.Colorize(color, sourceInstance) } else { sourceTypeColorized = sourceType sourceInstanceColorized = sourceInstance } prefix := fmt.Sprintf("[%s|%s]", sourceTypeColorized, sourceInstanceColorized) colorWidth := len(sourceTypeColorized+sourceInstanceColorized) - len(sourceType+sourceInstance) components := append([]string(nil), fmt.Sprintf("%-"+strconv.Itoa(34+colorWidth)+"s", prefix)) var whichFunc func(chug.Entry) []string if entry.IsLager { whichFunc = prettyPrintLog } else { whichFunc = prettyPrintRaw } components = append(components, whichFunc(entry)...) return strings.Join(components, " ") }
func prettyPrintLog(entry chug.Entry) []string { var logColor, level string switch entry.Log.LogLevel { case lager.INFO: logColor = colors.ColorDefault level = "[INFO]" case lager.DEBUG: logColor = colors.ColorGray level = "[DEBUG]" case lager.ERROR: logColor = colors.ColorRed level = "[ERROR]" case lager.FATAL: logColor = colors.ColorRed level = "[FATAL]" } var components []string components = append(components, colors.Colorize(logColor, "%-9s", level)) timestamp := entry.Log.Timestamp.Format("01/02 15:04:05.00") components = append(components, colors.Colorize(logColor, "%-17s", timestamp)) components = append(components, colors.Colorize(logColor, "%-14s", entry.Log.Session)) components = append(components, colors.Colorize(logColor, entry.Log.Message)) if entry.Log.Error != nil { components = append(components, fmt.Sprintf("\n%s%s", strings.Repeat(" ", 66), colors.Colorize(logColor, entry.Log.Error.Error()))) } if len(entry.Log.Data) > 0 { dataJSON, _ := json.Marshal(entry.Log.Data) components = append(components, fmt.Sprintf("\n%s%s", strings.Repeat(" ", 66), colors.Colorize(logColor, string(dataJSON)))) } return components }
BeforeEach(func() { previousTerm = os.Getenv("TERM") Expect(os.Setenv("TERM", "xterm")).To(Succeed()) }) AfterEach(func() { Expect(os.Setenv("TERM", previousTerm)).To(Succeed()) }) It("highlights the source type column with app-specific color", func() { input = []byte(`{"timestamp":"1429296198.620077372","source":"rep","message":"rep.event-consumer.operation-stream.executing-container-operation.succeeded-fetch-container","log_level":1,"data":{}}`) logMessage := buildLogMessage("rep", "cell-77", time.Time{}, input) prettyLog := prettify.Prettify(logMessage) Expect(prettyLog).To(MatchRegexp(strings.Replace(colors.Colorize("\x1b[34m", "rep"), "[", `\[`, -1))) }) It("chooses color based on file component of sourceType path", func() { input = []byte(`{"timestamp":"1429296198.620077372","source":"/var/vcap/packages/rep/bin/rep","message":"rep.event-consumer.operation-stream.executing-container-operation.succeeded-fetch-container","log_level":1,"data":{}}`) logMessage := buildLogMessage("/var/vcap/packages/rep/bin/rep", "cell-77", time.Time{}, input) prettyLog := prettify.Prettify(logMessage) Expect(prettyLog).To(MatchRegexp(strings.Replace(colors.Colorize("\x1b[34m", "rep"), "[", `\[`, -1))) }) Context("when the source type is unknown", func() { It("doesn't highlight the source type column", func() { input = []byte(`{"timestamp":"1429296198.620077372","source":"happyjoy","message":"rep.event-consumer.operation-stream.executing-container-operation.succeeded-fetch-container","log_level":1,"data":{"container-guid":"app-9eb203ad-72f3-4f26-6424-48f20dc12298","session":"7.1.10"}}`) logMessage := buildLogMessage("happyjoy", "", time.Time{}, input)
var _ = Describe("Colorize", func() { Context("when $TERM is set", func() { var previousTerm string BeforeEach(func() { previousTerm = os.Getenv("TERM") Expect(os.Setenv("TERM", "xterm")).To(Succeed()) }) AfterEach(func() { Expect(os.Setenv("TERM", previousTerm)).To(Succeed()) }) It("colors the text with printf-style syntax", func() { Expect(colors.Colorize("\x1b[98m", "%dxyz%s", 23, "happy")).To(Equal("\x1b[98m23xyzhappy\x1b[0m")) }) It("colors the text without printf-style syntax", func() { Expect(colors.Colorize("\x1b[98m", "happy")).To(Equal("\x1b[98mhappy\x1b[0m")) }) }) Context("when $TERM is not set", func() { var previousTerm string BeforeEach(func() { previousTerm = os.Getenv("TERM") Expect(os.Unsetenv("TERM")).To(Succeed()) })