From a6da7ae2826dce2abf1c390d613d7dc6905b7a20 Mon Sep 17 00:00:00 2001 From: detj Date: Mon, 16 Dec 2024 01:32:24 +0530 Subject: [PATCH] chore(backend): ios session timeline - modify changes for supporting iOS session timeline - update session timeline api to support iOS events Signed-off-by: detj --- backend/api/measure/app.go | 440 +++++++++++------- backend/api/{replay => timeline}/cpu.go | 6 +- backend/api/{replay => timeline}/critical.go | 10 +- backend/api/{replay => timeline}/custom.go | 4 +- backend/api/{replay => timeline}/doc.go | 18 +- backend/api/{replay => timeline}/exit.go | 6 +- backend/api/{replay => timeline}/gesture.go | 14 +- backend/api/{replay => timeline}/launch.go | 14 +- backend/api/{replay => timeline}/lifecycle.go | 92 +++- backend/api/{replay => timeline}/log.go | 6 +- backend/api/{replay => timeline}/massage.go | 6 +- backend/api/{replay => timeline}/memory.go | 35 +- backend/api/{replay => timeline}/nav.go | 10 +- backend/api/{replay => timeline}/network.go | 10 +- 14 files changed, 433 insertions(+), 238 deletions(-) rename backend/api/{replay => timeline}/cpu.go (70%) rename backend/api/{replay => timeline}/critical.go (97%) rename backend/api/{replay => timeline}/custom.go (96%) rename backend/api/{replay => timeline}/doc.go (77%) rename backend/api/{replay => timeline}/exit.go (92%) rename backend/api/{replay => timeline}/gesture.go (96%) rename backend/api/{replay => timeline}/launch.go (95%) rename backend/api/{replay => timeline}/lifecycle.go (53%) rename backend/api/{replay => timeline}/log.go (93%) rename backend/api/{replay => timeline}/massage.go (92%) rename backend/api/{replay => timeline}/memory.go (76%) rename backend/api/{replay => timeline}/nav.go (94%) rename backend/api/{replay => timeline}/network.go (93%) diff --git a/backend/api/measure/app.go b/backend/api/measure/app.go index 2d2117147..c563b0b89 100644 --- a/backend/api/measure/app.go +++ b/backend/api/measure/app.go @@ -18,9 +18,10 @@ import ( "backend/api/journey" "backend/api/metrics" "backend/api/paginate" - "backend/api/replay" + "backend/api/platform" "backend/api/server" "backend/api/span" + "backend/api/timeline" "github.com/gin-gonic/gin" "github.com/google/uuid" @@ -1214,10 +1215,11 @@ func (a *App) getTeam(ctx context.Context) (*Team, error) { stmt := sqlf.PostgreSQL. Select("team_id"). From("apps"). - Where("id = ?", nil) + Where("id = ?", a.ID) + defer stmt.Close() - if err := server.Server.PgPool.QueryRow(ctx, stmt.String(), a.ID).Scan(&team.ID); err != nil { + if err := server.Server.PgPool.QueryRow(ctx, stmt.String(), stmt.Args()...).Scan(&team.ID); err != nil { if errors.Is(err, pgx.ErrNoRows) { return nil, nil } else { @@ -1228,6 +1230,24 @@ func (a *App) getTeam(ctx context.Context) (*Team, error) { return team, nil } +func (a *App) Populate(ctx context.Context) (err error) { + stmt := sqlf.PostgreSQL.From("apps"). + Select("team_id::UUID"). + Select("unique_identifier"). + Select("app_name"). + Select("platform"). + Select("first_version"). + Select("onboarded"). + Select("onboarded_at"). + Select("created_at"). + Select("updated_at"). + Where("id = ?", a.ID) + + defer stmt.Close() + + return server.Server.PgPool.QueryRow(ctx, stmt.String(), stmt.Args()...).Scan(&a.TeamId, &a.UniqueId, &a.AppName, &a.Platform, &a.FirstVersion, &a.Onboarded, &a.OnboardedAt, &a.CreatedAt, &a.UpdatedAt) +} + func (a *App) Onboard(ctx context.Context, tx *pgx.Tx, uniqueIdentifier, platform, firstVersion string) error { now := time.Now() stmt := sqlf.PostgreSQL.Update("public.apps"). @@ -1285,22 +1305,7 @@ func (a *App) GetSessionEvents(ctx context.Context, sessionId uuid.UUID) (*Sessi `toString(attribute.network_type)`, `toString(attribute.network_generation)`, `toString(attribute.network_provider)`, - `anr.fingerprint`, - `anr.foreground`, - `anr.exceptions`, - `anr.threads`, - `exception.handled`, - `exception.fingerprint`, - `exception.foreground`, - `exception.exceptions`, - `exception.threads`, - `toString(app_exit.reason)`, - `toString(app_exit.importance)`, - `app_exit.trace`, - `app_exit.process_name`, - `app_exit.pid`, - `toString(string.severity_text)`, - `string.string`, + `user_defined_attribute`, `toString(gesture_long_click.target)`, `toString(gesture_long_click.target_id)`, `gesture_long_click.touch_down_time`, @@ -1326,15 +1331,6 @@ func (a *App) GetSessionEvents(ctx context.Context, sessionId uuid.UUID) (*Sessi `gesture_scroll.end_x`, `gesture_scroll.end_y`, `toString(gesture_scroll.direction)`, - `toString(lifecycle_activity.type)`, - `toString(lifecycle_activity.class_name)`, - `lifecycle_activity.intent`, - `lifecycle_activity.saved_instance_state`, - `toString(lifecycle_fragment.type)`, - `toString(lifecycle_fragment.class_name)`, - `lifecycle_fragment.parent_activity`, - `lifecycle_fragment.parent_fragment`, - `lifecycle_fragment.tag`, `toString(lifecycle_app.type)`, `cold_launch.process_start_uptime`, `cold_launch.process_start_requested_uptime`, @@ -1377,22 +1373,6 @@ func (a *App) GetSessionEvents(ctx context.Context, sessionId uuid.UUID) (*Sessi `http.failure_reason`, `http.failure_description`, `toString(http.client)`, - `memory_usage.java_max_heap`, - `memory_usage.java_total_heap`, - `memory_usage.java_free_heap`, - `memory_usage.total_pss`, - `memory_usage.rss`, - `memory_usage.native_total_heap`, - `memory_usage.native_free_heap`, - `memory_usage.interval`, - `low_memory.java_max_heap`, - `low_memory.java_total_heap`, - `low_memory.java_free_heap`, - `low_memory.total_pss`, - `low_memory.rss`, - `low_memory.native_total_heap`, - `low_memory.native_free_heap`, - `toString(trim_memory.level)`, `cpu_usage.num_cores`, `cpu_usage.clock_speed`, `cpu_usage.start_time`, @@ -1403,14 +1383,70 @@ func (a *App) GetSessionEvents(ctx context.Context, sessionId uuid.UUID) (*Sessi `cpu_usage.cstime`, `cpu_usage.interval`, `cpu_usage.percentage_usage`, - `toString(navigation.to)`, - `toString(navigation.from)`, - `toString(navigation.source)`, `toString(screen_view.name) `, - `user_defined_attribute`, `custom.name`, } + switch a.Platform { + case platform.Android: + cols = append(cols, []string{ + `anr.fingerprint`, + `anr.foreground`, + `anr.exceptions`, + `anr.threads`, + `exception.handled`, + `exception.fingerprint`, + `exception.foreground`, + `exception.exceptions`, + `exception.threads`, + `toString(app_exit.reason)`, + `toString(app_exit.importance)`, + `app_exit.trace`, + `app_exit.process_name`, + `app_exit.pid`, + `toString(string.severity_text)`, + `string.string`, + `toString(lifecycle_activity.type)`, + `toString(lifecycle_activity.class_name)`, + `lifecycle_activity.intent`, + `lifecycle_activity.saved_instance_state`, + `toString(lifecycle_fragment.type)`, + `toString(lifecycle_fragment.class_name)`, + `lifecycle_fragment.parent_activity`, + `lifecycle_fragment.parent_fragment`, + `lifecycle_fragment.tag`, + `memory_usage.java_max_heap`, + `memory_usage.java_total_heap`, + `memory_usage.java_free_heap`, + `memory_usage.total_pss`, + `memory_usage.rss`, + `memory_usage.native_total_heap`, + `memory_usage.native_free_heap`, + `memory_usage.interval`, + `low_memory.java_max_heap`, + `low_memory.java_total_heap`, + `low_memory.java_free_heap`, + `low_memory.total_pss`, + `low_memory.rss`, + `low_memory.native_total_heap`, + `low_memory.native_free_heap`, + `toString(trim_memory.level)`, + `toString(navigation.to)`, + `toString(navigation.from)`, + `toString(navigation.source)`, + }...) + case platform.IOS: + cols = append(cols, []string{ + `toString(lifecycle_view_controller.type)`, + `toString(lifecycle_view_controller.class_name)`, + `toString(lifecycle_swift_ui.type)`, + `toString(lifecycle_swift_ui.class_name)`, + `memory_usage_absolute.max_memory`, + `memory_usage_absolute.used_memory`, + `memory_usage_absolute.interval`, + }...) + } + stmt := sqlf.From("default.events") defer stmt.Close() @@ -1465,6 +1501,10 @@ func (a *App) GetSessionEvents(ctx context.Context, sessionId uuid.UUID) (*Sessi var warmLaunchDuration uint32 var hotLaunchDuration uint32 + var lifecycleViewController event.LifecycleViewController + var lifecycleSwiftUI event.LifecycleSwiftUI + var memoryUsageAbs event.MemoryUsageAbs + dest := []any{ &ev.ID, &ev.Type, @@ -1503,29 +1543,8 @@ func (a *App) GetSessionEvents(ctx context.Context, sessionId uuid.UUID) (*Sessi &ev.Attribute.NetworkGeneration, &ev.Attribute.NetworkProvider, - // anr - &anr.Fingerprint, - &anr.Foreground, - &anrExceptions, - &anrThreads, - - // excpetion - &exception.Handled, - &exception.Fingerprint, - &exception.Foreground, - &exceptionExceptions, - &exceptionThreads, - - // app exit - &appExit.Reason, - &appExit.Importance, - &appExit.Trace, - &appExit.ProcessName, - &appExit.PID, - - // log string - &logString.SeverityText, - &logString.String, + // user defined attributes + &userDefAttr, // gesture long click &gestureLongClick.Target, @@ -1558,19 +1577,6 @@ func (a *App) GetSessionEvents(ctx context.Context, sessionId uuid.UUID) (*Sessi &gestureScroll.EndY, &gestureScroll.Direction, - // lifecycle activity - &lifecycleActivity.Type, - &lifecycleActivity.ClassName, - &lifecycleActivity.Intent, - &lifecycleActivity.SavedInstanceState, - - // lifecycle fragment - &lifecycleFragment.Type, - &lifecycleFragment.ClassName, - &lifecycleFragment.ParentActivity, - &lifecycleFragment.ParentFragment, - &lifecycleFragment.Tag, - // lifecycle app &lifecycleApp.Type, @@ -1625,28 +1631,6 @@ func (a *App) GetSessionEvents(ctx context.Context, sessionId uuid.UUID) (*Sessi &http.FailureDescription, &http.Client, - // memory usage - &memoryUsage.JavaMaxHeap, - &memoryUsage.JavaTotalHeap, - &memoryUsage.JavaFreeHeap, - &memoryUsage.TotalPSS, - &memoryUsage.RSS, - &memoryUsage.NativeTotalHeap, - &memoryUsage.NativeFreeHeap, - &memoryUsage.Interval, - - // low memory - &lowMemory.JavaMaxHeap, - &lowMemory.JavaTotalHeap, - &lowMemory.JavaFreeHeap, - &lowMemory.TotalPSS, - &lowMemory.RSS, - &lowMemory.NativeTotalHeap, - &lowMemory.NativeFreeHeap, - - // trim memory - &trimMemory.Level, - // cpu usage &cpuUsage.NumCores, &cpuUsage.ClockSpeed, @@ -1659,21 +1643,92 @@ func (a *App) GetSessionEvents(ctx context.Context, sessionId uuid.UUID) (*Sessi &cpuUsage.Interval, &cpuUsage.PercentageUsage, - // navigation - &navigation.To, - &navigation.From, - &navigation.Source, - // screen view &screenView.Name, - // user defined attributes - &userDefAttr, - // custom &custom.Name, } + switch a.Platform { + case platform.Android: + dest = append(dest, []any{ + // anr + &anr.Fingerprint, + &anr.Foreground, + &anrExceptions, + &anrThreads, + + // excpetion + &exception.Handled, + &exception.Fingerprint, + &exception.Foreground, + &exceptionExceptions, + &exceptionThreads, + + // app exit + &appExit.Reason, + &appExit.Importance, + &appExit.Trace, + &appExit.ProcessName, + &appExit.PID, + + // log string + &logString.SeverityText, + &logString.String, + + // lifecycle activity + &lifecycleActivity.Type, + &lifecycleActivity.ClassName, + &lifecycleActivity.Intent, + &lifecycleActivity.SavedInstanceState, + + // lifecycle fragment + &lifecycleFragment.Type, + &lifecycleFragment.ClassName, + &lifecycleFragment.ParentActivity, + &lifecycleFragment.ParentFragment, + &lifecycleFragment.Tag, + + // memory usage + &memoryUsage.JavaMaxHeap, + &memoryUsage.JavaTotalHeap, + &memoryUsage.JavaFreeHeap, + &memoryUsage.TotalPSS, + &memoryUsage.RSS, + &memoryUsage.NativeTotalHeap, + &memoryUsage.NativeFreeHeap, + &memoryUsage.Interval, + + // low memory + &lowMemory.JavaMaxHeap, + &lowMemory.JavaTotalHeap, + &lowMemory.JavaFreeHeap, + &lowMemory.TotalPSS, + &lowMemory.RSS, + &lowMemory.NativeTotalHeap, + &lowMemory.NativeFreeHeap, + + // trim memory + &trimMemory.Level, + + // navigation + &navigation.To, + &navigation.From, + &navigation.Source, + }...) + case platform.IOS: + dest = append(dest, []any{ + &lifecycleViewController.Type, + &lifecycleViewController.ClassName, + &lifecycleSwiftUI.Type, + &lifecycleSwiftUI.ClassName, + &memoryUsageAbs.MaxMemory, + &memoryUsageAbs.UsedMemory, + &memoryUsageAbs.Interval, + }...) + } + if err := rows.Scan(dest...); err != nil { return nil, err } @@ -1774,6 +1829,15 @@ func (a *App) GetSessionEvents(ctx context.Context, sessionId uuid.UUID) (*Sessi case event.TypeCustom: ev.Custom = &custom session.Events = append(session.Events, ev) + case event.TypeLifecycleViewController: + ev.LifecycleViewController = &lifecycleViewController + session.Events = append(session.Events, ev) + case event.TypeLifecycleSwiftUI: + ev.LifecycleSwiftUI = &lifecycleSwiftUI + session.Events = append(session.Events, ev) + case event.TypeMemoryUsageAbs: + ev.MemoryUsageAbs = &memoryUsageAbs + session.Events = append(session.Events, ev) default: continue } @@ -4640,18 +4704,26 @@ func GetSession(c *gin.Context) { app := &App{ ID: &appId, } - team, err := app.getTeam(ctx) - if err != nil { - msg := `failed to fetch team from app` + + if err := app.Populate(ctx); err != nil { + msg := `failed to fetch app details` fmt.Println(msg, err) - c.JSON(http.StatusBadRequest, gin.H{"error": msg}) + status := http.StatusInternalServerError + + if errors.Is(err, pgx.ErrNoRows) { + status = http.StatusNotFound + msg = fmt.Sprintf(`app with id %q does not exist`, app.ID) + } + + c.JSON(status, gin.H{ + "error": msg, + }) + return } - if team == nil { - msg := fmt.Sprintf(`no team exists for app id: %q`, app.ID) - fmt.Println(msg) - c.JSON(http.StatusBadRequest, gin.H{"error": msg}) - return + + team := &Team{ + ID: &app.TeamId, } userId := c.GetString("userId") @@ -4684,7 +4756,7 @@ func GetSession(c *gin.Context) { session, err := app.GetSessionEvents(ctx, sessionId) if err != nil { - msg := `failed to fetch session data for replay` + msg := `failed to fetch session data for timeline` fmt.Println(msg, err) c.JSON(http.StatusInternalServerError, gin.H{"error": msg}) return @@ -4718,10 +4790,13 @@ func GetSession(c *gin.Context) { duration := session.DurationFromEvents().Milliseconds() cpuUsageEvents := session.EventsOfType(event.TypeCPUUsage) - cpuUsages := replay.ComputeCPUUsage(cpuUsageEvents) + cpuUsages := timeline.ComputeCPUUsage(cpuUsageEvents) memoryUsageEvents := session.EventsOfType(event.TypeMemoryUsage) - memoryUsages := replay.ComputeMemoryUsage(memoryUsageEvents) + memoryUsages := timeline.ComputeMemoryUsage(memoryUsageEvents) + + memoryUsageAbsEvents := session.EventsOfType(event.TypeMemoryUsageAbs) + memoryUsageAbsolutes := timeline.ComputeMemoryUsageAbs(memoryUsageAbsEvents) typeList := []string{ event.TypeGestureClick, @@ -4735,6 +4810,8 @@ func GetSession(c *gin.Context) { event.TypeHotLaunch, event.TypeLifecycleActivity, event.TypeLifecycleFragment, + event.TypeLifecycleViewController, + event.TypeLifecycleSwiftUI, event.TypeLifecycleApp, event.TypeTrimMemory, event.TypeLowMemory, @@ -4747,130 +4824,144 @@ func GetSession(c *gin.Context) { } eventMap := session.EventsOfTypes(typeList...) - threads := make(replay.Threads) + threads := make(timeline.Threads) gestureClickEvents := eventMap[event.TypeGestureClick] if len(gestureClickEvents) > 0 { - gestureClicks := replay.ComputeGestureClicks(gestureClickEvents) - threadedGestureClicks := replay.GroupByThreads(gestureClicks) + gestureClicks := timeline.ComputeGestureClicks(gestureClickEvents) + threadedGestureClicks := timeline.GroupByThreads(gestureClicks) threads.Organize(event.TypeGestureClick, threadedGestureClicks) } gestureLongClickEvents := eventMap[event.TypeGestureLongClick] if len(gestureLongClickEvents) > 0 { - gestureLongClicks := replay.ComputeGestureLongClicks(gestureLongClickEvents) - threadedGestureLongClicks := replay.GroupByThreads(gestureLongClicks) + gestureLongClicks := timeline.ComputeGestureLongClicks(gestureLongClickEvents) + threadedGestureLongClicks := timeline.GroupByThreads(gestureLongClicks) threads.Organize(event.TypeGestureLongClick, threadedGestureLongClicks) } gestureScrollEvents := eventMap[event.TypeGestureScroll] if len(gestureScrollEvents) > 0 { - gestureScrolls := replay.ComputeGestureScrolls(gestureScrollEvents) - threadedGestureScrolls := replay.GroupByThreads(gestureScrolls) + gestureScrolls := timeline.ComputeGestureScrolls(gestureScrollEvents) + threadedGestureScrolls := timeline.GroupByThreads(gestureScrolls) threads.Organize(event.TypeGestureScroll, threadedGestureScrolls) } navEvents := eventMap[event.TypeNavigation] if len(navEvents) > 0 { - navs := replay.ComputeNavigation(navEvents) - threadedNavs := replay.GroupByThreads(navs) + navs := timeline.ComputeNavigation(navEvents) + threadedNavs := timeline.GroupByThreads(navs) threads.Organize(event.TypeNavigation, threadedNavs) } screenViewEvents := eventMap[event.TypeScreenView] if len(screenViewEvents) > 0 { - screenViews := replay.ComputeScreenViews(screenViewEvents) - threadedScreenViews := replay.GroupByThreads(screenViews) + screenViews := timeline.ComputeScreenViews(screenViewEvents) + threadedScreenViews := timeline.GroupByThreads(screenViews) threads.Organize(event.TypeScreenView, threadedScreenViews) } customEvents := eventMap[event.TypeCustom] if len(customEvents) > 0 { - customs := replay.ComputeCustom(customEvents) - threadedCustoms := replay.GroupByThreads(customs) + customs := timeline.ComputeCustom(customEvents) + threadedCustoms := timeline.GroupByThreads(customs) threads.Organize(event.TypeCustom, threadedCustoms) } logEvents := eventMap[event.TypeString] if len(logEvents) > 0 { - logs := replay.ComputeLogString(logEvents) - threadedLogs := replay.GroupByThreads(logs) + logs := timeline.ComputeLogString(logEvents) + threadedLogs := timeline.GroupByThreads(logs) threads.Organize(event.TypeString, threadedLogs) } netChangeEvents := eventMap[event.TypeNetworkChange] if len(netChangeEvents) > 0 { - netChanges := replay.ComputeNetworkChange(netChangeEvents) - threadedNetChanges := replay.GroupByThreads(netChanges) + netChanges := timeline.ComputeNetworkChange(netChangeEvents) + threadedNetChanges := timeline.GroupByThreads(netChanges) threads.Organize(event.TypeNetworkChange, threadedNetChanges) } coldLaunchEvents := eventMap[event.TypeColdLaunch] if len(coldLaunchEvents) > 0 { - coldLaunches := replay.ComputeColdLaunches(coldLaunchEvents) - threadedColdLaunches := replay.GroupByThreads(coldLaunches) + coldLaunches := timeline.ComputeColdLaunches(coldLaunchEvents) + threadedColdLaunches := timeline.GroupByThreads(coldLaunches) threads.Organize(event.TypeColdLaunch, threadedColdLaunches) } warmLaunchEvents := eventMap[event.TypeWarmLaunch] if len(warmLaunchEvents) > 0 { - warmLaunches := replay.ComputeWarmLaunches(warmLaunchEvents) - threadedWarmLaunches := replay.GroupByThreads(warmLaunches) + warmLaunches := timeline.ComputeWarmLaunches(warmLaunchEvents) + threadedWarmLaunches := timeline.GroupByThreads(warmLaunches) threads.Organize(event.TypeWarmLaunch, threadedWarmLaunches) } hotLaunchEvents := eventMap[event.TypeHotLaunch] if len(hotLaunchEvents) > 0 { - hotLaunches := replay.ComputeHotLaunches(hotLaunchEvents) - threadedHotLaunches := replay.GroupByThreads(hotLaunches) + hotLaunches := timeline.ComputeHotLaunches(hotLaunchEvents) + threadedHotLaunches := timeline.GroupByThreads(hotLaunches) threads.Organize(event.TypeHotLaunch, threadedHotLaunches) } lifecycleActivityEvents := eventMap[event.TypeLifecycleActivity] if len(lifecycleActivityEvents) > 0 { - lifecycleActivities := replay.ComputeLifecycleActivities(lifecycleActivityEvents) - threadedLifecycleActivities := replay.GroupByThreads(lifecycleActivities) + lifecycleActivities := timeline.ComputeLifecycleActivities(lifecycleActivityEvents) + threadedLifecycleActivities := timeline.GroupByThreads(lifecycleActivities) threads.Organize(event.TypeLifecycleActivity, threadedLifecycleActivities) } lifecycleFragmentEvents := eventMap[event.TypeLifecycleFragment] if len(lifecycleActivityEvents) > 0 { - lifecycleFragments := replay.ComputeLifecycleFragments(lifecycleFragmentEvents) - threadedLifecycleFragments := replay.GroupByThreads(lifecycleFragments) + lifecycleFragments := timeline.ComputeLifecycleFragments(lifecycleFragmentEvents) + threadedLifecycleFragments := timeline.GroupByThreads(lifecycleFragments) threads.Organize(event.TypeLifecycleFragment, threadedLifecycleFragments) } + lifecycleViewControllerEvents := eventMap[event.TypeLifecycleViewController] + if len(lifecycleViewControllerEvents) > 0 { + lifecycleViewControllers := timeline.ComputeLifecycleViewControllers(lifecycleViewControllerEvents) + threadedLifecycleViewControllers := timeline.GroupByThreads(lifecycleViewControllers) + threads.Organize(event.TypeLifecycleViewController, threadedLifecycleViewControllers) + } + + lifecycleSwiftUIEvents := eventMap[event.TypeLifecycleSwiftUI] + if len(lifecycleSwiftUIEvents) > 0 { + lifecycleSwiftUIViews := timeline.ComputeLifecycleSwiftUIViews(lifecycleSwiftUIEvents) + threadedLifecycleSwiftUIViews := timeline.GroupByThreads(lifecycleSwiftUIViews) + threads.Organize(event.TypeLifecycleSwiftUI, threadedLifecycleSwiftUIViews) + } + lifecycleAppEvents := eventMap[event.TypeLifecycleApp] if len(lifecycleActivityEvents) > 0 { - lifecycleApps := replay.ComputeLifecycleApps(lifecycleAppEvents) - threadedLifecycleApps := replay.GroupByThreads(lifecycleApps) + lifecycleApps := timeline.ComputeLifecycleApps(lifecycleAppEvents) + threadedLifecycleApps := timeline.GroupByThreads(lifecycleApps) threads.Organize(event.TypeLifecycleApp, threadedLifecycleApps) } trimMemoryEvents := eventMap[event.TypeTrimMemory] if len(trimMemoryEvents) > 0 { - trimMemories := replay.ComputeTrimMemories(trimMemoryEvents) - threadedTrimMemories := replay.GroupByThreads(trimMemories) + trimMemories := timeline.ComputeTrimMemories(trimMemoryEvents) + threadedTrimMemories := timeline.GroupByThreads(trimMemories) threads.Organize(event.TypeTrimMemory, threadedTrimMemories) } lowMemoryEvents := eventMap[event.TypeLowMemory] if len(lowMemoryEvents) > 0 { - lowMemories := replay.ComputeLowMemories(lowMemoryEvents) - threadedLowMemories := replay.GroupByThreads(lowMemories) + lowMemories := timeline.ComputeLowMemories(lowMemoryEvents) + threadedLowMemories := timeline.GroupByThreads(lowMemories) threads.Organize(event.TypeLowMemory, threadedLowMemories) } appExitEvents := eventMap[event.TypeAppExit] if len(appExitEvents) > 0 { - appExits := replay.ComputeAppExits(appExitEvents) - threadedAppExits := replay.GroupByThreads(appExits) + appExits := timeline.ComputeAppExits(appExitEvents) + threadedAppExits := timeline.GroupByThreads(appExits) threads.Organize(event.TypeAppExit, threadedAppExits) } exceptionEvents := eventMap[event.TypeException] if len(exceptionEvents) > 0 { - exceptions, err := replay.ComputeExceptions(c, app.ID, exceptionEvents) + exceptions, err := timeline.ComputeExceptions(c, app.ID, exceptionEvents) if err != nil { msg := fmt.Sprintf(`unable to compute exceptions for session %q for app %q`, sessionId, app.ID) fmt.Println(msg, err) @@ -4879,13 +4970,13 @@ func GetSession(c *gin.Context) { }) return } - threadedExceptions := replay.GroupByThreads(exceptions) + threadedExceptions := timeline.GroupByThreads(exceptions) threads.Organize(event.TypeException, threadedExceptions) } anrEvents := eventMap[event.TypeANR] if len(anrEvents) > 0 { - anrs, err := replay.ComputeANRs(c, app.ID, anrEvents) + anrs, err := timeline.ComputeANRs(c, app.ID, anrEvents) if err != nil { msg := fmt.Sprintf(`unable to compute ANRs for session %q for app %q`, sessionId, app.ID) fmt.Println(msg, err) @@ -4894,27 +4985,28 @@ func GetSession(c *gin.Context) { }) return } - threadedANRs := replay.GroupByThreads(anrs) + threadedANRs := timeline.GroupByThreads(anrs) threads.Organize(event.TypeANR, threadedANRs) } httpEvents := eventMap[event.TypeHttp] if len(httpEvents) > 0 { - httpies := replay.ComputeHttp(httpEvents) - threadedHttpies := replay.GroupByThreads(httpies) + httpies := timeline.ComputeHttp(httpEvents) + threadedHttpies := timeline.GroupByThreads(httpies) threads.Organize(event.TypeHttp, threadedHttpies) } threads.Sort() response := gin.H{ - "session_id": sessionId, - "attribute": session.Attribute, - "app_id": appId, - "duration": duration, - "cpu_usage": cpuUsages, - "memory_usage": memoryUsages, - "threads": threads, + "session_id": sessionId, + "attribute": session.Attribute, + "app_id": appId, + "duration": duration, + "cpu_usage": cpuUsages, + "memory_usage": memoryUsages, + "memory_usage_absolute": memoryUsageAbsolutes, + "threads": threads, } c.JSON(http.StatusOK, response) diff --git a/backend/api/replay/cpu.go b/backend/api/timeline/cpu.go similarity index 70% rename from backend/api/replay/cpu.go rename to backend/api/timeline/cpu.go index 54d61e80b..f1e59f3e7 100644 --- a/backend/api/replay/cpu.go +++ b/backend/api/timeline/cpu.go @@ -1,15 +1,19 @@ -package replay +package timeline import ( "backend/api/event" "time" ) +// CPUUsage represents cpu usage +// events suitable for session timeline. type CPUUsage struct { Time time.Time `json:"timestamp"` Value float64 `json:"value"` } +// ComputeCPUUsage computes cpu usage +// events for session timeline. func ComputeCPUUsage(events []event.EventField) (result []CPUUsage) { for _, event := range events { usage := CPUUsage{ diff --git a/backend/api/replay/critical.go b/backend/api/timeline/critical.go similarity index 97% rename from backend/api/replay/critical.go rename to backend/api/timeline/critical.go index 9188a50eb..af9d8ddb4 100644 --- a/backend/api/replay/critical.go +++ b/backend/api/timeline/critical.go @@ -1,4 +1,4 @@ -package replay +package timeline import ( "backend/api/event" @@ -11,7 +11,7 @@ import ( ) // Exception represents exception events suitable -// for session replay. +// for session timeline. type Exception struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -43,7 +43,7 @@ func (e Exception) GetTimestamp() time.Time { } // ANR represents anr events suitable -// for session replay. +// for session timeline. type ANR struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -73,7 +73,7 @@ func (a ANR) GetTimestamp() time.Time { } // ComputeExceptions computes exceptions -// for session replay. +// for session timeline. func ComputeExceptions(ctx context.Context, appId *uuid.UUID, events []event.EventField) (result []ThreadGrouper, err error) { for _, event := range events { @@ -121,7 +121,7 @@ func ComputeExceptions(ctx context.Context, appId *uuid.UUID, events []event.Eve } // ComputeANR computes anrs -// for session replay. +// for session timeline. func ComputeANRs(ctx context.Context, appId *uuid.UUID, events []event.EventField) (result []ThreadGrouper, err error) { for _, event := range events { diff --git a/backend/api/replay/custom.go b/backend/api/timeline/custom.go similarity index 96% rename from backend/api/replay/custom.go rename to backend/api/timeline/custom.go index 8addc00b9..5028fae43 100644 --- a/backend/api/replay/custom.go +++ b/backend/api/timeline/custom.go @@ -1,4 +1,4 @@ -package replay +package timeline import ( "backend/api/event" @@ -28,7 +28,7 @@ func (c Custom) GetTimestamp() time.Time { } // ComputeCustom computes custom events -// for session replay. +// for session timeline. func ComputeCustom(events []event.EventField) (result []ThreadGrouper) { for _, event := range events { navs := Custom{ diff --git a/backend/api/replay/doc.go b/backend/api/timeline/doc.go similarity index 77% rename from backend/api/replay/doc.go rename to backend/api/timeline/doc.go index 02281cabc..e2f7f34ff 100644 --- a/backend/api/replay/doc.go +++ b/backend/api/timeline/doc.go @@ -1,10 +1,10 @@ -// Package replay provides capabilities & functionalities -// for session replay. -package replay +// Package timeline provides capabilities & functionalities +// for session timeline. +package timeline /* This package holds types and computational logic suited -for session replay functionality. Here's a high-level +for session timeline functionality. Here's a high-level breakdown of each. - **cpu**: operations related to app's cpu usage @@ -19,14 +19,14 @@ breakdown of each. - **exit** - operations related to app's stop timings and events Additionally, this package also contains glue code to massage the -shape of session replay objects. +shape of session timeline objects. Example: ```go import { "backend/api/event" - "backend/api/replay" + "backend/api/timeline" "fmt" } @@ -44,11 +44,11 @@ func main() { } // perform compute - gestureClicks := replay.ComputeGestureClicks(clickEvents) + gestureClicks := timeline.ComputeGestureClicks(clickEvents) // organize events by thread - gcThreads := replay.GroupByThreads(gestureClicks) - threads := make(replay.Threads) + gcThreads := timeline.GroupByThreads(gestureClicks) + threads := make(timeline.Threads) threads.Organize(event.TypeGestureClick, gcThreads) fmt.Println("threads", threads) diff --git a/backend/api/replay/exit.go b/backend/api/timeline/exit.go similarity index 92% rename from backend/api/replay/exit.go rename to backend/api/timeline/exit.go index b7547353a..ef2e9eacb 100644 --- a/backend/api/replay/exit.go +++ b/backend/api/timeline/exit.go @@ -1,4 +1,4 @@ -package replay +package timeline import ( "backend/api/event" @@ -6,7 +6,7 @@ import ( ) // AppExit represents app exit events -// suitable for session replay. +// suitable for session timeline. type AppExit struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -28,7 +28,7 @@ func (ae AppExit) GetTimestamp() time.Time { } // ComputeAppExits computes app exit -// events for session replay. +// events for session timeline. func ComputeAppExits(events []event.EventField) (result []ThreadGrouper) { for _, event := range events { appExits := AppExit{ diff --git a/backend/api/replay/gesture.go b/backend/api/timeline/gesture.go similarity index 96% rename from backend/api/replay/gesture.go rename to backend/api/timeline/gesture.go index a7cbaa084..1246084cf 100644 --- a/backend/api/replay/gesture.go +++ b/backend/api/timeline/gesture.go @@ -1,4 +1,4 @@ -package replay +package timeline import ( "backend/api/event" @@ -6,7 +6,7 @@ import ( ) // GestureClick represents click events suitable -// for session replay. +// for session timeline. type GestureClick struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -34,7 +34,7 @@ func (gc GestureClick) GetTimestamp() time.Time { } // GestureLongClick represents long press events -// suitable for session replay. +// suitable for session timeline. type GestureLongClick struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -61,7 +61,7 @@ func (glc GestureLongClick) GetTimestamp() time.Time { } // GestureScroll represents scroll gesture events -// suitable for session replay. +// suitable for session timeline. type GestureScroll struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -89,7 +89,7 @@ func (gs GestureScroll) GetTimestamp() time.Time { } // ComputeGestureClicks computes click gestures -// for session replay. +// for session timeline. func ComputeGestureClicks(events []event.EventField) (result []ThreadGrouper) { for _, event := range events { gestureClicks := GestureClick{ @@ -112,7 +112,7 @@ func ComputeGestureClicks(events []event.EventField) (result []ThreadGrouper) { } // ComputeGestureLongClicks computes long click gestures -// for session replay. +// for session timeline. func ComputeGestureLongClicks(events []event.EventField) (result []ThreadGrouper) { for _, event := range events { gestureLongClicks := GestureLongClick{ @@ -134,7 +134,7 @@ func ComputeGestureLongClicks(events []event.EventField) (result []ThreadGrouper } // ComputeGestureScrolls computes scroll gestures -// for session replay. +// for session timeline. func ComputeGestureScrolls(events []event.EventField) (result []ThreadGrouper) { for _, event := range events { gestureScrolls := GestureScroll{ diff --git a/backend/api/replay/launch.go b/backend/api/timeline/launch.go similarity index 95% rename from backend/api/replay/launch.go rename to backend/api/timeline/launch.go index 8402f70ab..82bb95abb 100644 --- a/backend/api/replay/launch.go +++ b/backend/api/timeline/launch.go @@ -1,4 +1,4 @@ -package replay +package timeline import ( "backend/api/event" @@ -10,7 +10,7 @@ import ( var NominalColdLaunchThreshold = 30 * time.Second // ColdLaunch represents cold launch events -// suitable for session replay. +// suitable for session timeline. type ColdLaunch struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -32,7 +32,7 @@ func (cl ColdLaunch) GetTimestamp() time.Time { } // WarmLaunch represents warm launch events -// suitable for session replay. +// suitable for session timeline. type WarmLaunch struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -57,7 +57,7 @@ func (wl WarmLaunch) GetTimestamp() time.Time { } // HotLaunch represents hot launch events -// suitable for session replay. +// suitable for session timeline. type HotLaunch struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -82,7 +82,7 @@ func (hl HotLaunch) GetTimestamp() time.Time { } // ComputeColdLaunches computes cold launch events -// for session replay. +// for session timeline. func ComputeColdLaunches(events []event.EventField) (result []ThreadGrouper) { for _, event := range events { coldLaunches := ColdLaunch{ @@ -99,7 +99,7 @@ func ComputeColdLaunches(events []event.EventField) (result []ThreadGrouper) { } // ComputeWarmLaunches computes warm launch events -// for session replay. +// for session timeline. func ComputeWarmLaunches(events []event.EventField) (result []ThreadGrouper) { for _, event := range events { warmLaunches := WarmLaunch{ @@ -119,7 +119,7 @@ func ComputeWarmLaunches(events []event.EventField) (result []ThreadGrouper) { } // ComputeHotLaunches computes hot launch events -// for session replay. +// for session timeline. func ComputeHotLaunches(events []event.EventField) (result []ThreadGrouper) { for _, event := range events { hotLaunches := HotLaunch{ diff --git a/backend/api/replay/lifecycle.go b/backend/api/timeline/lifecycle.go similarity index 53% rename from backend/api/replay/lifecycle.go rename to backend/api/timeline/lifecycle.go index cfba3871b..8f7dd6134 100644 --- a/backend/api/replay/lifecycle.go +++ b/backend/api/timeline/lifecycle.go @@ -1,4 +1,4 @@ -package replay +package timeline import ( "backend/api/event" @@ -6,7 +6,7 @@ import ( ) // LifecycleActivity represents lifecycle -// activity events suitable for session replay. +// activity events suitable for session timeline. type LifecycleActivity struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -28,7 +28,7 @@ func (la LifecycleActivity) GetTimestamp() time.Time { } // LifecycleFragment represents lifecycle -// fragment events suitable for session replay. +// fragment events suitable for session timeline. type LifecycleFragment struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -49,8 +49,52 @@ func (lf LifecycleFragment) GetTimestamp() time.Time { return lf.Timestamp } +// LifecycleViewController represents lifecycle +// view controller events suitable for session timeline. +type LifecycleViewController struct { + EventType string `json:"event_type"` + UDAttribute *event.UDAttribute `json:"user_defined_attribute"` + ThreadName string `json:"thread_name"` + *event.LifecycleViewController + Timestamp time.Time `json:"timestamp"` +} + +// GetThreadName provides the name of the thread +// where lifecycle view controller event took place. +func (lvc LifecycleViewController) GetThreadName() string { + return lvc.ThreadName +} + +// GetTimestamp provides the timestamp of +// the lifecycle view controller event. +func (lvc LifecycleViewController) GetTimestamp() time.Time { + return lvc.Timestamp +} + +// LifecycleSwiftUI represents lifecycle swift ui view +// events suitable for session timeline. +type LifecycleSwiftUI struct { + EventType string `json:"event_type"` + UDAttribute *event.UDAttribute `json:"user_defined_attribute"` + ThreadName string `json:"thread_name"` + *event.LifecycleSwiftUI + Timestamp time.Time `json:"timestamp"` +} + +// GetThreadName provides the name of the thread +// where lifecycle swift ui view event took place. +func (lsu LifecycleSwiftUI) GetThreadName() string { + return lsu.ThreadName +} + +// GetTimestamp provides the timestamp of +// the lifecycle swift ui view event. +func (lsu LifecycleSwiftUI) GetTimestamp() time.Time { + return lsu.Timestamp +} + // LifecycleApp represents lifecycle -// app events suitable for session replay. +// app events suitable for session timeline. type LifecycleApp struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -72,7 +116,7 @@ func (la LifecycleApp) GetTimestamp() time.Time { } // ComputeLifecycleActivities computes lifecycle -// activity events for session replay. +// activity events for session timeline. func ComputeLifecycleActivities(events []event.EventField) (result []ThreadGrouper) { for _, event := range events { activities := LifecycleActivity{ @@ -89,7 +133,7 @@ func ComputeLifecycleActivities(events []event.EventField) (result []ThreadGroup } // ComputeLifecycleFragments computes lifecycle -// fragment events for session replay. +// fragment events for session timeline. func ComputeLifecycleFragments(events []event.EventField) (result []ThreadGrouper) { for _, event := range events { fragments := LifecycleFragment{ @@ -105,8 +149,42 @@ func ComputeLifecycleFragments(events []event.EventField) (result []ThreadGroupe return } +// ComputeLifecycleViewControllers computes lifecycle +// view controller events for session timeline. +func ComputeLifecycleViewControllers(events []event.EventField) (result []ThreadGrouper) { + for _, event := range events { + viewControllers := LifecycleViewController{ + event.Type, + &event.UserDefinedAttribute, + event.Attribute.ThreadName, + event.LifecycleViewController, + event.Timestamp, + } + result = append(result, viewControllers) + } + + return +} + +// ComputeLifecycleSwiftUIViews computes lifecycle +// swift UI views events for session timeline. +func ComputeLifecycleSwiftUIViews(events []event.EventField) (result []ThreadGrouper) { + for _, event := range events { + swiftUIViews := LifecycleSwiftUI{ + event.Type, + &event.UserDefinedAttribute, + event.Attribute.ThreadName, + event.LifecycleSwiftUI, + event.Timestamp, + } + result = append(result, swiftUIViews) + } + + return +} + // ComputeLifecycleApp computes lifecycle -// app events for session replay. +// app events for session timeline. func ComputeLifecycleApps(events []event.EventField) (result []ThreadGrouper) { for _, event := range events { apps := LifecycleApp{ diff --git a/backend/api/replay/log.go b/backend/api/timeline/log.go similarity index 93% rename from backend/api/replay/log.go rename to backend/api/timeline/log.go index 5e60ac27c..df69d021c 100644 --- a/backend/api/replay/log.go +++ b/backend/api/timeline/log.go @@ -1,4 +1,4 @@ -package replay +package timeline import ( "backend/api/event" @@ -6,7 +6,7 @@ import ( ) // LogString represents log events suitable -// for session replay. +// for session timeline. type LogString struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -28,7 +28,7 @@ func (ls LogString) GetTimestamp() time.Time { } // ComputeLogString computes logging events -// for session replay. +// for session timeline. func ComputeLogString(events []event.EventField) (result []ThreadGrouper) { for _, event := range events { logs := LogString{ diff --git a/backend/api/replay/massage.go b/backend/api/timeline/massage.go similarity index 92% rename from backend/api/replay/massage.go rename to backend/api/timeline/massage.go index 31beb1543..fd0b112de 100644 --- a/backend/api/replay/massage.go +++ b/backend/api/timeline/massage.go @@ -1,4 +1,4 @@ -package replay +package timeline import ( "slices" @@ -13,7 +13,7 @@ type ThreadGrouper interface { } // Threads is the shape for events grouped by -// threads as expected for session replay. +// threads as expected for session timeline. type Threads map[string][]ThreadGrouper // Organize organizes a slice of event by event @@ -45,7 +45,7 @@ func (t *Threads) Sort() { } // GroupByThreads groups events by the thread name -// as needed for session replay. +// as needed for session timeline. func GroupByThreads(events []ThreadGrouper) (result map[string][]ThreadGrouper) { result = make(map[string][]ThreadGrouper) for i := range events { diff --git a/backend/api/replay/memory.go b/backend/api/timeline/memory.go similarity index 76% rename from backend/api/replay/memory.go rename to backend/api/timeline/memory.go index 0b742d29a..dff46d1f2 100644 --- a/backend/api/replay/memory.go +++ b/backend/api/timeline/memory.go @@ -1,4 +1,4 @@ -package replay +package timeline import ( "backend/api/event" @@ -6,14 +6,21 @@ import ( ) // MemoryUsage represents memory usage -// events suitable for session replay. +// events suitable for session timeline. type MemoryUsage struct { *event.MemoryUsage Timestamp time.Time `json:"timestamp"` } +// MemoryUsageAbs represents absolute +// memory usage suitable for session timeline. +type MemoryUsageAbs struct { + *event.MemoryUsageAbs + Timestamp time.Time `json:"timestamp"` +} + // TrimMemory represents trim memory events -// suitable for session replay. +// suitable for session timeline. type TrimMemory struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -35,7 +42,7 @@ func (tm TrimMemory) GetTimestamp() time.Time { } // LowMemory represents low memory events -// suitable for session replay. +// suitable for session timeline. type LowMemory struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -57,7 +64,7 @@ func (lm LowMemory) GetTimestamp() time.Time { } // ComputeMemoryUsage computes memory usage events -// for session replay. +// for session timeline. func ComputeMemoryUsage(events []event.EventField) (result []MemoryUsage) { for _, event := range events { usage := MemoryUsage{ @@ -70,8 +77,22 @@ func ComputeMemoryUsage(events []event.EventField) (result []MemoryUsage) { return } +// ComputeMemoryUsageAbs computes absolute memory +// usage events for session timeline. +func ComputeMemoryUsageAbs(events []event.EventField) (result []MemoryUsageAbs) { + for _, event := range events { + usage := MemoryUsageAbs{ + event.MemoryUsageAbs, + event.Timestamp, + } + + result = append(result, usage) + } + return +} + // ComputeTrimMemories computes trim memory events -// for session replay. +// for session timeline. func ComputeTrimMemories(events []event.EventField) (result []ThreadGrouper) { for _, event := range events { memories := TrimMemory{ @@ -88,7 +109,7 @@ func ComputeTrimMemories(events []event.EventField) (result []ThreadGrouper) { } // ComputeLowMemories computes low memory events -// for session replay. +// for session timeline. func ComputeLowMemories(events []event.EventField) (result []ThreadGrouper) { for _, event := range events { lowMemories := LowMemory{ diff --git a/backend/api/replay/nav.go b/backend/api/timeline/nav.go similarity index 94% rename from backend/api/replay/nav.go rename to backend/api/timeline/nav.go index dacd2bdc5..4f00b257e 100644 --- a/backend/api/replay/nav.go +++ b/backend/api/timeline/nav.go @@ -1,4 +1,4 @@ -package replay +package timeline import ( "backend/api/event" @@ -6,7 +6,7 @@ import ( ) // Navigation represents navigation events suitable -// for session replay. +// for session timeline. type Navigation struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -17,7 +17,7 @@ type Navigation struct { } // ScreenView represents screen view events suitable -// for session replay. +// for session timeline. type ScreenView struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -40,7 +40,7 @@ func (n Navigation) GetTimestamp() time.Time { } // ComputeNavigation computes navigation events -// for session replay. +// for session timeline. func ComputeNavigation(events []event.EventField) (result []ThreadGrouper) { for _, event := range events { navs := Navigation{ @@ -58,7 +58,7 @@ func ComputeNavigation(events []event.EventField) (result []ThreadGrouper) { } // ComputeScreemViews computes screen view events -// for session replay. +// for session timeline. func ComputeScreenViews(events []event.EventField) (result []ThreadGrouper) { for _, event := range events { sv := ScreenView{ diff --git a/backend/api/replay/network.go b/backend/api/timeline/network.go similarity index 93% rename from backend/api/replay/network.go rename to backend/api/timeline/network.go index 9037805cc..6fc982a0b 100644 --- a/backend/api/replay/network.go +++ b/backend/api/timeline/network.go @@ -1,4 +1,4 @@ -package replay +package timeline import ( "backend/api/event" @@ -6,7 +6,7 @@ import ( ) // NetworkChange represents network change events -// suitable for session replay. +// suitable for session timeline. type NetworkChange struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -28,7 +28,7 @@ func (nc NetworkChange) GetTimestamp() time.Time { } // Http represents http events -// suitable for session replay. +// suitable for session timeline. type Http struct { EventType string `json:"event_type"` UDAttribute *event.UDAttribute `json:"user_defined_attribute"` @@ -52,7 +52,7 @@ func (h Http) GetTimestamp() time.Time { } // ComputeNetworkChange computes network change -// events for session replay. +// events for session timeline. func ComputeNetworkChange(events []event.EventField) (result []ThreadGrouper) { for _, event := range events { netChanges := NetworkChange{ @@ -69,7 +69,7 @@ func ComputeNetworkChange(events []event.EventField) (result []ThreadGrouper) { } // ComputeHttp computes the http -// events for session replay. +// events for session timeline. func ComputeHttp(events []event.EventField) (result []ThreadGrouper) { for _, event := range events { endTime := event.Http.EndTime