Skip to content

Commit 6d90ab2

Browse files
authored
Merge pull request #87 from navikt/application-monitoring
Move Application monitoring from crm-platform-base to sf-platform
2 parents eb5b379 + c3b8efb commit 6d90ab2

File tree

63 files changed

+2562
-1
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

63 files changed

+2562
-1
lines changed

sfdx-project.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,21 @@
4646
"versionNumber": "0.1.27.LATEST"
4747
}
4848
]
49+
},
50+
{
51+
"versionName": "ver 0.1",
52+
"versionNumber": "0.1.0.NEXT",
53+
"path": "src/application-monitoring",
54+
"default": false,
55+
"package": "application-monitoring",
56+
"versionDescription": "Rammeverk for logging"
4957
}
5058
],
5159
"packageAliases": {
5260
"platform-data-model": "0HoKB00000000010AA",
5361
"custom-metadata-dao": "0HoKB000000000B0AQ",
5462
"custom-permission-helper": "0HoKB000000000f0AA",
55-
"feature-toggle": "0HoKB000000000V0AQ"
63+
"feature-toggle": "0HoKB000000000V0AQ",
64+
"application-monitoring": "0HoQC00000004d70AA"
5665
}
5766
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# application-monitoring
2+
3+
## Application Log
4+
5+
Logger rammeverk som publiserer logger til Application_Log\_\_c
6+
7+
Datamodellen ligger i pakken [platform-data-model](src/platform-data-model/README.md)
8+
9+
| | |
10+
| ------- | --- |
11+
| Apex ||
12+
| LWC ||
13+
| Flow ||
14+
| Trigger ||
15+
16+
## Hvordan ta i bruk
17+
18+
Husk å angi teamet som er ansvarlig for funksjonaliteten som logges i LoggerUtility.
19+
20+
```java
21+
private LoggerUtility logger = new LoggerUtility(
22+
CRM_ApplicationDomain.Domain.PLATFORCE,
23+
'LoginFlow'
24+
);
25+
26+
logger.errorAndPublish('Error message');
27+
logger.warningAndPublish('Warning message');
28+
logger.infoAndPublish('Info message');
29+
```
30+
31+
## Avhengigheter
32+
33+
- [platform-datamodel](src/platform-data-model/feature-flag-custom-metadata) - datamodell
34+
35+
```mermaid
36+
---
37+
title: Pakkeavhengigheter
38+
---
39+
graph TD
40+
application-monitoring --> platform-datamodel;
41+
```
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
@SuppressWarnings('PMD')
2+
public class ApplicationLogPublisher {
3+
public static Application_Log_Setting__mdt testSetting;
4+
//Introduce setting to determine if messages should be published also for sandboxes
5+
private static Boolean isSandbox = [
6+
SELECT Id, isSandbox
7+
FROM Organization
8+
LIMIT 1
9+
]
10+
.isSandbox;
11+
12+
/**
13+
* @description: Performs a check on created application logs to see if any meet
14+
* the requirements for publishing to slack channels.
15+
* @author Stian Ruud Schikora | 02-23-2021
16+
* @param appLogs
17+
**/
18+
public static void publishLogs(List<Application_Log__c> appLogs) {
19+
Set<String> appDomains = new Set<String>();
20+
List<AppLog> logsToPublish = new List<AppLog>();
21+
22+
for (Application_Log__c log : appLogs) {
23+
appDomains.add(log.Application_Domain__c);
24+
}
25+
26+
List<Application_Log_Setting__mdt> logSettings = getLogSettings(
27+
appDomains
28+
);
29+
30+
for (Application_Log__c log : appLogs) {
31+
for (Application_Log_Setting__mdt setting : logSettings) {
32+
if (
33+
log.Application_Domain__c == setting.Application_Domain__c
34+
) {
35+
String hook = getHook(setting);
36+
if (
37+
getLogLevelOrdinal(log.Log_Level__c) >=
38+
getLogLevelOrdinal(setting.Minimum_Log_Level__c) &&
39+
setting.Category__c == log.Category__c
40+
) {
41+
if (
42+
Setting.Immediate_Post__c && String.isNotBlank(hook)
43+
) {
44+
logsToPublish.add(
45+
new AppLog(
46+
log,
47+
hook,
48+
Setting.Message_Template__c
49+
)
50+
);
51+
}
52+
}
53+
} else {
54+
continue;
55+
}
56+
}
57+
}
58+
59+
if (!logsToPublish.isEmpty()) {
60+
//If there are more logs to publish than the transactional callout limit, generate several future contexts
61+
if (logsToPublish.size() > Limits.getLimitCallouts()) {
62+
List<AppLog> listToPublish = new List<AppLog>();
63+
while (logsToPublish.size() > 0) {
64+
listToPublish.add(logsToPublish.remove(0));
65+
if (listToPublish.size() == Limits.getLimitCallouts()) {
66+
publishToSlack(JSON.serialize(listToPublish));
67+
listToPublish.clear();
68+
}
69+
}
70+
} else {
71+
publishToSlack(JSON.serialize(logsToPublish));
72+
}
73+
}
74+
}
75+
76+
@future(Callout=true)
77+
private static void publishToSlack(String jsonAppLogs) {
78+
List<AppLog> logs = (List<AppLog>) JSON.deserialize(
79+
jsonAppLogs,
80+
List<AppLog>.class
81+
);
82+
ApiController apiCtrl = new ApiController();
83+
for (AppLog log : logs) {
84+
apiCtrl.setEndpoint(log.slackHook);
85+
apiCtrl.setMethod('POST');
86+
apiCtrl.addHeader('Content-Type', 'application/json');
87+
88+
SlackMessage message = new SlackMessage(log.messageTemplate);
89+
String errorMessage =
90+
'Log level: ' +
91+
log.logRecord.Log_Level__c +
92+
'\n Source: ' +
93+
log.logRecord.Source_Class__c +
94+
'\n Link: ' +
95+
URL.getSalesforceBaseUrl().toExternalForm() +
96+
'/' +
97+
log.logRecord.Id +
98+
'\n Message: ' +
99+
log.logRecord.Log_Message__c;
100+
message.addSection(errorMessage);
101+
102+
apiCtrl.setBody(JSON.serialize(message));
103+
104+
apiCtrl.doCallout();
105+
}
106+
}
107+
108+
/**
109+
* @description: Queries the relevant log settings for the defined application domains
110+
* @author Stian Ruud Schikora | 02-23-2021
111+
* @param appDomains
112+
* @return List<Application_Log_Setting__mdt>
113+
**/
114+
private static List<Application_Log_Setting__mdt> getLogSettings(
115+
Set<String> appDomains
116+
) {
117+
if (Test.isRunningTest()) {
118+
return testSetting != null
119+
? new List<Application_Log_Setting__mdt>{ testSetting }
120+
: new List<Application_Log_Setting__mdt>();
121+
}
122+
return [
123+
SELECT
124+
Id,
125+
MasterLabel,
126+
Application_Domain__c,
127+
Slack_Hook__c,
128+
Slack_Hook_Sandbox__c,
129+
Message_Template__c,
130+
Immediate_Post__c,
131+
Minimum_Log_Level__c,
132+
Named_Credential__c,
133+
Category__c
134+
FROM Application_Log_Setting__mdt
135+
WHERE Application_Domain__c IN :appDomains
136+
];
137+
}
138+
139+
/**
140+
* @description: Returns the correct slack hook for production or sandbox.
141+
* @author Stian Ruud Schikora | 03-13-2021
142+
* @param logSetting
143+
* @return String
144+
**/
145+
private static String getHook(Application_Log_Setting__mdt logSetting) {
146+
if (isSandbox) {
147+
return logSetting.Slack_Hook_Sandbox__c;
148+
}
149+
150+
return String.isNotBlank(logSetting.Named_Credential__c)
151+
? 'callout:' + logSetting.Named_Credential__c
152+
: logSetting.Slack_Hook__c;
153+
}
154+
155+
/**
156+
* @description: Returns the log level ordinal for a input loglevel string
157+
INFO = 0, WARNING = 1, ERROR = 2, CRITICAL = 3
158+
* @author Stian Ruud Schikora | 02-22-2021
159+
* @param logLevel
160+
* @return Integer
161+
**/
162+
private static Integer getLogLevelOrdinal(String logLevel) {
163+
return LoggerUtility.inverseLevelMap.get(logLevel).ordinal();
164+
}
165+
166+
private class AppLog {
167+
private AppLog(
168+
Application_Log__c appLog,
169+
String slackHook,
170+
String messageTemplate
171+
) {
172+
this.logRecord = appLog;
173+
this.slackHook = slackHook;
174+
this.messageTemplate = messageTemplate;
175+
}
176+
177+
private Application_Log__c logRecord;
178+
private String slackHook;
179+
private String messageTemplate;
180+
}
181+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
3+
<apiVersion>58.0</apiVersion>
4+
<status>Active</status>
5+
</ApexClass>

0 commit comments

Comments
 (0)