()
| 576 | } |
| 577 | |
| 578 | func (p *OpenMetricsParser) parseComment() error { |
| 579 | var err error |
| 580 | |
| 581 | if p.ignoreExemplar { |
| 582 | for t := p.nextToken(); t != tLinebreak; t = p.nextToken() { |
| 583 | if t == tEOF { |
| 584 | return errors.New("data does not end with # EOF") |
| 585 | } |
| 586 | } |
| 587 | return nil |
| 588 | } |
| 589 | |
| 590 | // Parse the labels. |
| 591 | p.eOffsets, err = p.parseLVals(p.eOffsets, true) |
| 592 | if err != nil { |
| 593 | return err |
| 594 | } |
| 595 | p.exemplar = p.l.b[p.start:p.l.i] |
| 596 | |
| 597 | // Get the value. |
| 598 | p.exemplarVal, err = p.getFloatValue(p.nextToken(), "exemplar labels") |
| 599 | if err != nil { |
| 600 | return err |
| 601 | } |
| 602 | |
| 603 | // Read the optional timestamp. |
| 604 | p.hasExemplarTs = false |
| 605 | switch t2 := p.nextToken(); t2 { |
| 606 | case tEOF: |
| 607 | return errors.New("data does not end with # EOF") |
| 608 | case tLinebreak: |
| 609 | break |
| 610 | case tTimestamp: |
| 611 | p.hasExemplarTs = true |
| 612 | var ts float64 |
| 613 | // A float is enough to hold what we need for millisecond resolution. |
| 614 | if ts, err = parseFloat(yoloString(p.l.buf()[1:])); err != nil { |
| 615 | return fmt.Errorf("%w while parsing: %q", err, p.l.b[p.start:p.l.i]) |
| 616 | } |
| 617 | if math.IsNaN(ts) || math.IsInf(ts, 0) { |
| 618 | return fmt.Errorf("invalid exemplar timestamp %f", ts) |
| 619 | } |
| 620 | p.exemplarTs = int64(ts * 1000) |
| 621 | switch t3 := p.nextToken(); t3 { |
| 622 | case tLinebreak: |
| 623 | default: |
| 624 | return p.parseError("expected next entry after exemplar timestamp", t3) |
| 625 | } |
| 626 | default: |
| 627 | return p.parseError("expected timestamp or comment", t2) |
| 628 | } |
| 629 | return nil |
| 630 | } |
| 631 | |
| 632 | func (p *OpenMetricsParser) parseLVals(offsets []int, isExemplar bool) ([]int, error) { |
| 633 | t := p.nextToken() |
no test coverage detected