Skip to content

Commit

Permalink
Merge pull request #10 from hypery2k/master
Browse files Browse the repository at this point in the history
Adding more event data
  • Loading branch information
tobilarscheid authored May 2, 2019
2 parents 78ba39b + 9d5ef8c commit 27e7fcc
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 9 deletions.
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@ This project counts those events and allows you to expose them to `prometheus` w
## What metrics do you get?
This project will help you expose two metrics:

- `keycloak_events_total` with labels
- `keycloak_events_total` with labels
- realm="String",
- type="[`org.keycloak.events.EventType`](https://github.com/keycloak/keycloak/blob/master/server-spi-private/src/main/java/org/keycloak/events/EventType.java)"
- `keycloak_admin_events_total` with labels
- type="[`org.keycloak.events.EventType`](https://github.com/keycloak/keycloak/blob/master/server-spi-private/src/main/java/org/keycloak/events/EventType.java)",
- client_id="String",
- ip_address="String"
- `keycloak_admin_events_total` with labels
- realm="String"
- operation="[`org.keycloak.events.admin.OperationType`](https://github.com/keycloak/keycloak/blob/master/server-spi-private/src/main/java/org/keycloak/events/admin/OperationType.java)"
- resource="[`org.keycloak.events.admin.ResourceType`](https://github.com/keycloak/keycloak/blob/master/server-spi-private/src/main/java/org/keycloak/events/admin/ResourceType.java)"
- resource="[`org.keycloak.events.admin.ResourceType`](https://github.com/keycloak/keycloak/blob/master/server-spi-private/src/main/java/org/keycloak/events/admin/ResourceType.java)",
- client_id="String",
- ip_address="String"

The magic lies in the labels. The labels basically expose the underlying keycloak event details and allow for detailed filtering. The unique metric + label combination's value will be increased by one whenever an event of this type is emmited in keycloak.
## Setup
Expand Down Expand Up @@ -48,5 +52,5 @@ Make sure you do this for every realm you want to monitor!
### Getting your metrics into prometheus
Once everything is setup in keycloak, you will start seeing files like `keycloak_admin_events_total;realm=master;operation=CREATE;resource=USER` in your configured events directory.
These files contain a number stating how often an event with the given parameters was emitted.
The naming scheme is compatible with [`prometheus-filesystem-exporter`](https://github.com/larscheid-schmitzhermes/prometheus-filesystem-exporter),
The naming scheme is compatible with [`prometheus-filesystem-exporter`](https://github.com/larscheid-schmitzhermes/prometheus-filesystem-exporter),
which you should run next to keycloak to get your events exposed in a prometheus compatible format.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public class MonitoringEventListenerProvider implements EventListenerProvider {
private final char DELIMITER = ';';
private final char LABEL_VALUE_DELIMITER = '=';
private final String REALM = "realm";
private final String CLIENT_ID = "client_id";
private final String IP_ADDRESS = "ip_address";
private final String TYPE = "type";
private final String OPERATION = "operation";
private final String RESOURCE = "resource";
Expand All @@ -43,6 +45,10 @@ private String generateMetricName(Event event) {
sb.append(DELIMITER);
sb.append(generateLabel(REALM, event.getRealmId()));
sb.append(DELIMITER);
sb.append(generateLabel(CLIENT_ID, event.getClientId()));
sb.append(DELIMITER);
sb.append(generateLabel(IP_ADDRESS, event.getIpAddress()));
sb.append(DELIMITER);
sb.append(generateLabel(TYPE, event.getType().toString()));
return sb.toString();
}
Expand All @@ -53,6 +59,10 @@ private String generateMetricName(AdminEvent event) {
sb.append(DELIMITER);
sb.append(generateLabel(REALM, event.getRealmId()));
sb.append(DELIMITER);
sb.append(generateLabel(CLIENT_ID, event.getAuthDetails().getClientId()));
sb.append(DELIMITER);
sb.append(generateLabel(IP_ADDRESS, event.getAuthDetails().getIpAddress()));
sb.append(DELIMITER);
sb.append(generateLabel(OPERATION, event.getOperationType().toString()));
sb.append(DELIMITER);
sb.append(generateLabel(RESOURCE, event.getResourceType().toString()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.keycloak.events.Event;
import org.keycloak.events.EventType;
import org.keycloak.events.admin.AdminEvent;
import org.keycloak.events.admin.AuthDetails;
import org.keycloak.events.admin.OperationType;
import org.keycloak.events.admin.ResourceType;

Expand All @@ -21,14 +22,20 @@ public class MonitoringEventListenerProviderTest {

private Event event() {
Event event = new Event();
event.setClientId("23");
event.setIpAddress("4.4.4.4");
event.setRealmId("test-realm");
event.setType(EventType.LOGIN);
return event;
}

private AdminEvent adminEvent() {
AuthDetails details = new AuthDetails();
details.setClientId("42");
details.setIpAddress("1.2.3.4");
AdminEvent event = new AdminEvent();
event.setRealmId("test-realm");
event.setAuthDetails(details);
event.setOperationType(OperationType.UPDATE);
event.setResourceType(ResourceType.CLIENT);
return event;
Expand All @@ -40,7 +47,7 @@ public void shouldGenerateFilesWithCorrectNamesForNormalEvents() throws IOExcept

listener.onEvent(event());

File expectedFile = new File(tmp.getRoot().getAbsolutePath() + File.separator + "keycloak_events_total;realm=test-realm;type=LOGIN");
File expectedFile = new File(tmp.getRoot().getAbsolutePath() + File.separator + "keycloak_events_total;realm=test-realm;client_id=23;ip_address=4.4.4.4;type=LOGIN");

MatcherAssert.assertThat(expectedFile.exists(), Is.is(true));
MatcherAssert.assertThat(FileUtils.readFileToString(expectedFile), Is.is("1"));
Expand All @@ -52,7 +59,7 @@ public void shouldGenerateFilesWithCorrectNamesForAdminEvents() throws IOExcepti

listener.onEvent(adminEvent(), false);

File expectedFile = new File(tmp.getRoot().getAbsolutePath() + File.separator + "keycloak_admin_events_total;realm=test-realm;operation=UPDATE;resource=CLIENT");
File expectedFile = new File(tmp.getRoot().getAbsolutePath() + File.separator + "keycloak_admin_events_total;realm=test-realm;client_id=42;ip_address=1.2.3.4;operation=UPDATE;resource=CLIENT");

MatcherAssert.assertThat(expectedFile.exists(), Is.is(true));
MatcherAssert.assertThat(FileUtils.readFileToString(expectedFile), Is.is("1"));
Expand All @@ -61,7 +68,7 @@ public void shouldGenerateFilesWithCorrectNamesForAdminEvents() throws IOExcepti
@Test
public void shouldProperlyIncreaseCounterForNormalEvents() throws IOException {
MonitoringEventListenerProvider listener = new MonitoringEventListenerProvider(tmp.getRoot().getAbsolutePath());
File existingCounter = new File(tmp.getRoot().getAbsolutePath() + File.separator + "keycloak_events_total;realm=test-realm;type=LOGIN");
File existingCounter = new File(tmp.getRoot().getAbsolutePath() + File.separator + "keycloak_events_total;realm=test-realm;client_id=23;ip_address=4.4.4.4;type=LOGIN");
FileUtils.writeStringToFile(existingCounter, "100");

listener.onEvent(event());
Expand All @@ -72,7 +79,7 @@ public void shouldProperlyIncreaseCounterForNormalEvents() throws IOException {
@Test
public void shouldProperlyIncreaseCounterForAdminEvents() throws IOException {
MonitoringEventListenerProvider listener = new MonitoringEventListenerProvider(tmp.getRoot().getAbsolutePath());
File existingCounter = new File(tmp.getRoot().getAbsolutePath() + File.separator + "keycloak_admin_events_total;realm=test-realm;operation=UPDATE;resource=CLIENT");
File existingCounter = new File(tmp.getRoot().getAbsolutePath() + File.separator + "keycloak_admin_events_total;realm=test-realm;client_id=42;ip_address=1.2.3.4;operation=UPDATE;resource=CLIENT");
FileUtils.writeStringToFile(existingCounter, "100");

listener.onEvent(adminEvent(), false);
Expand Down

0 comments on commit 27e7fcc

Please sign in to comment.