Codeunit 1932 Scheduled Perf. Profiler Impl. in 28

App
System Application
Namespace
System.Tooling

Procedures, 17

Versions171819202122232425262728latest

Source2526272829

Source in 28

src/System Application/App/Performance Profiler/src/ScheduledPerfProfilerImpl.Codeunit.al253 lines, Copyright (c) Microsoft Corporation. MIT

// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------

namespace System.Tooling;

using System.DataAdministration;
using System.Environment;
using System.PerformanceProfile;
using System.Security.AccessControl;
using System.Security.User;

codeunit 1932 "Scheduled Perf. Profiler Impl."
{
    Access = Internal;
    InherentEntitlements = X;
    InherentPermissions = X;
    SingleInstance = true;
    Permissions = tabledata "Retention Policy Setup" = ri;

    procedure MapActivityTypeToRecord(var PerformanceProfileScheduler: Record "Performance Profile Scheduler"; ActivityType: Enum "Perf. Profile Activity Type")
    var
        PerformanceProfileHelper: Codeunit "Perf. Prof. Activity Mapper";
    begin
        PerformanceProfileHelper.MapActivityTypeToClientType(PerformanceProfileScheduler."Client Type", ActivityType);
    end;

    procedure MapRecordToActivityType(PerformanceProfileScheduler: Record "Performance Profile Scheduler"; var ActivityType: Enum "Perf. Profile Activity Type")
    var
        PerfProfActivityMapper: Codeunit "Perf. Prof. Activity Mapper";
    begin
        PerfProfActivityMapper.MapClientTypeToActivityType(PerformanceProfileScheduler."Client Type", ActivityType);
    end;

    procedure MapRecordToUserName(PerformanceProfileScheduler: Record "Performance Profile Scheduler"): Text
    var
        User: Record User;
    begin
        if User.GET(PerformanceProfileScheduler."User ID") then;
        exit(User."User Name");
    end;

    procedure FilterUsers(var PerformanceProfileScheduler: Record "Performance Profile Scheduler"; SecurityID: Guid; ForceFilterToUser: Boolean)
    var
        RecordRef: RecordRef;
    begin
        RecordRef.GetTable(PerformanceProfileScheduler);
        this.FilterUsers(RecordRef, SecurityID, ForceFilterToUser);
        RecordRef.SetTable(PerformanceProfileScheduler);
    end;

    procedure FilterUsers(var RecordRef: RecordRef; SecurityID: Guid; ForceFilterToUser: Boolean)
    var
        UserPermissions: Codeunit "User Permissions";
        FilterView: Text;
        FilterTextTxt: Label 'where("User ID"=filter(''%1''))', locked = true;

    begin
        if (not ForceFilterToUser) and UserPermissions.CanManageUsersOnTenant(SecurityID) then
            exit; // No need for additional user filters

        FilterView := StrSubstNo(FilterTextTxt, SecurityID);
        RecordRef.FilterGroup(2);
        RecordRef.SetView(FilterView);
        RecordRef.FilterGroup(0);
    end;

    procedure ValidateScheduleCreationPermissions(UserID: Guid; ScheduleUserID: Guid)
    var
        UserPermissions: Codeunit "User Permissions";
    begin
        if (UserID = ScheduleUserID) then
            exit;

        if (not UserPermissions.CanManageUsersOnTenant(UserID)) then
            Error(CannotCreateSchedulesForOtherUsersErr);
    end;

    procedure InitializeFields(var PerformanceProfileScheduler: Record "Performance Profile Scheduler"; var ActivityType: Enum "Perf. Profile Activity Type")
    var
        FourHours: Duration;
    begin
        FourHours := 1000 * 60 * 60 * 4;
        PerformanceProfileScheduler.Init();
        PerformanceProfileScheduler."Schedule ID" := CreateGuid();
        PerformanceProfileScheduler."Starting Date-Time" := CurrentDateTime;
        PerformanceProfileScheduler."Ending Date-Time" := PerformanceProfileScheduler."Starting Date-Time" + FourHours;
        PerformanceProfileScheduler.Enabled := true;
        PerformanceProfileScheduler."Profile Creation Threshold" := 500;
        PerformanceProfileScheduler.Frequency := PerformanceProfileScheduler.Frequency::"100 milliseconds";
        PerformanceProfileScheduler."Client Type" := PerformanceProfileScheduler."Client Type"::"Web Client";
        PerformanceProfileScheduler."User ID" := UserSecurityId();
        ActivityType := ActivityType::"Web Client";
    end;

    procedure ValidatePerformanceProfileSchedulerDates(PerformanceProfileScheduler: Record "Performance Profile Scheduler"; MaxRetentionPeriod: Duration)
    var
        ScheduleDuration: Duration;
    begin
        this.ValidatePerformanceProfileSchedulerDatesRelation(PerformanceProfileScheduler);

        if (MaxRetentionPeriod = 0) then
            exit;

        ScheduleDuration := PerformanceProfileScheduler."Ending Date-Time" - PerformanceProfileScheduler."Starting Date-Time";
        if (ScheduleDuration > MaxRetentionPeriod) then
            Error(ScheduleDurationCannotExceedRetentionPeriodErr);
    end;

    procedure ValidatePerformanceProfileSchedulerDatesRelation(PerformanceProfileScheduler: Record "Performance Profile Scheduler")
    begin
        if ((PerformanceProfileScheduler."Ending Date-Time" <> 0DT) and (PerformanceProfileScheduler."Ending Date-Time" < CurrentDateTime())) then
            Error(ProfileCannotBeInThePastErr);

        if ((PerformanceProfileScheduler."Ending Date-Time" <> 0DT) and (PerformanceProfileScheduler."Starting Date-Time" > PerformanceProfileScheduler."Ending Date-Time")) then
            Error(ProfileStartingDateLessThenEndingDateErr);
    end;

    procedure ValidatePerformanceProfileEndTime(PerformanceProfileScheduler: Record "Performance Profile Scheduler")
    begin
        if (PerformanceProfileScheduler."Ending Date-Time" = 0DT) then
            Error(ScheduleEndTimeCannotBeEmptyErr);
    end;

    procedure ValidatePerformanceProfileScheduler(PerformanceProfileScheduler: Record "Performance Profile Scheduler"; ActivityType: Enum "Perf. Profile Activity Type")
    var
        LocalPerformanceProfileScheduler: Record "Performance Profile Scheduler";
    begin
        this.MapActivityTypeToRecord(PerformanceProfileScheduler, ActivityType);

        if ((PerformanceProfileScheduler."Ending Date-Time" = 0DT) or
            (PerformanceProfileScheduler."Starting Date-Time" = 0DT) or
            (IsNullGuid(PerformanceProfileScheduler."User ID"))) then
            exit;

        // The period sets should not intersect.
        LocalPerformanceProfileScheduler.Init();
        LocalPerformanceProfileScheduler.SetFilter("Client Type", '=%1', PerformanceProfileScheduler."Client Type");
        LocalPerformanceProfileScheduler.SetFilter("User ID", '=%1', PerformanceProfileScheduler."User ID");
        LocalPerformanceProfileScheduler.SetFilter("Schedule ID", '<>%1', PerformanceProfileScheduler."Schedule ID");
        LocalPerformanceProfileScheduler.SetFilter("Starting Date-Time", '<>%1', 0DT);
        LocalPerformanceProfileScheduler.SetFilter("Ending Date-Time", '<>%1', 0DT);

        if not LocalPerformanceProfileScheduler.FindSet() then
            exit;

        repeat
            if (this.Intersects(LocalPerformanceProfileScheduler, PerformanceProfileScheduler)) then
                Error(ProfileHasAlreadyBeenScheduledErr);

        until LocalPerformanceProfileScheduler.Next() = 0;

    end;

    procedure GetRetentionPeriod(): Code[20]
    var
        RetentionPolicySetup: Record "Retention Policy Setup";
    begin
        if RetentionPolicySetup.Get(Database::"Performance Profile Scheduler") then
            exit(RetentionPolicySetup."Retention Period");
    end;

    procedure CreateRetentionPolicySetup(ErrorInfo: ErrorInfo)
    var
        RetentionPolicySetupRec: Record "Retention Policy Setup";
        RetentionPolicySetup: Codeunit "Retention Policy Setup";
    begin
        this.CreateRetentionPolicySetup(Database::"Performance Profile Scheduler", RetentionPolicySetup.FindOrCreateRetentionPeriod("Retention Period Enum"::"1 Week"));
        if RetentionPolicySetupRec.Get(Database::"Performance Profile Scheduler") then
            Page.Run(Page::"Retention Policy Setup Card", RetentionPolicySetupRec);
    end;

    procedure CreateRetentionPolicySetup(TableId: Integer; RetentionPeriodCode: Code[20])
    var
        RetentionPolicySetup: Record "Retention Policy Setup";
        PerformanceProfileScheduler: Record "Performance Profile Scheduler";
        RetenPolAllowedTables: Codeunit "Reten. Pol. Allowed Tables";
    begin
        if RetentionPolicySetup.Get(TableId) then
            exit;
        if not RetenPolAllowedTables.IsAllowedTable(Database::"Performance Profile Scheduler") then
            RetenPolAllowedTables.AddAllowedTable(Database::"Performance Profile Scheduler", PerformanceProfileScheduler.FieldNo("Ending Date-Time"), 1);
        RetentionPolicySetup.Validate("Table Id", TableId);
        RetentionPolicySetup.Validate("Apply to all records", true);
        RetentionPolicySetup.Validate("Retention Period", RetentionPeriodCode);
        RetentionPolicySetup.Validate(Enabled, true);
        RetentionPolicySetup.Insert(true);
    end;

    procedure ValidateThreshold(var PerformanceProfileScheduler: Record "Performance Profile Scheduler")
    begin
        if (PerformanceProfileScheduler."Profile Creation Threshold" <= 0) then
            PerformanceProfileScheduler.Validate("Profile Creation Threshold", 500);
    end;

    local procedure Intersects(First: Record "Performance Profile Scheduler"; Second: Record "Performance Profile Scheduler"): Boolean
    var
        StartInterval1: DateTime;
        EndInterval1: DateTime;
        StartInterval2: DateTime;
        EndInterval2: Datetime;
    begin
        StartInterval1 := First."Starting Date-Time";
        EndInterval1 := First."Ending Date-Time";
        StartInterval2 := Second."Starting Date-Time";
        EndInterval2 := Second."Ending Date-Time";

        if (((StartInterval1 < EndInterval1) and (EndInterval1 <= StartInterval2) and (StartInterval2 < EndInterval2)) or
            ((StartInterval2 < EndInterval2) and (EndInterval2 <= StartInterval1) and (StartInterval1 < EndInterval1))) then
            exit(false);

        exit(true);
    end;

    internal procedure IsProfilingEnabled(var ScheduleId: Guid): Boolean
    var
        ProfilerHelper: DotNet ProfilerHelper;
        PerformanceProfileSchedulerRecord: DotNet PerformanceProfileSchedulerRecord;
    begin
        PerformanceProfileSchedulerRecord := ProfilerHelper.GetScheduleBasedProfilingStatus();
        ScheduleId := PerformanceProfileSchedulerRecord.ScheduleId;
        exit(PerformanceProfileSchedulerRecord.IsProfiling());
    end;

    internal procedure GetStatus(PerformanceProfileScheduler: Record "Performance Profile Scheduler"): Text
    begin
        if PerformanceProfileScheduler.Enabled then
            if (PerformanceProfileScheduler."Starting Date-Time" <= CurrentDateTime) and (PerformanceProfileScheduler."Ending Date-Time" >= CurrentDateTime) then
                exit(ActiveLbl)
            else
                exit(InactiveOutsideTimeWindowLbl)
        else
            exit(InactiveLbl);
    end;

    [EventSubscriber(ObjectType::Codeunit, Codeunit::"System Action Triggers", GetProfilerSchedulesPageId, '', false, false)]
    local procedure GetProfilerSchedulesPageId(var PageId: Integer)
    begin
        PageId := Page::"Perf. Profiler Schedules List";
    end;

    var
        ActiveLbl: Label 'Active';
        InactiveLbl: Label 'Inactive';
        InactiveOutsideTimeWindowLbl: Label 'Inactive (outside time window)';
        ProfileStartingDateLessThenEndingDateErr: Label 'The performance profile starting date must be set before the ending date.';
        ProfileHasAlreadyBeenScheduledErr: Label 'Only one performance profile session can be scheduled for a given activity type for a given user for a given period.';
        ProfileCannotBeInThePastErr: Label 'A schedule cannot be set to run in the past.';
        ScheduleDurationCannotExceedRetentionPeriodErr: Label 'The performance profile schedule duration cannot exceed the retention period.';
        ScheduleEndTimeCannotBeEmptyErr: Label 'The performance profile schedule must have an end time.';
        CannotCreateSchedulesForOtherUsersErr: Label 'You do not have sufficient permissions to create profiler schedules for other users. Please contact your administrator.';
}

Procedures, 17

NameParametersReturnsAccessObsolete
MapActivityTypeToRecord(var Record Performance Profile Scheduler, Enum Perf. Profile Activity Type)public-
MapRecordToActivityType(Record Performance Profile Scheduler, var Enum Perf. Profile Activity Type)public-
MapRecordToUserName(Record Performance Profile Scheduler)Textpublic-
FilterUsers(var Record Performance Profile Scheduler, Guid, Boolean)public-
FilterUsers(var RecordRef, Guid, Boolean)public-
ValidateScheduleCreationPermissions(Guid, Guid)public-
InitializeFields(var Record Performance Profile Scheduler, var Enum Perf. Profile Activity Type)public-
ValidatePerformanceProfileSchedulerDates(Record Performance Profile Scheduler, Duration)public-
ValidatePerformanceProfileSchedulerDatesRelation(Record Performance Profile Scheduler)public-
ValidatePerformanceProfileEndTime(Record Performance Profile Scheduler)public-
ValidatePerformanceProfileScheduler(Record Performance Profile Scheduler, Enum Perf. Profile Activity Type)public-
GetRetentionPeriod()Code[20]public-
CreateRetentionPolicySetup(ErrorInfo)public-
CreateRetentionPolicySetup(Integer, Code[20])public-
ValidateThreshold(var Record Performance Profile Scheduler)public-
IsProfilingEnabled(var Guid)Booleaninternal-
GetStatus(Record Performance Profile Scheduler)Textinternal-