-
-
Notifications
You must be signed in to change notification settings - Fork 174
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Added SlackLogPusher batch class to handle pushing logs to Slack * Added SlackLogPushScheduler schedulable class to schedule pushing logs to Slack * Added Slack record to LoggerIntegration__mdt custom metadata type * Added new Slack fields PushToSlack__c and PushedToSlackDate__c on Log__c object * Added remote site settings for Loggly & Slack
- Loading branch information
Showing
20 changed files
with
421 additions
and
152 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
public without sharing class SlackLogPushScheduler implements System.Schedulable { | ||
|
||
public static void scheduleEveryXMinutes(Integer x) { | ||
for(Integer i = 0; i < 60; i += x) { | ||
scheduleHourly(i); | ||
} | ||
} | ||
|
||
public static void scheduleHourly(Integer startingMinuteInHour) { | ||
String minuteString = String.valueOf(startingMinuteInHour); | ||
minuteString = minuteString.leftPad(2, '0'); | ||
scheduleHourly(startingMinuteInHour, 'Slack Log Sync: Every Hour at ' + minuteString); | ||
} | ||
|
||
public static void scheduleHourly(Integer startingMinuteInHour, String jobName) { | ||
System.schedule(jobName, '0 ' + startingMinuteInHour + ' * * * ?', new SlackLogPushScheduler()); | ||
} | ||
|
||
public void execute(SchedulableContext sc) { | ||
// Salesforce has a limit of 5 running batch jobs | ||
// If there are already 5 jobs running, then don't run this job | ||
// Any records that need to be processed will be processed the next time the job executes | ||
if(this.getNumberOfRunningBatchJobs() >= 5) return; | ||
|
||
Database.executebatch(new SlackLogPusher()); | ||
} | ||
|
||
private Integer getNumberOfRunningBatchJobs() { | ||
return [SELECT COUNT() FROM AsyncApexJob WHERE JobType='BatchApex' AND Status IN ('Processing', 'Preparing', 'Queued')]; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata"> | ||
<apiVersion>43.0</apiVersion> | ||
<status>Active</status> | ||
</ApexClass> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/************************************************************************************************* | ||
* This file is part of the Nebula Logger project, released under the MIT License. * | ||
* See LICENSE file or go to https://github.com/jongpie/NebulaLogger for full license details. * | ||
*************************************************************************************************/ | ||
@isTest | ||
private class SlackLogPushScheduler_Tests { | ||
|
||
@isTest | ||
static void it_should_schedule_the_batch_job() { | ||
String cronExpression = '0 0 0 15 3 ? 2022'; | ||
Integer numberOfScheduledJobs = [SELECT COUNT() FROM CronTrigger]; | ||
System.assertEquals(0, numberOfScheduledJobs); | ||
|
||
Test.startTest(); | ||
String jobId = System.schedule('SlackLogPushScheduler', cronExpression, new SlackLogPushScheduler()); | ||
Test.stopTest(); | ||
|
||
CronTrigger ct = [SELECT Id, CronExpression, TimesTriggered, NextFireTime FROM CronTrigger WHERE Id = :jobId]; | ||
System.assertEquals(cronExpression, ct.CronExpression); | ||
} | ||
|
||
@isTest | ||
static void it_should_schedule_the_batch_job_schedule_every_5_minutes() { | ||
Integer numberOfScheduledJobs = [SELECT COUNT() FROM CronTrigger]; | ||
System.assertEquals(0, numberOfScheduledJobs); | ||
|
||
Test.startTest(); | ||
SlackLogPushScheduler.scheduleEveryXMinutes(5); | ||
Test.stopTest(); | ||
} | ||
|
||
@isTest | ||
static void it_should_schedule_the_batch_job_schedule_hourly() { | ||
Integer numberOfScheduledJobs = [SELECT COUNT() FROM CronTrigger]; | ||
System.assertEquals(0, numberOfScheduledJobs); | ||
|
||
Test.startTest(); | ||
SlackLogPushScheduler.scheduleHourly(0); | ||
Test.stopTest(); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata"> | ||
<apiVersion>43.0</apiVersion> | ||
<status>Active</status> | ||
</ApexClass> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
/************************************************************************************************* | ||
* This file is part of the Nebula Logger project, released under the MIT License. * | ||
* See LICENSE file or go to https://github.com/jongpie/NebulaLogger for full license details. * | ||
*************************************************************************************************/ | ||
public without sharing class SlackLogPusher implements Database.AllowsCallouts, Database.Batchable<Log__c> { | ||
|
||
private static final Organization ORG = [SELECT Id, IsSandbox FROM Organization LIMIT 1]; | ||
private static final LoggerIntegration__mdt SETTINGS = [SELECT ApiToken__c, BaseUrl__c FROM LoggerIntegration__mdt WHERE DeveloperName = 'Slack']; | ||
|
||
public List<Log__c> start(Database.BatchableContext batchableContext) { | ||
return [ | ||
SELECT | ||
LoggedBy__c, LoggedBy__r.Name, Name, | ||
TotalDebugLogEntries__c, TotalExceptionLogEntries__c, TransactionId__c, | ||
(SELECT Topic.Name FROM TopicAssignments) | ||
FROM Log__c | ||
WHERE PushToSlack__c = true | ||
AND PushedToSlackDate__c = null | ||
AND TotalLogEntries__c > 0 | ||
]; | ||
} | ||
|
||
public void execute(Database.BatchableContext batchableContext, List<Log__c> logs) { | ||
for(Log__c log : logs) { | ||
NotificationDto notification = new NotificationDto(); | ||
notification.text = 'New Salesforce Log Created'; | ||
notification.attachments = new List<LogDto>(); | ||
notification.attachments.add(this.convertLog(log)); | ||
|
||
HttpRequest request = new HttpRequest(); | ||
request.setEndpoint(SETTINGS.BaseUrl__c + SETTINGS.ApiToken__c); | ||
request.setMethod('POST'); | ||
request.setHeader('Content-Type', 'application/json'); | ||
String jsonString = Json.serialize(notification); | ||
// 'Short' is a reserved word in Apex, but used in Slack's API, so the conversion happens in JSON | ||
jsonString = jsonString.replace('"isShort"', '"short"'); | ||
request.setBody(jsonString); | ||
|
||
HttpResponse response = new Http().send(request); | ||
|
||
log.PushedToSlackDate__c = System.now(); | ||
} | ||
|
||
update logs; | ||
} | ||
|
||
public void finish(Database.BatchableContext batchableContext) {} | ||
|
||
private LogDto convertLog(Log__c log) { | ||
LogDto notification = new LogDto(); | ||
notification.author_link = Url.getSalesforceBaseUrl().toExternalForm() + '/' + log.LoggedBy__c; | ||
notification.author_name = log.LoggedBy__r.Name; | ||
notification.color = log.TotalExceptionLogEntries__c >= 1 ? '#FF7373' : '#7CD197'; // Red if there are exceptions, otherwise green | ||
notification.fields = new List<FieldDto>(); | ||
notification.text = 'Transaction ID: ' + log.TransactionId__c; | ||
notification.title = log.Name; | ||
notification.title_link = Url.getSalesforceBaseUrl().toExternalForm() + '/' + log.Id; | ||
|
||
FieldDto orgNameField = new FieldDto(); | ||
orgNameField.isShort = false; | ||
orgNameField.title = 'Org Name'; | ||
orgNameField.value = UserInfo.getOrganizationName(); | ||
notification.fields.add(orgNameField); | ||
|
||
FieldDto orgIdField = new FieldDto(); | ||
orgIdField.isShort = true; | ||
orgIdField.title = 'Org ID'; | ||
orgIdField.value = '`' + UserInfo.getOrganizationId() + '`'; | ||
notification.fields.add(orgIdField); | ||
|
||
FieldDto orgIsProductionField = new FieldDto(); | ||
orgIsProductionField.isShort = true; | ||
orgIsProductionField.title = 'Production'; | ||
orgIsProductionField.value = '`' + !ORG.IsSandbox + '`'; | ||
notification.fields.add(orgIsProductionField); | ||
|
||
FieldDto totalDebugEntriesField = new FieldDto(); | ||
totalDebugEntriesField.isShort = true; | ||
totalDebugEntriesField.title = '# of Debug Entries'; | ||
totalDebugEntriesField.value = String.valueOf(log.TotalDebugLogEntries__c); | ||
notification.fields.add(totalDebugEntriesField); | ||
|
||
FieldDto totalExceptionEntriesField = new FieldDto(); | ||
totalExceptionEntriesField.isShort = true; | ||
totalExceptionEntriesField.title = '# of Exception Entries'; | ||
totalExceptionEntriesField.value = String.valueOf(log.TotalExceptionLogEntries__c); | ||
notification.fields.add(totalExceptionEntriesField); | ||
|
||
List<String> topicNames = new List<String>(); | ||
for(TopicAssignment topicAssignment : log.TopicAssignments) { | ||
topicNames.add(topicAssignment.Topic.Name); | ||
} | ||
topicNames.sort(); | ||
|
||
if(topicNames.isEmpty()) return notification; | ||
|
||
FieldDto topicsField = new FieldDto(); | ||
topicsField.isShort = false; | ||
topicsField.title = 'Topics'; | ||
topicsField.value = String.join(topicNames, ', '); | ||
notification.fields.add(topicsField); | ||
|
||
return notification; | ||
} | ||
|
||
private class NotificationDto { | ||
public List<LogDto> attachments; | ||
public String text; | ||
} | ||
|
||
private class LogDto { | ||
public List<ActionDto> actions; | ||
public String author_name; | ||
public String author_link; | ||
public String author_icon; | ||
public String color; | ||
public String fallback; | ||
public List<FieldDto> fields; | ||
public String pretext; | ||
public String text; | ||
public String title; | ||
public String title_link; | ||
} | ||
|
||
private class ActionDto { | ||
public String text; | ||
public String type; | ||
public String url; | ||
} | ||
|
||
private class FieldDto { | ||
public Boolean isShort; | ||
public String title; | ||
public String value; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata"> | ||
<apiVersion>43.0</apiVersion> | ||
<status>Active</status> | ||
</ApexClass> |
Oops, something went wrong.