github.com/go-kivik/kivik/v4@v4.3.2/couchdb/dbstats.go (about) 1 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 2 // use this file except in compliance with the License. You may obtain a copy of 3 // the License at 4 // 5 // http://www.apache.org/licenses/LICENSE-2.0 6 // 7 // Unless required by applicable law or agreed to in writing, software 8 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 9 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 10 // License for the specific language governing permissions and limitations under 11 // the License. 12 13 package couchdb 14 15 import ( 16 "bytes" 17 "context" 18 "encoding/json" 19 "net/http" 20 21 "github.com/go-kivik/kivik/v4/couchdb/chttp" 22 "github.com/go-kivik/kivik/v4/driver" 23 ) 24 25 type dbStats struct { 26 driver.DBStats 27 Sizes struct { 28 File int64 `json:"file"` 29 External int64 `json:"external"` 30 Active int64 `json:"active"` 31 } `json:"sizes"` 32 UpdateSeq json.RawMessage `json:"update_seq"` // nolint: govet 33 rawBody json.RawMessage 34 } 35 36 func (s *dbStats) UnmarshalJSON(p []byte) error { 37 type dbStatsClone dbStats 38 c := dbStatsClone(*s) 39 if err := json.Unmarshal(p, &c); err != nil { 40 return err 41 } 42 *s = dbStats(c) 43 s.rawBody = p 44 return nil 45 } 46 47 func (s *dbStats) driverStats() *driver.DBStats { 48 stats := &s.DBStats 49 if s.Sizes.File > 0 { 50 stats.DiskSize = s.Sizes.File 51 } 52 if s.Sizes.External > 0 { 53 stats.ExternalSize = s.Sizes.External 54 } 55 if s.Sizes.Active > 0 { 56 stats.ActiveSize = s.Sizes.Active 57 } 58 stats.UpdateSeq = string(bytes.Trim(s.UpdateSeq, `"`)) 59 stats.RawResponse = s.rawBody 60 return stats 61 } 62 63 func (d *db) Stats(ctx context.Context) (*driver.DBStats, error) { 64 result := dbStats{} 65 if err := d.Client.DoJSON(ctx, http.MethodGet, d.dbName, nil, &result); err != nil { 66 return nil, err 67 } 68 return result.driverStats(), nil 69 } 70 71 type dbsInfoRequest struct { 72 Keys []string `json:"keys"` 73 } 74 75 type dbsInfoResponse struct { 76 Key string `json:"key"` 77 DBInfo dbStats `json:"info"` 78 Error string `json:"error"` 79 } 80 81 func (c *client) DBsStats(_ context.Context, dbnames []string) ([]*driver.DBStats, error) { 82 opts := &chttp.Options{ 83 GetBody: chttp.BodyEncoder(dbsInfoRequest{Keys: dbnames}), 84 Header: http.Header{ 85 chttp.HeaderIdempotencyKey: []string{}, 86 }, 87 } 88 result := []dbsInfoResponse{} 89 err := c.DoJSON(context.Background(), http.MethodPost, "/_dbs_info", opts, &result) 90 if err != nil { 91 return nil, err 92 } 93 stats := make([]*driver.DBStats, len(result)) 94 for i := range result { 95 if result[i].Error == "" { 96 stats[i] = result[i].DBInfo.driverStats() 97 } 98 } 99 return stats, nil 100 } 101 102 func (c *client) AllDBsStats(ctx context.Context, options driver.Options) ([]*driver.DBStats, error) { 103 opts := map[string]interface{}{} 104 options.Apply(opts) 105 chttpOpts := &chttp.Options{ 106 Header: http.Header{ 107 chttp.HeaderIdempotencyKey: []string{}, 108 }, 109 } 110 var err error 111 chttpOpts.Query, err = optionsToParams(opts) 112 if err != nil { 113 return nil, err 114 } 115 result := []dbsInfoResponse{} 116 if err := c.DoJSON(ctx, http.MethodGet, "/_dbs_info", chttpOpts, &result); err != nil { 117 return nil, err 118 } 119 stats := make([]*driver.DBStats, len(result)) 120 for i := range result { 121 stats[i] = result[i].DBInfo.driverStats() 122 } 123 return stats, nil 124 } 125 126 type partitionStats struct { 127 DBName string `json:"db_name"` 128 DocCount int64 `json:"doc_count"` 129 DocDelCount int64 `json:"doc_del_count"` 130 Partition string `json:"partition"` 131 Sizes struct { 132 Active int64 `json:"active"` 133 External int64 `json:"external"` 134 } 135 rawBody json.RawMessage 136 } 137 138 func (s *partitionStats) UnmarshalJSON(p []byte) error { 139 c := struct { 140 partitionStats 141 UnmarshalJSON struct{} 142 }{} 143 if err := json.Unmarshal(p, &c); err != nil { 144 return err 145 } 146 *s = c.partitionStats 147 s.rawBody = p 148 return nil 149 } 150 151 func (d *db) PartitionStats(ctx context.Context, name string) (*driver.PartitionStats, error) { 152 result := partitionStats{} 153 if err := d.Client.DoJSON(ctx, http.MethodGet, d.path("_partition/"+name), nil, &result); err != nil { 154 return nil, err 155 } 156 return &driver.PartitionStats{ 157 DBName: result.DBName, 158 DocCount: result.DocCount, 159 DeletedDocCount: result.DocDelCount, 160 Partition: result.Partition, 161 ActiveSize: result.Sizes.Active, 162 ExternalSize: result.Sizes.External, 163 RawResponse: result.rawBody, 164 }, nil 165 }