Elasticsearch Loglarını Uygulamanızda Göstermek

ilyasaglar tarafından tarihinde yayınlandı

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

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir