Skip to content

Commit 2b16f66

Browse files
committed
Merge pull request Netflix#223 from ebukoski/master
Add a URL target to add events through HTTP GET; more Calendar logging
2 parents cd68af3 + dde65ef commit 2b16f66

4 files changed

Lines changed: 99 additions & 7 deletions

File tree

src/main/java/com/netflix/simianarmy/basic/BasicCalendar.java

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import java.util.TreeSet;
2525

2626
import org.apache.commons.lang.Validate;
27+
import org.slf4j.Logger;
28+
import org.slf4j.LoggerFactory;
2729

2830
import com.netflix.simianarmy.Monkey;
2931
import com.netflix.simianarmy.MonkeyCalendar;
@@ -35,6 +37,9 @@
3537
*/
3638
public class BasicCalendar implements MonkeyCalendar {
3739

40+
/** The Constant LOGGER. */
41+
private static final Logger LOGGER = LoggerFactory.getLogger(BasicCalendar.class);
42+
3843
/** The open hour. */
3944
private final int openHour;
4045

@@ -78,6 +83,23 @@ public BasicCalendar(int open, int close, TimeZone timezone) {
7883
closeHour = close;
7984
tz = timezone;
8085
}
86+
87+
/**
88+
* Instantiates a new basic calendar.
89+
*
90+
* @param open
91+
* the open hour
92+
* @param close
93+
* the close hour
94+
* @param timezone
95+
* the timezone
96+
*/
97+
public BasicCalendar(MonkeyConfiguration cfg, int open, int close, TimeZone timezone) {
98+
this.cfg = cfg;
99+
openHour = open;
100+
closeHour = close;
101+
tz = timezone;
102+
}
81103

82104
/** {@inheritDoc} */
83105
@Override
@@ -100,25 +122,32 @@ public Calendar now() {
100122
/** {@inheritDoc} */
101123
@Override
102124
public boolean isMonkeyTime(Monkey monkey) {
103-
if (cfg != null && cfg.getStrOrElse("simianarmy.calendar.isMonkeyTime", null) != null) {
104-
return cfg.getBool("simianarmy.calendar.isMonkeyTime");
125+
if (cfg != null && cfg.getStr("simianarmy.calendar.isMonkeyTime") != null) {
126+
boolean monkeyTime = cfg.getBool("simianarmy.calendar.isMonkeyTime");
127+
String msg = monkeyTime ? "Time for monkey." : "Not time for monkey.";
128+
LOGGER.debug("isMonkeyTime: Found property 'simianarmy.calendar.isMonkeyTime': " + monkeyTime + ". " + msg);
129+
return monkeyTime;
105130
}
106131

107132
Calendar now = now();
108133
int dow = now.get(Calendar.DAY_OF_WEEK);
109134
if (dow == Calendar.SATURDAY || dow == Calendar.SUNDAY) {
135+
LOGGER.debug("isMonkeyTime: Happy Weekend! Not time for monkey.");
110136
return false;
111137
}
112138

113139
int hour = now.get(Calendar.HOUR_OF_DAY);
114140
if (hour < openHour || hour > closeHour) {
141+
LOGGER.debug("isMonkeyTime: Not inside open hours. Not time for monkey.");
115142
return false;
116143
}
117144

118145
if (isHoliday(now)) {
146+
LOGGER.debug("isMonkeyTime: Happy Holiday! Not time for monkey.");
119147
return false;
120148
}
121149

150+
LOGGER.debug("isMonkeyTime: Time for monkey.");
122151
return true;
123152
}
124153

src/main/java/com/netflix/simianarmy/basic/janitor/BasicJanitorMonkey.java

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ public class BasicJanitorMonkey extends JanitorMonkey {
6868
/** Keep track of the number of monkey runs */
6969
protected final AtomicLong monkeyRuns = new AtomicLong(0);
7070

71+
/** Keep track of the number of monkey errors */
72+
protected final AtomicLong monkeyErrors = new AtomicLong(0);
73+
74+
/** Emit a servor signal to track the running monkey */
75+
protected final AtomicLong monkeyRunning = new AtomicLong(0);
76+
7177
/**
7278
* Instantiates a new basic janitor monkey.
7379
*
@@ -101,9 +107,15 @@ public void doMonkeyBusiness() {
101107
} else {
102108
LOGGER.info(String.format("Marking resources with %d janitors.", janitors.size()));
103109
monkeyRuns.incrementAndGet();
110+
monkeyRunning.set(1);
104111
for (AbstractJanitor janitor : janitors) {
105-
LOGGER.info(String.format("Running janitor for region %s", janitor.getRegion()));
106-
janitor.markResources();
112+
LOGGER.info(String.format("Running %s janitor for region %s", janitor.getResourceType(), janitor.getRegion()));
113+
try {
114+
janitor.markResources();
115+
} catch (Exception e) {
116+
monkeyErrors.incrementAndGet();
117+
LOGGER.error(String.format("Got an exception while %s janitor was marking for region %s", janitor.getResourceType()), janitor.getRegion(), e);
118+
}
107119
LOGGER.info(String.format("Marked %d resources of type %s in the last run.",
108120
janitor.getMarkedResources().size(), janitor.getResourceType().name()));
109121
LOGGER.info(String.format("Unmarked %d resources of type %s in the last run.",
@@ -118,7 +130,12 @@ public void doMonkeyBusiness() {
118130

119131
LOGGER.info(String.format("Cleaning resources with %d janitors.", janitors.size()));
120132
for (AbstractJanitor janitor : janitors) {
121-
janitor.cleanupResources();
133+
try {
134+
janitor.cleanupResources();
135+
} catch (Exception e) {
136+
monkeyErrors.incrementAndGet();
137+
LOGGER.error(String.format("Got an exception while %s janitor was cleaning for region %s", janitor.getResourceType()), janitor.getRegion(), e);
138+
}
122139
LOGGER.info(String.format("Cleaned %d resources of type %s in the last run.",
123140
janitor.getCleanedResources().size(), janitor.getResourceType()));
124141
LOGGER.info(String.format("Failed to clean %d resources of type %s in the last run.",
@@ -127,6 +144,7 @@ public void doMonkeyBusiness() {
127144
if (cfg.getBoolOrElse(NS + "summaryEmail.enabled", true)) {
128145
sendJanitorSummaryEmail();
129146
}
147+
monkeyRunning.set(0);
130148
}
131149
}
132150

@@ -237,4 +255,15 @@ private boolean isJanitorMonkeyEnabled() {
237255
public long getMonkeyRuns() {
238256
return monkeyRuns.get();
239257
}
258+
259+
@Monitor(name="errors", type=DataSourceType.GAUGE)
260+
public long getMonkeyErrors() {
261+
return monkeyErrors.get();
262+
}
263+
264+
@Monitor(name="running", type=DataSourceType.GAUGE)
265+
public long getMonkeyRunning() {
266+
return monkeyRunning.get();
267+
}
268+
240269
}

src/main/java/com/netflix/simianarmy/janitor/AbstractJanitor.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ public String getRegion() {
106106
private boolean leashed;
107107

108108
private final MonkeyRecorder recorder;
109+
110+
/** The number of resources that have been checked on this run. */
111+
private int checkedResourcesCount;
109112

110113
/**
111114
* Sets the flag to indicate if the janitor is leashed.
@@ -217,13 +220,15 @@ public ResourceType getResourceType() {
217220
public void markResources() {
218221
markedResources.clear();
219222
unmarkedResources.clear();
223+
checkedResourcesCount = 0;
220224
Map<String, Resource> trackedMarkedResources = getTrackedMarkedResources();
221225

222226
List<Resource> crawledResources = crawler.resources(resourceType);
223227
LOGGER.info(String.format("Looking for cleanup candidate in %d crawled resources.",
224228
crawledResources.size()));
225229
Date now = calendar.now().getTime();
226230
for (Resource resource : crawledResources) {
231+
checkedResourcesCount++;
227232
Resource trackedResource = trackedMarkedResources.get(resource.getId());
228233
if (!ruleEngine.isValid(resource)) {
229234
// If the resource is already marked, ignore it
@@ -238,6 +243,7 @@ public void markResources() {
238243
if (!leashed) {
239244
if (recorder != null) {
240245
Event evt = recorder.newEvent(Type.JANITOR, EventTypes.MARK_RESOURCE, region, resource.getId());
246+
addFieldsAndTagsToEvent(resource, evt);
241247
recorder.recordEvent(evt);
242248
}
243249
resourceTracker.addOrUpdate(resource);
@@ -257,6 +263,7 @@ public void markResources() {
257263
if (recorder != null) {
258264
Event evt = recorder.newEvent(
259265
Type.JANITOR, EventTypes.UNMARK_RESOURCE, region, resource.getId());
266+
addFieldsAndTagsToEvent(resource, evt);
260267
recorder.recordEvent(evt);
261268
}
262269
resourceTracker.addOrUpdate(resource);
@@ -337,8 +344,11 @@ public void cleanupResources() {
337344
* @param event the event that will hold the source data as additional fields
338345
*/
339346
private void addFieldsAndTagsToEvent(Resource resource, Event event) {
340-
for(String key : resource.getAllTagKeys()) {
341-
event.addField(key, resource.getTag(key));
347+
if (resource == null) return;
348+
if (resource.getAllTagKeys() != null) {
349+
for(String key : resource.getAllTagKeys()) {
350+
event.addField(key, resource.getTag(key));
351+
}
342352
}
343353
event.addField("ResourceDescription", resource.getDescription());
344354
event.addField("ResourceType", resource.getResourceType().toString());
@@ -448,4 +458,10 @@ public int getFailedToCleanResourcesCount() {
448458
public int getUnmarkedResourcesCount() {
449459
return unmarkedResources.size();
450460
}
461+
462+
@Monitor(name="checkedResourcesCount", type=DataSourceType.GAUGE)
463+
public int getCheckedResourcesCount() {
464+
return checkedResourcesCount;
465+
}
466+
451467
}

src/main/java/com/netflix/simianarmy/resources/janitor/JanitorMonkeyResource.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import javax.ws.rs.GET;
2525
import javax.ws.rs.POST;
2626
import javax.ws.rs.Path;
27+
import javax.ws.rs.QueryParam;
2728
import javax.ws.rs.core.Context;
2829
import javax.ws.rs.core.Response;
2930
import javax.ws.rs.core.UriInfo;
@@ -72,6 +73,23 @@ public JanitorMonkeyResource(JanitorMonkey monkey) {
7273
public JanitorMonkeyResource() {
7374
this.monkey = MonkeyRunner.getInstance().factory(JanitorMonkey.class);
7475
}
76+
77+
/**
78+
* GET /api/v1/janitor/addEvent will try to a add a new event with the information in the url query string.
79+
* This is the same as the regular POST addEvent except through a query string. This technically isn't
80+
* very REST-ful as it is a GET call that creates an Opt-out/in event, but is a convenience method
81+
* for exposing opt-in/opt-out functionality more directly, for example in an email notification.
82+
*
83+
* @param eventType eventType from the query string
84+
* @param resourceId resourceId from the query string
85+
* @return the response
86+
* @throws IOException
87+
*/
88+
@GET @Path("addEvent")
89+
public Response addEventThroughHttpGet( @QueryParam("eventType") String eventType, @QueryParam("resourceId") String resourceId) throws IOException {
90+
String content = "{\"eventType\":\"" + eventType + "\",\"resourceId\":\"" + resourceId + "\"}";
91+
return addEvent(content);
92+
}
7593

7694
/**
7795
* POST /api/v1/janitor will try a add a new event with the information in the url context.

0 commit comments

Comments
 (0)