diff --git a/README.md b/README.md index 608e8e31..cedc0b39 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ The API has the following endpoints: - Type: `POST` - Path: `/api/v1/feel/evaluate` -Request: +Request: ```json { @@ -41,7 +41,7 @@ Response: - Type: `POST` - Path: `/api/v1/feel-unary-tests/evaluate` -Request: +Request: ```json { @@ -89,6 +89,12 @@ kubectl create namespace feel kubectl apply -f service.yaml -n feel ``` +To deploy the secrets, edit `secret.yaml` and set `mixpanel_project_token` to your Mixpanel project token. Then run the following: + +```shell +kubectl apply -f secret.yaml -n feel +``` + To deploy the rest api, edit `deployment.yaml` and set `spec.template.spec.containers[0].img` to point to the latest docker image. Then run the following: diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml index c218bcdb..50751dd4 100644 --- a/k8s/deployment.yaml +++ b/k8s/deployment.yaml @@ -21,3 +21,9 @@ spec: port: 8080 initialDelaySeconds: 10 timeoutSeconds: 5 + env: + - name: MIXPANEL_PROJECT_TOKEN + valueFrom: + secretKeyRef: + name: feel-scala-playground-secret + key: mixpanel_project_token diff --git a/k8s/secret.yaml b/k8s/secret.yaml new file mode 100644 index 00000000..068161a2 --- /dev/null +++ b/k8s/secret.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Secret +metadata: + name: feel-scala-playground-secret +type: Opaque +stringData: + mixpanel_project_token: x diff --git a/pom.xml b/pom.xml index d4c3b8ef..069902bc 100644 --- a/pom.xml +++ b/pom.xml @@ -39,6 +39,12 @@ ${feel.version} + + com.mixpanel + mixpanel-java + 1.5.2 + + @@ -59,6 +65,11 @@ spring-boot-starter-actuator + + com.mixpanel + mixpanel-java + + org.springframework.boot spring-boot-starter-test diff --git a/src/main/java/org/camunda/feel/playground/api/FeelEvaluationController.java b/src/main/java/org/camunda/feel/playground/api/FeelEvaluationController.java index 85c1be6b..3b0eb7ae 100644 --- a/src/main/java/org/camunda/feel/playground/api/FeelEvaluationController.java +++ b/src/main/java/org/camunda/feel/playground/api/FeelEvaluationController.java @@ -4,6 +4,7 @@ import org.camunda.feel.playground.dto.FeelEvaluationResponse; import org.camunda.feel.playground.dto.FeelUnaryTestsEvaluationRequest; import org.camunda.feel.playground.sevice.FeelEvaluationService; +import org.camunda.feel.playground.sevice.TrackingService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; @@ -22,9 +23,11 @@ public class FeelEvaluationController { private static final Logger LOG = LoggerFactory.getLogger(FeelEvaluationController.class); private final FeelEvaluationService evaluationService; + private final TrackingService trackingService; - public FeelEvaluationController(final FeelEvaluationService evaluationService) { + public FeelEvaluationController(final FeelEvaluationService evaluationService, TrackingService trackingService) { this.evaluationService = evaluationService; + this.trackingService = trackingService; } @PostMapping("/feel/evaluate") @@ -40,6 +43,9 @@ public ResponseEntity evaluate( } catch (Exception e) { return new ResponseEntity<>(FeelEvaluationResponse.withError(e.getMessage()), HttpStatus.OK); + + } finally { + trackingService.trackExpressionEvaluation(request.metadata); } } @@ -58,6 +64,9 @@ public ResponseEntity evaluateUnaryTests( } catch (Exception e) { return new ResponseEntity<>(FeelEvaluationResponse.withError(e.getMessage()), HttpStatus.OK); + + } finally { + trackingService.trackUnaryTestsExpressionEvaluation(request.metadata); } } } diff --git a/src/main/java/org/camunda/feel/playground/sevice/MixpanelProperties.java b/src/main/java/org/camunda/feel/playground/sevice/MixpanelProperties.java new file mode 100644 index 00000000..1b9c04e5 --- /dev/null +++ b/src/main/java/org/camunda/feel/playground/sevice/MixpanelProperties.java @@ -0,0 +1,17 @@ +package org.camunda.feel.playground.sevice; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConditionalOnProperty(prefix = "playground.tracking", name = "enabled", havingValue = "true") +public class MixpanelProperties { + + @Value("${MIXPANEL_PROJECT_TOKEN}") + private String projectToken; + + public String getProjectToken() { + return projectToken; + } +} diff --git a/src/main/java/org/camunda/feel/playground/sevice/MixpanelTrackingService.java b/src/main/java/org/camunda/feel/playground/sevice/MixpanelTrackingService.java new file mode 100644 index 00000000..22a36786 --- /dev/null +++ b/src/main/java/org/camunda/feel/playground/sevice/MixpanelTrackingService.java @@ -0,0 +1,56 @@ +package org.camunda.feel.playground.sevice; + +import com.mixpanel.mixpanelapi.MessageBuilder; +import com.mixpanel.mixpanelapi.MixpanelAPI; +import org.json.JSONObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.Optional; + +@Component +@ConditionalOnBean(MixpanelProperties.class) +public class MixpanelTrackingService implements TrackingService { + + private static final Logger LOGGER = LoggerFactory.getLogger(MixpanelTrackingService.class); + + private final MixpanelAPI mixpanelAPI = new MixpanelAPI(); + + private final MessageBuilder messageBuilder; + + public MixpanelTrackingService(MixpanelProperties mixpanelProperties) { + messageBuilder = new MessageBuilder(mixpanelProperties.getProjectToken()); + } + + private void sendMixpanelEvent(EVENT_TYPE eventType, Map metadata) { + + var properties = new JSONObject(); + Optional.ofNullable(metadata).ifPresent(entry -> entry.forEach(properties::put)); + + var message = messageBuilder.event(null, eventType.name(), properties); + + try { + mixpanelAPI.sendMessage(message); + } catch (Exception e) { + LOGGER.warn("Failed to send Mixpanel event.", e); + } + } + + @Override + public void trackExpressionEvaluation(Map metadata) { + sendMixpanelEvent(EVENT_TYPE.FEEL_EXPRESSION_EVALUATION, metadata); + } + + @Override + public void trackUnaryTestsExpressionEvaluation(Map metadata) { + sendMixpanelEvent(EVENT_TYPE.FEEL_UNARY_TESTS_EXPRESSION_EVALUATION, metadata); + } + + private enum EVENT_TYPE { + FEEL_EXPRESSION_EVALUATION, + FEEL_UNARY_TESTS_EXPRESSION_EVALUATION + } +} diff --git a/src/main/java/org/camunda/feel/playground/sevice/NoopTrackingService.java b/src/main/java/org/camunda/feel/playground/sevice/NoopTrackingService.java new file mode 100644 index 00000000..b9c37c9a --- /dev/null +++ b/src/main/java/org/camunda/feel/playground/sevice/NoopTrackingService.java @@ -0,0 +1,21 @@ +package org.camunda.feel.playground.sevice; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.stereotype.Component; + +import java.util.Map; + +@Component +@ConditionalOnMissingBean(MixpanelProperties.class) +public class NoopTrackingService implements TrackingService { + + @Override + public void trackExpressionEvaluation(Map metadata) { + // no-op + } + + @Override + public void trackUnaryTestsExpressionEvaluation(Map metadata) { + // no-op + } +} diff --git a/src/main/java/org/camunda/feel/playground/sevice/TrackingService.java b/src/main/java/org/camunda/feel/playground/sevice/TrackingService.java new file mode 100644 index 00000000..99d74ef7 --- /dev/null +++ b/src/main/java/org/camunda/feel/playground/sevice/TrackingService.java @@ -0,0 +1,11 @@ +package org.camunda.feel.playground.sevice; + +import java.util.Map; + +public interface TrackingService { + + void trackExpressionEvaluation(Map metadata); + + void trackUnaryTestsExpressionEvaluation(Map metadata); + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index d90e718b..eafe1af4 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,2 +1,3 @@ server.port=${PORT:8080} +playground.tracking.enabled=true diff --git a/src/test/resources/application.properties b/src/test/resources/application.properties new file mode 100644 index 00000000..bb1ceb6a --- /dev/null +++ b/src/test/resources/application.properties @@ -0,0 +1,3 @@ +server.port=${PORT:8080} + +playground.tracking.enabled=false