An Introduction to the Analytics API in Apex -...

Post on 28-Apr-2018

234 views 4 download

Transcript of An Introduction to the Analytics API in Apex -...

An Introduction to the Analytics API in Apex

Peter Knolle - peterknolle.com Salesforce.com Solutions Architect – Trifecta Technologies

What will be covered

�  History / Background

�  Example uses

�  Running a report

�  Accessing report metadata

�  Filtering

�  Unit testing

�  Debugging / Exploring the API

History

�  Salesforce had excellent reporting capabilities, but…

�  …did not have an “official/supported” way to access the reports through code.

�  Screen scraping – Ick!

�  iframe – Yuck!

Analytics API Releases

�  Winter ‘14 – REST-based API released �  Requires Oauth session �  JSON requests/ responses

�  Spring ‘14 – Apex-based API released �  Same functionality as REST-based API, but in Apex

What can we do with it?

�  Easily use with charting libraries such as d3, Google Charts, etc.

What can we do with it?

�  Dynamic filtering

What can we do with it?

�  Reduce maintenance: no need to create parallel SOQL to get report data.

�  Dynamic Dashboards

�  It is very new, so much much more to come…

API

�  REST and Apex APIs have same functionality �  Run reports (synchronous and asynchronous) �  Get report metadata �  Get report result data �  Dynamic filtering �  Get list of recent asynchronous report runs

�  Classes are in the Reports namespace, e.g., Reports.ReportManager, Reports.ReportMetadata, etc.

Running a Report

�  Set of four overloaded methods for both synchronous and asynchronous

�  Synchronously Reports.ReportResults res = Reports.ReportManager.runReport(reportId);

�  Asynchronously Reports.ReportInstance instance = Reports.ReportManager.runAsyncReport(reportId);

// later…

Reports.ReportResults res = instance.getReportResults();

Overloaded runReport / runAsyncReport methods

�  runReport(reportId) – Includes summary level information but will not include details (i.e., rows).

�  runReport(reportId, includeDetails) – Includes the details, too.

�  runReport(reportId, metadata) – Applies additional filters specified in the Reports.ReportMetadata metadata argument

�  runReport(reportId, metadata, includeDetails) – Includes the details, too.

More on Asynchronous

Reports.ReportInstance instance = Reports.ReportManager.runAsyncReport(reportId);

instId = instance.getId();

//some other method…

Reports.ReportInstance inst = Reports.ReportManager.getInstance(instId);

String status = inst.getStatus();

if (status != 'Running’ && status != 'New’) {

reportResults = inst.getReportResults();

}

ReportResults

“Contains the results of running a report.”

�  getFactMap() – Returns summary-level data or summary and detailed data for each row or column grouping. Detailed data is available if the includeDetails parameter is set to true when the report is run.

Fact Map Keys

Report format   Fact map key pattern  

Tabular   T!T: The grand total of a report. Both record data values and the grand total are represented by this key.  

Summary   <First level row grouping_second level row grouping_third level row grouping>!T: T refers to the row grand total.  

Matrix   <First level row grouping_second level row grouping>!<First level column grouping_second level column grouping>.  

Report with two grouping levels

Using ReportResults – Aggregates

Map<String,ReportFact> fm = results.getFactMap();

Reports.ReportFact fact = fm.get(‘T!T’);

Decimal grandTotal = (Decimal) fact.getAggregates().get(0).getValue();

Decimal rowCount = (Decimal) fact.getAggregates().get(1).getValue();

Using ReportResults - Details

Reports.ReportResults results = Reports.ReportManager.runReport(REPORT_ID, true);

Using ReportResults - Details

Reports.ReportFactWithDetails detailFact = (Reports.ReportFactWithDetails)results.getFactMap().get('0_0!T');

List<Reports.ReportDetailRow> allRows = detailFact.getRows();

Decimal cellValue = (Decimal) rows.get(0).getDataCells().get(0).getValue();

System.assert(cellValue == 114048);

Want more on the fact map?

�  See Decode the Fact Map section in Apex Developer’s Guide:http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_analytics_fact_map.htm

Metadata

Three types of metadata

�  Report Metadata �  Reports.ReportMetadata

�  Report Extended Metadata �  Reports.ReportExtendedMedtadata

�  Report Type Metadata �  Reports.ReportTypeMetadata

ReportMetadata

“Report metadata gives information about the report as a whole, such as the report type, format, summary fields, row or column groupings, and filters that are saved to the report.“

�  Simple attributes - getId(), getName(), getDeveloperName(), getReportFormat(), getReportType()

�  Complex collections - getReportFilters(), getDetailColumns(), getAggregates(), getGroupingsDown/Across()

Accessing ReportMetadata

Reports.ReportDescribeResult descRes = Reports.ReportManager.describeReport(reportId);

ReportMetadata md = descRes.getReportMetadata(),

OR the ReportMetadata from a specific run

ReportMetadata md = reportResults.getReportMetadata();

// Example Uses

Id reportId = md.getId();

List<String> colApiNames = md.getDetailColumns();

ReportExtendedMetadata

“Report extended metadata provides additional, detailed metadata about summary and grouping fields, including data type and label information.”

�  getAggregateColumnInfo() – API name, label, data type of aggregations (row count, sum, etc.)

�  getDetailColumnInfo() – API name, label, data type of columns

�  getGroupingColumnInfo() – API name, label, data type, grouping level of each grouping in the ReportMetadata’s groupingsDown/Across.

Accessing ReportExtendedMetadata

Reports.ReportDescribeResult descRes = Reports.ReportManager.describeReport(reportId);

Reports.ReportExtendedMetadata md = descRes.getReportExtendedMetadata(),

OR the ReportExtendedMetadata for a specific run

Reports.ReportExtendedMetadata emd = reportResults.getReportExtendedMetadata();

Accessing ReportExtendedMetadata

Integer level = emd.getGroupingColumnInfo()

.get(‘STAGE_NAME’)

.getGroupingLevel();

System.assert(0 == level);

ReportTypeMetadata

“Contains report type metadata, which gives you information about the fields that are available in each section of the report type, plus filter information for those fields.”

�  List<Reports.ReportTypeColumnCategory> getCategories()– returns a list of categories, which in turn contain their list of fields with information about the fields

Accessing ReportTypeMetadata

Reports.ReportDescribeResult descRes = Reports.ReportManager.describeReport(reportId);

Reports.ReportTypeMetadata tmd = descRes.getReportTypeMetadata(),

// Not part of Reports.ReportResults

Accessing ReportTypeMetadata

Reports.ReportTypeColumnCategory category = tmd.getCategories().get(0);

String oppInfoLabel = category.getLabel();

Boolean isFilterable = category

.getColumns().get(‘AMOUNT’)

.getFilterable();

Filtering

�  Columns must be filterable.

�  Must use only allowed filter operators per data type – ReportManager. getDatatypeFilterOperatorMap()

�  Can override existing filter by getting and setting value

�  Can add additional filters

�  Use Reports.ReportMetadata run/AsyncReport versions, e.g., �  runReport(reportId, reportMetadata)

Adding a filter

Reports.ReportFilter fromFilter = new Reports.ReportFilter();

fromFilter.setColumn('CLOSE_DATE');

fromFilter.setOperator('greaterOrEqual');

fromFilter.setValue('2014-01-01');

Reports.ReportDescribeResult dr = Reports.ReportManager.describeReport(REPT_ID)

Reports.ReportMetadata md = dr.getReportMetadata();

md.getReportFilters().add(fromFilter);

Reports.ReportResults results = Reports.ReportManager.runReport(REPT_ID, md, true);

Unit Testing

�  Report runs always ignore SeeAllData annotation, and always include org data

�  Use a filter to limit testing to data created in the unit test

Opportunity opp = TestUtil.generateOpp(‘ApexUnitTest’);

List<Reports.ReportFilter> filters = getTestFilter(opp.Name);

reportMetadata.setReportFilters(filters);

Exploring / Debugging

�  Useful to see entire object

�  Helpful to determine API names

�  Debug logs and Developer Console aren’t really designed for viewing that information

Debugging - JSON

Output to <pre> tag JSON.serailizePretty(results);

public String debugRes{ get; set; }

// somewhere in a method

Reports.ReportResults results = Reports.ReportManager.runReport(REPORT_ID);

debugRes = JSON.serializePretty(results);

<apex:outputPanel id="debug">

<pre>{!debugRes}</pre>

</apex:outputPanel>

Debugging View State

Debugging REST Explorer

Selected Limitations

�  500 synchronous report runs / hour

�  20 synchronous report run requests at a time

�  1,200 asynchronous requests / hour

�  200 requests at a time for async instances

�  Returns up to the first 2,000 report rows

�  Apex: Asynchronous not allowed in Batch

�  Apex: Report runs in unit tests include org data

What was covered

�  Apex API new in Spring ’14

�  Some examples

�  Methods to run reports, filter, get results, get metadata

�  Unit testing

�  Debugging / Exploring

More

�  Apex Developer’s Guide - http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_analytics_intro.htm

�  Articles by Product Manager, Analytics @ Salesforce: https://medium.com/@arun_sfdc

�  Articles on my blog – http://peterknolle.com/posts

�  Spring ‘14 right around the corner or get a pre-release org in the meantime