Skip to content

Commit 85c5f09

Browse files
authored
tolldemo: working on the slow query (#887)
* working on slow query and metrics --- Signed-off-by: Mark Nelson <mark.x.nelson@oracle.com>
1 parent 2e58f53 commit 85c5f09

File tree

9 files changed

+223
-33
lines changed

9 files changed

+223
-33
lines changed

tolldemo/queue-reader/pom.xml

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
<java.version>11</java.version>
1818
<spring-cloud.version>2021.0.8</spring-cloud.version>
1919
<oracle-springboot-starter.version>2.7.12</oracle-springboot-starter.version>
20-
<micrometer-core.version>1.12.5</micrometer-core.version>
21-
<datasource-micrometer-spring-boot.version>1.0.3</datasource-micrometer-spring-boot.version>
20+
<!-- <micrometer-core.version>1.12.5</micrometer-core.version>
21+
<datasource-micrometer-spring-boot.version>1.0.3</datasource-micrometer-spring-boot.version> -->
2222
</properties>
2323
<dependencies>
2424
<dependency>
@@ -29,10 +29,24 @@
2929
<groupId>org.springframework.boot</groupId>
3030
<artifactId>spring-boot-starter-web</artifactId>
3131
</dependency>
32+
<dependency>
33+
<groupId>org.springframework</groupId>
34+
<artifactId>spring-jdbc</artifactId>
35+
</dependency>
36+
<dependency>
37+
<groupId>org.springframework.boot</groupId>
38+
<artifactId>spring-boot-starter-jdbc</artifactId>
39+
</dependency>
3240
<dependency>
3341
<groupId>org.springframework.cloud</groupId>
3442
<artifactId>spring-cloud-starter-openfeign</artifactId>
3543
</dependency>
44+
<dependency>
45+
<groupId>com.oracle.database.spring</groupId>
46+
<artifactId>oracle-spring-boot-starter-ucp</artifactId>
47+
<version>${oracle-springboot-starter.version}</version>
48+
<type>pom</type>
49+
</dependency>
3650
<dependency>
3751
<groupId>com.oracle.database.spring</groupId>
3852
<artifactId>oracle-spring-boot-starter-aqjms</artifactId>
@@ -44,44 +58,44 @@
4458
<version>2.17.0</version>
4559
</dependency>
4660
<!-- Core module of Micrometer -->
47-
<dependency>
61+
<!-- <dependency>
4862
<groupId>io.micrometer</groupId>
4963
<artifactId>micrometer-core</artifactId>
5064
<version>${micrometer-core.version}</version>
51-
</dependency>
65+
</dependency> -->
5266
<!-- Prometheues-->
5367
<dependency>
5468
<groupId>io.micrometer</groupId>
5569
<artifactId>micrometer-registry-prometheus</artifactId>
5670
</dependency>
5771
<!-- Adds the Tracer Implementation -->
58-
<dependency>
72+
<!-- <dependency>
5973
<groupId>io.micrometer</groupId>
6074
<artifactId>micrometer-tracing-bridge-otel</artifactId>
6175
<version>1.2.5</version>
62-
</dependency>
76+
</dependency> -->
6377
<!-- Adds an exporter to store the traces -->
64-
<dependency>
78+
<!-- <dependency>
6579
<groupId>io.opentelemetry</groupId>
6680
<artifactId>opentelemetry-exporter-otlp</artifactId>
6781
<version>1.37.0</version>
68-
</dependency>
82+
</dependency> -->
6983
<!-- Adds the Tracing API -->
70-
<dependency>
84+
<!-- <dependency>
7185
<groupId>io.micrometer</groupId>
7286
<artifactId>micrometer-tracing</artifactId>
7387
<version>1.2.5</version>
74-
</dependency>
88+
</dependency> -->
7589
<!-- Eureka client-->
76-
<dependency>
90+
<!-- <dependency>
7791
<groupId>org.springframework.cloud</groupId>
7892
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
79-
</dependency>
80-
<dependency>
93+
</dependency> -->
94+
<!-- <dependency>
8195
<groupId>net.ttddyy.observation</groupId>
8296
<artifactId>datasource-micrometer-spring-boot</artifactId>
8397
<version>${datasource-micrometer-spring-boot.version}</version>
84-
</dependency>
98+
</dependency> -->
8599
<dependency>
86100
<groupId>org.springframework.boot</groupId>
87101
<artifactId>spring-boot-starter-test</artifactId>
@@ -93,6 +107,11 @@
93107
<groupId>com.oracle.oci.sdk</groupId>
94108
<artifactId>oci-java-sdk-common-httpclient-jersey</artifactId>
95109
</dependency>
110+
<dependency>
111+
<groupId>com.sun.jersey</groupId>
112+
<artifactId>jersey-client</artifactId>
113+
<version>1.19.4</version>
114+
</dependency>
96115
<dependency>
97116
<groupId>com.oracle.oci.sdk</groupId>
98117
<artifactId>oci-java-sdk-core</artifactId>

tolldemo/queue-reader/src/main/java/com/example/queuereader/client/AIVisionClient.java

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
package com.example.queuereader.client;
22

3-
import java.io.IOException;
43
import java.util.ArrayList;
54
import java.util.Arrays;
65
import java.util.List;
76

87
import org.springframework.stereotype.Component;
98

10-
import com.oracle.bmc.ConfigFileReader;
119
import com.oracle.bmc.aivision.AIServiceVisionClient;
1210
import com.oracle.bmc.aivision.model.AnalyzeImageDetails;
1311
import com.oracle.bmc.aivision.model.ImageClassificationFeature;
1412
import com.oracle.bmc.aivision.model.Label;
1513
import com.oracle.bmc.aivision.model.ObjectStorageImageDetails;
1614
import com.oracle.bmc.aivision.requests.AnalyzeImageRequest;
1715
import com.oracle.bmc.aivision.responses.AnalyzeImageResponse;
18-
import com.oracle.bmc.auth.AuthenticationDetailsProvider;
19-
import com.oracle.bmc.auth.ConfigFileAuthenticationDetailsProvider;
16+
import com.oracle.bmc.auth.InstancePrincipalsAuthenticationDetailsProvider;
2017

2118
import lombok.extern.slf4j.Slf4j;
2219

@@ -25,16 +22,24 @@
2522
public class AIVisionClient {
2623

2724
public String analyzeImage(String imageUrl) {
28-
ConfigFileReader.ConfigFile configFile = null;
25+
// ConfigFileReader.ConfigFile configFile = null;
26+
// try {
27+
// configFile = ConfigFileReader.parseDefault();
28+
// } catch (IOException ioe) {
29+
// return null;
30+
// }
31+
// AuthenticationDetailsProvider provider = new ConfigFileAuthenticationDetailsProvider(configFile);
32+
final InstancePrincipalsAuthenticationDetailsProvider provider;
2933
try {
30-
configFile = ConfigFileReader.parseDefault();
31-
} catch (IOException ioe) {
34+
provider = InstancePrincipalsAuthenticationDetailsProvider.builder().build();
35+
} catch (Exception e) {
36+
log.error("Could not create Instance Principal Auth Provider", e);
3237
return null;
3338
}
34-
AuthenticationDetailsProvider provider = new ConfigFileAuthenticationDetailsProvider(configFile);
39+
3540
AIServiceVisionClient client = AIServiceVisionClient.builder().build(provider);
3641

37-
String objectName = "cars-images/htsngg9tpc-2/" + imageUrl;
42+
String objectName = "cars-images/" + imageUrl;
3843
log.info("object name: " + objectName);
3944

4045
AnalyzeImageDetails analyzeImageDetails = AnalyzeImageDetails.builder()

tolldemo/queue-reader/src/main/java/com/example/queuereader/client/JournalClient.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44
package com.example.queuereader.client;
55

66
import com.fasterxml.jackson.databind.JsonNode;
7+
8+
import io.micrometer.core.annotation.Timed;
9+
710
import org.springframework.cloud.openfeign.FeignClient;
811
import org.springframework.web.bind.annotation.PostMapping;
912
import org.springframework.web.bind.annotation.RequestBody;
1013

11-
@FeignClient(name = "journal", url = "http://localhost:8080")
14+
@FeignClient(name = "journal", url = "http://journal-app:8080")
1215
public interface JournalClient {
1316

1417
@PostMapping("/api/v1/journal")

tolldemo/queue-reader/src/main/java/com/example/queuereader/controller/TollReaderReceiver.java

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,23 @@
33

44
package com.example.queuereader.controller;
55

6+
import com.example.queuereader.model.AccountDetails;
67
import com.example.queuereader.service.AIVisionService;
8+
import com.example.queuereader.service.CustomerDataService;
79
import com.example.queuereader.service.JournalService;
810
import com.fasterxml.jackson.core.JsonProcessingException;
911
import com.fasterxml.jackson.databind.JsonNode;
1012
import com.fasterxml.jackson.databind.ObjectMapper;
1113
import com.fasterxml.jackson.databind.node.ObjectNode;
1214

15+
import io.micrometer.core.annotation.Timed;
16+
import io.micrometer.core.instrument.Tags;
17+
import io.micrometer.core.instrument.Timer;
18+
import io.micrometer.prometheus.PrometheusMeterRegistry;
1319
import lombok.extern.slf4j.Slf4j;
20+
21+
import java.util.List;
22+
1423
import org.springframework.jms.annotation.JmsListener;
1524
import org.springframework.stereotype.Component;
1625

@@ -22,19 +31,50 @@ public class TollReaderReceiver {
2231

2332
private JournalService journalService;
2433
private AIVisionService aiVisionService;
34+
private CustomerDataService customerDataService;
35+
private Timer timer;
2536

26-
public TollReaderReceiver(JournalService journalService, AIVisionService aiVisionService) {
37+
public TollReaderReceiver(
38+
JournalService journalService,
39+
AIVisionService aiVisionService,
40+
CustomerDataService customerDataService,
41+
PrometheusMeterRegistry registry
42+
) {
2743
this.journalService = journalService;
2844
this.aiVisionService = aiVisionService;
45+
this.customerDataService = customerDataService;
46+
timer = registry.timer("process.toll.read", Tags.empty());
2947
}
3048

3149
@JmsListener(destination = "TollGate")
3250
public void receiveTollData(String tollData) {
51+
Timer.Sample sample = Timer.start();
3352
log.info("Received message {}", tollData);
3453
try {
3554
JsonNode tollDataJson = objectMapper.readTree(tollData);
3655
log.info(String.valueOf(tollDataJson));
56+
57+
// check account
58+
log.info("Check that the tag, licensePlate and accountNumber match up");
59+
String tagId = tollDataJson.get("tagId").asText();
60+
String accountId = tollDataJson.get("accountNumber").asText();
61+
String licensePlate = tollDataJson.get("licensePlate").asText().split("-")[1];
62+
63+
List<AccountDetails> accountDetails = customerDataService.getAccountDetails(licensePlate);
64+
boolean found = false;
65+
for (AccountDetails a : accountDetails) {
66+
if (a.getAccountNumber().equalsIgnoreCase(accountId) && a.getTagId().equalsIgnoreCase(tagId)) {
67+
found = true;
68+
}
69+
}
70+
if (found) {
71+
log.info("Details match, proceeding...");
72+
} else {
73+
log.info("Details do not match - so ignoring this message");
74+
}
75+
3776
// call ai vision model to detect vehicle type
77+
log.info("Call the Vision AI Service to check if the vehicle photo matches the registration...");
3878
String aiResult = aiVisionService.analyzeImage(tollDataJson.get("image").asText());
3979
log.info("result from ai (type,confidence): " + aiResult);
4080
String detectedVehicleType = aiResult.split(",")[0];
@@ -44,6 +84,8 @@ public void receiveTollData(String tollData) {
4484
journalService.journal(updatedTollDataJson);
4585
} catch (JsonProcessingException e) {
4686
e.printStackTrace();
87+
} finally {
88+
timer.record(() -> sample.stop(timer) / 1_000_000);
4789
}
4890
}
4991
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package com.example.queuereader.model;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Data;
5+
import lombok.NoArgsConstructor;
6+
7+
@Data
8+
@NoArgsConstructor
9+
@AllArgsConstructor
10+
public class AccountDetails {
11+
private String customerId;
12+
private String accountNumber;
13+
private String firstName;
14+
private String lastName;
15+
private String address;
16+
private String city;
17+
private String zipcode;
18+
private String vehicleId;
19+
private String tagId;
20+
private String state;
21+
private String licensePlate;
22+
private String vehicleType;
23+
}

tolldemo/queue-reader/src/main/java/com/example/queuereader/service/AIVisionService.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,26 @@
44

55
import com.example.queuereader.client.AIVisionClient;
66

7+
import io.micrometer.core.instrument.Tags;
8+
import io.micrometer.core.instrument.Timer;
9+
import io.micrometer.prometheus.PrometheusMeterRegistry;
10+
711
@Service
812
public class AIVisionService {
913

1014
private AIVisionClient client;
15+
private Timer timer;
1116

12-
AIVisionService(AIVisionClient client) {
17+
AIVisionService(AIVisionClient client, PrometheusMeterRegistry registry) {
1318
this.client = client;
19+
timer = registry.timer("ai.vision", Tags.empty());
1420
}
1521

1622
public String analyzeImage(String imageUrl) {
17-
return client.analyzeImage(imageUrl);
23+
Timer.Sample sample = Timer.start();
24+
String response = client.analyzeImage(imageUrl);
25+
timer.record(() -> sample.stop(timer) / 1_000_000);
26+
return response;
1827
}
1928

2029
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.example.queuereader.service;
2+
3+
import java.util.ArrayList;
4+
import java.util.Date;
5+
import java.util.List;
6+
7+
import org.springframework.jdbc.core.JdbcTemplate;
8+
import org.springframework.stereotype.Service;
9+
10+
import com.example.queuereader.model.AccountDetails;
11+
12+
import lombok.extern.slf4j.Slf4j;
13+
14+
@Service
15+
@Slf4j
16+
public class CustomerDataService {
17+
18+
private final JdbcTemplate jdbcTemplate;
19+
20+
public CustomerDataService(JdbcTemplate jdbcTemplate) {
21+
this.jdbcTemplate = jdbcTemplate;
22+
}
23+
24+
25+
final String accountDetailsQuery =
26+
"select c.customer_id, c.account_number, c.first_name, c.last_name, c.address, c.city, c.zipcode, "
27+
+ "v.vehicle_id, v.tag_id, v.state, v.license_plate, v.vehicle_type "
28+
+ "from customer c, vehicle v "
29+
+ "where c.customer_id like '%'||v.customer_id||'%' "
30+
+ "and c.customer_id like ("
31+
+ " select '%'||customer_id||'%' "
32+
+ " from vehicle "
33+
+ " where license_plate like '%XXXXXX%'"
34+
+ ")";
35+
36+
37+
public List<AccountDetails> getAccountDetails(String licensePlate) {
38+
List<AccountDetails> result = new ArrayList<AccountDetails>();
39+
long startTime = System.currentTimeMillis();
40+
jdbcTemplate.query(accountDetailsQuery.replace("XXXXXX", licensePlate),
41+
(rs, rowNum) -> new AccountDetails(
42+
rs.getString("customer_id"),
43+
rs.getString("account_number"),
44+
rs.getString("first_name"),
45+
rs.getString("last_name"),
46+
rs.getString("address"),
47+
rs.getString("city"),
48+
rs.getString("zipcode"),
49+
rs.getString("vehicle_id"),
50+
rs.getString("tag_id"),
51+
rs.getString("state"),
52+
rs.getString("license_plate"),
53+
rs.getString("vehicle_type")
54+
)).forEach(accountDetails -> result.add(accountDetails));
55+
long endTime = System.currentTimeMillis();
56+
log.info("The query took " + (endTime - startTime) + "ms");
57+
58+
log.info("returning " + result.size() + " account detail rows");
59+
return result;
60+
}
61+
62+
}

0 commit comments

Comments
 (0)