Merge pull request #962 from SigNoz/ttl-plus

Add remove TTL api, and do not allow zero or negative TTL
This commit is contained in:
Ankit Nayan 2022-05-19 16:01:17 +02:00 committed by GitHub
commit 42269a7c78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 105 additions and 2 deletions

View File

@ -2333,6 +2333,40 @@ func (r *ClickHouseReader) setColdStorage(ctx context.Context, tableName string,
return nil
}
func (r *ClickHouseReader) RemoveTTL(ctx context.Context,
params *model.RemoveTTLParams) (*model.RemoveTTLResponseItem, *model.ApiError) {
var reqs []string
templateQuery := `ALTER TABLE %v REMOVE TTL`
tracesTables := []string{signozTraceDBName + "." + signozTraceTableName, signozTraceDBName + "." + signozDurationMVTable, signozTraceDBName + "." + signozSpansTable, signozTraceDBName + "." + signozErrorIndexTable}
metricsTables := []string{signozMetricDBName + "." + signozSampleName}
switch params.Type {
case constants.TraceTTL:
for _, tableName := range tracesTables {
reqs = append(reqs, fmt.Sprintf(templateQuery, tableName))
}
case constants.MetricsTTL:
for _, tableName := range metricsTables {
reqs = append(reqs, fmt.Sprintf(templateQuery, tableName))
}
default:
for _, tableName := range append(append([]string{}, tracesTables...), metricsTables...) {
reqs = append(reqs, fmt.Sprintf(templateQuery, tableName))
}
}
zap.S().Debugf("Executing remove TTL requests: %s\n", reqs)
for _, req := range reqs {
if err := r.db.Exec(ctx, req); err != nil {
zap.S().Error(fmt.Errorf("error while removing ttl. Err=%v", err))
return nil, &model.ApiError{Typ: model.ErrorExec,
Err: 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

@ -310,6 +310,7 @@ func (aH *APIHandler) RegisterRoutes(router *mux.Router) {
router.HandleFunc("/api/v1/serviceMapDependencies", ViewAccess(aH.serviceMapDependencies)).Methods(http.MethodPost)
router.HandleFunc("/api/v1/settings/ttl", AdminAccess(aH.setTTL)).Methods(http.MethodPost)
router.HandleFunc("/api/v1/settings/ttl", ViewAccess(aH.getTTL)).Methods(http.MethodGet)
router.HandleFunc("/api/v1/settings/ttl", AdminAccess(aH.removeTTL)).Methods(http.MethodDelete)
router.HandleFunc("/api/v1/version", OpenAccess(aH.getVersion)).Methods(http.MethodGet)
@ -1162,6 +1163,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

@ -50,6 +50,7 @@ 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)
GetMetricAutocompleteMetricNames(ctx context.Context, matchText string) (*[]string, *model.ApiError)
GetMetricAutocompleteTagKey(ctx context.Context, params *model.MetricAutocompleteTagParams) (*[]string, *model.ApiError)

View File

@ -545,7 +545,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)
}
@ -554,7 +554,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() {
@ -587,6 +587,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 parseUserRequest(r *http.Request) (*model.User, error) {
var req model.User
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {

View File

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

View File

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