github.com/cloudfoundry/libcfbuildpack@v1.91.23/logger/logger.go (about)

     1  /*
     2   * Copyright 2018-2020 the original author or authors.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *      https://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package logger
    18  
    19  import (
    20  	"fmt"
    21  	"regexp"
    22  	"strings"
    23  
    24  	"github.com/buildpack/libbuildpack/logger"
    25  	"github.com/fatih/color"
    26  )
    27  
    28  const (
    29  	BodyIndent   = "    "
    30  	HeaderIndent = "  "
    31  
    32  	indent = "      "
    33  )
    34  
    35  var (
    36  	description      = color.New(color.FgBlue)
    37  	error            = color.New(color.FgRed, color.Bold)
    38  	errorName        = color.New(color.FgRed, color.Bold)
    39  	errorDescription = color.New(color.FgRed)
    40  	lines            = regexp.MustCompile(`(?m)^`)
    41  	name             = color.New(color.FgBlue, color.Bold)
    42  	warning          = color.New(color.FgYellow, color.Bold)
    43  
    44  	errorEyeCatcher     string
    45  	firstLineEyeCatcher string
    46  	warningEyeCatcher   string
    47  )
    48  
    49  func init() {
    50  	color.NoColor = false
    51  	errorEyeCatcher = error.Sprint("----->")
    52  	firstLineEyeCatcher = color.New(color.FgRed, color.Bold).Sprint("----->")
    53  	warningEyeCatcher = warning.Sprint("----->")
    54  }
    55  
    56  // Logger is an extension to libbuildpack.Logger to add additional functionality.
    57  type Logger struct {
    58  	logger.Logger
    59  }
    60  
    61  // Title prints the buildpack description flush left, with an empty line above it.
    62  func (l Logger) Title(v Identifiable) {
    63  	if !l.IsInfoEnabled() {
    64  		return
    65  	}
    66  
    67  	l.Info("\n%s", l.prettyIdentity(v, name, description))
    68  }
    69  
    70  // Terminal error prints the build description colored red and bold, flush left, with an empty line above it, followed
    71  // by the log message message red and bold, and indented two spaces.
    72  func (l Logger) TerminalError(v Identifiable, format string, args ...interface{}) {
    73  	if !l.IsInfoEnabled() {
    74  		return
    75  	}
    76  
    77  	l.Info("\n%s", l.prettyIdentity(v, errorName, errorDescription))
    78  	l.HeaderError(format, args...)
    79  }
    80  
    81  // Header prints the log message indented two spaces, with an empty line above it.
    82  func (l Logger) Header(format string, args ...interface{}) {
    83  	if !l.IsInfoEnabled() {
    84  		return
    85  	}
    86  
    87  	l.Info("%s%s", HeaderIndent, fmt.Sprintf(format, args...))
    88  }
    89  
    90  // HeaderError prints the log message colored red and bold, indented two spaces, with an empty line above it.
    91  func (l Logger) HeaderError(format string, args ...interface{}) {
    92  	if !l.IsInfoEnabled() {
    93  		return
    94  	}
    95  
    96  	l.Header(error.Sprintf(format, args...))
    97  }
    98  
    99  // HeaderWarning prints the log message colored yellow and bold, indented two spaces, with an empty line above it.
   100  func (l Logger) HeaderWarning(format string, args ...interface{}) {
   101  	if !l.IsInfoEnabled() {
   102  		return
   103  	}
   104  
   105  	l.Header(warning.Sprintf(format, args...))
   106  }
   107  
   108  // Body prints the log message with each line indented four spaces.
   109  func (l Logger) Body(format string, args ...interface{}) {
   110  	if !l.IsInfoEnabled() {
   111  		return
   112  	}
   113  
   114  	l.Info(color.New(color.Faint).Sprint(
   115  		strings.ReplaceAll(
   116  			l.BodyIndent(format, args...),
   117  			fmt.Sprintf("\x1b[%dm", color.Reset),
   118  			fmt.Sprintf("\x1b[%dm\x1b[%dm", color.Reset, color.Faint))))
   119  }
   120  
   121  // BodyError prints the log message colored red and bold with each line indented four spaces.
   122  func (l Logger) BodyError(format string, args ...interface{}) {
   123  	if !l.IsInfoEnabled() {
   124  		return
   125  	}
   126  
   127  	l.Body(error.Sprintf(format, args...))
   128  }
   129  
   130  // BodyIndent indents each line of a log message to the BodyIndent offset.
   131  func (l Logger) BodyIndent(format string, args ...interface{}) string {
   132  	return lines.ReplaceAllString(fmt.Sprintf(format, args...), BodyIndent)
   133  }
   134  
   135  // BodyWarning prints the log message colored yellow and bold with each line indented four spaces.
   136  func (l Logger) BodyWarning(format string, args ...interface{}) {
   137  	if !l.IsInfoEnabled() {
   138  		return
   139  	}
   140  
   141  	l.Body(warning.Sprintf(format, args...))
   142  }
   143  
   144  func (l Logger) LaunchConfiguration(format string, defaultValue string) {
   145  	l.Body("%s. Default %s", format, color.New(color.Italic).Sprint(defaultValue))
   146  }
   147  
   148  func (l Logger) prettyIdentity(v Identifiable, nameColor *color.Color, descriptionColor *color.Color) string {
   149  	if v == nil {
   150  		return ""
   151  	}
   152  
   153  	name, description := v.Identity()
   154  
   155  	if description == "" {
   156  		return nameColor.Sprint(name)
   157  	}
   158  
   159  	return fmt.Sprintf("%s %s", nameColor.Sprint(name), descriptionColor.Sprint(description))
   160  }
   161  
   162  // PrettyIdentity formats a standard pretty identity of a type.
   163  //
   164  // Deprecated: Use Title
   165  func (l Logger) PrettyIdentity(v Identifiable) string {
   166  	if v == nil {
   167  		return ""
   168  	}
   169  
   170  	n, d := v.Identity()
   171  
   172  	if d == "" {
   173  		return name.Sprint(n)
   174  	}
   175  
   176  	return fmt.Sprintf("%s %s", name.Sprint(n), description.Sprint(description))
   177  }
   178  
   179  // Error prints the log message with the error eye catcher.
   180  //
   181  // Deprecated: Use HeaderError or BodyError
   182  func (l Logger) Error(format string, args ...interface{}) {
   183  	if !l.IsInfoEnabled() {
   184  		return
   185  	}
   186  
   187  	l.Info("%s %s", errorEyeCatcher, fmt.Sprintf(format, args...))
   188  }
   189  
   190  // FirstLine prints the log messages with the first line eye catcher.
   191  //
   192  // Deprecated: Use Title
   193  func (l Logger) FirstLine(format string, args ...interface{}) {
   194  	if !l.IsInfoEnabled() {
   195  		return
   196  	}
   197  
   198  	l.Info("%s %s", firstLineEyeCatcher, fmt.Sprintf(format, args...))
   199  }
   200  
   201  // SubsequentLine prints log message with the subsequent line indent.
   202  //
   203  // Deprecated: Use Body
   204  func (l Logger) SubsequentLine(format string, args ...interface{}) {
   205  	if !l.IsInfoEnabled() {
   206  		return
   207  	}
   208  
   209  	l.Info("%s %s", indent, fmt.Sprintf(format, args...))
   210  }
   211  
   212  // Warning prints the log message with the warning eye catcher.
   213  //
   214  // Deprecated: Use HeaderWarning or BodyWarning
   215  func (l Logger) Warning(format string, args ...interface{}) {
   216  	if !l.IsInfoEnabled() {
   217  		return
   218  	}
   219  
   220  	l.Info("%s %s", warningEyeCatcher, fmt.Sprintf(format, args...))
   221  }