Select Git revision
time_series.go
-
Jan Semmelink authored
Added DocumentStore() to search, which will be used in V3 to store orders in OpenSearch then do text searches on them
Jan Semmelink authoredAdded DocumentStore() to search, which will be used in V3 to store orders in OpenSearch then do text searches on them
time_series.go 13.04 KiB
package search
import (
"bytes"
"context"
"encoding/json"
"io/ioutil"
"net/http"
"reflect"
"strings"
"time"
opensearchapi "github.com/opensearch-project/opensearch-go/opensearchapi"
"gitlab.com/uafrica/go-utils/errors"
"gitlab.com/uafrica/go-utils/logger"
"gitlab.com/uafrica/go-utils/reflection"
)
const TimeFormat = "2006-01-02T15:04:05+07:00"
//embed this into your log struct
type TimeSeriesHeader struct {
StartTime time.Time `json:"@timestamp"`
EndTime time.Time `json:"@end_time"`
DurationMs int64 `json:"@duration_ms"`
}
type TimeSeries interface {
Write(StartTime time.Time, EndTime time.Time, data interface{}) error
Search(query Query, limit int64) (docs interface{}, totalCount int, err error)
}
type timeSeries struct {
w *writer
name string
dataType reflect.Type
settings Settings
mappings Mappings
jsonSettings []byte
jsonMappings []byte
createdDates map[string]bool
searchResponseBodyType reflect.Type
}
//purpose:
// create a time series to write e.g. api logs
//parameters:
// name must be the openSearch index name prefix without the date, e.g. "uafrica-v3-api-logs"
// the actual indices in openSearch will be called "<indexName>-<ccyymmdd>" e.g. "uafrica-v3-api-logs-20210102"
// tmpl must be your log data struct consisting of public fields as:
// Xxx string `json:"<name>" search:"keyword|text|long|date"` (can later add more types)
// Xxx time.Time `json:"<name>"` assumes type "date" for opensearch
// Xxx int `json:"<name>"` assumes type "long" for opensearch, specify keyword if required
func (w *writer) TimeSeries(name string, tmpl interface{}) (TimeSeries, error) {
if !indexNameRegex.MatchString(name) {
return nil, errors.Errorf("invalid index_name:\"%s\"", name)
}
//if already created, just return
if existingTimeSeries, ok := w.timeSeriesByName[name]; ok {
return existingTimeSeries, nil
}
structType := reflect.TypeOf(tmpl)
if tmpl == nil || structType.Kind() != reflect.Struct {
return nil, errors.Errorf("%T is not a struct", tmpl)
}
if structType.NumField() < 1 || !structType.Field(0).Anonymous || structType.Field(0).Type != reflect.TypeOf(TimeSeriesHeader{}) {
return nil, errors.Errorf("%T does not start with anonymous TimeSeriesHeader", tmpl)