1
1
package dev .vml .es .acm .core .instance ;
2
2
3
+ import dev .vml .es .acm .core .code .*;
4
+ import dev .vml .es .acm .core .code .script .ExtensionScriptSyntax ;
3
5
import dev .vml .es .acm .core .osgi .*;
4
6
import dev .vml .es .acm .core .repo .Repo ;
7
+ import dev .vml .es .acm .core .util .ExceptionUtils ;
5
8
import dev .vml .es .acm .core .util .ResourceUtils ;
6
9
import java .util .*;
7
10
import java .util .stream .Collectors ;
8
11
import org .apache .commons .collections .CollectionUtils ;
9
12
import org .apache .commons .io .FilenameUtils ;
10
13
import org .apache .commons .lang3 .ArrayUtils ;
14
+ import org .apache .commons .lang3 .StringUtils ;
11
15
import org .apache .sling .api .resource .ResourceResolver ;
12
16
import org .apache .sling .api .resource .ResourceResolverFactory ;
13
17
import org .apache .sling .discovery .DiscoveryService ;
@@ -38,6 +42,9 @@ public class HealthChecker implements EventHandler {
38
42
@ Reference
39
43
private ResourceResolverFactory resourceResolverFactory ;
40
44
45
+ @ Reference
46
+ private Executor executor ;
47
+
41
48
@ Reference
42
49
private InstanceInfo instanceInfo ;
43
50
@@ -85,6 +92,7 @@ private HealthStatus checkStatus(ResourceResolver resourceResolver) {
85
92
checkBundles (result );
86
93
checkEvents (result );
87
94
checkComponents (result );
95
+ checkCodeExecutor (result , resourceResolver );
88
96
result .healthy = CollectionUtils .isEmpty (result .issues );
89
97
return result ;
90
98
}
@@ -94,7 +102,8 @@ private void checkCluster(HealthStatus result) {
94
102
return ;
95
103
}
96
104
if (!isClusterLeader ()) {
97
- result .issues .add (new HealthIssue (HealthIssueSeverity .CRITICAL , "Instance is not a cluster leader" ));
105
+ result .issues .add (new HealthIssue (
106
+ HealthIssueSeverity .CRITICAL , HealthIssueCategory .INSTANCE , "Not a cluster leader" , null ));
98
107
}
99
108
}
100
109
@@ -115,12 +124,16 @@ private void checkInstaller(HealthStatus result, ResourceResolver resourceResolv
115
124
if (state .isActive ()) {
116
125
result .issues .add (new HealthIssue (
117
126
HealthIssueSeverity .CRITICAL ,
118
- String .format ("Sling Installer is active (%d)" , state .getActiveResourceCount ())));
127
+ HealthIssueCategory .INSTALLER ,
128
+ String .format ("Active resource count: %d" , state .getActiveResourceCount ()),
129
+ null ));
119
130
}
120
131
if (state .isPaused ()) {
121
132
result .issues .add (new HealthIssue (
122
133
HealthIssueSeverity .CRITICAL ,
123
- String .format ("Sling Installer is paused (%d)" , state .getPauseCount ())));
134
+ HealthIssueCategory .INSTALLER ,
135
+ String .format ("Pause count: %d" , state .getPauseCount ()),
136
+ null ));
124
137
}
125
138
}
126
139
@@ -130,14 +143,20 @@ private void checkRepository(HealthStatus result, ResourceResolver resourceResol
130
143
}
131
144
Repo repo = new Repo (resourceResolver );
132
145
if ((instanceInfo .getType () == InstanceType .CLOUD_CONTAINER ) && !repo .isCompositeNodeStore ()) {
133
- result .issues .add (
134
- new HealthIssue (HealthIssueSeverity .CRITICAL , "Repository is not yet using composite node store" ));
146
+ result .issues .add (new HealthIssue (
147
+ HealthIssueSeverity .CRITICAL ,
148
+ HealthIssueCategory .REPOSITORY ,
149
+ "Composite node store not available" ,
150
+ null ));
135
151
}
136
152
if (ArrayUtils .isNotEmpty (config .repositoryPathsExisted ())) {
137
153
Arrays .stream (config .repositoryPathsExisted ()).forEach (path -> {
138
154
if (!repo .get (path ).exists ()) {
139
155
result .issues .add (new HealthIssue (
140
- HealthIssueSeverity .CRITICAL , String .format ("Repository path '%s' does not exist" , path )));
156
+ HealthIssueSeverity .CRITICAL ,
157
+ HealthIssueCategory .REPOSITORY ,
158
+ String .format ("Path does not exist: '%s'" , path ),
159
+ null ));
141
160
}
142
161
});
143
162
}
@@ -152,13 +171,17 @@ private void checkBundles(HealthStatus result) {
152
171
if (!osgiScanner .isBundleResolved (bundle )) {
153
172
result .issues .add (new HealthIssue (
154
173
HealthIssueSeverity .CRITICAL ,
155
- String .format ("Bundle fragment '%s' is not resolved" , bundle .getSymbolicName ())));
174
+ HealthIssueCategory .OSGI ,
175
+ String .format ("Bundle fragment not resolved: '%s'" , bundle .getSymbolicName ()),
176
+ null ));
156
177
}
157
178
} else {
158
179
if (!osgiScanner .isBundleActive (bundle )) {
159
180
result .issues .add (new HealthIssue (
160
181
HealthIssueSeverity .CRITICAL ,
161
- String .format ("Bundle '%s' is not active" , bundle .getSymbolicName ())));
182
+ HealthIssueCategory .OSGI ,
183
+ String .format ("Bundle not active: '%s'" , bundle .getSymbolicName ()),
184
+ null ));
162
185
}
163
186
}
164
187
});
@@ -186,7 +209,10 @@ private void checkEvents(HealthStatus result) {
186
209
Map <String , Long > eventCounts =
187
210
recentEvents .stream ().collect (Collectors .groupingBy (OsgiEvent ::getTopic , Collectors .counting ()));
188
211
eventCounts .forEach ((topic , count ) -> result .issues .add (new HealthIssue (
189
- HealthIssueSeverity .CRITICAL , String .format ("Event '%s' occurred (%d)" , topic , count ))));
212
+ HealthIssueSeverity .CRITICAL ,
213
+ HealthIssueCategory .OSGI ,
214
+ String .format ("Event occurred (%d): %s" , count , topic ),
215
+ null )));
190
216
}
191
217
}
192
218
@@ -213,6 +239,30 @@ private void checkComponents(HealthStatus result) {
213
239
// TODO ...
214
240
}
215
241
242
+ private void checkCodeExecutor (HealthStatus result , ResourceResolver resourceResolver ) {
243
+ try (ExecutionContext context = executor .createContext (
244
+ ExecutionId .generate (), ExecutionMode .RUN , Code .consoleMinimal (), resourceResolver )) {
245
+ context .setHistory (false );
246
+ Execution execution = executor .execute (context );
247
+ if (execution .getStatus () != ExecutionStatus .SUCCEEDED ) {
248
+ result .issues .add (new HealthIssue (
249
+ HealthIssueSeverity .CRITICAL ,
250
+ HealthIssueCategory .CODE_EXECUTOR ,
251
+ String .format (
252
+ "Execution not succeeded: %s" ,
253
+ execution .getStatus ().name ().toLowerCase ()),
254
+ execution .getError ()));
255
+ }
256
+ } catch (Exception e ) {
257
+ String error = ExceptionUtils .toString (e );
258
+ String issue = StringUtils .contains (error , ExtensionScriptSyntax .MAIN_CLASS + ":" )
259
+ ? "Extension script error"
260
+ : "Execution context error" ;
261
+ result .issues .add (
262
+ new HealthIssue (HealthIssueSeverity .CRITICAL , HealthIssueCategory .CODE_EXECUTOR , issue , error ));
263
+ }
264
+ }
265
+
216
266
@ ObjectClassDefinition (name = "AEM Content Manager - Health Checker" )
217
267
public @interface Config {
218
268
0 commit comments