github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/parser/outputhelpers.go (about)

     1  // Copyright 2022-2023 The Inspektor Gadget authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package parser
    16  
    17  import (
    18  	"encoding/json"
    19  
    20  	"github.com/inspektor-gadget/inspektor-gadget/pkg/columns/formatter/textcolumns"
    21  	"github.com/inspektor-gadget/inspektor-gadget/pkg/logger"
    22  	"github.com/inspektor-gadget/inspektor-gadget/pkg/types"
    23  )
    24  
    25  // TextColumnsFormatter is the interface used for outputHelper
    26  type TextColumnsFormatter interface {
    27  	FormatHeader() string
    28  	SetShowColumns([]string) error
    29  	TransformEvent(string) (string, error)
    30  	EventHandlerFunc() any
    31  	EventHandlerFuncArray(...func()) any
    32  	SetEventCallback(eventCallback func(string))
    33  	SetEnableExtraLines(bool)
    34  }
    35  
    36  type ExtraLines interface {
    37  	ExtraLines() []string
    38  }
    39  
    40  type ErrorGetter interface {
    41  	GetType() types.EventType
    42  	GetMessage() string
    43  }
    44  
    45  // outputHelpers hides all information about underlying types from the application
    46  type outputHelper[T any] struct {
    47  	parser *parser[T]
    48  	*textcolumns.TextColumnsFormatter[T]
    49  	eventCallback    func(string)
    50  	enableExtraLines bool
    51  }
    52  
    53  func (oh *outputHelper[T]) forwardEvent(ev *T) {
    54  	oh.eventCallback(oh.TextColumnsFormatter.FormatEntry(ev))
    55  	if !oh.enableExtraLines {
    56  		return
    57  	}
    58  	// Output extra lines if the events support this
    59  	for _, line := range any(ev).(ExtraLines).ExtraLines() {
    60  		oh.eventCallback(line)
    61  	}
    62  }
    63  
    64  func (oh *outputHelper[T]) EventHandlerFunc() any {
    65  	if oh.eventCallback == nil {
    66  		panic("set event callback before getting the EventHandlerFunc from TextColumnsFormatter")
    67  	}
    68  	return func(ev *T) {
    69  		if getter, ok := any(ev).(ErrorGetter); ok {
    70  			switch getter.GetType() {
    71  			case types.ERR:
    72  				oh.parser.writeLogMessage(logger.ErrorLevel, getter.GetMessage())
    73  				return
    74  			case types.WARN:
    75  				oh.parser.writeLogMessage(logger.WarnLevel, getter.GetMessage())
    76  				return
    77  			case types.DEBUG:
    78  				oh.parser.writeLogMessage(logger.DebugLevel, getter.GetMessage())
    79  				return
    80  			case types.INFO:
    81  				oh.parser.writeLogMessage(logger.InfoLevel, getter.GetMessage())
    82  				return
    83  			}
    84  		}
    85  
    86  		oh.forwardEvent(ev)
    87  	}
    88  }
    89  
    90  func (oh *outputHelper[T]) EventHandlerFuncArray(headerFuncs ...func()) any {
    91  	if oh.eventCallback == nil {
    92  		panic("set event callback before getting the EventHandlerFunc from TextColumnsFormatter")
    93  	}
    94  	return func(events []*T) {
    95  		for _, hf := range headerFuncs {
    96  			hf()
    97  		}
    98  		for _, ev := range events {
    99  			oh.forwardEvent(ev)
   100  		}
   101  	}
   102  }
   103  
   104  func (oh *outputHelper[T]) SetEventCallback(eventCallback func(string)) {
   105  	oh.eventCallback = eventCallback
   106  }
   107  
   108  // TransformEvent takes a JSON encoded line and transforms it to columns view
   109  func (oh *outputHelper[T]) TransformEvent(line string) (string, error) {
   110  	ev := new(T)
   111  	err := json.Unmarshal([]byte(line), &ev)
   112  	if err != nil {
   113  		return "", err
   114  	}
   115  
   116  	// Apply filters
   117  	if oh.parser.filterSpecs != nil && !oh.parser.filterSpecs.MatchAll(ev) {
   118  		return "", nil
   119  	}
   120  
   121  	return oh.FormatEntry(ev), nil
   122  }
   123  
   124  func (oh *outputHelper[T]) SetShowColumns(cols []string) error {
   125  	return oh.TextColumnsFormatter.SetShowColumns(cols)
   126  }
   127  
   128  func (oh *outputHelper[T]) SetEnableExtraLines(newVal bool) {
   129  	// Check, whether the type actually supports extra lines
   130  	if _, ok := any(new(T)).(ExtraLines); !ok {
   131  		return
   132  	}
   133  	oh.enableExtraLines = newVal
   134  }