欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot?Loki安裝簡介及實戰(zhàn)思路

 更新時間:2022年11月03日 14:59:27   作者:怒放吧德德  
這篇文章主要為大家介紹了SpringBoot?Loki安裝簡介及實戰(zhàn)思路詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪的相關(guān)資料

前言

因為網(wǎng)上好多都沒有通過Loki的API自己實現(xiàn)對日志監(jiān)控系統(tǒng),所以我就下定決心自己出一版關(guān)于loki與springboot的博文供大家參考,這個可以說是比較實用,很適合中小型企業(yè)。因此我醞釀了挺久了,對于loki的研究也比較久,希望各位讀者能有新的收獲。

簡介

Loki是Grafana Labs團隊的開源項目,可以組成一個功能齊全的日志堆棧。Loki是一個水平可擴展,高可用性,多租戶的日志聚合系統(tǒng)。它的設(shè)計非常經(jīng)濟高效且易于操作,因為它不會為日志內(nèi)容編制索引,而是為每個日志流編制一組標簽。Loki是用來存儲日志和處理查詢,需要通過promtail來收集日志,也可是通過后端的logback等日志框架來收集日志,通過grafana提供的loki可視化查看日志,當然了loki也提供了API,可以根據(jù)自己的需求來自己實現(xiàn)可視化界面,能夠減少三方插件的使用。

安裝

上一篇文章已經(jīng)介紹了如何安裝以及使用Grafana+loki+promtail進行搭建日志系統(tǒng),http://www.dbjr.com.cn/article/248318.htm可以看看這篇文章。接下來筆者要介紹的是通過Loki的API編寫自己可視化界面,并且通過logback來實現(xiàn)收集日志。 大致的結(jié)構(gòu)如圖

簡單介紹一下,主要就是通過springboot后端的logback日志框架來收集日志,在推送到loki中存儲,loki執(zhí)行對日志的查詢,通過API根據(jù)標簽等信息去查詢?nèi)罩静⑶以谧远x的前端界面中展示。

整體思路

其實宏觀來看,要達成這個需求說起來是十分簡單的,只需配置logback配置,在通過MDC寫入、收集日志,這里可以好多的寫法,可以是通過反射寫入日志,也可以是在需要打印的地方寫入日志,并且是將日志區(qū)分為不同的標簽。在前端就可以根據(jù)所定義的標簽來查看相應(yīng)的日志。前端獲取日志信息邏輯也很簡單,就只是通過Loki提供的API獲取每行的日志。接下來我就一一詳細的介紹SpringBoot與Loki的那些事。 可以查看此圖便于理解:

Loki實戰(zhàn)開發(fā)

接下來就詳細講解筆者在實戰(zhàn)開發(fā)中是如何編寫的,本次介紹只是對編寫的代碼進行詳講,對于代碼可能不會全部粘貼,不然冗余起來效果不好,各位讀者可以各自發(fā)揮,更加完善。其實整個業(yè)務(wù)也不難,基本都是loki自身提供的API,讀者可以通過Loki官方網(wǎng)站grafana.com/docs/loki/l… 去進一步對Loki的API進行查閱,后面筆者可能也會出一篇來專門對Loki的API以及配置進行介紹。好了,廢話不多說,馬上進入正題。

springboot中的配置

首先需要配置向Loki推送日志,也就是需要通過Loki的API:POST /loki/api/v1/push ,可以直接將地址通過appender寫死在logback日志框架中,但是在項目開發(fā)中,要考慮到環(huán)境的不同,應(yīng)該是能夠根據(jù)需要來修改loki服務(wù)器的地址,因此將loki的服務(wù)器地址配置在application-dev.yml中。

loki:
  url: http://localhost:3100/loki/api/v1

配置logback日志框架

先獲取yml配置的地址,通過appender添加到日志框架中,當然,配置客戶端也不一定是LogBack框架,還有Log4j2框架也是能夠使用的,具體配置可以看官網(wǎng)github.com/loki4j/loki…github.com/tkowalcz/tj… ,本章只對loki進行講解,對于日志框架,后期也會一一列出,各位讀者有什么不了解的,可以先到網(wǎng)上查閱資料。因為筆者不是部署多臺Loki服務(wù)器,不同的系統(tǒng)采用system這個標簽來進行區(qū)分。

<springProperty scope="context" name="lokiUrl" source="loki.url"/>
<property name="LOKI_URL" value="${lokiUrl}"/>
<!--添加loki-->
<appender name="lokiAppender" class="com.github.loki4j.logback.Loki4jAppender">
    <batchTimeoutMs>1000</batchTimeoutMs>
    <http class="com.github.loki4j.logback.ApacheHttpSender">
        <url>${LOKI_URL}/push</url>
    </http>
    <format>
        <label>
            <pattern>system=${SYSTEM_NAME},level=%level,logType=%X{log_file_type:-logType}</pattern>
        </label>
        <message>
            <pattern>${log.pattern}</pattern>
        </message>
        <sortByTime>true</sortByTime>
    </format>
</appender>

注解與切面寫入日志

自定義注解,并且設(shè)置日志標簽值。

/**
 * @author: lyd
 * @description: 自定義日志注解,用作LOKI日志分類
 * @Date: 2022/10/10
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD})
@Documented
public @interface LokiLog {
    LokiLogType type() default LokiLogType.DEFAULT;
}

通過枚舉的方式來定義日志類型的標簽值

/**
 * @author: lyd
 * @description: 枚舉便簽值 - 類型自己定義
 * @Date: 2022/10/11
 */
public enum LokiLogType {
    DEFAULT("默認"),
    A("A"),
    B("B"),
    C("C");
    private String desc;
    LokiLogType(String desc) {
     this.desc=desc;
    }
    public String getDesc() {
        return desc;
    }
}

編寫切面,寫入日志(詳情可以參照這篇文章http://www.dbjr.com.cn/article/230135.htm,內(nèi)部通過MDC.put("log_file_type", logType.getDesc());(MDC ( Mapped Diagnostic Contexts ),它是一個線程安全的存放診斷日志的容器??梢詤⒄?http://www.dbjr.com.cn/article/232986.htm可以理解為log_file_type是標簽名,logType.getDesc()是標簽值。

/**
 * @author: lyd
 * @description: 自定義日志切面:https://cloud.tencent.com/developer/article/1655923
 * @Date: 2022/10/10
 */
@Aspect
@Slf4j
@Component
public class LokiLogAspect {
    /**
     * 切到所有OperatorLog注解修飾的方法
     */
    @Pointcut("@annotation(org.nl.wms.log.LokiLog)")
    public void operatorLog() {
        // 空方法
    }
    /**
     * 利用@Around環(huán)繞增強
     *
     * @return
     */
    @Around("operatorLog()")
    public synchronized Object around(ProceedingJoinPoint pjp) throws Throwable {
//        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
//        HttpServletRequest request = attributes.getRequest();
//        HttpServletResponse response = attributes.getResponse();
        Signature signature = pjp.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        LokiLog lokiLog = method.getAnnotation(LokiLog.class);
        // 獲取描述信息
        LokiLogType logType = lokiLog.type();
        MDC.put("log_file_type", logType.getDesc());
        log.info("輸入?yún)?shù):" + JSONObject.toJSONString(pjp.getArgs()));
        Object proceed = pjp.proceed();
        log.info("返回參數(shù):" + JSONObject.toJSONString(proceed));
        MDC.remove("log_file_type");
        return proceed;
    }
}

使用注解,在方法中引用注解即可

@LokiLog(type = LokiLogType.A)

前端界面與后端接口

前端界面介紹起來可能比較麻煩,畢竟寫的代碼也比較多,這里就選取講解,代碼量比較多,也不會是全部代碼粘貼,樣式之類的,我相信讀者會根據(jù)自己的需求去實現(xiàn),這里主要的是記錄開發(fā)的思路。

日志的初步獲取

前端的界面就如圖,本次是以el-admin這個為基礎(chǔ)制作的demo。

查找日志是需要通過標簽與標簽值來獲取日志信息,因此首先需要的是攜帶標簽對到后端訪問Loki的API拿到數(shù)據(jù),讀者可以查閱官網(wǎng)的API,結(jié)合著學(xué)習(xí)。

一開始當vue視圖渲染的時候,就會從后端獲取loki日志標簽,具體后端接口的業(yè)務(wù)代碼如下:

/**
 * 獲取labels和values樹
 *
 * @return
 */
@Override
public JSONArray getLabelsValues() {
    JSONArray result = new JSONArray();
    // 獲取所有標簽
    String labelString = HttpUtil.get(lokiUrl + "/labels", CharsetUtil.CHARSET_UTF_8);
    JSONObject parse = (JSONObject) JSONObject.parse(labelString);
    JSONArray labels = parse.getJSONArray("data");
    for (int i=0; i<labels.size(); i++) {
        // 獲取標簽下的所有值
        String valueString = HttpUtil.get(lokiUrl + "/label/" + labels.getString(i) + "/values", CharsetUtil.CHARSET_UTF_8);
        JSONObject parse2 = (JSONObject) JSONObject.parse(valueString);
        JSONArray values = parse2.getJSONArray("data");
        JSONArray children = new JSONArray();
        // 組成樹形狀態(tài) 兩級
        for (int j=0; j<values.size(); j++) {
            JSONObject leaf = new JSONObject();
            leaf.put("label", values.getString(j));
            leaf.put("value", values.getString(j));
            children.add(leaf);
        }
        JSONObject node = new JSONObject();
        node.put("label", labels.getString(i));
        node.put("value", labels.getString(i));
        node.put("children", children);
        result.add(node);
    }
    return result;
}

核心代碼就只有通過Hutool工具包去訪問API獲取標簽HttpUtil.get(lokiUrl + "/labels", CharsetUtil.CHARSET_UTF_8); 以及 獲取標簽值HttpUtil.get(lokiUrl + "/label/" + labels.getString(i) + "/values", CharsetUtil.CHARSET_UTF_8); 因為我的前端是用elment-ui的樹來接收的,因此我就將返回的數(shù)據(jù)設(shè)計成相應(yīng)的形式。

<el-form-item label="日志標簽">
  <el-cascader
    v-model="labelAndValue"
    :options="labelsOptions"
    placeholder="請選擇標簽"
    @change="queryData"
  />
</el-form-item>

模糊查找與更多參數(shù)

loki提供了相應(yīng)的API來進行模糊查找日志,無非就是通過loki的API攜帶關(guān)鍵字進行模糊查找日志,筆者的做法是獲取含有關(guān)鍵字的日志內(nèi)容。

"/query_range?query={system=\"" + systemName + "\", " + logLabel + "=\"" + logLabelValue + "\"} |= `" + text + "`"

并且還能夠通過時間段來查詢,筆者實現(xiàn)了的效果如圖

不僅可以通過關(guān)鍵字,還有時間段時間范圍以及查找的方向和一次性顯示的條數(shù),最好是建議不要超過1000條數(shù)據(jù),滾動步數(shù)是實現(xiàn)滾動下拉的時候獲取新的日志數(shù)據(jù)的條目數(shù)。 后端代碼如下,簡單介紹一下,就是提供所需要的查詢條件來對日志進行篩選。不管是獲取日志數(shù)據(jù)還是滾動下拉獲取的日志數(shù)據(jù)都可以通用這個接口,然而主要的參數(shù)設(shè)置可以在前端進行打磨,以下代碼還有優(yōu)化的空間,畢竟當時剛開始寫的時候沒考慮這么多。

@Override
    public JSONObject getLogData(JSONObject json) {
        String logLabel = "";
        String logLabelValue = "";
        Long start = 0L;
        Long end = 0L;
        String text = "";
        String limit = "100";
        String direction = "backward";
        if (json.get("logLabel") != null) logLabel = json.getString("logLabel");
        if (json.get("logLabelValue") != null) logLabelValue = json.getString("logLabelValue");
        if (json.get("text") != null) text = json.getString("text");
        if (json.get("start") != null) start = json.getLong("start");
        if (json.get("end") != null) end = json.getLong("end");
        if (json.get("limits") != null) limit = json.getString("limits");
        if (json.get("direction") != null) direction = json.getString("direction");
        /**
         * 組織參數(shù)
         * 納秒數(shù)
         * 1660037391880000000
         * 1641453208415000000
         * http://localhost:3100/loki/api/v1/query_range?query={host="localhost"} |= ``&limit=1500&start=1641453208415000000&end=1660027623419419002
         */
        JSONObject parse = null;
        String query = lokiUrl + "/query_range?query={system=\"" + systemName + "\", " + logLabel + "=\"" + logLabelValue + "\"} |= `" + text + "`";
        String result = "";
        if (start==0L) {
            result = HttpUtil.get(query + "&limit=" + limit + "&direction=" + direction, CharsetUtil.CHARSET_UTF_8);
        } else {
            result = HttpUtil.get(query + "&limit=" + limit + "&start=" + start + "&end=" + end + "&direction=" + direction, CharsetUtil.CHARSET_UTF_8);
        }
        try {
            parse = (JSONObject) JSONObject.parse(result);
        } catch (Exception e) {
//            reslut的值可能為:too many outstanding requests,無法轉(zhuǎn)化成Json
            System.out.println("reslut:" + result);
//            e.printStackTrace();
        }
        return parse;
    }

前端的邏輯是比較復(fù)雜的,因為需要做大量的賦值與設(shè)置。 前端js方法代碼,主要是對參數(shù)數(shù)據(jù)的組織,這里需要注意的是,因為loki需要的是納秒級別的時間戳,這里就需要十分注意前端js的精度。還有一點就是,如果后端日志是有顏色標簽的,那么前端直接渲染就會顯示標簽,所以這里需要進行相應(yīng)的處理,就是用過AnsiUp插件進行操作,詳細看此篇文章:http://www.dbjr.com.cn/article/266641.htm

queryData() {
  console.log(this.labelAndValue)
  // 清空查詢數(shù)據(jù)
  this.clearParam()
  if (this.labelAndValue.length > 0) {
    queryParam.logLabel = this.labelAndValue[0]
    queryParam.logLabelValue = this.labelAndValue[1]
  }
  if (queryParam.logLabelValue === null) { // 判空
    this.$message({
      showClose: true,
      message: '請選擇標簽',
      type: 'warning'
    })
    this.showEmpty = true
    this.emptyText = '請選擇標簽'
    return
  }
  if (this.timeRange.length !== 0) { // 如果是輸入時間范圍
    queryParam.start = (new Date(this.timeRange[0]).getTime() * 1000000).toString()
    queryParam.end = (new Date(this.timeRange[1]).getTime() * 1000000).toString()
  }
  if (this.timeZoneValue) {
    const time = new Date()
    queryParam.start = ((time.getTime() - this.timeZoneValue) * 1000000).toString()
    queryParam.end = (time.getTime() * 1000000).toString()
  }
  if (this.text) {
    queryParam.text = this.text.replace(/^\s*|\s*$/g, '') // 去空
  }
  if (this.limits) {
    queryParam.limits = this.limits
  }
  queryParam.direction = this.direction
  var ansi_up = new AnsiUp()
  logOperation.getLogData(queryParam).then(res => {
    this.showEmpty = false
    if (res.data.result.length === 1) {
      this.logs = res.data.result[0].values
      for (const i in res.data.result[0].values) {
        this.logs[i][1] = ansi_up.ansi_to_html(res.data.result[0].values[i][1])
      }
    } else if (res.data.result.length > 1) {
      // 清空
      this.logs = []
      for (const j in res.data.result) { // 用push的方式將所有日志數(shù)組添加進去
        for (const values_index in res.data.result[j].values) {
          this.logs.push(res.data.result[j].values[values_index])
        }
      }
      for (const k in this.logs) {
        this.logs[k][1] = ansi_up.ansi_to_html(this.logs[k][1])
      }
      if (this.direction === 'backward') { // 由于使用公共標簽會導(dǎo)致時間順序錯亂,因此對二維數(shù)組進行排序
        this.logs.sort((a, b) => b[0] - a[0])
      } else {
        this.logs.sort((a, b) => a[0] - b[0])
      }
    } else {
      this.showEmpty = true
      this.emptyText = '暫無日志信息,請選擇時間段試試'
    }
  })
},

通過AnsiUp插件可以將帶有顏色標簽的日志以顏色展示,代碼如下:

<div style="margin: 3px; min-height: 80vh;">
  <!--數(shù)據(jù)判空-->
  <el-empty v-if="showEmpty" :description="emptyText" />
  <!--數(shù)據(jù)加載-->
  <el-card v-else shadow="hover" style="width: 100%" class="log-warpper">
    <div style="width: 100%">
      <div v-for="(log, index) in logs" :key="index">
        <div style="margin-bottom: 5px; font-size: 12px;" v-html="log[1]" />
      </div>
    </div>
  </el-card>
</div>

向后端請求日志返回的結(jié)果是如下圖所示

滾動追加日志

其實下拉滾動的代碼與上面直接獲取日志的是差不多的,只是在數(shù)據(jù)的追加是不一樣的做法,這里需要注意的是要考慮日志的展示是正序還是逆序,不同的順序計算時間范圍是不一樣的,就如下代碼

if (this.direction === 'backward') { // 設(shè)置時間區(qū)間
  queryParam.start = (this.logs[this.logs.length - 1][0] - zone).toString()
  queryParam.end = this.logs[this.logs.length - 1][0]
} else {
  queryParam.start = this.logs[this.logs.length - 1][0]
  queryParam.end = (parseFloat(this.logs[this.logs.length - 1][0]) + parseFloat(zone.toString())).toString()
}

在滾動獲取日志的思路是獲取最后一條數(shù)據(jù)的時間,往后推一定的時間差,所以需要考慮是正序還是倒序,默認是6小時。

mounted() {
  window.addEventListener('scroll', this.handleScroll)
}
methods: {
    handleScroll() { // 滾動事件
      const scrollTop = document.documentElement.scrollTop// 滾動高度
      const clientHeight = document.documentElement.clientHeight// 可視高度
      const scrollHeight = document.documentElement.scrollHeight// 內(nèi)容高度
      const bottomest = Math.ceil(scrollTop + clientHeight)
      if (bottomest >= scrollHeight) {
        // 加載新數(shù)據(jù)
        queryParam.limits = this.scrollStep
        queryParam.direction = this.direction
        // 獲取時間差
        let zone = queryParam.end - queryParam.start
        if (this.timeRange.length) { // 如果是輸入時間范圍
          zone = ((new Date(this.timeRange[1]).getTime() - new Date(this.timeRange[0]).getTime()) * 1000000).toString()
        }
        if (this.timeZoneValue) {
          zone = this.timeZoneValue * 1000000
        }
        if (zone === 0) {
          zone = 3600 * 1000 * 6
        }
        if (this.direction === 'backward') { // 設(shè)置時間區(qū)間
          queryParam.start = (this.logs[this.logs.length - 1][0] - zone).toString()
          queryParam.end = this.logs[this.logs.length - 1][0]
        } else {
          queryParam.start = this.logs[this.logs.length - 1][0]
          queryParam.end = (parseFloat(this.logs[this.logs.length - 1][0]) + parseFloat(zone.toString())).toString()
        }
        var ansi_up = new AnsiUp()
        logOperation.getLogData(queryParam).then(res => {
          console.log(res)
          this.showEmpty = false
          if (res.data.result.length === 1) {
            // 如果返回的日志是一樣的就不顯示
            if (res.data.result[0].values.length === 1 && ansi_up.ansi_to_html(res.data.result[0].values[0][1]) === this.logs[this.logs.length - 1][1]) {
              this.$notify({
                title: '警告',
                duration: 1000,
                message: '當前時間段日志已最新!',
                type: 'warning'
              })
              return
            }
            const log = res.data.result[0].values
            for (const i in res.data.result[0].values) {
              log[i][1] = ansi_up.ansi_to_html(res.data.result[0].values[i][1])
              this.logs.push(log[i])
            }
          } else if (res.data.result.length > 1) {
            const tempArray = [] // 數(shù)據(jù)需要處理,由于是追加數(shù)組,所以需要用額外變量來存放
            // 刷新就是添加,不清空原數(shù)組
            for (const j in res.data.result) { // 用push的方式將所有日志數(shù)組添加進去
              for (const values_index in res.data.result[j].values) {
                tempArray.push(res.data.result[j].values[values_index])
              }
            }
            if (this.direction === 'backward') { // 由于使用公共標簽會導(dǎo)致時間順序錯亂,因此對二維數(shù)組進行排序
              tempArray.sort((a, b) => b[0] - a[0])
            } else {
              tempArray.sort((a, b) => a[0] - b[0])
            }
            for (const k in tempArray) {
              tempArray[k][1] = ansi_up.ansi_to_html(tempArray[k][1]) // 數(shù)據(jù)轉(zhuǎn)換
              this.logs.push(tempArray[k]) // 追加數(shù)據(jù)
            }
          } else {
            this.$notify({
              title: '警告',
              duration: 1000,
              message: '暫無以往日志數(shù)據(jù)!',
              type: 'warning'
            })
          }
        })
      }
    }
}

定時刷新日志

當然,日志的獲取也是需要實時刷新的,這種不僅可以使用定時器還能夠使用websocket,筆者使用的是定時器,因為這個寫起來比較簡單。相關(guān)的代碼以及解析如下: 視圖

<el-form-item>
  <el-dropdown split-button type="primary" size="mini" @click="queryData">
    查詢{{ runStatu }}
    <el-dropdown-menu slot="dropdown">
      <el-dropdown-item v-for="(item, index) in runStatuOptions" :key="index" @click.native="startInterval(item)">{{ item.label }}</el-dropdown-item>
    </el-dropdown-menu>
  </el-dropdown>
</el-form-item>

方法代碼 代碼大致也和上面兩種情況是類似的,思路是獲取當前時間前(時間差)的時間到當前時間的日志信息。這里不需要管日志的時序方向,只需要做好始終時間,注意納秒級別,還有定時器不要忘記銷毀。

startInterval(item) {
  this.runStatu = item.label
  console.log(item.value)
  if (item.value !== 0) {
    this.timer = setInterval(() => { // 定時刷新
      this.intervalLogs()
    }, item.value)
  } else {
    console.log('銷毀了')
    clearInterval(this.timer)
  }
},
intervalLogs() { // 定時器的方法
  // 組織參數(shù)
  // 設(shè)置開始時間和結(jié)束時間
  // 開始為現(xiàn)在時間
  const start = new Date()
  const end = new Date()
  // 時差判斷
  let zone = queryParam.end - queryParam.start
  if (this.timeRange.length) { // 如果是輸入時間范圍
    zone = ((new Date(this.timeRange[1]).getTime() - new Date(this.timeRange[0]).getTime()) * 1000000).toString()
  }
  if (this.timeZoneValue) {
    zone = this.timeZoneValue * 1000000
  }
  if (zone === 0) { // 防止空指針
    start.setTime(start.getTime() - 3600 * 1000 * 6)
    queryParam.start = (start.getTime() * 1000000).toString()
  } else {
    queryParam.start = (start.getTime() * 1000000 - zone).toString()
  }
  queryParam.end = (end.getTime() * 1000000).toString()
  queryParam.limits = this.limits
  console.log('定時器最后參數(shù):', queryParam)
  var ansi_up = new AnsiUp() // 后端日志格式轉(zhuǎn)化
  logOperation.getLogData(queryParam).then(res => {
    console.log('res', res)
    this.showEmpty = false
    debugger
    if (res.data.result.length === 1) {
      this.logs = res.data.result[0].values
      for (const i in res.data.result[0].values) { // 格式轉(zhuǎn)換
        this.logs[i][1] = ansi_up.ansi_to_html(res.data.result[0].values[i][1])
      }
    } else if (res.data.result.length > 1) {
      // 清空
      this.logs = []
      for (const j in res.data.result) { // 用push的方式將所有日志數(shù)組添加進去
        for (const values_index in res.data.result[j].values) {
          this.logs.push(res.data.result[j].values[values_index])
        }
      }
      for (const k in this.logs) {
        this.logs[k][1] = ansi_up.ansi_to_html(this.logs[k][1])
      }
      if (this.direction === 'backward') { // 由于使用公共標簽會導(dǎo)致時間順序錯亂,因此對二維數(shù)組進行排序
        this.logs.sort((a, b) => b[0] - a[0])
      } else {
        this.logs.sort((a, b) => a[0] - b[0])
      }
    } else {
      this.showEmpty = true
      this.emptyText = '暫無日志信息,請選擇時間段試試'
    }
  })
},

最后粘一小段展示的界面

總結(jié)

loki是輕量級的分布式日志查詢框架,特別適合中小型企業(yè),尤其是工業(yè)項目,在項目上線的時候可以通過這樣的一個界面來觀察日志,確實能夠得到很大的幫助,但是這個loki不是特別的穩(wěn)定,最為常見的是會出現(xiàn)ERP ERROR,這種錯誤是最頭疼的,個人感覺可能是計算機或者網(wǎng)絡(luò)的因素造成。

以上就是SpringBoot Loki安裝簡介及實戰(zhàn)思路的詳細內(nèi)容,更多關(guān)于SpringBoot Loki安裝的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • RocketMQ4.5.2 修改mqnamesrv 和 mqbroker的日志路徑操作

    RocketMQ4.5.2 修改mqnamesrv 和 mqbroker的日志路徑操作

    這篇文章主要介紹了RocketMQ 4.5.2 修改mqnamesrv 和 mqbroker的日志路徑操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • java基礎(chǔ)學(xué)習(xí)筆記之泛型

    java基礎(chǔ)學(xué)習(xí)筆記之泛型

    所謂泛型,就是變量類型的參數(shù)化。泛型是JDK1.5中一個最重要的特征。通過引入泛型,我們將獲得編譯時類型的安全和運行時更小的拋出ClassCastException的可能。在JDK1.5中,你可以聲明一個集合將接收/返回的對象的類型。
    2016-02-02
  • java學(xué)習(xí)教程之常量折疊詳解

    java學(xué)習(xí)教程之常量折疊詳解

    這篇文章主要給大家介紹了關(guān)于java學(xué)習(xí)教程之常量折疊的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-09-09
  • Java獲取堆棧信息的三種方法小結(jié)

    Java獲取堆棧信息的三種方法小結(jié)

    在Java編程中,獲取堆棧信息對于調(diào)試和故障排除非常重要,Java提供了多種方式來獲取當前線程的堆棧信息,下面就跟隨小編一起學(xué)習(xí)一下常用的三種吧
    2024-03-03
  • Java實現(xiàn)每日給女友微信發(fā)送早安信息

    Java實現(xiàn)每日給女友微信發(fā)送早安信息

    這篇文章主要為大家詳細介紹了Java如何實現(xiàn)每日給女友微信發(fā)送早安等微信信息,文中的示例代碼講解詳細,具有一定的借鑒價值,需要的可以了解一下
    2022-12-12
  • Java中使用BigDecimal進行精確運算

    Java中使用BigDecimal進行精確運算

    這篇文章主要介紹了Java中使用BigDecimal進行精確運算的方法,非常不錯,需要的朋友參考下
    2017-02-02
  • redis實現(xiàn)隊列的阻塞、延時、發(fā)布和訂閱

    redis實現(xiàn)隊列的阻塞、延時、發(fā)布和訂閱

    本文主要介紹了redis實現(xiàn)隊列的阻塞、延時、發(fā)布和訂閱,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • Spring boot熱部署devtools過程解析

    Spring boot熱部署devtools過程解析

    這篇文章主要介紹了Spring boot熱部署devtools過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • org.apache.zookeeper.KeeperException.BadVersionException異常的解決

    org.apache.zookeeper.KeeperException.BadVersionException異常的解

    在使用Apache ZooKeeper進行分布式協(xié)調(diào)時,你可能會遇到org.apache.zookeeper.KeeperException.BadVersionException異常,本文就來介紹一下解決方法,感興趣的可以了解一下
    2024-03-03
  • SpringCloud Zuul在何種情況下使用Hystrix及問題小結(jié)

    SpringCloud Zuul在何種情況下使用Hystrix及問題小結(jié)

    這篇文章主要介紹了SpringCloud Zuul在何種情況下使用Hystrix 及問題小結(jié),感興趣的朋友跟隨小編一起看看吧
    2018-11-11

最新評論