Compare commits

...

17 Commits

Author SHA1 Message Date
f5c0930494 VERKEERDE CONFIG MEE NAAR PRODUCTIE OMG 2025-01-23 23:59:09 +01:00
a06b3cadd1 heheh toch niet 2025-01-21 21:52:01 +01:00
93ab8196fa Jenkinsfile meldingen betreft builds poging 3 2025-01-21 21:39:19 +01:00
ebf79fa15d Jenkinsfile meldingen betreft builds poging 2 2025-01-21 21:35:12 +01:00
3fbd77ca13 Jenkinsfile meldingen betreft builds 2025-01-21 21:32:23 +01:00
6f9349b13c fix betreft opslaan van al bestaande vacatures 2025-01-21 21:20:45 +01:00
dea9c2eb27 CRON job voor het schonen van de logging fix 2025-01-20 22:31:09 +01:00
9f24b94aaa CRON job voor het schonen van de logging 2025-01-20 22:29:30 +01:00
4a786e506c websocket :(
database :)
2025-01-20 22:18:44 +01:00
c696d61091 websocket :(
database :)
2025-01-20 22:13:39 +01:00
79473e4cfc event logging aangepast 2025-01-20 21:16:47 +01:00
7b303df1ea event logging toegevoegd 2025-01-20 20:47:58 +01:00
be78b764a3 logging loki verwijderd 2025-01-20 20:47:33 +01:00
2b9ba0da6a logging loki verwijderd 2025-01-20 20:47:23 +01:00
3e173f68d7 Merge pull request 'Add src/main/resources/logback.xml' (#1) from logging-loki into main
Reviewed-on: #1
2025-01-20 10:30:26 +00:00
d5a769e1de Update pom.xml 2025-01-20 10:30:01 +00:00
d63fafc397 Add src/main/resources/logback.xml 2025-01-20 10:25:47 +00:00
10 changed files with 244 additions and 37 deletions

11
pom.xml
View File

@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>nl.veenm</groupId> <groupId>nl.veenm</groupId>
<artifactId>jobfindr</artifactId> <artifactId>jobfindr</artifactId>
@@ -71,13 +70,16 @@
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm-panache</artifactId> <artifactId>quarkus-hibernate-orm-panache</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<!-- jsoup HTML parser library @ https://jsoup.org/ --> <!-- jsoup HTML parser library @ https://jsoup.org/ -->
<groupId>org.jsoup</groupId> <groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId> <artifactId>jsoup</artifactId>
<version>1.18.3</version> <version>1.18.3</version>
</dependency> </dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-websockets</artifactId>
</dependency>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId> <artifactId>quarkus-junit5</artifactId>
@@ -138,8 +140,7 @@
</executions> </executions>
<configuration> <configuration>
<systemPropertyVariables> <systemPropertyVariables>
<native.image.path>${project.build.directory}/${project.build.finalName}-runner <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
</native.image.path>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home> <maven.home>${maven.home}</maven.home>
</systemPropertyVariables> </systemPropertyVariables>

View File

@@ -0,0 +1,88 @@
package nl.veenm.jobfindr.domain;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity
public class Event {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String timestamp;
private String className;
private String methodName;
private String message;
private String level;
private String error;
public Event(String timestamp, String className, String methodName, String message, String level) {
this.timestamp = timestamp;
this.className = className;
this.methodName = methodName;
this.message = message;
this.level = level;
}
public Event(String timestamp, String className, String methodName, String message, String level, String error) {
this.timestamp = timestamp;
this.className = className;
this.methodName = methodName;
this.message = message;
this.level = level;
this.error = error;
}
public Event() {
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getMethodName() {
return methodName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
}

View File

@@ -0,0 +1,12 @@
package nl.veenm.jobfindr.repository;
import io.quarkus.hibernate.orm.panache.PanacheRepository;
import jakarta.enterprise.context.ApplicationScoped;
import nl.veenm.jobfindr.domain.Event;
import nl.veenm.jobfindr.domain.VacatureDetail;
@ApplicationScoped
public class EventRepository implements PanacheRepository<Event> {
}

View File

@@ -4,10 +4,6 @@ import io.quarkus.hibernate.orm.panache.PanacheRepository;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import nl.veenm.jobfindr.domain.VacatureDetail; import nl.veenm.jobfindr.domain.VacatureDetail;
import java.time.LocalDate;
import java.util.List;
@ApplicationScoped @ApplicationScoped
public class VacatureDetailRepository implements PanacheRepository<VacatureDetail> { public class VacatureDetailRepository implements PanacheRepository<VacatureDetail> {

View File

@@ -3,7 +3,9 @@ package nl.veenm.jobfindr.services;
import io.quarkus.mailer.Mail; import io.quarkus.mailer.Mail;
import io.quarkus.mailer.Mailer; import io.quarkus.mailer.Mailer;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import nl.veenm.jobfindr.domain.Vacature; import nl.veenm.jobfindr.domain.Vacature;
import nl.veenm.jobfindr.util.EventService;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import java.time.LocalDateTime; import java.time.LocalDateTime;
@@ -12,6 +14,11 @@ import java.util.List;
@ApplicationScoped @ApplicationScoped
public class EmailService { public class EmailService {
@Inject
EventService eventService;
private final String className = this.getClass().getSimpleName();
private static final Logger log = Logger.getLogger(EmailService.class); private static final Logger log = Logger.getLogger(EmailService.class);
private final Mailer mailer; private final Mailer mailer;
@@ -76,7 +83,15 @@ public class EmailService {
// Verstuur de e-mail met HTML-inhoud // Verstuur de e-mail met HTML-inhoud
log.info("Sending email to " + recipient); log.info("Sending email to " + recipient);
eventService.logInfo(className, "stuurVacatureEmail", "Sending email to " + recipient);
try{
mailer.send(Mail.withHtml(recipient, subject, emailBody.toString())); mailer.send(Mail.withHtml(recipient, subject, emailBody.toString()));
eventService.logSucces(className, "stuurVacatureEmail", "Email sent");
} catch (Exception e) {
eventService.logError(className, "stuurVacatureEmail", "Sending email failed", e);
}
} }
} }

View File

@@ -8,6 +8,7 @@ import nl.veenm.jobfindr.domain.Vacature;
import nl.veenm.jobfindr.repository.VacatureDetailRepository; import nl.veenm.jobfindr.repository.VacatureDetailRepository;
import nl.veenm.jobfindr.repository.VacatureRepository; import nl.veenm.jobfindr.repository.VacatureRepository;
import nl.veenm.jobfindr.scrapers.ScraperService; import nl.veenm.jobfindr.scrapers.ScraperService;
import nl.veenm.jobfindr.util.EventService;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import java.io.IOException; import java.io.IOException;
@@ -16,13 +17,15 @@ import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException; import java.time.format.DateTimeParseException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
@ApplicationScoped @ApplicationScoped
public class VacatureService { public class VacatureService {
@Inject @Inject
ScraperService scraperService; ScraperService scraperService;
@Inject
EventService eventService;
@Inject @Inject
EmailService emailService; EmailService emailService;
@@ -34,7 +37,10 @@ public class VacatureService {
private static final Logger logger = Logger.getLogger(VacatureService.class); private static final Logger logger = Logger.getLogger(VacatureService.class);
private final String className = this.getClass().getSimpleName();
public List<Vacature> getServices() throws IOException { public List<Vacature> getServices() throws IOException {
eventService.logInfo(VacatureService.class.getName(), "getServices", "getServices aangeroepen");
List<Vacature> vacatures = new ArrayList<>(); List<Vacature> vacatures = new ArrayList<>();
vacatures.addAll(scraperService.scrapeVacatures("https://www.meesterbaan.nl/vacatures/50-km?trefwoord=duits&locatie=Apeldoorn")); vacatures.addAll(scraperService.scrapeVacatures("https://www.meesterbaan.nl/vacatures/50-km?trefwoord=duits&locatie=Apeldoorn"));
vacatures.addAll(scraperService.scrapeVacatures("https://www.meesterbaan.nl/vacatures/50-km?trefwoord=frans&locatie=Apeldoorn")); vacatures.addAll(scraperService.scrapeVacatures("https://www.meesterbaan.nl/vacatures/50-km?trefwoord=frans&locatie=Apeldoorn"));
@@ -43,8 +49,9 @@ public class VacatureService {
} }
public void checkAndSendNewVacatures() throws IOException { public void checkAndSendNewVacatures() throws IOException {
logger.info("Checking for new vacatures");
eventService.logInfo(className, "checkAndSendNewVacatures", "Checking for new vacatures");
LocalDate today = LocalDate.now(); LocalDate today = LocalDate.now();
LocalDate yesterday = today.minusDays(1);
// Scrape de nieuwste vacatures // Scrape de nieuwste vacatures
String url = "https://www.meesterbaan.nl/vacatures/50-km?trefwoord=duits&locatie=Apeldoorn"; String url = "https://www.meesterbaan.nl/vacatures/50-km?trefwoord=duits&locatie=Apeldoorn";
@@ -57,34 +64,38 @@ public class VacatureService {
try { try {
scraperService.getVacatureDetails(todayVacature); scraperService.getVacatureDetails(todayVacature);
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); eventService.logError(className, "checkAndSendNewVacatures", "checkAndSendNewVacatures failed", e);
} }
}); });
// Haal de vacatures van gisteren op // Haal de vacatures van gisteren op
List<Vacature> yesterdayVacatures = vacatureRepository.findByDate(yesterday); List<Vacature> yesterdayVacatures = vacatureRepository.findAll().stream().toList();
// Filter nieuwe vacatures System.out.println(todayVacatures.size());
List<Vacature> newVacatures = todayVacatures.stream() System.out.println(yesterdayVacatures.size());
.filter(vacature -> yesterdayVacatures.stream()
.noneMatch(yv -> yv.getTitel().equals(vacature.getTitel()) && yv.getUrl().equals(vacature.getUrl())))
.collect(Collectors.toList()); todayVacatures.removeIf(a -> yesterdayVacatures.stream().anyMatch(b -> b.getUrl().equals(a.getUrl())));
System.out.println(todayVacatures.size());
// Alleen nieuwe vacatures opslaan en versturen // Alleen nieuwe vacatures opslaan en versturen
if (!newVacatures.isEmpty()) { if (!todayVacatures.isEmpty()) {
// Sla de nieuwe vacatures op // Sla de nieuwe vacatures op
newVacatures.forEach(vacature -> { todayVacatures.forEach(vacature -> {
vacature.setDatum(today); vacature.setDatum(today);
vacatureDetailRepository.persist(vacature.getDetail()); vacatureDetailRepository.persist(vacature.getDetail());
vacatureRepository.persist(vacature); vacatureRepository.persist(vacature);
}); });
// Verstuur een e-mail // Verstuur een e-mail
emailService.stuurVacatureEmail("danthefranken@gmail.com", newVacatures); emailService.stuurVacatureEmail("danthefranken@gmail.com", todayVacatures);
emailService.stuurVacatureEmail("vanveenmel11@gmail.com", newVacatures); emailService.stuurVacatureEmail("vanveenmel11@gmail.com", todayVacatures);
logger.info("Nieuwe vacatures verstuurd en opgeslagen."); logger.info("Nieuwe vacatures verstuurd en opgeslagen.");
eventService.logSucces(className, "checkAndSendNewVacatures", "Nieuwe vacatures verstuurd en opgeslagen.");
} else { } else {
logger.info("Geen nieuwe vacatures gevonden."); logger.info("Geen nieuwe vacatures gevonden.");
eventService.logInfo(className, "checkAndSendNewVacatures", "Geen nieuwe vacatures gevonden.");
} }
} }
@@ -96,7 +107,7 @@ public class VacatureService {
} }
public List<Vacature> getAllVacatures() { public List<Vacature> getAllVacatures() {
logger.info("Get all vacatures"); eventService.logInfo(className, "getAllVacatures", "fetching all vacatures");
return vacatureRepository.listAll(); return vacatureRepository.listAll();
} }
@@ -108,6 +119,7 @@ public class VacatureService {
@Transactional @Transactional
public void cleanVacatures() { public void cleanVacatures() {
logger.info("Cleaning vacatures"); logger.info("Cleaning vacatures");
eventService.logInfo(className, "cleanVacatures", "Cleaning vacatures");
getAllVacatures().forEach(vacature -> { getAllVacatures().forEach(vacature -> {
var date = convertStringToLocalDate(vacature.getDetail().getSluitingsdatum()); var date = convertStringToLocalDate(vacature.getDetail().getSluitingsdatum());
var today = LocalDate.now(); var today = LocalDate.now();
@@ -115,11 +127,12 @@ public class VacatureService {
if (date != null) { if (date != null) {
if (date.isBefore(today)) { if (date.isBefore(today)) {
logger.info("Deleting vacature " + vacature.getTitel()); logger.info("Deleting vacature " + vacature.getTitel());
eventService.logInfo(className, "cleanVacatures", "Deleting vacature " + vacature.getTitel());
vacatureDetailRepository.delete(vacature.getDetail()); vacatureDetailRepository.delete(vacature.getDetail());
vacatureRepository.delete(vacature); vacatureRepository.delete(vacature);
} }
} }
eventService.logSucces(className, "cleanVacatures", "Cleaning vacatures done");
}); });
} }

View File

@@ -0,0 +1,75 @@
package nl.veenm.jobfindr.util;
import io.quarkus.scheduler.Scheduled;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
import nl.veenm.jobfindr.domain.Event;
import nl.veenm.jobfindr.repository.EventRepository;
import java.time.Instant;
@ApplicationScoped
public class EventService {
@Inject
EventRepository eventRepository;
@Transactional
public void logInfo(String className, String methodName, String message) {
// Maak een nieuw event
Event event = new Event(
Instant.now().toString(), // Tijdstempel
className, // Naam van de klasse
methodName, // Naam van de methode
message,
"INFO"
// Bericht
);
saveEvent(event);
}
@Transactional
public void logSucces(String className, String methodName, String message) {
// Maak een nieuw event
Event event = new Event(
Instant.now().toString(), // Tijdstempel
className, // Naam van de klasse
methodName, // Naam van de methode
message,
"SUCCESS"
// Bericht
);
saveEvent(event);
}
@Transactional
public void logError(String className, String methodName, String message, Exception e) {
// Maak een nieuw event
Event event = new Event(
Instant.now().toString(), // Tijdstempel
className, // Naam van de klasse
methodName, // Naam van de methode
message,
"ERROR",
e.getMessage()
// Bericht
);
saveEvent(event);
}
private void saveEvent(Event event) {
eventRepository.persist(event);
}
@Scheduled(cron = "0 00 00 ? * 1#1")
@Transactional
public void cleanEvents() {
eventRepository.deleteAll();
}
}

View File

@@ -12,8 +12,10 @@ quarkus.datasource.jdbc.url=jdbc:postgresql://${DB_HOST}:${DB_PORT}/vacaturesdb
quarkus.datasource.username=${DB_USERNAME} quarkus.datasource.username=${DB_USERNAME}
quarkus.datasource.password=${DB_PASSWORD} quarkus.datasource.password=${DB_PASSWORD}
quarkus.hibernate-orm.database.generation=update quarkus.hibernate-orm.database.generation=update
quarkus.hibernate-orm.log.sql=true
quarkus.hibernate-orm.sql-load-script=no-file quarkus.hibernate-orm.sql-load-script=no-file
quarkus.hibernate-orm.log.highlight-sql=false
quarkus.hibernate-orm.log.sql=false
# CORS configuratie # CORS configuratie
quarkus.http.cors=true quarkus.http.cors=true
@@ -32,13 +34,3 @@ quarkus.log.console.format=%d{yyyy-MM-dd} %d{HH:mm:ss} %-5p [%c] (%s%e)%n
quarkus.log.file.enable=true quarkus.log.file.enable=true
quarkus.log.file.path=logs/app.log quarkus.log.file.path=logs/app.log
quarkus.log.file.format=%d{yyyy-MM-dd} %d{HH:mm:ss} %-5p [%c] (%s%e)%n quarkus.log.file.format=%d{yyyy-MM-dd} %d{HH:mm:ss} %-5p [%c] (%s%e)%n
# Schakel Micrometer en Prometheus in
quarkus.micrometer.export.prometheus.enabled=true
# Prometheus-metrieken beschikbaar maken op een endpoint
quarkus.micrometer.export.prometheus.path=/q/metrics
# (Optioneel) Metrieken voor HTTP-verzoeken en foutcodes
quarkus.micrometer.binder.http-server.enabled=true

View File

@@ -0,0 +1,15 @@
<configuration>
<appender name="LOKI" class="com.github.loki4j.logback.LokiAppender">
<loki4j>
<batchSize>100</batchSize>
<sendQueueSize>10</sendQueueSize>
<url>http://192.168.2.31:3100/loki/api/v1/push</url>
<labels>
<label>app</label><value>jobfindr-jvm</value>
</labels>
</loki4j>
</appender>
<root level="INFO">
<appender-ref ref="LOKI" />
</root>
</configuration>