# Proactively Auditing Report Speed and Design

Part of the Performance and Scaling series.

Administrators can take some proactive steps to improve communication with report creators in order to reduce instances of user error leading to poorly performing reports. Users can be informed, when a report is run, that they have made mistakes which will cause inappropriate or non-performant behavior. This is possible simply by taking a diagnostic look at how certain aspects of the report have been designed.

A server event can intercept a report before it runs and audit the design for potential issues. If any flags are raised, the event can notify the user and halt the execution, thus enforcing that all errors are fixed before ever reaching the execution stage and hitting the network and database. We have provided an example that detects several common mistakes for most environments. Of course, since this is all done in code, you may customize the event however you wish. You can disable certain checks for cases that you wish to permit, or add additional checks for cases that we had not considered.

For example, we include a procedure that checks whether a report has any non-joined data objects because this will cause a Cartesian product to be returned.

    internal static bool HasUnjoinedEntities(this Report report)
    {
        List<string> entities = report.Entities.Select(entity => entity.Name).ToList();

        if (entities.Count == 1)
            return false;

        foreach (Join join in report.Joins)
            foreach (JoinColumn joinCol in join.JoinColumns) {
                if (joinCol.FromColumn.ExpressionType == JoinExpressionType.Column)
                    entities.Remove(joinCol.FromColumn.EntityName);
                if (joinCol.ToColumn.ExpressionType == JoinExpressionType.Column)
                    entities.Remove(joinCol.ToColumn.EntityName);
                if (entities.Count == 0)
                    return false;
            }

        return true;
    }

Once added to the Admin Console, the server event can run globally whenever a report is executed by any user. To enable this behavior, select OnReportExecuteStart from the Global Events list. Then you may choose to disable it for certain classes of trusted users by switching the type to None using an API call.

Alternatively, the event can be attached to reports individually. Users or admins would add it from the Events Window in the Report Designer, and then select OnReportExecuteStart from the Event list.

A third option is to use the Action Event version. This will allow you to show a custom html dialog instead of the basic application user message, which allows the user to choose whether to proceed with or halt the execution. Once added to the Admin Console, select OnExecuteReport from the Global Event Type list. (Note: This version will not trigger from the Run Report button in the Advanced Designer.)

Click here to download the example!

> See Intro to Server Events for more information on using server events. See .NET General Reference for more examples on the API classes used in this example.