Skip to content

Commit

Permalink
feat: add upvote and downvote tracker
Browse files Browse the repository at this point in the history
  • Loading branch information
guqing committed Oct 13, 2022
1 parent 83b40b6 commit 8669882
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 5 deletions.
5 changes: 5 additions & 0 deletions src/main/java/run/halo/app/core/extension/Counter.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public class Counter extends AbstractExtension {

private Integer upvote;

private Integer downvote;

private Integer totalComment;

private Integer approvedComment;
Expand All @@ -41,6 +43,8 @@ public <T extends Meter> void populateFrom(Collection<T> meters) {
this.visit = (int) meterCounter.count();
} else if (MeterUtils.isUpvoteCounter(meterCounter)) {
this.upvote = (int) meterCounter.count();
} else if (MeterUtils.isDownvoteCounter(meterCounter)) {
this.downvote = (int) meterCounter.count();
} else if (MeterUtils.isTotalCommentCounter(meterCounter)) {
this.totalComment = (int) meterCounter.count();
} else if (MeterUtils.isApprovedCommentCounter(meterCounter)) {
Expand All @@ -53,6 +57,7 @@ public <T extends Meter> void populateFrom(Collection<T> meters) {
private void populateDefaultValue() {
this.visit = 0;
this.upvote = 0;
this.downvote = 0;
this.totalComment = 0;
this.approvedComment = 0;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public TrackerEndpoint(MeterRegistry meterRegistry, VisitLogWriter visitLogWrite
public RouterFunction<ServerResponse> endpoint() {
final var tag = "api.halo.run/v1alpha1/Tracker";
return SpringdocRouteBuilder.route()
.POST("trackers/counter", this::increase,
.POST("trackers/counter", this::increaseVisit,
builder -> builder.operationId("count")
.description("Count an extension resource visits.")
.tag(tag)
Expand All @@ -55,12 +55,40 @@ public RouterFunction<ServerResponse> endpoint() {
.implementation(CounterRequest.class))
))
.response(responseBuilder()
.implementation(Double.class))
.implementation(Integer.class))
)
.POST("trackers/upvote", this::upvote,
builder -> builder.operationId("upvote")
.description("Upvote an extension resource.")
.tag(tag)
.requestBody(requestBodyBuilder()
.required(true)
.content(contentBuilder()
.mediaType(MediaType.APPLICATION_JSON_VALUE)
.schema(Builder.schemaBuilder()
.implementation(VoteRequest.class))
))
.response(responseBuilder()
.implementation(Integer.class))
)
.POST("trackers/downvote", this::downvote,
builder -> builder.operationId("downvote")
.description("Downvote an extension resource.")
.tag(tag)
.requestBody(requestBodyBuilder()
.required(true)
.content(contentBuilder()
.mediaType(MediaType.APPLICATION_JSON_VALUE)
.schema(Builder.schemaBuilder()
.implementation(VoteRequest.class))
))
.response(responseBuilder()
.implementation(Integer.class))
)
.build();
}

private Mono<ServerResponse> increase(ServerRequest request) {
private Mono<ServerResponse> increaseVisit(ServerRequest request) {
return request.bodyToMono(CounterRequest.class)
.switchIfEmpty(
Mono.error(new IllegalArgumentException("Counter request body must not be empty")))
Expand All @@ -78,6 +106,41 @@ private Mono<ServerResponse> increase(ServerRequest request) {
.flatMap(count -> ServerResponse.ok().bodyValue(count));
}

private Mono<ServerResponse> upvote(ServerRequest request) {
return request.bodyToMono(VoteRequest.class)
.switchIfEmpty(
Mono.error(new IllegalArgumentException("Upvote request body must not be empty")))
.map(voteRequest -> {
String counterName =
MeterUtils.nameOf(voteRequest.group(), voteRequest.plural(),
voteRequest.name());

Counter counter = MeterUtils.upvoteCounter(meterRegistry, counterName);
counter.increment();
return (int) counter.count();
})
.flatMap(count -> ServerResponse.ok().bodyValue(count));
}

private Mono<ServerResponse> downvote(ServerRequest request) {
return request.bodyToMono(VoteRequest.class)
.switchIfEmpty(
Mono.error(new IllegalArgumentException("Downvote request body must not be empty")))
.map(voteRequest -> {
String counterName =
MeterUtils.nameOf(voteRequest.group(), voteRequest.plural(),
voteRequest.name());

Counter counter = MeterUtils.downvoteCounter(meterRegistry, counterName);
counter.increment();
return (int) counter.count();
})
.flatMap(count -> ServerResponse.ok().bodyValue(count));
}

public record VoteRequest(String group, String plural, String name) {
}

public record CounterRequest(String group, String plural, String name, String hostname,
String screen, String language, String referrer) {
/**
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/run/halo/app/metrics/CounterMeterHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ public Mono<Void> onApplicationReady(ApplicationReadyEvent event) {
MeterUtils.upvoteCounter(meterRegistry, name);
upvoteCounter.increment(nullSafe(counter.getUpvote()));

// downvote counter
io.micrometer.core.instrument.Counter downvoteCounter =
MeterUtils.downvoteCounter(meterRegistry, name);
downvoteCounter.increment(nullSafe(counter.getDownvote()));

// total comment counter
io.micrometer.core.instrument.Counter totalCommentCounter =
MeterUtils.totalCommentCounter(meterRegistry, name);
Expand Down
13 changes: 13 additions & 0 deletions src/main/java/run/halo/app/metrics/MeterUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public class MeterUtils {
public static final String SCENE = "scene";
public static final String VISIT_SCENE = "visit";
public static final String UPVOTE_SCENE = "upvote";
public static final String DOWNVOTE_SCENE = "downvote";
public static final String TOTAL_COMMENT_SCENE = "total_comment";
public static final String APPROVED_COMMENT_SCENE = "approved_comment";

Expand Down Expand Up @@ -51,6 +52,10 @@ public static Counter upvoteCounter(MeterRegistry registry, String name) {
return counter(registry, name, Tag.of(SCENE, UPVOTE_SCENE));
}

public static Counter downvoteCounter(MeterRegistry registry, String name) {
return counter(registry, name, Tag.of(SCENE, DOWNVOTE_SCENE));
}

public static Counter totalCommentCounter(MeterRegistry registry, String name) {
return counter(registry, name, Tag.of(SCENE, TOTAL_COMMENT_SCENE));
}
Expand All @@ -75,6 +80,14 @@ public static boolean isUpvoteCounter(Counter counter) {
return UPVOTE_SCENE.equals(sceneValue);
}

public static boolean isDownvoteCounter(Counter counter) {
String sceneValue = counter.getId().getTag(SCENE);
if (StringUtils.isBlank(sceneValue)) {
return false;
}
return DOWNVOTE_SCENE.equals(sceneValue);
}

public static boolean isTotalCommentCounter(Counter counter) {
String sceneValue = counter.getId().getTag(SCENE);
if (StringUtils.isBlank(sceneValue)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ protected boolean nonResourceURLMatches(Role.PolicyRule rule, String requestedUR
if (Objects.equals(ruleURL, requestedURL)) {
return true;
}
if (StringUtils.startsWith(ruleURL, WildCard.NonResourceAll)
if (StringUtils.endsWith(ruleURL, WildCard.NonResourceAll)
&& StringUtils.startsWith(requestedURL,
StringUtils.stripEnd(ruleURL, WildCard.NonResourceAll))) {
return true;
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/extensions/role-template-anonymous.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ rules:
- apiGroups: [ "api.halo.run" ]
resources: [ "*" ]
verbs: [ "*" ]
- nonResourceURLs: [ "/apis/api.halo.run/v1alpha1/trackers/counter" ]
- nonResourceURLs: [ "/apis/api.halo.run/v1alpha1/trackers/*" ]
verbs: [ "create" ]
9 changes: 9 additions & 0 deletions src/test/java/run/halo/app/metrics/MeterUtilsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ void isUpvoteCounter() {
assertThat(MeterUtils.isVisitCounter(upvoteCounter)).isFalse();
}

@Test
void isDownvoteCounter() {
MeterRegistry meterRegistry = new SimpleMeterRegistry();
Counter downvoteCounter =
MeterUtils.downvoteCounter(meterRegistry, "posts.content.halo.run/fake-post");
assertThat(MeterUtils.isDownvoteCounter(downvoteCounter)).isTrue();
assertThat(MeterUtils.isVisitCounter(downvoteCounter)).isFalse();
}

@Test
void isTotalCommentCounter() {
MeterRegistry meterRegistry = new SimpleMeterRegistry();
Expand Down

0 comments on commit 8669882

Please sign in to comment.