func (protoParser *ProtoParser) promSampleBy(sampleBy FrameworkStatement) (string, error) {
	if agg, hasAggregator := sampleBy.attributes[SampleAggregator]; hasAggregator {
		if agg.tokenType != LAST {
			message := "steps are used to control query jump to sample data. Only the last aggregator is allowed in sampleBy methods"
			return "", protoParser.NewProtoError(message, sampleBy.pos)
		}
	}
	if _, hasSpan := sampleBy.attributes[SampleSpan]; !hasSpan {
		message := "sampling expects a sample span as duration value (1m) as first parameter"
		return "", protoParser.NewProtoError(message, sampleBy.pos)
	}
	return sampleBy.attributes[SampleSpan].lit, nil
}
Load promQL sampleBy
package tsl
import (
	"bytes"
	"fmt"
	"strconv"
	"strings"
	"time"
)
var toPromQl = [...]string{
	MEAN:      "avg",
	ADDSERIES: "+",
	ANDL:      "and",
	ORL:       "or",
	SUBSERIES:      "-",
	MULSERIES:      "*",
	DIVSERIES:      "/",
	EQUAL:          "==",
	NOTEQUAL:       "!=",
	PERCENTILE:     "quantile",
	GREATEROREQUAL: ">=",
	GREATERTHAN:    ">",
	LESSOREQUAL:    "<=",
	LESSTHAN:       "<",
	EqualMatch:     "=",
	NotEqualMatch:  "!=",
	RegexMatch:     "=~",
	RegexNoMatch:   "!~",
	WEEKDAY:        "day_of_week",
	DAY:            "day_of_month",
	MAXWITH:        "clamp_min",
	MINWITH:        "clamp_max",
	SORTDESC:       "sort_desc",
	TOPN:           "topk",
	BOTTOMN:        "bottomk",
}
type Ql struct {
	API          string `json:"api,omitempty"`
	Token        string `json:"token,omitempty"`
	Query        string `json:"query,omitempty"`
	InstantQuery bool   `json:"instantQuery,omitempty"`
	Start        string `json:"start,omitempty"`
	End          string `json:"end,omitempty"`
	Step         string `json:"step,omitempty"`
}
func (protoParser *ProtoParser) GeneratePromQl(instruction Instruction, now time.Time) (*Ql, error) {
	promql := &Ql{}
	if instruction.hasSelect {
		return protoParser.promSelectQuery(instruction, now)
	} else if instruction.isGlobalOperator {
		gOp := instruction.globalOperator
		joiner := " " + toPromQl[gOp.operator]
		if len(gOp.ignoring) > 0 {
			labels := protoParser.getOnLabels(gOp.ignoring, IGNORING.String(), gOp.group, gOp.groupLabels)
			joiner = joiner + " " + labels
		} else if len(gOp.labels) > 0 {
			labels := protoParser.getOnLabels(gOp.labels, ON.String(), gOp.group, gOp.groupLabels)
			joiner = joiner + " " + labels
		}
		joiner = joiner + " "
		for index, gOpInstruction := range gOp.instructions {
			internalQl, err := protoParser.GeneratePromQl(*gOpInstruction, now)
			if err != nil {
				return nil, err
			}
			if index == 0 {
				promql = internalQl
			} else {
				if !(promql.Step == internalQl.Step && promql.Start == internalQl.Start && promql.End == internalQl.End) {
					message := "expects same time properties for each metrics selector of an operator at method " + gOp.operator.String()
					return nil, protoParser.NewProtoError(message, gOp.pos)
				}
				promql.Query = promql.Query + joiner + internalQl.Query
			}
		}
		if len(instruction.selectStatement.frameworks) > 0 {
			var err error
			promql.Query, promql.InstantQuery, err = protoParser.promFrameworksOp(instruction.selectStatement.frameworks, promql, true)
			if err != nil {
				return nil, err
			}
		}
	} else {
		promql.Query = ""
	}
	return promql, nil
}
func (protoParser *ProtoParser) getOnLabels(labels []string, operator string, group InternalField, groupLabels []string) string {
	var buffer bytes.Buffer
	buffer.WriteString(operator + "(")
	prefix := ""
	for _, label := range labels {
		buffer.WriteString(prefix)
		buffer.WriteString(label)
		prefix = ","
	}
	buffer.WriteString(")")
	if group.lit != "" {
		buffer.WriteString(" " + group.lit)
		if len(groupLabels) > 0 {
			buffer.WriteString("(")
			prefix := ""
			for _, label := range groupLabels {
				buffer.WriteString(prefix)
				buffer.WriteString(label)
				prefix = ","
			}
			buffer.WriteString(")")
		}
	}
	return buffer.String()
}
func (protoParser *ProtoParser) promSelectQuery(instruction Instruction, now time.Time) (*Ql, error) {
	var err error
	promql := &Ql{}
	if instruction.selectStatement.selectAll {
		message := "select all metrics not supported"
		return nil, protoParser.NewProtoError(message, instruction.selectStatement.pos)
	}
	promql.Query = instruction.selectStatement.metric
	promql.Token = instruction.connectStatement.token
	end := float64(now.UnixNano()/int64(time.Millisecond)) / 1000.0
	hour := time.Hour
	then := now.Add(-hour)
	start := float64(then.UnixNano()/int64(time.Millisecond)) / 1000.0
	promql.End = strconv.FormatFloat(end, 'f', -1, 64)
	promql.Start = strconv.FormatFloat(start, 'f', -1, 64)
	promql.Step = "30s"
	if instruction.selectStatement.hasFrom {
		promql.Start = instruction.selectStatement.from.from.lit
		if instruction.selectStatement.from.hasTo {
			promql.End = instruction.selectStatement.from.to.lit
		}
	}
	if instruction.selectStatement.hasLast {
		if instruction.selectStatement.last.isDuration {
			lastValue := instruction.selectStatement.last.last
			userDuration, err := time.ParseDuration(lastValue)
			if err != nil {
				return nil, err
			}
			then := now.Add(-userDuration)
			start := float64(then.UnixNano()/int64(time.Millisecond)) / 1000.0
			promql.Start = strconv.FormatFloat(start, 'f', -1, 64)
		} else {
			message := "last supports only duration values in select statement"
			return nil, protoParser.NewProtoError(message, instruction.selectStatement.pos)
		}
	}
	findSample := false
	if len(instruction.selectStatement.frameworks) > 0 {
		if instruction.selectStatement.frameworks[0].operator == SAMPLEBY ||
			instruction.selectStatement.frameworks[0].operator == SAMPLE {
			findSample = true
			var err error
			promql.Step, err = protoParser.promSampleBy(instruction.selectStatement.frameworks[0])
			if err != nil {
				return nil, err
			}
		}
	}
	if !findSample {
		message := "expects a default sample for each select statement"
		return nil, protoParser.NewProtoError(message, instruction.selectStatement.pos)
	}
	if len(instruction.selectStatement.where) > 0 {
		promql.Query = promql.Query + promWhereFields(promql.Query, instruction.selectStatement.where)
	}
	if len(instruction.selectStatement.frameworks) > 0 {
		promql.Query, promql.InstantQuery, err = protoParser.promFrameworksOp(instruction.selectStatement.frameworks, promql, false)
	}
	if err != nil {
		return nil, err
	}
	return promql, nil
}
func promWhereFields(query string, fields []WhereField) string {
	var buffer bytes.Buffer
	buffer.WriteString("{")
	prefix := ""
	for _, label := range fields {
		buffer.WriteString(prefix)
		newLabels := fmt.Sprintf(label.key+toPromQl[label.op]+"%q", label.value)
		buffer.WriteString(newLabels)
		prefix = ","
	}
	buffer.WriteString("}")
	return buffer.String()
}