በ Kapacitor ውስጥ መለኪያዎችን ለመቆጣጠር ዘዴዎች

ምናልባትም ዛሬ ማንም ሰው የአገልግሎት መለኪያዎችን መሰብሰብ ለምን እንደሚያስፈልግ አይጠይቅም. ቀጣዩ አመክንዮአዊ እርምጃ ለተሰበሰቡት መለኪያዎች ማንቂያ ማዘጋጀት ነው, ይህም ለእርስዎ በሚመች ቻናል ውስጥ ስላለው ማንኛውም ልዩነት (ሜል, ስላክ, ቴሌግራም) ያሳውቃል. በኦንላይን የሆቴል ቦታ ማስያዝ አገልግሎት ውስጥ Ostrovok.ru ሁሉም የአገልግሎታችን መለኪያዎች በ InfluxDB ውስጥ ይፈስሳሉ እና በግራፋና ውስጥ ይታያሉ፣ እና መሰረታዊ ማንቂያ እዚያም ተዋቅሯል። እንደ "አንድ ነገር ማስላት እና ከእሱ ጋር ማወዳደር ያስፈልግዎታል" ለመሳሰሉት ስራዎች Kapacitor እንጠቀማለን.

በ Kapacitor ውስጥ መለኪያዎችን ለመቆጣጠር ዘዴዎች
ካፓሲተር ከInfluxDB መለኪያዎችን ማካሄድ የሚችል የTICK ቁልል አካል ነው። ብዙ መለኪያዎችን በአንድ ላይ ማገናኘት ይችላል (መቀላቀል) ፣ ከተቀበለው መረጃ ጠቃሚ ነገር ያሰላል ፣ ውጤቱን ወደ InfluxDB መልሰው ይፃፉ ፣ ለ Slack/Telegram/mail ማንቂያ ይልካል።

ጠቅላላው ቁልል አሪፍ እና ዝርዝር ነው። ሰነዶች, ነገር ግን ሁልጊዜ በመመሪያው ውስጥ በግልጽ ያልተገለጹ ጠቃሚ ነገሮች ይኖራሉ. በዚህ ጽሑፍ ውስጥ ብዙ እንደዚህ ያሉ ጠቃሚ ፣ ግልጽ ያልሆኑ ምክሮችን ለመሰብሰብ ወሰንኩ (የTICKscipt መሠረታዊ አገባብ ተብራርቷል) እዚህ) እና ከችግሮቻችን ውስጥ አንዱን የመፍታት ምሳሌ በመጠቀም እንዴት እንደሚተገበሩ አሳይ.

እንሂድ!

ተንሳፋፊ እና int፣ የስሌት ስህተቶች

ፍጹም ደረጃውን የጠበቀ ችግር፣ በ castes የሚፈታ፡-

var alert_float = 5.0
var alert_int = 10
data|eval(lambda: float("value") > alert_float OR float("value") < float("alert_int"))

ነባሪ () በመጠቀም

መለያ/መስክ ካልተሞላ፣ የስሌት ስህተቶች ይከሰታሉ፡-

|default()
        .tag('status', 'empty')
        .field('value', 0)

መቀላቀልን ሙላ (ውስጣዊ እና ውጫዊ)

በነባሪ፣ መቀላቀል ምንም ውሂብ የሌለበትን ነጥቦች ያስወግዳል (ውስጣዊ)።
በመሙላት('null')፣ የውጪ መቀላቀል ይከናወናል፣ከዚያ በኋላ ነባሪ() ማድረግ እና ባዶ እሴቶቹን መሙላት ያስፈልግዎታል፡-

var data = res1
    |join(res2)
        .as('res1', 'res2)
        .fill('null')
    |default()
        .field('res1.value', 0.0)
        .field('res2.value', 100.0)

እዚህ አሁንም አንድ ልዩነት አለ. ከላይ ባለው ምሳሌ፣ ከተከታታይ አንዱ (res1 ወይም res2) ባዶ ከሆነ፣ የተገኘው ተከታታይ (ዳታ) እንዲሁ ባዶ ይሆናል። በዚህ ርዕስ ላይ በ Github ላይ በርካታ ቲኬቶች አሉ (1633, 1871, 6967) - ጥገናዎችን እየጠበቅን እና ትንሽ እንሰቃያለን.

በስሌቶች ውስጥ ሁኔታዎችን መጠቀም (lambda ውስጥ ከሆነ)

|eval(lambda: if("value" > 0, true, false)

ለጊዜው ከቧንቧው አምስት ደቂቃዎች ይቆዩ

ለምሳሌ፣ ያለፉትን አምስት ደቂቃዎች እሴቶች ካለፈው ሳምንት ጋር ማወዳደር ያስፈልግዎታል። በሁለት የተለያዩ ክፍሎች ውስጥ ሁለት የውሂብ ስብስቦችን መውሰድ ወይም የመረጃውን የተወሰነ ክፍል ከትልቅ ጊዜ ማውጣት ይችላሉ፡

 |where(lambda: duration((unixNano(now()) - unixNano("time"))/1000, 1u) < 5m)

ላለፉት አምስት ደቂቃዎች ያለው አማራጭ ከተጠቀሰው ጊዜ በፊት ውሂብን የሚቆርጥ BarrierNodeን መጠቀም ነው።

|barrier()
        .period(5m)

በመልእክት ውስጥ የ Go አብነቶችን የመጠቀም ምሳሌዎች

አብነቶች ከጥቅሉ ቅርጸት ጋር ይዛመዳሉ ጽሑፍ.አብነትከዚህ በታች በተደጋጋሚ የሚያጋጥሙ አንዳንድ እንቆቅልሾች አሉ።

ከሆነ-

ነገሮችን በቅደም ተከተል እናስቀምጣለን እና ሰዎችን በድጋሚ በጽሁፍ አናነሳም፡-

|alert()
    ...
    .message(
        '{{ if eq .Level "OK" }}It is ok now{{ else }}Chief, everything is broken{{end}}'
    )

በመልእክት ውስጥ ካለው የአስርዮሽ ነጥብ በኋላ ሁለት አሃዞች

የመልእክቱን ተነባቢነት ማሻሻል፡-

|alert()
    ...
    .message(
        'now value is {{ index .Fields "value" | printf "%0.2f" }}'
    )

በመልእክት ውስጥ ተለዋዋጮችን ማስፋፋት።

"ለምን ይጮኻል" የሚለውን ጥያቄ ለመመለስ በመልእክቱ ውስጥ ተጨማሪ መረጃ እናሳያለን።

var warnAlert = 10
  |alert()
    ...
    .message(
       'Today value less then '+string(warnAlert)+'%'
    )

ልዩ ማንቂያ ለዪ

በመረጃው ውስጥ ከአንድ በላይ ቡድን ሲኖር ይህ አስፈላጊ ነገር ነው ፣ አለበለዚያ አንድ ማንቂያ ብቻ ይነሳል

|alert()
      ...
      .id('{{ index .Tags "myname" }}/{{ index .Tags "myfield" }}')

ብጁ ተቆጣጣሪዎች

ትልቁ የተቆጣጣሪዎች ዝርዝር execን ያጠቃልላል ፣ ይህም ስክሪፕትዎን ካለፉ መለኪያዎች (stdin) ጋር እንዲፈጽሙ ያስችልዎታል - ፈጠራ እና ምንም ተጨማሪ!

ከጉምሩክ ልማዳችን አንዱ ለደካማ ማሳወቂያዎችን ለመላክ ትንሽ የፓይዘን ስክሪፕት ነው።
መጀመሪያ ላይ በመልእክት ውስጥ በፍቃድ የተጠበቀ የግራፋና ሥዕል መላክ እንፈልጋለን። ከዚያ በኋላ፣ ከተመሳሳይ ቡድን ወደ ቀድሞው ማንቂያ በክር ውስጥ እሺን ይፃፉ እንጂ እንደ የተለየ መልእክት አይደለም። ትንሽ ቆይቶ - በመጨረሻዎቹ X ደቂቃዎች ውስጥ በጣም የተለመደው ስህተት ወደ መልእክቱ ጨምር.

የተለየ ርዕስ ከሌሎች አገልግሎቶች ጋር መገናኘት እና በማንቂያ የተጀመሩ ማንኛቸውም እርምጃዎች (ክትትልዎ በበቂ ሁኔታ የሚሰራ ከሆነ ብቻ) ነው።
slack_handler.py በራሳችን የተጻፈ ስክሪፕት የሆነበት የተቆጣጣሪ መግለጫ ምሳሌ፡-

topic: slack_graph
id: slack_graph.alert
match: level() != INFO AND changed() == TRUE
kind: exec
options:
  prog: /sbin/slack_handler.py
  args: ["-c", "CHANNELID", "--graph", "--search"]

እንዴት ማረም ይቻላል?

የምዝግብ ማስታወሻ ውፅዓት ያለው አማራጭ

|log()
      .level("error")
      .prefix("something")

ይመልከቱ (cli): kapacitor -url አስተናጋጅ-ወይም-አይ.ፒ:9092 መዝገቦች lvl=ስህተት

አማራጭ ከ httpOut ጋር

አሁን ባለው የቧንቧ መስመር ላይ ያለውን መረጃ ያሳያል፡-

|httpOut('something')

ይመልከቱ (አግኝ) አስተናጋጅ-ወይም-አይ.ፒ: 9092 / kapacitor / v1 / ተግባራት / የተግባር_ስም / የሆነ ነገር

የማስፈጸሚያ ንድፍ

  • እያንዳንዱ ተግባር በቅርጸቱ ውስጥ ጠቃሚ ቁጥሮች ያለው የማስፈጸሚያ ዛፍ ይመልሳል ግራፍቪዝ.
  • ብሎክ ይውሰዱ ነጥብ.
  • ወደ ተመልካች ይለጥፉት፣ ተደሰት.

ሌላ ከየት ማግኘት ይችላሉ?

timestamp influxdb በጽሑፍ መልሶ መፃፍ ላይ

ለምሳሌ፣ በሰዓት ለሚቀርቡ ጥያቄዎች ድምር ማንቂያ አዘጋጅተናል (ቡድን በ(1ሰ)) እና በ influxdb ውስጥ የተከሰተውን ማንቂያ መቅዳት እንፈልጋለን (በግራፋና ግራፍ ላይ ያለውን የችግሩን እውነታ በሚያምር ሁኔታ ለማሳየት)።

influxDBOut() የሰዓት እሴቱን ከማንቂያው እስከ የጊዜ ማህተም ይጽፋል፤ በዚህ መሰረት፣ በገበታው ላይ ያለው ነጥብ ማስጠንቀቂያው ከደረሰው ቀደም ብሎ/በኋላ ይፃፋል።

ትክክለኛነት በሚያስፈልግበት ጊዜ፡ በዚህ ችግር ዙሪያ ወደ ብጁ ተቆጣጣሪ በመደወል እንሰራለን፣ ይህም አሁን ካለው የጊዜ ማህተም ጋር መረጃን ወደ ፍሰት ይጽፋል።

docker, መገንባት እና ማሰማራት

በሚነሳበት ጊዜ kapacitor በ [ሎድ] ብሎክ ውስጥ ባለው ውቅረት ውስጥ ከተጠቀሰው ማውጫ ውስጥ ተግባሮችን ፣ አብነቶችን እና ተቆጣጣሪዎችን መጫን ይችላል።

አንድን ተግባር በትክክል ለመፍጠር የሚከተሉትን ነገሮች ያስፈልግዎታል

  1. የፋይል ስም - ወደ ስክሪፕት መታወቂያ/ስም ተዘርግቷል።
  2. አይነት - ዥረት / ባች
  3. dbrp - ስክሪፕቱ በየትኛው የውሂብ ጎታ + ፖሊሲ ውስጥ እንደሚሠራ ለማመልከት ቁልፍ ቃል (dbrp “አቅራቢ” “autogen”)

አንዳንድ የቡድን ተግባር ከ dbrp ጋር መስመር ከሌለው አገልግሎቱ ለመጀመር ፈቃደኛ አይሆንም እና በቅንነት ምዝግብ ማስታወሻ ውስጥ ይጽፋል።

በ chronograf ውስጥ ፣ በተቃራኒው ፣ ይህ መስመር መኖር የለበትም ፣ በይነገጽ ተቀባይነት የለውም እና ስህተት ይፈጥራል።

ኮንቴይነሩን በሚገነቡበት ጊዜ Hack: Dockerfile በ //.+dbrp መስመሮች ካሉ ከ -1 ጋር ይወጣል, ይህም ግንባታውን በሚገጣጠሙበት ጊዜ የውድቀቱን ምክንያት ወዲያውኑ እንዲረዱ ያስችልዎታል.

አንዱን ለብዙዎች መቀላቀል

ምሳሌ ተግባር፡ የአገልግሎቱን የስራ ጊዜ 95ኛ ፐርሰንታይል ለአንድ ሳምንት መውሰድ አለብህ፣ ያለፉት 10 ደቂቃዎች እያንዳንዱን ደቂቃ ከዚህ እሴት ጋር አወዳድር።

ከአንድ እስከ ብዙ መቀላቀል፣ የመጨረሻ/አማካይ/ሚዲያን በቡድን ነጥቦች ላይ ማድረግ አይችሉም፣ መስቀለኛ መንገድን ወደ ዥረት ይቀይረዋል፣ ስህተቱ "የልጆች ያልተዛመዱ ጠርዞችን ማከል አይቻልም፡ ባች -> ዥረት" ይመለሳል።

በላምዳ አገላለጽ ውስጥ እንደ ተለዋዋጭ የቡድን ውጤት እንዲሁ አልተተካም.

አስፈላጊዎቹን ቁጥሮች ከመጀመሪያው ባች ወደ ፋይል በ udf በኩል ለማስቀመጥ እና ይህንን ፋይል በጎን ጭነት ለመጫን አማራጭ አለ.

በዚህ ምን ፈታን?

ወደ 100 የሚጠጉ የሆቴል አቅራቢዎች አሉን ፣ እያንዳንዳቸው ብዙ ግንኙነት ሊኖራቸው ይችላል ፣ ቻናል እንበለው ። ከእነዚህ ውስጥ 300 የሚያህሉ ቻናሎች አሉ፣ እያንዳንዱ ቻናሎች ሊወድቁ ይችላሉ። ከተመዘገቡት መለኪያዎች ሁሉ የስህተት መጠኑን (ጥያቄዎችን እና ስህተቶችን) እንቆጣጠራለን።

ለምን ግራፋና አይሆንም?

በግራፋና ውስጥ የተዋቀሩ የስህተት ማንቂያዎች ብዙ ጉዳቶች አሏቸው። አንዳንዶቹ ወሳኝ ናቸው, አንዳንዶቹ እንደ ሁኔታው ​​ዓይኖችዎን መዝጋት ይችላሉ.

Grafana በመለኪያዎች + ማንቂያዎች መካከል እንዴት እንደሚሰላ አያውቅም ነገር ግን ተመን (ጥያቄዎች-ስህተት)/ጥያቄዎች እንፈልጋለን።

ስህተቶቹ አስቀያሚ ይመስላሉ-

በ Kapacitor ውስጥ መለኪያዎችን ለመቆጣጠር ዘዴዎች

እና ከተሳካላቸው ጥያቄዎች ጋር ሲታይ ያነሰ ክፋት፡-

በ Kapacitor ውስጥ መለኪያዎችን ለመቆጣጠር ዘዴዎች

እሺ፣ ከግራፋና በፊት በአገልግሎቱ ውስጥ ያለውን ዋጋ አስቀድመን ማስላት እንችላለን፣ እና በአንዳንድ ሁኔታዎች ይሄ ይሰራል። ግን በእኛ ውስጥ አይደለም, ምክንያቱም ... ለእያንዳንዱ ቻናል የራሱ ሬሾ እንደ “መደበኛ” ይቆጠራል ፣ እና ማንቂያዎች በስታቲስቲክስ እሴቶች መሠረት ይሰራሉ ​​(በአይኖቻችን እንፈልጋቸዋለን ፣ ተደጋጋሚ ማንቂያዎች ካሉ እንለውጣቸዋለን)።

እነዚህ ለተለያዩ ቻናሎች የ"መደበኛ" ምሳሌዎች ናቸው፡

በ Kapacitor ውስጥ መለኪያዎችን ለመቆጣጠር ዘዴዎች

በ Kapacitor ውስጥ መለኪያዎችን ለመቆጣጠር ዘዴዎች

የቀደመውን ነጥብ ችላ ብለን "የተለመደው" ምስል ለሁሉም አቅራቢዎች ተመሳሳይ ነው ብለን እንገምታለን. አሁን ሁሉም ነገር ደህና ነው፣ እና በግራፋና ውስጥ ባሉ ማንቂያዎች ማግኘት እንችላለን?
እንችላለን፣ ግን በእርግጥ አንፈልግም፣ ምክንያቱም ከአማራጮች ውስጥ አንዱን መምረጥ አለብን፡-
ሀ) ለእያንዳንዱ ቻናል ብዙ ግራፎችን ለየብቻ ይስሩ (እና በሚያሳምም ያጅቧቸው)
ለ) ከሁሉም ቻናሎች ጋር አንድ ገበታ ይተው (እና በቀለማት ያሸበረቁ መስመሮች እና ብጁ ማንቂያዎች ውስጥ ይጠፉ)

በ Kapacitor ውስጥ መለኪያዎችን ለመቆጣጠር ዘዴዎች

እንዴት አደረጋችሁት?

እንደገና፣ በሰነዱ ውስጥ ጥሩ መነሻ ምሳሌ አለ (በተቀላቀሉት ተከታታዮች ላይ ተመኖችን በማስላት ላይ), በተመሳሳይ ችግሮች ውስጥ ማየት ወይም እንደ መነሻ ሊወሰድ ይችላል.

በመጨረሻ ያደረግነው፡-

  • በጥቂት ሰዓታት ውስጥ ሁለት ተከታታዮችን መቀላቀል, በሰርጦች መቧደን;
  • ምንም ውሂብ ከሌለ ተከታታዩን በቡድን ይሙሉ;
  • ያለፉትን 10 ደቂቃዎች አማካይ ከቀዳሚው መረጃ ጋር ማወዳደር;
  • የሆነ ነገር ካገኘን እንጮሃለን;
  • በ influxdb ውስጥ የተከሰቱትን የተቆጠሩ ተመኖች እና ማንቂያዎችን እንጽፋለን;
  • ለደካማ ጠቃሚ መልእክት ይላኩ።

በእኔ አስተያየት መጨረሻ ላይ ማግኘት የምንፈልገውን ሁሉ (እና እንዲያውም ትንሽ ተጨማሪ በብጁ ተቆጣጣሪዎች) በተቻለ መጠን በሚያምር ሁኔታ ማሳካት ችለናል።

github.com ላይ ማየት ትችላለህ ኮድ ምሳሌ и አነስተኛ ወረዳ (ግራፍቪዝ) የተገኘው ስክሪፕት.

የውጤቱ ኮድ ምሳሌ፡-

dbrp "supplier"."autogen"
var name = 'requests.rate'
var grafana_dash = 'pczpmYZWU/mydashboard'
var grafana_panel = '26'
var period = 8h
var todayPeriod = 10m
var every = 1m
var warnAlert = 15
var warnReset = 5
var reqQuery = 'SELECT sum("count") AS value FROM "supplier"."autogen"."requests"'
var errQuery = 'SELECT sum("count") AS value FROM "supplier"."autogen"."errors"'

var prevErr = batch
    |query(errQuery)
        .period(period)
        .every(every)
        .groupBy(1m, 'channel', 'supplier')

var prevReq = batch
    |query(reqQuery)
        .period(period)
        .every(every)
        .groupBy(1m, 'channel', 'supplier')

var rates = prevReq
    |join(prevErr)
        .as('req', 'err')
        .tolerance(1m)
        .fill('null')
    // заполняем значения нулями, если их не было
    |default()
        .field('err.value', 0.0)
        .field('req.value', 0.0)
    // if в lambda: считаем рейт, только если ошибки были
    |eval(lambda: if("err.value" > 0, 100.0 * (float("req.value") - float("err.value")) / float("req.value"), 100.0))
        .as('rate')

// записываем посчитанные значения в инфлюкс
rates
    |influxDBOut()
        .quiet()
        .create()
        .database('kapacitor')
        .retentionPolicy('autogen')
        .measurement('rates')

// выбираем данные за последние 10 минут, считаем медиану
var todayRate = rates
    |where(lambda: duration((unixNano(now()) - unixNano("time")) / 1000, 1u) < todayPeriod)
    |median('rate')
        .as('median')

var prevRate = rates
    |median('rate')
        .as('median')

var joined = todayRate
    |join(prevRate)
        .as('today', 'prev')
    |httpOut('join')

var trigger = joined
    |alert()
        .warn(lambda: ("prev.median" - "today.median") > warnAlert)
        .warnReset(lambda: ("prev.median" - "today.median") < warnReset)
        .flapping(0.25, 0.5)
        .stateChangesOnly()
        // собираем в message ссылку на график дашборда графаны
        .message(
            '{{ .Level }}: {{ index .Tags "channel" }} err/req ratio ({{ index .Tags "supplier" }})
{{ if eq .Level "OK" }}It is ok now{{ else }}
'+string(todayPeriod)+' median is {{ index .Fields "today.median" | printf "%0.2f" }}%, by previous '+string(period)+' is {{ index .Fields "prev.median" | printf "%0.2f" }}%{{ end }}
http://grafana.ostrovok.in/d/'+string(grafana_dash)+
'?var-supplier={{ index .Tags "supplier" }}&var-channel={{ index .Tags "channel" }}&panelId='+string(grafana_panel)+'&fullscreen&tz=UTC%2B03%3A00'
        )
        .id('{{ index .Tags "name" }}/{{ index .Tags "channel" }}')
        .levelTag('level')
        .messageField('message')
        .durationField('duration')
        .topic('slack_graph')

// "today.median" дублируем как "value", также пишем в инфлюкс остальные филды алерта (keep)
trigger
    |eval(lambda: "today.median")
        .as('value')
        .keep()
    |influxDBOut()
        .quiet()
        .create()
        .database('kapacitor')
        .retentionPolicy('autogen')
        .measurement('alerts')
        .tag('alertName', name)

መደምደሚያው ምንድን ነው?

ካፓሲተር ከብዙ ቡድን ስብስብ ጋር የክትትል-ማንቂያዎችን በማከናወን፣ ቀደም ሲል በተመዘገቡ መለኪያዎች ላይ በመመስረት ተጨማሪ ስሌቶችን በመፈጸም፣ ብጁ ድርጊቶችን እና ስክሪፕቶችን (udf) በማስኬድ ረገድ ጥሩ ነው።

የመግባት እንቅፋት በጣም ከፍተኛ አይደለም - ግራፋና ወይም ሌሎች መሳሪያዎች ፍላጎቶችዎን ሙሉ በሙሉ ካላሟሉ ይሞክሩት።

ምንጭ: hab.com

አስተያየት ያክሉ