How to use NewSampleFromTrail method of cloud Package

Best K6 code snippet using cloud.NewSampleFromTrail

output.go

Source:output.go Github

copy

Full Screen

...316 // Check if aggregation is enabled,317 if out.config.AggregationPeriod.Duration > 0 {318 newHTTPTrails = append(newHTTPTrails, sc)319 } else {320 newSamples = append(newSamples, NewSampleFromTrail(sc))321 }322 case *netext.NetTrail:323 // TODO: aggregate?324 values := map[string]float64{325 metrics.DataSentName: float64(sc.BytesWritten),326 metrics.DataReceivedName: float64(sc.BytesRead),327 }328 if sc.FullIteration {329 values[metrics.IterationDurationName] = metrics.D(sc.EndTime.Sub(sc.StartTime))330 values[metrics.IterationsName] = 1331 }332 newSamples = append(newSamples, &Sample{333 Type: DataTypeMap,334 Metric: "iter_li_all",335 Data: &SampleDataMap{336 Time: toMicroSecond(sc.GetTime()),337 Tags: sc.GetTags(),338 Values: values,339 },340 })341 default:342 for _, sample := range sampleContainer.GetSamples() {343 newSamples = append(newSamples, &Sample{344 Type: DataTypeSingle,345 Metric: sample.Metric.Name,346 Data: &SampleDataSingle{347 Type: sample.Metric.Type,348 Time: toMicroSecond(sample.Time),349 Tags: sample.Tags,350 Value: sample.Value,351 },352 })353 }354 }355 }356 if len(newSamples) > 0 || len(newHTTPTrails) > 0 {357 out.bufferMutex.Lock()358 out.bufferSamples = append(out.bufferSamples, newSamples...)359 out.bufferHTTPTrails = append(out.bufferHTTPTrails, newHTTPTrails...)360 out.bufferMutex.Unlock()361 }362}363//nolint:funlen,nestif,gocognit364func (out *Output) aggregateHTTPTrails(waitPeriod time.Duration) {365 out.bufferMutex.Lock()366 newHTTPTrails := out.bufferHTTPTrails367 out.bufferHTTPTrails = nil368 out.bufferMutex.Unlock()369 aggrPeriod := int64(out.config.AggregationPeriod.Duration)370 // Distribute all newly buffered HTTP trails into buckets and sub-buckets371 // this key is here specifically to not incur more allocations then necessary372 // if you change this code please run the benchmarks and add the results to the commit message373 var subBucketKey [3]string374 for _, trail := range newHTTPTrails {375 trailTags := trail.GetTags()376 bucketID := trail.GetTime().UnixNano() / aggrPeriod377 // Get or create a time bucket for that trail period378 bucket, ok := out.aggrBuckets[bucketID]379 if !ok {380 bucket = make(map[[3]string]aggregationBucket)381 out.aggrBuckets[bucketID] = bucket382 }383 subBucketKey[0], _ = trailTags.Get("name")384 subBucketKey[1], _ = trailTags.Get("group")385 subBucketKey[2], _ = trailTags.Get("status")386 subBucket, ok := bucket[subBucketKey]387 if !ok {388 subBucket = aggregationBucket{}389 bucket[subBucketKey] = subBucket390 }391 // Either use an existing subbucket key or use the trail tags as a new one392 subSubBucketKey := trailTags393 subSubBucket, ok := subBucket[subSubBucketKey]394 if !ok {395 for sbTags, sb := range subBucket {396 if trailTags.IsEqual(sbTags) {397 subSubBucketKey = sbTags398 subSubBucket = sb399 break400 }401 }402 }403 subBucket[subSubBucketKey] = append(subSubBucket, trail)404 }405 // Which buckets are still new and we'll wait for trails to accumulate before aggregating406 bucketCutoffID := time.Now().Add(-waitPeriod).UnixNano() / aggrPeriod407 iqrRadius := out.config.AggregationOutlierIqrRadius.Float64408 iqrLowerCoef := out.config.AggregationOutlierIqrCoefLower.Float64409 iqrUpperCoef := out.config.AggregationOutlierIqrCoefUpper.Float64410 newSamples := []*Sample{}411 // Handle all aggregation buckets older than bucketCutoffID412 for bucketID, subBuckets := range out.aggrBuckets {413 if bucketID > bucketCutoffID {414 continue415 }416 for _, subBucket := range subBuckets {417 for tags, httpTrails := range subBucket {418 // start := time.Now() // this is in a combination with the log at the end419 trailCount := int64(len(httpTrails))420 if trailCount < out.config.AggregationMinSamples.Int64 {421 for _, trail := range httpTrails {422 newSamples = append(newSamples, NewSampleFromTrail(trail))423 }424 continue425 }426 aggrData := &SampleDataAggregatedHTTPReqs{427 Time: toMicroSecond(time.Unix(0, bucketID*aggrPeriod+aggrPeriod/2)),428 Type: "aggregated_trend",429 Tags: tags,430 }431 if out.config.AggregationSkipOutlierDetection.Bool {432 // Simply add up all HTTP trails, no outlier detection433 for _, trail := range httpTrails {434 aggrData.Add(trail)435 }436 } else {437 connDurations := make(durations, trailCount)438 reqDurations := make(durations, trailCount)439 for i, trail := range httpTrails {440 connDurations[i] = trail.ConnDuration441 reqDurations[i] = trail.Duration442 }443 var minConnDur, maxConnDur, minReqDur, maxReqDur time.Duration444 if trailCount < out.config.AggregationOutlierAlgoThreshold.Int64 {445 // Since there are fewer samples, we'll use the interpolation-enabled and446 // more precise sorting-based algorithm447 minConnDur, maxConnDur = connDurations.SortGetNormalBounds(iqrRadius, iqrLowerCoef, iqrUpperCoef, true)448 minReqDur, maxReqDur = reqDurations.SortGetNormalBounds(iqrRadius, iqrLowerCoef, iqrUpperCoef, true)449 } else {450 minConnDur, maxConnDur = connDurations.SelectGetNormalBounds(iqrRadius, iqrLowerCoef, iqrUpperCoef)451 minReqDur, maxReqDur = reqDurations.SelectGetNormalBounds(iqrRadius, iqrLowerCoef, iqrUpperCoef)452 }453 for _, trail := range httpTrails {454 if trail.ConnDuration < minConnDur ||455 trail.ConnDuration > maxConnDur ||456 trail.Duration < minReqDur ||457 trail.Duration > maxReqDur {458 // Seems like an outlier, add it as a standalone metric459 newSamples = append(newSamples, NewSampleFromTrail(trail))460 } else {461 // Aggregate the trail462 aggrData.Add(trail)463 }464 }465 }466 aggrData.CalcAverages()467 if aggrData.Count > 0 {468 /*469 out.logger.WithFields(logrus.Fields{470 "http_samples": aggrData.Count,471 "ratio": fmt.Sprintf("%.2f", float64(aggrData.Count)/float64(trailCount)),472 "t": time.Since(start),473 }).Debug("Aggregated HTTP metrics")474 //*/475 newSamples = append(newSamples, &Sample{476 Type: DataTypeAggregatedHTTPReqs,477 Metric: "http_req_li_all",478 Data: aggrData,479 })480 }481 }482 }483 delete(out.aggrBuckets, bucketID)484 }485 if len(newSamples) > 0 {486 out.bufferMutex.Lock()487 out.bufferSamples = append(out.bufferSamples, newSamples...)488 out.bufferMutex.Unlock()489 }490}491func (out *Output) flushHTTPTrails() {492 out.bufferMutex.Lock()493 defer out.bufferMutex.Unlock()494 newSamples := []*Sample{}495 for _, trail := range out.bufferHTTPTrails {496 newSamples = append(newSamples, NewSampleFromTrail(trail))497 }498 for _, bucket := range out.aggrBuckets {499 for _, subBucket := range bucket {500 for _, trails := range subBucket {501 for _, trail := range trails {502 newSamples = append(newSamples, NewSampleFromTrail(trail))503 }504 }505 }506 }507 out.bufferHTTPTrails = nil508 out.aggrBuckets = map[int64]map[[3]string]aggregationBucket{}509 out.bufferSamples = append(out.bufferSamples, newSamples...)510}511func (out *Output) shouldStopSendingMetrics(err error) bool {512 if err == nil {513 return false514 }515 if errResp, ok := err.(cloudapi.ErrorResponse); ok && errResp.Response != nil {516 return errResp.Response.StatusCode == http.StatusForbidden && errResp.Code == 4...

Full Screen

Full Screen

collector.go

Source:collector.go Github

copy

Full Screen

...250 // Check if aggregation is enabled,251 if c.config.AggregationPeriod.Duration > 0 {252 newHTTPTrails = append(newHTTPTrails, sc)253 } else {254 newSamples = append(newSamples, NewSampleFromTrail(sc))255 }256 case *netext.NetTrail:257 //TODO: aggregate?258 values := map[string]float64{259 metrics.DataSent.Name: float64(sc.BytesWritten),260 metrics.DataReceived.Name: float64(sc.BytesRead),261 }262 if sc.FullIteration {263 values[metrics.IterationDuration.Name] = stats.D(sc.EndTime.Sub(sc.StartTime))264 values[metrics.Iterations.Name] = 1265 }266 newSamples = append(newSamples, &Sample{267 Type: DataTypeMap,268 Metric: "iter_li_all",269 Data: &SampleDataMap{270 Time: Timestamp(sc.GetTime()),271 Tags: sc.GetTags(),272 Values: values,273 }})274 default:275 for _, sample := range sampleContainer.GetSamples() {276 newSamples = append(newSamples, &Sample{277 Type: DataTypeSingle,278 Metric: sample.Metric.Name,279 Data: &SampleDataSingle{280 Type: sample.Metric.Type,281 Time: Timestamp(sample.Time),282 Tags: sample.Tags,283 Value: sample.Value,284 },285 })286 }287 }288 }289 if len(newSamples) > 0 || len(newHTTPTrails) > 0 {290 c.bufferMutex.Lock()291 c.bufferSamples = append(c.bufferSamples, newSamples...)292 c.bufferHTTPTrails = append(c.bufferHTTPTrails, newHTTPTrails...)293 c.bufferMutex.Unlock()294 }295}296func (c *Collector) aggregateHTTPTrails(waitPeriod time.Duration) {297 c.bufferMutex.Lock()298 newHTTPTrails := c.bufferHTTPTrails299 c.bufferHTTPTrails = nil300 c.bufferMutex.Unlock()301 aggrPeriod := int64(c.config.AggregationPeriod.Duration)302 // Distribute all newly buffered HTTP trails into buckets and sub-buckets303 for _, trail := range newHTTPTrails {304 trailTags := trail.GetTags()305 bucketID := trail.GetTime().UnixNano() / aggrPeriod306 // Get or create a time bucket for that trail period307 bucket, ok := c.aggrBuckets[bucketID]308 if !ok {309 bucket = aggregationBucket{}310 c.aggrBuckets[bucketID] = bucket311 }312 // Either use an existing subbucket key or use the trail tags as a new one313 subBucketKey := trailTags314 subBucket, ok := bucket[subBucketKey]315 if !ok {316 for sbTags, sb := range bucket {317 if trailTags.IsEqual(sbTags) {318 subBucketKey = sbTags319 subBucket = sb320 break321 }322 }323 }324 bucket[subBucketKey] = append(subBucket, trail)325 }326 // Which buckets are still new and we'll wait for trails to accumulate before aggregating327 bucketCutoffID := time.Now().Add(-waitPeriod).UnixNano() / aggrPeriod328 iqrRadius := c.config.AggregationOutlierIqrRadius.Float64329 iqrLowerCoef := c.config.AggregationOutlierIqrCoefLower.Float64330 iqrUpperCoef := c.config.AggregationOutlierIqrCoefUpper.Float64331 newSamples := []*Sample{}332 // Handle all aggregation buckets older than bucketCutoffID333 for bucketID, subBuckets := range c.aggrBuckets {334 if bucketID > bucketCutoffID {335 continue336 }337 for tags, httpTrails := range subBuckets {338 trailCount := int64(len(httpTrails))339 if trailCount < c.config.AggregationMinSamples.Int64 {340 for _, trail := range httpTrails {341 newSamples = append(newSamples, NewSampleFromTrail(trail))342 }343 continue344 }345 aggrData := &SampleDataAggregatedHTTPReqs{346 Time: Timestamp(time.Unix(0, bucketID*aggrPeriod+aggrPeriod/2)),347 Type: "aggregated_trend",348 Tags: tags,349 }350 if c.config.AggregationSkipOutlierDetection.Bool {351 // Simply add up all HTTP trails, no outlier detection352 for _, trail := range httpTrails {353 aggrData.Add(trail)354 }355 } else {356 connDurations := make(durations, trailCount)357 reqDurations := make(durations, trailCount)358 for i, trail := range httpTrails {359 connDurations[i] = trail.ConnDuration360 reqDurations[i] = trail.Duration361 }362 var minConnDur, maxConnDur, minReqDur, maxReqDur time.Duration363 if trailCount < c.config.AggregationOutlierAlgoThreshold.Int64 {364 // Since there are fewer samples, we'll use the interpolation-enabled and365 // more precise sorting-based algorithm366 minConnDur, maxConnDur = connDurations.SortGetNormalBounds(iqrRadius, iqrLowerCoef, iqrUpperCoef, true)367 minReqDur, maxReqDur = reqDurations.SortGetNormalBounds(iqrRadius, iqrLowerCoef, iqrUpperCoef, true)368 } else {369 minConnDur, maxConnDur = connDurations.SelectGetNormalBounds(iqrRadius, iqrLowerCoef, iqrUpperCoef)370 minReqDur, maxReqDur = reqDurations.SelectGetNormalBounds(iqrRadius, iqrLowerCoef, iqrUpperCoef)371 }372 for _, trail := range httpTrails {373 if trail.ConnDuration < minConnDur ||374 trail.ConnDuration > maxConnDur ||375 trail.Duration < minReqDur ||376 trail.Duration > maxReqDur {377 // Seems like an outlier, add it as a standalone metric378 newSamples = append(newSamples, NewSampleFromTrail(trail))379 } else {380 // Aggregate the trail381 aggrData.Add(trail)382 }383 }384 }385 aggrData.CalcAverages()386 if aggrData.Count > 0 {387 logrus.WithFields(logrus.Fields{388 "http_samples": aggrData.Count,389 }).Debug("Aggregated HTTP metrics")390 newSamples = append(newSamples, &Sample{391 Type: DataTypeAggregatedHTTPReqs,392 Metric: "http_req_li_all",393 Data: aggrData,394 })395 }396 }397 delete(c.aggrBuckets, bucketID)398 }399 if len(newSamples) > 0 {400 c.bufferMutex.Lock()401 c.bufferSamples = append(c.bufferSamples, newSamples...)402 c.bufferMutex.Unlock()403 }404}405func (c *Collector) flushHTTPTrails() {406 c.bufferMutex.Lock()407 defer c.bufferMutex.Unlock()408 newSamples := []*Sample{}409 for _, trail := range c.bufferHTTPTrails {410 newSamples = append(newSamples, NewSampleFromTrail(trail))411 }412 for _, bucket := range c.aggrBuckets {413 for _, trails := range bucket {414 for _, trail := range trails {415 newSamples = append(newSamples, NewSampleFromTrail(trail))416 }417 }418 }419 c.bufferHTTPTrails = nil420 c.aggrBuckets = map[int64]aggregationBucket{}421 c.bufferSamples = append(c.bufferSamples, newSamples...)422}423func (c *Collector) shouldStopSendingMetrics(err error) bool {424 if err == nil {425 return false426 }427 if errResp, ok := err.(ErrorResponse); ok && errResp.Response != nil {428 return errResp.Response.StatusCode == http.StatusForbidden && errResp.Code == 4429 }...

Full Screen

Full Screen

NewSampleFromTrail

Using AI Code Generation

copy

Full Screen

1import (2func init() {3 http.HandleFunc("/", indexHandler)4 http.HandleFunc("/books", booksHandler)5 http.HandleFunc("/books/add", addHandler)6 http.HandleFunc("/books/delete", deleteHandler)7 http.HandleFunc("/books/show", showHandler)8 http.HandleFunc("/books/edit", editHandler)9 http.HandleFunc("/books/save", saveHandler)10}11func indexHandler(w http.ResponseWriter, r *http.Request) {12 c := appengine.NewContext(r)13 books, err := data.ListBooks(c, "", 10, "")14 if err != nil {15 http.Error(w, err.Error(), http.StatusInternalServerError)16 }17 if err := indexTemplate.Execute(w, books); err != nil {18 http.Error(w, err.Error(), http.StatusInternalServerError)19 }20}21func booksHandler(w http.ResponseWriter, r *http.Request) {22 c := appengine.NewContext(r)23 books, err := data.ListBooks(c, "", 10, "")24 if err != nil {25 http.Error(w, err.Error(), http.StatusInternalServerError)26 }27 if err := booksTemplate.Execute(w, books); err != nil {28 http.Error(w, err.Error(), http.StatusInternalServerError)29 }30}31func addHandler(w http.ResponseWriter, r *http.Request) {32 if r.Method == "POST" {33 c := appengine.NewContext(r)34 book := &data.Book{35 Title: r.FormValue("title"),

Full Screen

Full Screen

NewSampleFromTrail

Using AI Code Generation

copy

Full Screen

1import (2func handler(request events.CloudWatchEvent) {3 fmt.Println("Hello World")4}5func main() {6 lambda.Start(handler)7}8import (9func handler(request events.CloudWatchEvent) {10 fmt.Println("Hello World")11}12func main() {13 lambda.Start(handler)14}15import (16func handler(request events.CloudWatchEvent) {17 fmt.Println("Hello World")18}19func main() {20 lambda.Start(handler)21}22import (23func handler(request events.CloudWatchEvent) {24 fmt.Println("Hello World")25}26func main() {27 lambda.Start(handler)28}29import (30func handler(request events.CloudWatchEvent) {31 fmt.Println("Hello World")32}33func main() {34 lambda.Start(handler)35}36import (37func handler(request events.CloudWatchEvent) {38 fmt.Println("Hello World")39}40func main() {41 lambda.Start(handler)42}43import (

Full Screen

Full Screen

NewSampleFromTrail

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 s := bookshelf.NewSampleFromTrail()4 fmt.Println(s)5}6import (7func main() {8 s := bookshelf.NewSampleFromEnv()9 fmt.Println(s)10}11import (12func main() {13 s := bookshelf.NewSample()14 fmt.Println(s)15}16import (17func main() {18 s := bookshelf.NewSampleFromContext()19 fmt.Println(s)20}21import (22func main() {23 s := bookshelf.NewSampleFromFlags()24 fmt.Println(s)25}26import (27func main() {28 s := bookshelf.NewSampleFromContextAndFlags()29 fmt.Println(s)30}31import (32func main() {33 s := bookshelf.NewSampleFromContextAndFlags()34 fmt.Println(s)35}36import (37func main() {

Full Screen

Full Screen

NewSampleFromTrail

Using AI Code Generation

copy

Full Screen

1func main() {2 cloud.NewSampleFromTrail()3}4func main() {5 cloud := cloud.Cloud{}6 cloud.NewSampleFromTrail()7}8func main() {9 cloud.NewSampleFromTrail()10 cloud.NewSampleFromTrailPointer()11}12import "fmt"13type Cloud struct {14}15func (cloud *Cloud) NewSampleFromTrailPointer() {16 fmt.Println("NewSampleFromTrailPointer")17}18func (cloud Cloud) NewSampleFromTrail() {19 fmt.Println("NewSampleFromTrail")20}

Full Screen

Full Screen

NewSampleFromTrail

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 projectID, err := metadata.ProjectID()4 if err != nil {5 fmt.Println("error getting project ID from metadata: %v", err)6 }7 fmt.Println("Project ID: ", projectID)8}9import (10func main() {11 fmt.Println("Project ID: ", projectID)12}13import (14func main() {15 fmt.Println("Project ID: ", projectID)16}17import (18func main() {19 fmt.Println("Project ID: ", projectID)20}21import (22func main() {23 fmt.Println("Project ID: ", projectID)24}25import (26func main() {27 fmt.Println("Project ID: ", projectID)28}

Full Screen

Full Screen

NewSampleFromTrail

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 r := mux.NewRouter()4 r.HandleFunc("/", handler)5 http.Handle("/", r)6 appengine.Main()7}8func handler(w http.ResponseWriter, r *http.Request) {9 ctx := appengine.NewContext(r)10 client := urlfetch.Client(ctx)11 s, err := helloworld.NewSampleFromTrail(client)12 if err != nil {13 log.Fatal(err)14 }15 fmt.Fprintf(w, "Hello, %v", s)16}17import (18func main() {19 r := mux.NewRouter()20 r.HandleFunc("/", handler)21 http.Handle("/", r)22 appengine.Main()23}24func handler(w http.ResponseWriter, r *http.Request) {25 ctx := appengine.NewContext(r)26 client := urlfetch.Client(ctx)27 s, err := helloworld.NewSampleFromContext(ctx)28 if err != nil {29 log.Fatal(err)30 }31 fmt.Fprintf(w, "Hello, %v", s)32}33import (34func main() {35 r := mux.NewRouter()

Full Screen

Full Screen

NewSampleFromTrail

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 trail := cloud.NewTrail()4 trail.AddStep("A")5 trail.AddStep("B")6 trail.AddStep("C")7 trail.AddStep("D")8 trail.AddStep("E")9 trail.AddStep("F")10 trail.AddStep("G")11 trail.AddStep("H")12 trail.AddStep("I")13 trail.AddStep("J")14 trail.AddStep("K")15 trail.AddStep("L")16 trail.AddStep("M")17 trail.AddStep("N")18 trail.AddStep("O")19 trail.AddStep("P")20 trail.AddStep("Q")21 trail.AddStep("R")22 trail.AddStep("S")23 trail.AddStep("T")24 trail.AddStep("U")25 trail.AddStep("V")26 trail.AddStep("W")27 trail.AddStep("X")28 trail.AddStep("Y")29 trail.AddStep("Z")30 fmt.Println(trail)31 sample := cloud.NewSampleFromTrail(trail)32 fmt.Println(sample)33}34import (35func main() {36 trail := cloud.NewTrail()37 trail.AddStep("A")38 trail.AddStep("B")39 trail.AddStep("C")40 trail.AddStep("D")41 trail.AddStep("E")42 trail.AddStep("F")43 trail.AddStep("G")44 trail.AddStep("H")45 trail.AddStep("I")46 trail.AddStep("J")47 trail.AddStep("K")48 trail.AddStep("L")49 trail.AddStep("M")50 trail.AddStep("N")51 trail.AddStep("O")52 trail.AddStep("P")53 trail.AddStep("Q")54 trail.AddStep("R")55 trail.AddStep("S")56 trail.AddStep("T")57 trail.AddStep("U")58 trail.AddStep("V")59 trail.AddStep("W")60 trail.AddStep("X")

Full Screen

Full Screen

NewSampleFromTrail

Using AI Code Generation

copy

Full Screen

1import (2func main() {3 cloud := cloud.NewCloud()4 sample := cloud.NewSampleFromTrail("trail.txt")5 fmt.Println(sample)6}7import (8func main() {9 cloud := cloud.NewCloud()10 sample := cloud.NewSampleFromTrail("trail.txt")11 fmt.Println(sample)12}13import (14func main() {15 cloud := cloud.NewCloud()16 sample := cloud.NewSampleFromTrail("trail.txt")17 fmt.Println(sample)18}19import (20func main() {21 cloud := cloud.NewCloud()22 sample := cloud.NewSampleFromTrail("trail.txt")23 fmt.Println(sample)24}25import (26func main() {27 cloud := cloud.NewCloud()28 sample := cloud.NewSampleFromTrail("trail.txt")29 fmt.Println(sample)30}31import (32func main() {33 cloud := cloud.NewCloud()34 sample := cloud.NewSampleFromTrail("trail.txt")35 fmt.Println(sample)36}37import (

Full Screen

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run K6 automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Most used method in

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful