github.com/hasnat/dolt/go@v0.0.0-20210628190320-9eb5d843fbb7/libraries/events/emitter.go (about) 1 // Copyright 2019 Dolthub, Inc. 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 events 16 17 import ( 18 "context" 19 "fmt" 20 "io" 21 "runtime" 22 "strings" 23 "time" 24 25 "github.com/golang/protobuf/proto" 26 "google.golang.org/grpc" 27 28 eventsapi "github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi/v1alpha1" 29 "github.com/dolthub/dolt/go/libraries/utils/filesys" 30 "github.com/dolthub/dolt/go/libraries/utils/iohelp" 31 ) 32 33 // Emitter is an interface used for processing a batch of events 34 type Emitter interface { 35 // LogEvents takes a batch of events and processes them 36 LogEvents(version string, evts []*eventsapi.ClientEvent) error 37 } 38 39 // NullEmitter is an emitter that drops events 40 type NullEmitter struct{} 41 42 // LogEvents takes a batch of events and processes them. In this case it just drops them 43 func (ne NullEmitter) LogEvents(version string, evts []*eventsapi.ClientEvent) error { 44 return nil 45 } 46 47 // WriterEmitter is an emitter that writes the text encoding of the events to it's writer 48 type WriterEmitter struct { 49 // Wr the writer to log events to 50 Wr io.Writer 51 } 52 53 // LogEvents takes a batch of events and processes them. In this case the text encoding of the events is written to 54 // the writer 55 func (we WriterEmitter) LogEvents(version string, evts []*eventsapi.ClientEvent) error { 56 for i, evt := range evts { 57 header := fmt.Sprintf("event%03d: <\n", i) 58 59 err := iohelp.WriteAll(we.Wr, []byte(header)) 60 61 if err != nil { 62 return err 63 } 64 65 str := proto.MarshalTextString(evt) 66 tokens := strings.Split(strings.TrimSpace(str), "\n") 67 str = "\t" + strings.Join(tokens, "\n\t") + "\n>\n" 68 69 err = iohelp.WriteAll(we.Wr, []byte(str)) 70 71 if err != nil { 72 return err 73 } 74 } 75 76 return nil 77 } 78 79 // GrpcEmitter sends events to a GRPC service implementing the eventsapi 80 type GrpcEmitter struct { 81 client eventsapi.ClientEventsServiceClient 82 } 83 84 // NewGrpcEmitter creates a new GrpcEmitter 85 func NewGrpcEmitter(conn *grpc.ClientConn) *GrpcEmitter { 86 client := eventsapi.NewClientEventsServiceClient(conn) 87 return &GrpcEmitter{client} 88 } 89 90 func (em *GrpcEmitter) LogEvents(version string, evts []*eventsapi.ClientEvent) error { 91 ctx, cnclFn := context.WithDeadline(context.Background(), time.Now().Add(time.Second+500*time.Millisecond)) 92 defer cnclFn() 93 94 var plat eventsapi.Platform 95 switch strings.ToLower(runtime.GOOS) { 96 case "darwin": 97 plat = eventsapi.Platform_DARWIN 98 case "linux": 99 plat = eventsapi.Platform_LINUX 100 case "windows": 101 plat = eventsapi.Platform_WINDOWS 102 } 103 104 req := eventsapi.LogEventsRequest{ 105 MachineId: getMachineID(), 106 Version: version, 107 Platform: plat, 108 Events: evts, 109 App: eventsapi.AppID_APP_DOLT, 110 } 111 112 _, err := em.client.LogEvents(ctx, &req) 113 114 return err 115 } 116 117 // SendLogEventsRequest sends a request using the grpc client 118 func (em *GrpcEmitter) SendLogEventsRequest(ctx context.Context, req *eventsapi.LogEventsRequest) error { 119 _, err := em.client.LogEvents(ctx, req) 120 if err != nil { 121 return err 122 } 123 return nil 124 } 125 126 // FileEmitter saves event requests to files 127 type FileEmitter struct { 128 fbp *FileBackedProc 129 } 130 131 // NewFileEmitter creates a new file emitter 132 func NewFileEmitter(userHomeDir string, doltDir string) *FileEmitter { 133 fs := filesys.LocalFS 134 135 return &FileEmitter{fbp: NewFileBackedProc(fs, userHomeDir, doltDir, MD5FileNamer, CheckFilenameMD5)} 136 } 137 138 // LogEvents implements the Emitter interface and writes events requests to files 139 func (fe *FileEmitter) LogEvents(version string, evts []*eventsapi.ClientEvent) error { 140 if err := fe.fbp.WriteEvents(version, evts); err != nil { 141 return err 142 } 143 144 return nil 145 }