123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- package service
- import (
- "context"
- "fmt"
- "go-admin/app/observe/models"
- "go-admin/utils"
- "time"
- "github.com/pkg/errors"
- )
- type AppAnalyst struct {
- utils.OtService
- }
- func (e *AppAnalyst) GetAppLatencyListByInterval(ctx context.Context, p *models.AppInterval, l *models.AppLatencyByInterval) error {
- // timestamp 秒级单位
- /*
- 计算90分位值
- WITH durations AS (
- SELECT quantile(0.98)(Duration) AS Duration_90th_percentile
- FROM otel_traces_duration_ts otdt
- )
- */
- sql := `WITH durations AS (
- SELECT quantile(?)(Duration) AS Duration_90th_percentile
- FROM otel_traces
- WHERE
- toTimeZone(Timestamp,'Asia/Hong_Kong') >= ? and toTimeZone(Timestamp,'Asia/Hong_Kong') < ? and AppAlias = ?
- )
- Select
- toTimeZone(Timestamp,'Asia/Hong_Kong') as ts,
- round(Duration/1e6, 2) AS Dms,
- if(SpanAttributes['http.status_code']>0, SpanAttributes['http.status_code'], if(SpanAttributes['http.response.status_code']>0, SpanAttributes['http.response.status_code'], 0)) as HttpCode
- FROM otel_traces
- WHERE
- toTimeZone(Timestamp,'Asia/Hong_Kong') >= ? and toTimeZone(Timestamp,'Asia/Hong_Kong') < ? and AppAlias = ? %s AND (ParentSpanId = '') and Duration >= (SELECT Duration_90th_percentile FROM durations)
- ORDER BY Timestamp ASC;`
- if p.ServiceName != "" {
- sql = fmt.Sprintf(sql, fmt.Sprintf("AND ServiceName = '%s'", p.ServiceName))
- } else {
- sql = fmt.Sprintf(sql, " ")
- }
- rows, err := e.OlapConn.Query(ctx,
- sql,
- p.Percentile,
- time.Unix(p.StartTime, 0).Format(time.DateTime),
- time.Unix(p.EndTime, 0).Format(time.DateTime),
- p.AppAlias,
- time.Unix(p.StartTime, 0).Format(time.DateTime),
- time.Unix(p.EndTime, 0).Format(time.DateTime),
- p.AppAlias)
- if err != nil {
- e.Log.Errorf("olap error query: rows, %s", err)
- return err
- }
- var t time.Time
- var hc int32
- var d float64
- for rows.Next() {
- if err := rows.Scan(&t, &d, &hc); err != nil {
- e.Log.Errorf("olap error query: successRows, %s", err)
- return err
- }
- if hc < 400 {
- l.Success = append(l.Success, []any{t, d})
- } else {
- l.Failed = append(l.Failed, []any{t, d})
- }
- }
- rows.Close()
- return nil
- }
- // for rows.Next() {
- // err = rows.Scan(&t, &d, &e, &r)
- // if err != nil {
- // s.Log.Errorf("扫描行到变量失败:%s", err)
- // break
- // }
- // estr := "success"
- // if e {
- // estr = "error"
- // }
- // if _, ok := (*result)[r]; !ok {
- // (*result)[r] = map[string][]models.CoordinatePoint{
- // "success": {},
- // "error": {},
- // }
- // }
- // (*result)[r][estr] = append((*result)[r][estr], [2]any{t, d})
- // }
- // return
- func (e *AppAnalyst) GetServiceLatencyListByInterval(ctx context.Context, p *models.AppServiceInterval, l *models.AppLatencyByInterval) error {
- // timestamp 秒级单位
- /*
- 计算90分位值
- WITH durations AS (
- SELECT quantile(0.98)(Duration) AS Duration_90th_percentile
- FROM otel_traces_duration_ts otdt
- )
- */
- sql := `WITH durations AS (
- SELECT quantile(?)(Duration) AS Duration_90th_percentile
- FROM otel_traces
- WHERE
- Timestamp >= ?
- and Timestamp < ?
- and AppAlias = ?
- and ServiceName = ?
- )
- Select
- distinct
- toStartOfInterval(Timestamp, interval ? second, 'Asia/Hong_Kong') as Ts,
- round(Duration/1e6) AS Dms,
- if(StatusCode='STATUS_CODE_ERROR', 1, 0) AS Err
- FROM otel_traces
- WHERE
- Timestamp >= ? and Timestamp < ?
- and AppAlias = ? AND ServiceName = ?
- and Duration >= (SELECT Duration_90th_percentile FROM durations)
- order by Err desc, Duration desc
- limit 1000` // 为了查询效率,不按时间排序,按错误 和 延迟排序,取前1000条
- interval := 60
- if p.EndTime-p.StartTime <= 20*60 {
- interval = 10
- } else if p.EndTime-p.StartTime <= 60*60 {
- interval = 30
- }
- list := []struct {
- Ts string
- Dms float64
- Err bool
- }{}
- err := e.ChOrm.Raw(sql, p.Percentile, p.StartTime, p.EndTime, p.AppAlias, p.SourceService, interval, p.StartTime, p.EndTime, p.AppAlias, p.SourceService).Scan(&list).Error
- if err != nil {
- return errors.Wrap(err, "查询失败")
- }
- for _, item := range list {
- if item.Err {
- l.Failed = append(l.Failed, []any{item.Ts, item.Dms})
- } else {
- l.Success = append(l.Success, []any{item.Ts, item.Dms})
- }
- }
- return nil
- // rows, err := e.OlapConn.Query(ctx,
- // sql,
- // p.Percentile,
- // time.Unix(p.StartTime, 0).Format(time.DateTime),
- // time.Unix(p.EndTime, 0).Format(time.DateTime),
- // p.AppAlias,
- // p.SourceService,
- // time.Unix(p.StartTime, 0).Format(time.DateTime),
- // time.Unix(p.EndTime, 0).Format(time.DateTime),
- // p.AppAlias,
- // p.SourceService)
- // if err != nil {
- // e.Log.Errorf("olap error query: rows, %s", err)
- // return err
- // }
- // var t time.Time
- // var hc string
- // var d float64
- // for rows.Next() {
- // if err := rows.Scan(&t, &d, &hc); err != nil {
- // e.Log.Errorf("olap error query: successRows, %s", err)
- // return err
- // }
- // // 以下d之所以乘以10, 是因为上面的sql 除以的1e7, *10后才是毫秒; 为了缩小数据量, sql按时间和延迟进行了分组
- // if hc != "STATUS_CODE_ERROR" {
- // l.Success = append(l.Success, [2]any{t, d * 10})
- // } else {
- // l.Failed = append(l.Failed, [2]any{t, d * 10})
- // }
- // }
- // rows.Close()
- // return nil
- }
- func (e *AppAnalyst) GetEdgeLatencyListByInterval(ctx context.Context, p *models.AppServiceInterval, l *models.AppLatencyByInterval) error {
- // timestamp 秒级单位
- /*
- 计算90分位值
- WITH durations AS (
- SELECT quantile(0.98)(Duration) AS Duration_90th_percentile
- FROM otel_traces_duration_ts otdt
- )
- */
- sql := `WITH ? AS StartTime, ? AS EndTime, ? AS appAlias,
- durations AS (
- SELECT quantile(?)(Duration) AS Duration_90th_percentile
- FROM
- (
- SELECT
- TraceId,
- SpanId,
- ParentSpanId,
- ServiceName,
- Duration,
- StatusCode,
- AppAlias,
- if(SpanAttributes['http.status_code']>0, SpanAttributes['http.status_code'], if(SpanAttributes['http.response.status_code']>0, SpanAttributes['http.response.status_code'], 0)) as HttpCode
- FROM otel.otel_traces
- WHERE AppAlias=appAlias AND Timestamp > StartTime AND Timestamp < EndTime AND ServiceName = ?
- ) AS ot1
- INNER JOIN
- (
- SELECT
- SpanId,
- ServiceName
- FROM otel.otel_traces
- WHERE AppAlias=appAlias and Timestamp > StartTime AND Timestamp < EndTime AND ServiceName = ?
- ) AS ot2 ON ot2.SpanId = ot1.ParentSpanId
- )
- Select
- toTimeZone(Timestamp,'Asia/Hong_Kong') as ts,
- round(Duration/1e6, 2) AS Dms,
- if(SpanAttributes['http.status_code']>0, SpanAttributes['http.status_code'], if(SpanAttributes['http.response.status_code']>0, SpanAttributes['http.response.status_code'], 0)) as HttpCode
- FROM
- (
- SELECT
- Timestamp,
- TraceId,
- SpanId,
- ParentSpanId,
- ServiceName,
- Duration,
- StatusCode,
- AppAlias,
- if(SpanAttributes['http.status_code']>0, SpanAttributes['http.status_code'], if(SpanAttributes['http.response.status_code']>0, SpanAttributes['http.response.status_code'], 0)) as HttpCode
- FROM otel.otel_traces
- WHERE AppAlias=appAlias AND Timestamp > StartTime AND Timestamp < EndTime AND ServiceName = ?
- ) AS ot1
- INNER JOIN
- (
- SELECT
- SpanId,
- ServiceName
- FROM otel.otel_traces
- WHERE AppAlias=appAlias and Timestamp > StartTime AND Timestamp < EndTime AND ServiceName = ?
- ) AS ot2 ON ot2.SpanId = ot1.ParentSpanId
- WHERE
- Duration >= (SELECT Duration_90th_percentile FROM durations)
- ORDER BY Timestamp ASC;`
- rows, err := e.OlapConn.Query(ctx,
- sql,
- p.StartTime,
- p.EndTime,
- p.AppAlias,
- p.Percentile,
- p.TargetService,
- p.SourceService,
- p.TargetService,
- p.SourceService,
- )
- if err != nil {
- e.Log.Errorf("olap error query: rows, %s", err)
- return err
- }
- var t time.Time
- var hc int32
- var d float64
- for rows.Next() {
- if err := rows.Scan(&t, &d, &hc); err != nil {
- e.Log.Errorf("olap error query: successRows, %s", err)
- return err
- }
- if hc < 400 {
- l.Success = append(l.Success, []any{t, d})
- } else {
- l.Failed = append(l.Failed, []any{t, d})
- }
- }
- rows.Close()
- return nil
- }
|