github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/segment/writer/metrics/meta/metricsmeta.go (about) 1 /* 2 Copyright 2023. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package meta 18 19 import ( 20 "bufio" 21 "encoding/json" 22 "os" 23 "path" 24 "sync" 25 26 "github.com/siglens/siglens/pkg/common/fileutils" 27 "github.com/siglens/siglens/pkg/config" 28 "github.com/siglens/siglens/pkg/segment/structs" 29 log "github.com/sirupsen/logrus" 30 ) 31 32 /** 33 34 This module exposes require functions to read/write/query the hosts' metricsmeta.json 35 36 **/ 37 38 var MetricsMetaSuffix = "metricmeta.json" 39 40 var mMetaLock *sync.RWMutex = &sync.RWMutex{} 41 var localMetricsMeta string 42 43 func GetLocalMetricsMetaFName() string { 44 return config.GetSmrBaseDir() + MetricsMetaSuffix 45 } 46 47 func InitMetricsMeta() error { 48 localMetricsMeta = GetLocalMetricsMetaFName() 49 return nil 50 } 51 52 func AddMetricsMetaEntry(entry *structs.MetricsMeta) error { 53 mMetaLock.Lock() 54 defer mMetaLock.Unlock() 55 fd, err := os.OpenFile(localMetricsMeta, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644) 56 if err != nil { 57 log.Errorf("AddMetricsMetaEntry: failed to open filename=%v: err=%v", localMetricsMeta, err) 58 return err 59 } 60 61 defer fd.Close() 62 63 rawMeta, err := json.Marshal(entry) 64 if err != nil { 65 log.Errorf("AddMetricsMetaEntry: failed to Marshal: err=%v", err) 66 return err 67 } 68 69 if _, err := fd.Write(rawMeta); err != nil { 70 log.Errorf("AddMetricsMetaEntry: failed to write segmeta filename=%v: err=%v", localMetricsMeta, err) 71 return err 72 } 73 74 if _, err := fd.WriteString("\n"); err != nil { 75 log.Errorf("AddMetricsMetaEntry: failed to write newline filename=%v: err=%v", localMetricsMeta, err) 76 return err 77 } 78 err = fd.Sync() 79 if err != nil { 80 log.Errorf("AddMetricsMetaEntry: failed to sync filename=%v: err=%v", localMetricsMeta, err) 81 return err 82 } 83 84 return nil 85 } 86 87 func GetLocalMetricsMetaEntries() (map[string]*structs.MetricsMeta, error) { 88 return ReadMetricsMeta(localMetricsMeta) 89 } 90 91 func ReadMetricsMeta(mmeta string) (map[string]*structs.MetricsMeta, error) { 92 mMetaLock.RLock() 93 defer mMetaLock.RUnlock() 94 fd, err := os.OpenFile(mmeta, os.O_APPEND|os.O_RDONLY|os.O_CREATE, 0644) 95 if err != nil { 96 if os.IsNotExist(err) { 97 return map[string]*structs.MetricsMeta{}, nil 98 } 99 log.Errorf("GetLocalMetricsMetaEntries: failed to open filename=%v: err=%v", mmeta, err) 100 return nil, err 101 } 102 103 defer fd.Close() 104 105 retVal := make(map[string]*structs.MetricsMeta) 106 scanner := bufio.NewScanner(fd) 107 for scanner.Scan() { 108 rawbytes := scanner.Bytes() 109 var mMeta structs.MetricsMeta 110 err := json.Unmarshal(rawbytes, &mMeta) 111 if err != nil { 112 log.Errorf("GetLocalMetricsMetaEntries: Cannot unmarshal data = %v, err= %v", string(rawbytes), err) 113 continue 114 } 115 retVal[mMeta.MSegmentDir] = &mMeta 116 } 117 118 return retVal, nil 119 } 120 121 // includes remote metrics meta entries 122 func GetAllMetricsMetaEntries(orgid uint64) (map[string]*structs.MetricsMeta, error) { 123 nDir := config.GetIngestNodeBaseDir() 124 files, err := os.ReadDir(nDir) 125 if err != nil { 126 log.Errorf("ReadAllSegmetas: read dir err=%v ", err) 127 return make(map[string]*structs.MetricsMeta, 0), nil 128 } 129 130 // read all mmetas 131 iNodes := make([]string, 0) 132 for _, file := range files { 133 fName := file.Name() 134 iNodes = append(iNodes, fName) 135 } 136 137 allSegmetas := make([]string, 0) 138 for _, iNode := range iNodes { 139 mDir := path.Join(nDir, iNode, MetricsMetaSuffix) 140 if _, err := os.Stat(mDir); err != nil { 141 continue 142 } 143 allSegmetas = append(allSegmetas, mDir) 144 } 145 146 retVal := make(map[string]*structs.MetricsMeta) 147 for _, fName := range allSegmetas { 148 mMetas, err := ReadMetricsMeta(fName) 149 if err != nil { 150 log.Errorf("ReadAllSegmetas: read segmeta err=%v ", err) 151 continue 152 } 153 154 for k, v := range mMetas { 155 if v.OrgId == orgid { 156 retVal[k] = v 157 } 158 } 159 } 160 return retVal, nil 161 } 162 163 func RemoveMetricsSegments(mmetaName string, metricsSegmentsToDelete map[string]*structs.MetricsMeta) { 164 mMetaLock.Lock() 165 defer mMetaLock.Unlock() 166 167 removeMetricsSegmentsByList(mmetaName, metricsSegmentsToDelete) 168 } 169 170 func removeMetricsSegmentsByList(metricsMetaFile string, metricsSegmentsToDelete map[string]*structs.MetricsMeta) { 171 172 if metricsSegmentsToDelete == nil { 173 return 174 } 175 176 preservedEntries := make([]*structs.MetricsMeta, 0) 177 tagsTreeToDelete := make(map[string]bool) 178 179 entriesRead := 0 180 entriesRemoved := 0 181 fd, err := os.OpenFile(metricsMetaFile, os.O_RDONLY, 0644) 182 if err != nil { 183 log.Errorf("removeMetricsSegmentsByList: Failed to open metrics meta file name=%v, err:%v", metricsMetaFile, err) 184 return 185 } 186 defer fd.Close() 187 188 reader := bufio.NewScanner(fd) 189 for reader.Scan() { 190 metricSegmentMeta := structs.MetricsMeta{} 191 err = json.Unmarshal(reader.Bytes(), &metricSegmentMeta) 192 if err != nil { 193 log.Errorf("removeMetricsSegmentsByList: Failed to unmarshal metrics meta file=%v, err:%v", metricsMetaFile, err) 194 continue 195 } 196 entriesRead++ 197 198 _, ok := metricsSegmentsToDelete[metricSegmentMeta.MSegmentDir] 199 if !ok { 200 preservedEntries = append(preservedEntries, &metricSegmentMeta) 201 continue 202 } 203 entriesRemoved++ 204 dir := path.Dir(metricSegmentMeta.MSegmentDir) 205 if err := os.RemoveAll(dir); err != nil { 206 log.Errorf("removeMetricsSegmentsByList: Failed to remove directory name=%v, err:%v", 207 metricSegmentMeta.MSegmentDir, err) 208 } 209 fileutils.RecursivelyDeleteEmptyParentDirectories(dir) 210 211 if _, ok := tagsTreeToDelete[metricSegmentMeta.TTreeDir]; !ok { 212 tagsTreeToDelete[metricSegmentMeta.TTreeDir] = true 213 } 214 } 215 if entriesRemoved > 0 { 216 // if we removed entries and there was nothing preserved then we must delete this metrics meta file 217 if len(preservedEntries) == 0 { 218 if err := os.RemoveAll(metricsMetaFile); err != nil { 219 log.Errorf("removeMetricsSegmentsByList: Failed to remove metrics meta file name=%v, err:%v", metricsMetaFile, err) 220 } 221 } else { 222 wfd, err := os.OpenFile(metricsMetaFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) 223 if err != nil { 224 log.Errorf("removeMetricsSegmentsByList: Failed to open temp metrics meta file name=%v, err:%v", metricsMetaFile, err) 225 return 226 } 227 defer wfd.Close() 228 for _, mentry := range preservedEntries { 229 // delete tags trees for removed segments 230 // if ttdir existed in tagsTreeToDelete, that means a preserved metrics entry still will use this ttree 231 delete(tagsTreeToDelete, mentry.TTreeDir) 232 233 msegjson, err := json.Marshal(*mentry) 234 if err != nil { 235 log.Errorf("removeMetricsSegmentsByList: failed to Marshal: err=%v", err) 236 return 237 } 238 239 if _, err := wfd.Write(msegjson); err != nil { 240 log.Errorf("removeMetricsSegmentsByList: failed to write metrics meta filename=%v: err=%v", metricsMetaFile, err) 241 return 242 } 243 244 if _, err := wfd.WriteString("\n"); err != nil { 245 log.Errorf("removeMetricsSegmentsByList: failed to write new line to metrics meta filename=%v: err=%v", metricsMetaFile, err) 246 return 247 } 248 } 249 } 250 } 251 for ttreeDir := range tagsTreeToDelete { 252 dir := path.Dir(ttreeDir) 253 if err := os.RemoveAll(ttreeDir); err != nil { 254 log.Errorf("removeMetricsSegmentsByList: Failed to remove tags tree directory=%v, err:%v", ttreeDir, err) 255 } 256 fileutils.RecursivelyDeleteEmptyParentDirectories(dir) 257 } 258 }