Elasticsearch Loglarını Uygulamanızda Göstermek
Uygulamanız için tuttugunuz logları projenizin içerisinde göstermenize saglayan adımları anlatmaya çalışacagım. Logları yazmak için Log4j & RabbitMq kullanımına yönelik ayarları şuradan bulunan yazıdan okuyabilirsiniz.
ilk olarak pom.xml dosyasımıza bunu ekliyoruz.
<!– https://mvnrepository.com/artifact/org.elasticsearch.client/elasticsearch-rest-high-level-client –> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> <version>7.9.3</version> </dependency>
Elascticsearch ortamında Loglarımız aşagıdaki gibi json formatına uygun şekilde tutuluyor
{ "_index": "change_event-2020.12.31", "_type": "_doc", "_id": "QtIVhXYBwD_BtNmdU3TT", "_score": 1, "_source": { "objectId": "123", "oldValue": "test deger", "userId": 1, "eventTime": 1608550536016, "newValue": "test degeri 2", "objectName": "ObjectName", "fieldName": "identityNumber", "@timestamp": "2020-12-21T11:35:36.016Z", "ip": "0:0:0:0:0:0:0:1", "userName": "ilyasaglar", "@version": "1", "eventType": "UPDATE" } }
Bu formatı java uygulamamızda bir Model’e map ettikten sonra projemiz içerisinde istenilen yerlerde göstermemiz çok kolay olacak. Buraya Json dosyasında yer alan tüm alanları eklemeniz gerekiyor. Ben sadece 3 alanı ekledim sizin hepsini eklemeniz gerekiyor. Json dosyanız’dan hızlıca model oluşturmak için şu tarz siteleri kullanabilirsiniz. Örnek modelimiz şu şekilde.
public class ChangeLog { @JsonProperty("newValue") private String newValue; @JsonProperty("fieldName") private String fieldName; @JsonProperty("@timestamp") private String timestamp; @JsonProperty("objectId") private String objectId; public String getNewValue() { return newValue; } public void setNewValue(String newValue) { this.newValue = newValue; } public String getFieldName() { return fieldName; } public void setFieldName(String fieldName) { this.fieldName = fieldName; } public String getTimestamp() { return timestamp; } public void setTimestamp(String timestamp) { this.timestamp = timestamp; } public String getObjectId() { return objectId; } public void setObjectId(String objectId) { this.objectId = objectId; } }
Logları Elascticsearh sunucusundan getirme işlemini burada yapıyoruz ve getirilen logları yukarıda yer alan modelimize map ediyoruz. Ve bu adımda bir sorgu oluşturup filtreleme yapabiliyoruz. Burada objectId’ye göre ve eger varsa filtrelere göre getiriyorum loglarımızı
public class ChangeLogLazyDataModel extends LazyDataModel<ChangeLog> { private String filter1; private String filter2; private int objectId; private String hostname; public ChangeLogLazyDataModel(String filter1, String filter2, int objectId, String hostName) { this.filter1 = filter1; this.filter2 = filter2; this.objectId = objectId; this.hostname = hostName; } @Override public List<ChangeLog> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) { RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost(hostname))); SearchRequest searchRequest = new SearchRequest(); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); if (StringUtils.isEmpty(objectId)) { throw new BusinessException("current user should be selected"); } //objectId'ye göre filtreleme yapılıyor BoolQueryBuilder bqb= QueryBuilders.boolQuery() .must(QueryBuilders.matchQuery("objectId", objectId)); if (!StringUtils.isEmpty(filter1)) { bqb.must(QueryBuilders.matchQuery("fieldName", filter1)); } if (!StringUtils.isEmpty(filter2)) { bqb.must(QueryBuilders.matchQuery("newValue", filter2)); } //istediginiz kadar filtre ekleyebilirsiniz yukarıda oldugu gibi //timestamp'e göre sıralama için kullanıyoruz searchRequest.source(searchSourceBuilder.query(bqb).size(pageSize).from(first).sort("@timestamp", org.elasticsearch.search.sort.SortOrder.DESC)); List<ChangeLog> changeLogList = null; try { SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); SearchHits hits = searchResponse.getHits(); this.setRowCount(((Long)searchResponse.getHits().getTotalHits().value).intValue()); changeLogList = Arrays.stream(hits.getHits()) .map(SearchHit::getSourceAsString) .map(ChangeLogLazyDataModel::convert2Object) .collect(Collectors.toList()); } catch (IOException e) { throw new RuntimeException(e); } return changeLogList; } //objectMapper kullanarak json veriyi model'e dönüştürme public static ChangeLog convert2Object(String json) { ObjectMapper objectMapper = new ObjectMapper(); try { ChangeLog obj = objectMapper.readValue(json, ChangeLog.class); return obj; } catch (JsonProcessingException e) { return new ChangeLog(); } } }
Bean Class’ımız şu ise şu şekilde oluyor. Burada “request” Scope tercih ettik. Burada init metodumuz sayfaya yapılan her istekte çalışıyor ve ChangeLogLazyDataModel’e gidiyor. Burada ise sorgulama yapılıyor. Sayfamızın ön yüzünden getLazyDataModel()’e erişecegiz ve sorgudan gelen verileri sayfada gösterecegiz
Aşagıda yer alan hostname değişkeninde ise properties dosyamızda bulunan hostName bilgisini @Value annotasyonu kullanarak okuyoruz.
@Controller @Scope("request") public class ChangeLogBean { private String filter1; private String filter2; private int objectId; private LazyDataModel<ChangeLog> lazyDataModel = null; @Value("${changeLog.hostName}") private String hostname; @PostConstruct public void init() { if(objectId!=null) { objectId = Integer.parseInt(obj); lazyDataModel = new ChangeLogLazyDataModel(filter1,filter2, objectId, hostname); } public LazyDataModel<ChangeLog> getLazyDataModel() { return lazyDataModel; } }
Bu aşama itibariyle Logları getirdik ve Modelimize map ettik, şuan sadece ekranda göstermek işlemimiz kaldı. Biz bu projede JSF kullandıgımız için Primefaces Datatable kullanarak loglarımızı şu şekilde gösterebiliriz.
<h:form id="logForm"> <p:dataTable id="tableChangelog" scrollRows="5" widgetVar=cChangelogTablo" resizableColumns="true" lazy="true" liveResize="true" liveScroll="true" scrollWidth="100%" value="#{changeLogBean.lazyDataModel}" emptyMessage="Log Bulunamadı" var="log"> <p:column> <table class="table-minh"> <tr> <td width="20%"> <h:outputText value="#{log.fieldName}"/> </td> <td width="40%"> <h:outputText value="#{log.newValue}"/> </td> <td width="40%"> <h:outputText value="#{log.timestamp}"/> </td> </tr> </table> </p:column> </p:dataTable> </h:form>
Burada basitce 3 field için gösterimi yaptım. Sizler istediginiz kadar alan ekleyebilirsiniz. Tekrar hatırlatma geregi duyuyorum Model’e tüm alanları ekleyerek yapmanız gerekiyor. Çok fazla field oldugu için 3 alanı ekledim ben.
Logları Elasticsearch’e göndermek için Log4j ve RabbitMq kullandık, bu işlemin ayarlarını şurada bulunan örnekten inceleyebilirsiniz. Ayrıca log basmak için buradaki örnege de bakabilirsiniz. Hatalarım olduysa kusura bakmayın. Sağlıklı, mutlu yıllar dilerim..
0 yorum