Add remove TTL api, and do not allow zero or negative TTL

This commit is contained in:
Srikanth Chekuri 2022-04-06 16:29:10 +05:30
parent 1d28ceb3d7
commit d6c4df8b4b
7 changed files with 105 additions and 5 deletions

View File

@ -2591,6 +2591,32 @@ func (r *ClickHouseReader) SetTTL(ctx context.Context,
return &model.SetTTLResponseItem{Message: "move ttl has been successfully set up"}, nil
}
func (r *ClickHouseReader) RemoveTTL(ctx context.Context,
params *model.RemoveTTLParams) (*model.RemoveTTLResponseItem, *model.ApiError) {
var reqs []string
tracesQuery := fmt.Sprintf("ALTER TABLE default.%v REMOVE TTL", signozTraceTableName)
metricsQuery := fmt.Sprintf("ALTER TABLE %v REMOVE TTL", signozMetricDBName+"."+signozSampleName)
switch params.Type {
case constants.TraceTTL:
reqs = append(reqs, tracesQuery)
case constants.MetricsTTL:
reqs = append(reqs, metricsQuery)
default:
reqs = append(reqs, tracesQuery, metricsQuery)
}
zap.S().Debugf("Executing remove TTL requests: %s\n", reqs)
for _, req := range reqs {
if _, err := r.db.Exec(req); err != nil {
zap.S().Error(fmt.Errorf("error while removing ttl. Err=%v", err))
return nil, &model.ApiError{model.ErrorExec,
fmt.Errorf("error while removing ttl. Err=%v", err)}
}
}
return &model.RemoveTTLResponseItem{Message: "ttl has been successfully removed"}, nil
}
// GetDisks returns a list of disks {name, type} configured in clickhouse DB.
func (r *ClickHouseReader) GetDisks(ctx context.Context) (*[]model.DiskItem, *model.ApiError) {
diskItems := []model.DiskItem{}

View File

@ -10,8 +10,8 @@ import (
"github.com/prometheus/prometheus/util/stats"
"go.signoz.io/query-service/druidQuery"
"go.signoz.io/query-service/godruid"
"go.signoz.io/query-service/model"
am "go.signoz.io/query-service/integrations/alertManager"
"go.signoz.io/query-service/model"
)
type DruidReader struct {
@ -201,3 +201,7 @@ func (druid *DruidReader) GetErrorForId(_ context.Context, _ *model.GetErrorPara
func (druid *DruidReader) GetErrorForType(_ context.Context, _ *model.GetErrorParams) (*model.ErrorWithSpan, *model.ApiError) {
return nil, &model.ApiError{model.ErrorNotImplemented, fmt.Errorf("druid does not support get error API")}
}
func (druid *DruidReader) RemoveTTL(_ context.Context, _ *model.RemoveTTLParams) (*model.RemoveTTLResponseItem, *model.ApiError) {
return nil, &model.ApiError{model.ErrorNotImplemented, fmt.Errorf("druid does not support ttl configuration")}
}

View File

@ -12,11 +12,12 @@ import (
_ "github.com/mattn/go-sqlite3"
"github.com/prometheus/prometheus/promql"
"go.signoz.io/query-service/app/dashboards"
"go.signoz.io/query-service/constants"
"go.signoz.io/query-service/dao/interfaces"
am "go.signoz.io/query-service/integrations/alertManager"
"go.signoz.io/query-service/model"
"go.signoz.io/query-service/telemetry"
"go.signoz.io/query-service/version"
am "go.signoz.io/query-service/integrations/alertManager"
"go.uber.org/zap"
)
@ -205,6 +206,7 @@ func (aH *APIHandler) RegisterRoutes(router *mux.Router) {
router.HandleFunc("/api/v1/serviceMapDependencies", aH.serviceMapDependencies).Methods(http.MethodGet)
router.HandleFunc("/api/v1/settings/ttl", aH.setTTL).Methods(http.MethodPost)
router.HandleFunc("/api/v1/settings/ttl", aH.getTTL).Methods(http.MethodGet)
router.HandleFunc("/api/v1/settings/ttl", aH.removeTTL).Methods(http.MethodDelete)
router.HandleFunc("/api/v1/userPreferences", aH.setUserPreferences).Methods(http.MethodPost)
router.HandleFunc("/api/v1/userPreferences", aH.getUserPreferences).Methods(http.MethodGet)
@ -1090,6 +1092,47 @@ func (aH *APIHandler) getTTL(w http.ResponseWriter, r *http.Request) {
aH.writeJSON(w, r, result)
}
func (aH *APIHandler) removeTTL(w http.ResponseWriter, r *http.Request) {
ttlParams, err := parseRemoveTTL(r)
if aH.handleError(w, err, http.StatusBadRequest) {
return
}
existingTTL, apiErr := (*aH.reader).GetTTL(context.Background(), &model.GetTTLParams{GetAllTTL: true})
if apiErr != nil && aH.handleError(w, apiErr.Err, http.StatusInternalServerError) {
return
}
if ttlParams.Type == constants.TraceTTL && existingTTL.TracesTime == -1 &&
aH.handleError(w, fmt.Errorf("traces doesn't have any TTL set, cannot remove"), http.StatusBadRequest) {
return
}
if ttlParams.Type == constants.MetricsTTL && existingTTL.MetricsTime == -1 &&
aH.handleError(w, fmt.Errorf("metrics doesn't have any TTL set, cannot remove"), http.StatusBadRequest) {
return
}
if ttlParams.RemoveAllTTL {
if existingTTL.TracesTime == -1 && existingTTL.MetricsTime != -1 {
ttlParams.Type = constants.MetricsTTL
ttlParams.RemoveAllTTL = false
} else if existingTTL.TracesTime != -1 && existingTTL.MetricsTime == -1 {
ttlParams.Type = constants.TraceTTL
ttlParams.RemoveAllTTL = false
} else if aH.handleError(w, fmt.Errorf("no TTL set, cannot remove"), http.StatusBadRequest) {
return
}
}
result, apiErr := (*aH.reader).RemoveTTL(context.Background(), ttlParams)
if apiErr != nil && aH.handleError(w, apiErr.Err, http.StatusInternalServerError) {
return
}
aH.writeJSON(w, r, result)
}
func (aH *APIHandler) getDisks(w http.ResponseWriter, r *http.Request) {
result, apiErr := (*aH.reader).GetDisks(context.Background())
if apiErr != nil && aH.handleError(w, apiErr.Err, http.StatusInternalServerError) {

View File

@ -5,8 +5,8 @@ import (
"github.com/prometheus/prometheus/promql"
"github.com/prometheus/prometheus/util/stats"
"go.signoz.io/query-service/model"
am "go.signoz.io/query-service/integrations/alertManager"
"go.signoz.io/query-service/model"
)
type Reader interface {
@ -58,4 +58,5 @@ type Reader interface {
// Setter Interfaces
SetTTL(ctx context.Context, ttlParams *model.TTLParams) (*model.SetTTLResponseItem, *model.ApiError)
RemoveTTL(ctx context.Context, ttlParams *model.RemoveTTLParams) (*model.RemoveTTLResponseItem, *model.ApiError)
}

View File

@ -902,7 +902,7 @@ func parseTTLParams(r *http.Request) (*model.TTLParams, error) {
// Validate the TTL duration.
durationParsed, err := time.ParseDuration(delDuration)
if err != nil {
if err != nil || durationParsed.Seconds() <= 0 {
return nil, fmt.Errorf("Not a valid TTL duration %v", delDuration)
}
@ -911,7 +911,7 @@ func parseTTLParams(r *http.Request) (*model.TTLParams, error) {
// If some cold storage is provided, validate the cold storage move TTL.
if len(coldStorage) > 0 {
toColdParsed, err = time.ParseDuration(toColdDuration)
if err != nil {
if err != nil || toColdParsed.Seconds() <= 0 {
return nil, fmt.Errorf("Not a valid toCold TTL duration %v", toColdDuration)
}
if toColdParsed.Seconds() != 0 && toColdParsed.Seconds() >= durationParsed.Seconds() {
@ -944,6 +944,23 @@ func parseGetTTL(r *http.Request) (*model.GetTTLParams, error) {
return &model.GetTTLParams{Type: typeTTL, GetAllTTL: getAllTTL}, nil
}
func parseRemoveTTL(r *http.Request) (*model.RemoveTTLParams, error) {
typeTTL := r.URL.Query().Get("type")
removeAllTTL := false
if len(typeTTL) == 0 {
removeAllTTL = true
} else {
// Validate the type parameter
if typeTTL != constants.TraceTTL && typeTTL != constants.MetricsTTL {
return nil, fmt.Errorf("type param should be <metrics|traces>, got %v", typeTTL)
}
}
return &model.RemoveTTLParams{Type: typeTTL, RemoveAllTTL: removeAllTTL}, nil
}
func parseUserPreferences(r *http.Request) (*model.UserPreferences, error) {
var userPreferences model.UserPreferences

View File

@ -229,3 +229,8 @@ type GetErrorParams struct {
ErrorID string
ServiceName string
}
type RemoveTTLParams struct {
Type string
RemoveAllTTL bool
}

View File

@ -273,6 +273,10 @@ type SetTTLResponseItem struct {
Message string `json:"message"`
}
type RemoveTTLResponseItem struct {
Message string `json:"message"`
}
type DiskItem struct {
Name string `json:"name,omitempty" db:"name,omitempty"`
Type string `json:"type,omitempty" db:"type,omitempty"`