筆者喜歡做一些小工具,給PM或者組內同學使用,不僅僅可以提高工作效率,而且也可以學一些前端方面的知識。之前使用Elasticsearch API做過管理後臺的小工具,一直沒有總結,最近給PM哥們又做了一個小工具,而且也使用到了Elasticsearch API,正好做個簡單分享。
需求
PM最近經常讓我統計每家機構調用某個接口的失敗記錄信息,雖然接口調用記錄已經打到日誌了,但是沒有關鍵字信息所以很難去統計,顯然之前做過根據一個或多個關鍵字查詢我們平臺所有日誌的後臺管理小工具不適用了。
方案
- 業務底層必須把三方返回信息返回到上層
- 業務上層統一處理,按照固定格式把信息打到日誌裏
- 管理後臺根據條件篩選查找,通過es根據關鍵字查找
編碼
- 業務代碼日誌打印
JSONObject jsonObject = new JSONObject(); jsonObject.put("time", new Date()); jsonObject.put("companyId", companyId); jsonObject.put("companyName", CompanyAppIdEnum.getCompanyAppIdEnum(companyId).getDesc()); jsonObject.put("orderNo", "暫不展示敏感信息"); jsonObject.put("orderStatus", -1); jsonObject.put("type",FilterFailEnum.FILTER.getName()); // 關鍵字 jsonObject.put("keyword", CompanyAppIdEnum.getCompanyAppIdEnum(companyId).getDesc() + FilterFailEnum.FILTER.getDesc()); jsonObject.put("fail", response.getErrorMsg()); thirdLogger.info(jsonObject.toJSONString());
- Elasticsearch Client構建 因爲是Java程序員,所以用的Java客戶端 構建TransportClient
/** * elasticsearch集羣 * TransportClient獲取 * * @return */ protected TransportClient getTransportClient() { if (transportClient == null) { synchronized (ElkLogSearchServiceImpl.class) { if (transportClient == null) { //ES集羣地址 String[] ESHosts = configUtil.getEsClientHosts().split(","); //設置es實例名稱 Settings settings = Settings.builder().put("cluster.name", configUtil.getEsClusterName()) //自動嗅探整個集羣的狀態,把集羣中其他ES節點的ip添加到本地的客戶端列表中、 .put("client.transport.sniff", true) .put("xpack.security.user", configUtil.getEsClientUser()) .put("xpack.security.transport.ssl.verification_mode", "certificate") .put("xpack.security.transport.ssl.enabled", "true") .put("xpack.security.transport.ssl.keystore.path", configUtil.getEsCertificates()) .put("xpack.security.transport.ssl.truststore.path", configUtil.getEsCertificates()).build(); TransportClient preBuiltTransportClient = new PreBuiltXPackTransportClient(settings); for (String esHost : ESHosts) { preBuiltTransportClient.addTransportAddress(new TransportAddress(new InetSocketAddress(esHost, 9300))); } return preBuiltTransportClient; } } } return transportClient; }
- 根據時間獲取索引、構建查詢條件
/** * 根據時間範圍獲得索引 * @param startDate * @param endDate * @return */ protected String[] getIndices(long startDate, long endDate,String indiceName) { int days = (int) (endDate - startDate) / 86400000 + 1; String[] indices = new String[days]; for (int i = 0; i < days; i++) { String dayIndex = simpleDateFormat.format(new Date(startDate + i * 86400000)); indices[i] = indiceName + dayIndex; } return indices; }
protected QueryBuilder getFilterQueryBuilder(String keywords){ BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery(); // 可以添加多個查詢條件 queryBuilder.must(QueryBuilders.matchPhraseQuery("message.params",keywords)); return queryBuilder; }
- 查詢
public ResponseVo getFilterFailByES(Long companyId, int pageNo, FilterFailEnum filterFailEnum, long startDate, long endDate) { ResponseVo vo = new ResponseVo(); LinkedList linkedList = new LinkedList(); transportClient = getTransportClient(); String regexp = CompanyAppIdEnum.getCompanyAppIdEnum(companyId).getDesc() + filterFailEnum.getDesc(); String[] indices = getIndices(startDate, endDate, IndiceTypeEnum.JKZJ_API_THIRD_SERVER_LOG.getIndiceName()); QueryBuilder queryBuilder = getFilterQueryBuilder(regexp); try { SearchResponse searchResponse = transportClient.prepareSearch(indices).setQuery(queryBuilder).addSort("logdate", SortOrder.DESC).setSize(10).setFrom((pageNo - 1) * 10).execute().actionGet(); SearchHits searchHits = searchResponse.getHits(); if (searchHits.getTotalHits() > 0) { for (SearchHit searchHit : searchHits) { JSONObject paramsDetailsJO = JSONObject.parseObject(searchHit.getSourceAsString()); JSONObject messapgeParam = paramsDetailsJO.getJSONObject("message").getJSONObject("params"); Long time = messapgeParam.getLong("time"); String companyIds = messapgeParam.getString("companyId"); String companyName = messapgeParam.getString("companyName"); String orderNo = messapgeParam.getString("orderNo"); String orderStatus = messapgeParam.getString("orderStatus"); String fail = messapgeParam.getString("fail"); String type = messapgeParam.getString("type"); Map map = new HashMap(); map.put("companyId", companyIds); Date times = new Date(Long.valueOf(time)); map.put("time", DateUtils.getDate(times)); map.put("companyName", companyName); map.put("orderNo", orderNo); map.put("orderStatus", orderStatus); map.put("fail", fail); map.put("type", type); linkedList.add(map); } } vo.setVoList(linkedList); //總條數 vo.setMsg(searchHits.getTotalHits() + ""); } catch (Exception e) { logger.error(e.getMessage(), e); vo.setCode(204); vo.setMsg("查詢失敗"); } return vo; }
頁面展示
好啦,再也不用被PM老哥煩了。