Skip to content

Commit

Permalink
Query Optimizations & More Configurable Controls (#394)
Browse files Browse the repository at this point in the history
* Added new LoggerParameter__mdt records to control stacktrace parsing & synchronously querying/setting some fields, centralized the usage of UserInfo.getSessionId(), fixed milestone link in README to use v4.7.0 (instead of the old v4.6.0 milestone link)

* Updated LogEntryEventBuilder to only run queries/set relevant fields based on the corresponding LoggerParameter__mdt "synchronous" records, implemented enabling/disabling stack trace parsing via LoggerParameter__mdt record

* Updated LogEntryEventHandler to handle setting queried fields when corresponding LoggerParameter__mdt records are set to asynchronously query

* Updated LogEntryEventBuilder and LogEntryEventHandler to fully skip some queries, based on new CMDT records to complete enable/disable different queries

* Added all included parameters as constants in LoggerParameter, renamed some constant names and LoggerParameter__mdt records

* Updated LogEntryEventBuilder & LoggerDataStore to use more lazy loading on some static variables/constants,

* Updated LogEntryEventBuilder to consistently use of shouldShould() method internally instead of the shouldSave property

* Updated LoggerCache to leverage a new platform cache partition (cleverly also named LoggerCache). Also added a new LoggerParameter__mdt record 'UsePlatformCache' to enable/disable the usage of platform cache

* Updated the 2 data selector classes LoggerEngineDataSelector & LogManagementDataSelector to now use either org or session cache - the original transaction cache is now used internally as a fallback/secondary cache

* Added new fields LogEntryEvent__e.RequestId__c and Log__c.RequestId__c to store the value of System.Request.getCurrent().getRequestId(). Previously, this value was used for Log__c.TransactionId__c, and I reverted to using a more reliable UUID in v4.7.3, but some orgs would still like to report on the request ID

* Fixed an unreported bug where the value for the workaround field LogEntryEvent__e.TimestampString__c was out of sync with LogEntryEvent__e.TimestampString__c, resulting in inaccurate data on LogEntry__c.Timestamp__c

* Fixed the approach used to dynamically determine if Experience Cloud is enabled in the current org

* Fixed #393 by removing the ORDER BY statements in several queries because sorting didn't serve a functional purpose. Instead, the results are now sorted just in the tests to help with asserting on the returned values.

* Updated build.yml to run Apex test twice - synchronously & synchronously. This helps with automatically testing functionality that relies on the AuthSession object by ensuring the code works with & without an active session

* Added some new integration tests in the extra-tests folder

* Added some additional Experience Site metadata to better test Network fields being queried & set

* Updated pwsh script to not include the build number in sfdx-project.json, removed existing build numbers in sfdx-project.json

* Created new version of async failure additions plugin based on changes made by @jamessimone in #392

* Create new version v1.5.1 of Slack plugin that fixes the formatting of multi-line text fields in SlackLoggerPlugin
  • Loading branch information
jongpie authored Oct 30, 2022
1 parent 790fe44 commit 977993e
Show file tree
Hide file tree
Showing 99 changed files with 3,479 additions and 615 deletions.
1 change: 1 addition & 0 deletions .forceignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
nebula-logger/**/main/default/
nebula-logger/managed-package/sfdx-project.json
nebula-logger/managed-package/**/*.testSuite-meta.xml
/**/Admin.profile-meta.xml

# Directory/package-specific README files
**/README.md
Expand Down
30 changes: 27 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,17 @@ jobs:
- name: 'Assign Logger Admin Permission Set'
run: npm run permset:assign:admin

- name: 'Run Apex Tests'
# Nebula Logger has functionality that queries the AuthSession object when the current user has an active session.
# The code should work with or without an active session, so the pipeline runs the tests twice - asynchronously and synchronously.
# This is done because, based on how you execute Apex tests, the running user may have an active session (synchrously) or not (asynchronously).
# Utlimately, this could/should probably be better mocked during tests, but the AuthSession is read-only in Apex, so it's a bit difficult to work with.
# Running the Apex tests sync & async serves as an extra level of integration testing to ensure that everything works with or without an active session.
- name: 'Run Apex Tests Asynchronously'
run: npm run test:apex

- name: 'Run Apex Tests Synchronously'
run: npm run test:apex -- --synchronous

- name: 'Delete Base Scratch Org'
run: npm run org:delete:noprompt
if: ${{ always() }}
Expand Down Expand Up @@ -219,9 +227,17 @@ jobs:
- name: 'Assign Logger Admin Permission Set'
run: npm run permset:assign:admin

- name: 'Run Apex Tests'
# Nebula Logger has functionality that queries the AuthSession object when the current user has an active session.
# The code should work with or without an active session, so the pipeline runs the tests twice - asynchronously and synchronously.
# This is done because, based on how you execute Apex tests, the running user may have an active session (synchrously) or not (asynchronously).
# Utlimately, this could/should probably be better mocked during tests, but the AuthSession is read-only in Apex, so it's a bit difficult to work with.
# Running the Apex tests sync & async serves as an extra level of integration testing to ensure that everything works with or without an active session.
- name: 'Run Apex Tests Asynchronously'
run: npm run test:apex

- name: 'Run Apex Tests Synchronously'
run: npm run test:apex -- --synchronous

- name: 'Delete unsupported code coverage files'
run: rm ./test-coverage/apex/test-result-707*-codecoverage.json

Expand Down Expand Up @@ -323,9 +339,17 @@ jobs:
- name: 'Create & Install Package Version'
run: npx pwsh ./scripts/build/create-and-install-package-version.ps1 -targetpackagealias '"Nebula Logger - Core"' -targetreadme ./README.md -targetusername nebula-logger-package-demo

- name: 'Run Apex Tests'
# Nebula Logger has functionality that queries the AuthSession object when the current user has an active session.
# The code should work with or without an active session, so the pipeline runs the tests twice - asynchronously and synchronously.
# This is done because, based on how you execute Apex tests, the running user may have an active session (synchrously) or not (asynchronously).
# Utlimately, this could/should probably be better mocked during tests, but the AuthSession is read-only in Apex, so it's a bit difficult to work with.
# Running the Apex tests sync & async serves as an extra level of integration testing in the meantime to ensure that everything works with or without an active session.
- name: 'Run Apex Tests Asynchronously'
run: npm run test:apex:nocoverage -- --targetusername nebula-logger-package-demo

- name: 'Run Apex Tests Synchronously'
run: npm run test:apex:nocoverage -- --targetusername nebula-logger-package-demo --synchronous

- name: 'Commit New Package Version'
run: |
git config --local user.email "action@github.com"
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
.sf/
.sfdx/
.vscode/
nebula-logger/**/main/default/
# nebula-logger/**/main/default/
tests/
test-coverage/
temp/

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@

The most robust logger for Salesforce. Works with Apex, Lightning Components, Flow, Process Builder & Integrations. Designed for Salesforce admins, developers & architects.

## Unlocked Package - v4.8.3
## Unlocked Package - v4.8.4

[![Install Unlocked Package in a Sandbox](./images/btn-install-unlocked-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000015lw9QAA)
[![Install Unlocked Package in Production](./images/btn-install-unlocked-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000015lw9QAA)
[![Install Unlocked Package in a Sandbox](./images/btn-install-unlocked-package-sandbox.png)](https://test.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000023R02QAE)
[![Install Unlocked Package in Production](./images/btn-install-unlocked-package-production.png)](https://login.salesforce.com/packaging/installPackage.apexp?p0=04t5Y0000023R02QAE)
[![View Documentation](./images/btn-view-documentation.png)](https://jongpie.github.io/NebulaLogger/)

## Managed Package - v4.8.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
"LinkTextDecorationHover": "underline",
"MaxContentWidthDesktop": "1800px",
"MaxContentWidthMobile": "none",
"MobileBaseFontSize": "1rem",
"MobileBaseFontSize": "16px",
"PrimaryAccentColor": "#005fb2",
"PrimaryAccentForegroundColor": "#ffffff",
"SiteLogo": "",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"activeViewId": "e02c0193-8cb2-41b6-8298-f31c4f3a3f3f",
"appPageId": "3772c2ec-1566-4ffa-9231-d5db8d42b47d",
"configurationTags": ["allow-in-static-site", "too-many-requests"],
"configurationTags": ["too-many-requests", "allow-in-static-site"],
"id": "58bd1d16-3a54-4cf5-84a9-16a870bce9d2",
"label": "Too Many Requests",
"routeType": "too-many-requests",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
<gatherCustomerSentimentData>false</gatherCustomerSentimentData>
<networkMemberGroups>
<profile>admin</profile>
<profile>logger test site user profile</profile>
</networkMemberGroups>
<networkPageOverrides>
<changePasswordPageOverrideSetting>Standard</changePasswordPageOverrideSetting>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Profile xmlns="http://soap.sforce.com/2006/04/metadata">
<userLicense>High Volume Customer Portal</userLicense>
</Profile>
160 changes: 160 additions & 0 deletions docs/apex/Configuration/LoggerCache.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
---
layout: default
---

## LoggerCache class

Class used to cache query results returned by the selector classes

---

### Methods

#### `contains(String key)``Boolean`

Manages interacting with platform cache partitions, and can be mocked during unit tests so that tests don&apos;t have to rely on the actual platform cache partitions configured in the org.

#### `contains(String key)``Boolean`

Manages interacting with platform cache. The provided transaction cache instance is used internally as the primary caching method, and is further augmented by using Platform Cache to provide caching that spans multiple transactions.

#### `contains(String key)``Boolean`

Manages any transaction-specific caching, using `Map&lt;String, Object&gt;`

#### `get(String key)``Object`

#### `get(String key)``Object`

#### `get(String key)``Object`

#### `getOrganizationCache()``Cacheable`

The instance of `Cacheable` used for any organization-specific caching via Platform Cache. When Platform Cache is disabled or not available, the transaction cache is instead used.

##### Return

**Type**

Cacheable

**Description**

The singleton instance of `Cacheable`

#### `getSessionCache()``Cacheable`

The instance of `Cacheable` used for any session-specific caching via Platform Cache. When Platform Cache is disabled or not available, the transaction cache is instead used.

##### Return

**Type**

Cacheable

**Description**

The singleton instance of `Cacheable`

#### `getTransactionCache()``Cacheable`

The instance of `Cacheable` used for any transaction-specific caching. Cached data is stored internally in-memory for the duration of the transaction.

##### Return

**Type**

Cacheable

**Description**

The singleton instance of `Cacheable`

#### `isAvailable()``Boolean`

#### `put(String key, Object value, Integer cacheTtlSeconds, Cache.Visibility cacheVisiblity, Boolean isCacheImmutable)``void`

#### `put(String key, Object value)``void`

#### `put(String key, Object value)``void`

#### `remove(String key)``void`

#### `remove(String key)``void`

#### `remove(String key)``void`

---

### Inner Classes

#### LoggerCache.Cacheable interface

Interface used to define caches that can be used to store values via different mechanisms

---

##### Methods

###### `contains(String key)``Boolean`

Indicates if the specified key has already been added to the cache

####### Parameters

| Param | Description |
| ----- | ---------------------------------------------- |
| `key` | The `String` key to check for within the cache |

####### Return

**Type**

Boolean

**Description**

The `Boolean` result that indicates if the specified key is contained in the cache

###### `get(String key)``Object`

Returns the cached value for the specified key, or `null` if the specified key does not exist in the cache

####### Parameters

| Param | Description |
| ----- | ---------------------------------------------- |
| `key` | The `String` key to check for within the cache |

####### Return

**Type**

Object

**Description**

The cached value, or null if no cached value is found for the specified key

###### `put(String key, Object value)``void`

Adds the provided `Object` value to the cache, using the specified `String` key

####### Parameters

| Param | Description |
| ------- | ------------------------------------------------- |
| `key` | The `String` key to add to the cache |
| `value` | The `Object` value to cache for the specified key |

###### `remove(String key)``void`

Removes the specified `String` key from the cache

####### Parameters

| Param | Description |
| ----- | ----------------------------------------- |
| `key` | The `String` key to remove from the cache |

---
72 changes: 64 additions & 8 deletions docs/apex/Configuration/LoggerParameter.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,83 @@ Provides a centralized way to load parameters for SObject handlers &amp; plugins

#### `CALL_STATUS_API``Boolean`

Indicates if Logger will make an async callout to https://api.status.salesforce.com to get additional details about the current org, which is then stored on the Log\_\_c record. Controlled by the custom metadata record LoggerParamer.CallStatusApi, or `false` as the default
Indicates if Nebula Logger will make an async callout to `https://api.status.salesforce.com` to get additional details about the current org, which is then stored on the Log\_\_c record. Controlled by the custom metadata record `LoggerParameter.CallStatusApi`, or `false` as the default

#### `ENABLE_STACK_TRACE_PARSING``Boolean`

Indicates if Nebula Logger will parse a stack trace for each log entry, which is then used to populate fields like `LogEntry__c.StackTrace__c` and `LogEntry__c.OriginLocation__c`. Controlled by the custom metadata record `LoggerParameter.EnableStackTraceParsing`, or `true` as the default

#### `ENABLE_SYSTEM_MESSAGES``Boolean`

Indicates if Logger will append its own log entries about the logging system. Controlled by the custom metadata record LoggerParamer.EnableLoggerSystemMessages, or `false` as the default
Indicates if Nebula Logger will append its own log entries about the logging system. Controlled by the custom metadata record `LoggerParameter.EnableLoggerSystemMessages`, or `false` as the default

#### `ENABLE_TAGGING``Boolean`

Indicates if Nebula Logger&apos;s tagging system is enabled. Controlled by the custom metadata record `LoggerParameter.EnableTagging`, or `true` as the default

#### `QUERY_APEX_CLASS_DATA``Boolean`

Controls if Nebula Logger queries `ApexClass` data. When set to `false`, any `ApexClass` fields on `LogEntryEvent__e` and `Log__c` will not be populated Controlled by the custom metadata record `LoggerParameter.QueryApexClassData`, or `true` as the default

#### `QUERY_AUTH_SESSION_DATA``Boolean`

Controls if Nebula Logger queries `AuthSession` data. When set to `false`, any `AuthSession` fields on `LogEntryEvent__e` and `Log__c` will not be populated Controlled by the custom metadata record `LoggerParameter.QueryAuthSessionData`, or `true` as the default

#### `QUERY_AUTH_SESSION_DATA_SYNCHRONOUSLY``Boolean`

Controls if Nebula Logger queries `AuthSession` data synchronously &amp; populated on `LogEntryEvent__e` records. When set to `false`, any `AuthSession` fields on `LogEntryEvent__e` will not be populated - the data will instead be queried asynchronously and populated on any resulting `Log__c` records. Controlled by the custom metadata record `LoggerParameter.QueryAuthSessionDataSynchronously`, or `true` as the default

#### `QUERY_FLOW_DEFINITION_VIEW_DATA``Boolean`

Controls if Nebula Logger queries `FlowDefinitionView` data. When set to `false`, any `FlowDefinitionView` fields on `LogEntryEvent__e` and `Log__c` will not be populated Controlled by the custom metadata record `LoggerParameter.QueryFlowDefinitionViewData`, or `true` as the default

#### `QUERY_NETWORK_DATA``Boolean`

Controls if Nebula Logger queries `Network` data. When set to `false`, any `Network` fields on `LogEntryEvent__e` and `Log__c` will not be populated Controlled by the custom metadata record `LoggerParameter.QueryNetworkData`, or `true` as the default

#### `QUERY_NETWORK_DATA_SYNCHRONOUSLY``Boolean`

Controls if Nebula Logger queries `Network` data is queried synchronously &amp; populated on `LogEntryEvent__e` records. When set to `false`, any `Network` fields on `LogEntryEvent__e` will not be populated - the data will instead be queried asynchronously and populated on any resulting `Log__c` records. Controlled by the custom metadata record `LoggerParameter.QueryNetworkDataSynchronously`, or `true` as the default

#### `QUERY_ORGANIZATION_DATA``Boolean`

Controls if Nebula Logger queries `Organization` data. When set to `false`, any `Organization` fields on `LogEntryEvent__e` and `Log__c` will not be populated Controlled by the custom metadata record `LoggerParameter.QueryOrganizationData`, or `true` as the default

#### `QUERY_ORGANIZATION_DATA_SYNCHRONOUSLY``Boolean`

Indicates if Nebula Logger queries `Organization` data is queried synchronously &amp; populated on `LogEntryEvent__e` records. When set to `false`, any `Organization` fields on `LogEntryEvent__e` will not be populated - the data will instead be queried asynchronously and populated on any resulting `Log__c` records. Controlled by the custom metadata record `LoggerParameter.QueryOrganizationDataSynchronously`, or `true` as the default

#### `QUERY_RELATED_RECORD_DATA``Boolean`

Controls if Nebula Logger queries data for records synthetically related to a `LogEntry__c` via `LogEntry__c.RecordId__c`. When set to `false`, any fields on `LogEntry__c` related to `LogEntry__c.RecordId__c` not be populated Controlled by the custom metadata record `LoggerParameter.QueryRelatedRecordData`, or `true` as the default

#### `QUERY_USER_DATA``Boolean`

Controls if Nebula Logger queries `User` data. When set to `false`, any `User` fields on `LogEntryEvent__e` and `Log__c` will not be populated Controlled by the custom metadata record `LoggerParameter.QueryUserData`, or `true` as the default

#### `QUERY_USER_DATA_SYNCHRONOUSLY``Boolean`

Indicates if Nebula Logger queries `User` data is queried synchronously &amp; populated on `LogEntryEvent__e` records. When set to `false`, any `User` fields on `LogEntryEvent__e` that rely on querying will not be populated - the data will instead be queried asynchronously and populated on any resulting `Log__c` records. Controlled by the custom metadata record `LoggerParameter.QueryUserDataSynchronously`, or `true` as the default

#### `SEND_ERROR_EMAIL_NOTIFICATIONS``Boolean`

Indicates if Logger will send an error email notification if any internal exceptions occur. Controlled by the custom metadata record LoggerParamer.SendErrorEmailNotifications, or `true` as the default
Indicates if Logger will send an error email notification if any internal exceptions occur. Controlled by the custom metadata record `LoggerParameter.SendErrorEmailNotifications`, or `true` as the default

#### `SYSTEM_DEBUG_MESSAGE_FORMAT``String`

The merge-field syntax to use when calling System.debug(). Controlled by the custom metadata record LoggerParamer.SystebugMessageFormat, or `{OriginLocation__c}\n{Message__c}` as the default
The merge-field syntax to use when calling System.debug(). Controlled by the custom metadata record `LoggerParameter.SystebugMessageFormat`, or `{OriginLocation__c}\n{Message__c}` as the default

#### `USE_FIRST_SCENARIO_FOR_TRANSACTION``Boolean`

Indicates if `Logger.setScenario(String)` uses the first specified value (when `true`), or the last specified value (when `false`) Controlled by the custom metadata record `LoggerParameter.UseFirstSpecifiedScenario`, or `true` as the default

#### `TAGGING_IS_ENABLED``Boolean`
#### `USE_PLATFORM_CACHE``Boolean`

Indicates if Logger&apos;s tagging system is enabled. Controlled by the custom metadata record LoggerParamer.EnableTagging, or `true` as the default
Indicates if Platform Cache is used to cache organization &amp; session data in the cache partition `LoggerCache` Controlled by the custom metadata record `LoggerParameter.UsePlatformCache`, or `true` as the default

#### `TAG_USING_TOPICS``Boolean`
#### `USE_TOPICS_FOR_TAGS``Boolean`

Indicates if Logger&apos;s tagging will use Topic and TopicAssignment for storing tags, or `false` as the default
Indicates if Logger&apos;s tagging will use `Topic` and `TopicAssignment` for storing tags (when `true`), or uses Nebula Logger&apos;s custom objects `LoggerTag__c` and `LogEntryTag__c` (when `false`) Controlled by the custom metadata record `LoggerParameter.UseTopicsForTags`, or `false` as the default

---

Expand Down
14 changes: 14 additions & 0 deletions docs/apex/Log-Management/LogManagementDataSelector.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,20 @@ List&lt;ApexEmailNotification&gt;

The cached `List&lt;ApexEmailNotification&gt;` records

#### `getCachedRecentLogWithApiReleaseDetails()``Log__c`

Returns a cached `Log__c` record that has been created within the last 4 hours that has API details populated from calling https://api.status.salesforce.com

##### Return

**Type**

Log\_\_c

**Description**

The cached `Log__c` record, or `null` if no match is found

#### `getCountOfAsyncApexJobs(String apexClassName, String apexMethodName, List<String> jobStatuses)``Integer`

Returns the count of `AsyncApexJob` records with the specified Apex class name, method name &amp; job status
Expand Down
Loading

0 comments on commit 977993e

Please sign in to comment.