package playwright import "fmt" type tracingImpl struct { channelOwner includeSources bool isTracing bool stacksId string tracesDir string } func (t *tracingImpl) Start(options ...TracingStartOptions) error { chunkOption := TracingStartChunkOptions{} if len(options) == 1 { if options[0].Sources != nil { t.includeSources = *options[0].Sources } chunkOption.Name = options[0].Name chunkOption.Title = options[0].Title } innerStart := func() (interface{}, error) { if _, err := t.channel.Send("tracingStart", options); err != nil { return "", err } return t.channel.Send("tracingStartChunk", chunkOption) } name, err := innerStart() if err != nil { return err } return t.startCollectingStacks(name.(string)) } func (t *tracingImpl) StartChunk(options ...TracingStartChunkOptions) error { name, err := t.channel.Send("tracingStartChunk", options) if err != nil { return err } return t.startCollectingStacks(name.(string)) } func (t *tracingImpl) StopChunk(path ...string) error { filePath := "" if len(path) == 1 { filePath = path[0] } return t.doStopChunk(filePath) } func (t *tracingImpl) Stop(path ...string) error { filePath := "" if len(path) == 1 { filePath = path[0] } if err := t.doStopChunk(filePath); err != nil { return err } _, err := t.channel.Send("tracingStop") return err } func (t *tracingImpl) doStopChunk(filePath string) (err error) { if t.isTracing { t.isTracing = false t.connection.setInTracing(false) } if filePath == "" { // Not interested in artifacts. _, err = t.channel.Send("tracingStopChunk", map[string]interface{}{ "mode": "discard", }) if t.stacksId != "" { return t.connection.LocalUtils().TraceDiscarded(t.stacksId) } return err } isLocal := !t.connection.isRemote if isLocal { result, err := t.channel.SendReturnAsDict("tracingStopChunk", map[string]interface{}{ "mode": "entries", }) if err != nil { return err } entries, ok := result["entries"] if !ok { return fmt.Errorf("could not convert result to map: %v", result) } _, err = t.connection.LocalUtils().Zip(localUtilsZipOptions{ ZipFile: filePath, Entries: entries.([]interface{}), StacksId: t.stacksId, Mode: "write", IncludeSources: t.includeSources, }) return err } result, err := t.channel.SendReturnAsDict("tracingStopChunk", map[string]interface{}{ "mode": "archive", }) if err != nil { return err } artifactChannel, ok := result["artifact"] if !ok { return fmt.Errorf("could not convert result to map: %v", result) } // Save trace to the final local file. artifact := fromNullableChannel(artifactChannel).(*artifactImpl) // The artifact may be missing if the browser closed while stopping tracing. if artifact == nil { if t.stacksId != "" { return t.connection.LocalUtils().TraceDiscarded(t.stacksId) } return } if err := artifact.SaveAs(filePath); err != nil { return err } if err := artifact.Delete(); err != nil { return err } _, err = t.connection.LocalUtils().Zip(localUtilsZipOptions{ ZipFile: filePath, Entries: []interface{}{}, StacksId: t.stacksId, Mode: "append", IncludeSources: t.includeSources, }) return err } func (t *tracingImpl) startCollectingStacks(name string) (err error) { if !t.isTracing { t.isTracing = true t.connection.setInTracing(true) } t.stacksId, err = t.connection.LocalUtils().TracingStarted(name, t.tracesDir) return } func (t *tracingImpl) Group(name string, options ...TracingGroupOptions) error { var option TracingGroupOptions if len(options) == 1 { option = options[0] } _, err := t.channel.Send("tracingGroup", option, map[string]interface{}{"name": name}) return err } func (t *tracingImpl) GroupEnd() error { _, err := t.channel.Send("tracingGroupEnd") return err } func newTracing(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *tracingImpl { bt := &tracingImpl{} bt.createChannelOwner(bt, parent, objectType, guid, initializer) bt.markAsInternalType() return bt }