github.com/inspektor-gadget/inspektor-gadget@v0.28.1/pkg/gadget-collection/gadgets/profile/block-io/gadget.go (about) 1 // Copyright 2019-2021 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 biolatency 16 17 import ( 18 "fmt" 19 20 gadgetv1alpha1 "github.com/inspektor-gadget/inspektor-gadget/pkg/apis/gadget/v1alpha1" 21 "github.com/inspektor-gadget/inspektor-gadget/pkg/gadget-collection/gadgets" 22 "github.com/inspektor-gadget/inspektor-gadget/pkg/gadget-collection/gadgets/profile" 23 "github.com/inspektor-gadget/inspektor-gadget/pkg/gadgets/profile/block-io/tracer" 24 ) 25 26 type Trace struct { 27 helpers gadgets.GadgetHelpers 28 29 started bool 30 tracer profile.Tracer 31 } 32 33 type TraceFactory struct { 34 gadgets.BaseFactory 35 } 36 37 func NewFactory() gadgets.TraceFactory { 38 return &TraceFactory{ 39 BaseFactory: gadgets.BaseFactory{DeleteTrace: deleteTrace}, 40 } 41 } 42 43 func (f *TraceFactory) Description() string { 44 return `The biolatency gadget traces block device I/O (disk I/O), and records the 45 distribution of I/O latency (time), giving this as a histogram when it is 46 stopped.` 47 } 48 49 func (f *TraceFactory) OutputModesSupported() map[gadgetv1alpha1.TraceOutputMode]struct{} { 50 return map[gadgetv1alpha1.TraceOutputMode]struct{}{ 51 gadgetv1alpha1.TraceOutputModeStatus: {}, 52 } 53 } 54 55 func deleteTrace(name string, t interface{}) { 56 trace := t.(*Trace) 57 if trace.tracer != nil && trace.started { 58 trace.tracer.Stop() 59 } 60 } 61 62 func (f *TraceFactory) Operations() map[gadgetv1alpha1.Operation]gadgets.TraceOperation { 63 n := func() interface{} { 64 return &Trace{} 65 } 66 67 return map[gadgetv1alpha1.Operation]gadgets.TraceOperation{ 68 gadgetv1alpha1.OperationStart: { 69 Doc: "Start biolatency", 70 Operation: func(name string, trace *gadgetv1alpha1.Trace) { 71 f.LookupOrCreate(name, n).(*Trace).Start(trace) 72 }, 73 }, 74 gadgetv1alpha1.OperationStop: { 75 Doc: "Stop biolatency and store results", 76 Operation: func(name string, trace *gadgetv1alpha1.Trace) { 77 f.LookupOrCreate(name, n).(*Trace).Stop(trace) 78 }, 79 }, 80 } 81 } 82 83 func (t *Trace) Start(trace *gadgetv1alpha1.Trace) { 84 if trace.Spec.Filter != nil { 85 trace.Status.OperationError = "Invalid filter: Filtering is not supported" 86 return 87 } 88 89 if t.started { 90 trace.Status.State = gadgetv1alpha1.TraceStateStarted 91 return 92 } 93 94 var err error 95 t.tracer, err = tracer.NewTracer() 96 if err != nil { 97 trace.Status.OperationError = fmt.Sprintf("failed to create tracer: %s", err) 98 return 99 } 100 t.started = true 101 102 trace.Status.Output = "" 103 trace.Status.State = gadgetv1alpha1.TraceStateStarted 104 } 105 106 func (t *Trace) Stop(trace *gadgetv1alpha1.Trace) { 107 if !t.started { 108 trace.Status.OperationError = "Not started" 109 return 110 } 111 112 defer func() { 113 t.started = false 114 t.tracer = nil 115 }() 116 117 output, err := t.tracer.Stop() 118 if err != nil { 119 trace.Status.OperationError = err.Error() 120 return 121 } 122 123 trace.Status.Output = output 124 trace.Status.State = gadgetv1alpha1.TraceStateCompleted 125 }