github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/pkg/remoteenforcer/internal/client/reportsclient/client.go (about) 1 package reports 2 3 import ( 4 "context" 5 "errors" 6 "os" 7 8 "go.aporeto.io/enforcerd/trireme-lib/controller/constants" 9 "go.aporeto.io/enforcerd/trireme-lib/controller/internal/enforcer/utils/rpcwrapper" 10 "go.aporeto.io/enforcerd/trireme-lib/controller/pkg/remoteenforcer/internal/client" 11 "go.aporeto.io/enforcerd/trireme-lib/controller/pkg/remoteenforcer/internal/statscollector" 12 "go.uber.org/zap" 13 ) 14 15 const ( 16 reportContextID = "UNUSED" 17 reportRPCCommand = "ProxyRPCServer.PostReportEvent" 18 ) 19 20 // reportClient This is the struct for storing state for the rpc client 21 // which reports events back to the controller process 22 type reportsClient struct { 23 collector statscollector.Collector 24 rpchdl *rpcwrapper.RPCWrapper 25 secret string 26 reportChannel string 27 stop chan bool 28 } 29 30 // NewClient initializes a new ping report client 31 func NewClient(cr statscollector.Collector) (client.Reporter, error) { 32 33 p := &reportsClient{ 34 collector: cr, 35 rpchdl: rpcwrapper.NewRPCWrapper(), 36 secret: os.Getenv(constants.EnvStatsSecret), 37 reportChannel: os.Getenv(constants.EnvStatsChannel), 38 stop: make(chan bool), 39 } 40 41 if p.reportChannel == "" { 42 return nil, errors.New("no path to stats socket provided") 43 } 44 45 if p.secret == "" { 46 return nil, errors.New("no secret provided for stats channel") 47 } 48 49 return p, nil 50 } 51 52 func (p *reportsClient) sendStats(ctx context.Context) { 53 54 for { 55 select { 56 case <-ctx.Done(): 57 return 58 case r := <-p.collector.GetReports(): 59 p.sendRequest(r) 60 } 61 } 62 } 63 64 func (p *reportsClient) sendRequest(report *statscollector.Report) { 65 66 request := rpcwrapper.Request{ 67 PayloadType: reportTypeToPayloadType(report.Type), 68 Payload: report.Payload, 69 } 70 71 if err := p.rpchdl.RemoteCall( 72 reportContextID, 73 reportRPCCommand, 74 &request, 75 &rpcwrapper.Response{}, 76 ); err != nil { 77 zap.L().Error("unable to execute rpc", zap.Error(err)) 78 } 79 } 80 81 // Start This is an private function called by the remoteenforcer to connect back 82 // to the controller over a stats channel 83 func (p *reportsClient) Run(ctx context.Context) error { 84 if err := p.rpchdl.NewRPCClient(reportContextID, p.reportChannel, p.secret); err != nil { 85 zap.L().Error("unable to create new rpc client", zap.Error(err)) 86 return err 87 } 88 89 go p.sendStats(ctx) 90 91 return nil 92 } 93 94 // Send is unimplemented. 95 func (p *reportsClient) Send() error { 96 return nil 97 } 98 99 func reportTypeToPayloadType(rtype statscollector.ReportType) (ptype rpcwrapper.PayloadType) { 100 101 switch rtype { 102 case statscollector.PacketReport: 103 ptype = rpcwrapper.PacketReport 104 case statscollector.CounterReport: 105 ptype = rpcwrapper.CounterReport 106 case statscollector.DNSReport: 107 ptype = rpcwrapper.DNSReport 108 case statscollector.PingReport: 109 ptype = rpcwrapper.PingReport 110 case statscollector.ConnectionExceptionReport: 111 ptype = rpcwrapper.ConnectionExceptionReport 112 default: 113 return 114 } 115 116 return ptype 117 }