Skip to content

Commit 2cd255a

Browse files
committed
cli: use Datadog API client in tsdump uploader
Previously, we used raw POST requests in the tsdump uploader. Now, we use the Datadog API client which is already linked in elsewhere in the CockroachDB binary, for use in the cockroach workload command. Epic: none Release note: None
1 parent ab54419 commit 2cd255a

File tree

8 files changed

+171
-226
lines changed

8 files changed

+171
-226
lines changed

pkg/cli/BUILD.bazel

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,8 @@ go_library(
256256
"@com_github_cockroachdb_pebble//vfs",
257257
"@com_github_cockroachdb_redact//:redact",
258258
"@com_github_cockroachdb_ttycolor//:ttycolor",
259+
"@com_github_datadog_datadog_api_client_go_v2//api/datadog",
260+
"@com_github_datadog_datadog_api_client_go_v2//api/datadogV2",
259261
"@com_github_dustin_go_humanize//:go-humanize",
260262
"@com_github_fsnotify_fsnotify//:fsnotify",
261263
"@com_github_gogo_protobuf//jsonpb",
@@ -467,6 +469,7 @@ go_test(
467469
"@com_github_cockroachdb_errors//:errors",
468470
"@com_github_cockroachdb_errors//oserror",
469471
"@com_github_cockroachdb_pebble//vfs",
472+
"@com_github_datadog_datadog_api_client_go_v2//api/datadogV2",
470473
"@com_github_google_pprof//profile",
471474
"@com_github_pmezard_go_difflib//difflib",
472475
"@com_github_spf13_cobra//:cobra",

pkg/cli/debug.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,6 +1615,7 @@ func init() {
16151615
f.StringVar(&debugTimeSeriesDumpOpts.organizationName, "org-name", "", "organization name to use in datadog upload")
16161616
f.StringVar(&debugTimeSeriesDumpOpts.userName, "user-name", "", "name of the user to perform datadog upload")
16171617
f.StringVar(&debugTimeSeriesDumpOpts.storeToNodeMapYAMLFile, "store-to-node-map-file", "", "yaml file path which contains the mapping of store ID to node ID for datadog upload.")
1618+
f.BoolVar(&debugTimeSeriesDumpOpts.dryRun, "dry-run", false, "run in dry-run mode without making any actual uploads")
16181619

16191620
f = debugSendKVBatchCmd.Flags()
16201621
f.StringVar(&debugSendKVBatchContext.traceFormat, "trace", debugSendKVBatchContext.traceFormat,

pkg/cli/testdata/tsdump/json

Lines changed: 34 additions & 34 deletions
Large diffs are not rendered by default.

pkg/cli/testdata/tsdump_upload_e2e

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ cr.node.sql.query.count,2021-01-01T00:00:00Z,1,100.5
55
cr.node.sql.query.count,2021-01-01T00:00:10Z,1,102.3
66
cr.store.rocksdb.block.cache.usage,2021-01-01T00:00:00Z,2,75.2
77
----
8-
{"series":[{"metric":"crdb.tsdump.admission.admitted.elastic-cpu","type":0,"points":[{"timestamp":1748248320,"value":1}],"interval":10,"resources":null,"tags":["node_id:1","cluster_type:SELF_HOSTED","cluster_label:\"test-cluster\"","cluster_id:test-cluster-id","zendesk_ticket:zd-test","org_name:test-org","user_name:test-user","upload_id:\"test-cluster\"-20241114000000","upload_timestamp:2024-11-14 00:00:00","upload_year:2024","upload_month:11","upload_day:14"]},{"metric":"crdb.tsdump.sql.query.count","type":0,"points":[{"timestamp":1609459200,"value":100.5}],"interval":10,"resources":null,"tags":["node_id:1","cluster_type:SELF_HOSTED","cluster_label:\"test-cluster\"","cluster_id:test-cluster-id","zendesk_ticket:zd-test","org_name:test-org","user_name:test-user","upload_id:\"test-cluster\"-20241114000000","upload_timestamp:2024-11-14 00:00:00","upload_year:2024","upload_month:11","upload_day:14"]},{"metric":"crdb.tsdump.sql.query.count","type":0,"points":[{"timestamp":1609459210,"value":102.3}],"interval":10,"resources":null,"tags":["node_id:1","cluster_type:SELF_HOSTED","cluster_label:\"test-cluster\"","cluster_id:test-cluster-id","zendesk_ticket:zd-test","org_name:test-org","user_name:test-user","upload_id:\"test-cluster\"-20241114000000","upload_timestamp:2024-11-14 00:00:00","upload_year:2024","upload_month:11","upload_day:14"]},{"metric":"crdb.tsdump.rocksdb.block.cache.usage","type":0,"points":[{"timestamp":1609459200,"value":75.2}],"interval":10,"resources":null,"tags":["store:2","cluster_type:SELF_HOSTED","cluster_label:\"test-cluster\"","cluster_id:test-cluster-id","zendesk_ticket:zd-test","org_name:test-org","user_name:test-user","upload_id:\"test-cluster\"-20241114000000","upload_timestamp:2024-11-14 00:00:00","upload_year:2024","upload_month:11","upload_day:14"]}]}
8+
{"series":[{"interval":10,"metric":"crdb.tsdump.admission.admitted.elastic-cpu","points":[{"timestamp":1748248320,"value":1}],"tags":["node_id:1","cluster_type:SELF_HOSTED","cluster_label:\"test-cluster\"","cluster_id:test-cluster-id","zendesk_ticket:zd-test","org_name:test-org","user_name:test-user","upload_id:\"test-cluster\"-20241114000000","upload_timestamp:2024-11-14 00:00:00","upload_year:2024","upload_month:11","upload_day:14"],"type":0},{"interval":10,"metric":"crdb.tsdump.sql.query.count","points":[{"timestamp":1609459200,"value":100.5}],"tags":["node_id:1","cluster_type:SELF_HOSTED","cluster_label:\"test-cluster\"","cluster_id:test-cluster-id","zendesk_ticket:zd-test","org_name:test-org","user_name:test-user","upload_id:\"test-cluster\"-20241114000000","upload_timestamp:2024-11-14 00:00:00","upload_year:2024","upload_month:11","upload_day:14"],"type":0},{"interval":10,"metric":"crdb.tsdump.sql.query.count","points":[{"timestamp":1609459210,"value":102.3}],"tags":["node_id:1","cluster_type:SELF_HOSTED","cluster_label:\"test-cluster\"","cluster_id:test-cluster-id","zendesk_ticket:zd-test","org_name:test-org","user_name:test-user","upload_id:\"test-cluster\"-20241114000000","upload_timestamp:2024-11-14 00:00:00","upload_year:2024","upload_month:11","upload_day:14"],"type":0},{"interval":10,"metric":"crdb.tsdump.rocksdb.block.cache.usage","points":[{"timestamp":1609459200,"value":75.2}],"tags":["store:2","cluster_type:SELF_HOSTED","cluster_label:\"test-cluster\"","cluster_id:test-cluster-id","zendesk_ticket:zd-test","org_name:test-org","user_name:test-user","upload_id:\"test-cluster\"-20241114000000","upload_timestamp:2024-11-14 00:00:00","upload_year:2024","upload_month:11","upload_day:14"],"type":0}]}

pkg/cli/tsdump.go

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ var debugTimeSeriesDumpOpts = struct {
5151
organizationName string
5252
userName string
5353
storeToNodeMapYAMLFile string
54+
dryRun bool
5455
}{
5556
format: tsDumpText,
5657
from: timestampValue{},
@@ -59,6 +60,9 @@ var debugTimeSeriesDumpOpts = struct {
5960
yaml: "/tmp/tsdump.yaml",
6061
}
6162

63+
// hostNameOverride is used to override the hostname for testing purpose.
64+
var hostNameOverride string
65+
6266
var debugTimeSeriesDumpCmd = &cobra.Command{
6367
Use: "tsdump",
6468
Short: "dump all the raw timeseries values in a cluster",
@@ -111,18 +115,16 @@ will then convert it to the --format requested in the current invocation.
111115
return errors.New("no input file provided")
112116
}
113117

114-
targetURL, err := getDatadogTargetURL(debugTimeSeriesDumpOpts.ddSite)
115-
if err != nil {
116-
return err
117-
}
118-
119-
var datadogWriter = makeDatadogWriter(
120-
targetURL,
118+
datadogWriter, err := makeDatadogWriter(
119+
debugTimeSeriesDumpOpts.ddSite,
121120
cmd == tsDumpDatadogInit,
122121
debugTimeSeriesDumpOpts.ddApiKey,
123122
100,
124-
doDDRequest,
123+
hostNameOverride,
125124
)
125+
if err != nil {
126+
return err
127+
}
126128
return datadogWriter.upload(args[0])
127129
case tsDumpOpenMetrics:
128130
if debugTimeSeriesDumpOpts.targetURL != "" {
@@ -259,15 +261,6 @@ will then convert it to the --format requested in the current invocation.
259261
}),
260262
}
261263

262-
func getDatadogTargetURL(site string) (string, error) {
263-
host, ok := ddSiteToHostMap[site]
264-
if !ok {
265-
return "", fmt.Errorf("unsupported datadog site '%s'", site)
266-
}
267-
targetURL := fmt.Sprintf(targetURLFormat, host)
268-
return targetURL, nil
269-
}
270-
271264
func doRequest(req *http.Request) error {
272265
resp, err := http.DefaultClient.Do(req)
273266
if err != nil {

pkg/cli/tsdump_test.go

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@ import (
1313
"math/rand"
1414
"net"
1515
"net/http"
16+
"net/http/httptest"
1617
"os"
1718
"strconv"
1819
"strings"
1920
"testing"
2021
"time"
2122

23+
"github.com/DataDog/datadog-api-client-go/v2/api/datadogV2"
2224
"github.com/cockroachdb/cockroach/pkg/testutils"
2325
"github.com/cockroachdb/cockroach/pkg/ts/tspb"
2426
"github.com/cockroachdb/cockroach/pkg/util/leaktest"
@@ -145,7 +147,7 @@ func parseTSInput(t *testing.T, input string, w tsWriter) {
145147
}
146148

147149
func parseDDInput(t *testing.T, input string, w *datadogWriter) {
148-
var data *DatadogSeries
150+
var data *datadogV2.MetricSeries
149151
var source, storeNodeKey string
150152

151153
for _, s := range strings.Split(input, "\n") {
@@ -164,10 +166,10 @@ func parseDDInput(t *testing.T, input string, w *datadogWriter) {
164166
(data != nil && data.Metric != metricName ||
165167
(data != nil && source != nameValueTimestamp[1])) {
166168
if data != nil {
167-
_, err := w.emitDataDogMetrics([]DatadogSeries{*data})
169+
_, err := w.emitDataDogMetrics([]datadogV2.MetricSeries{*data})
168170
require.NoError(t, err)
169171
}
170-
data = &DatadogSeries{
172+
data = &datadogV2.MetricSeries{
171173
Metric: metricName,
172174
Type: w.resolveMetricType(metricName),
173175
}
@@ -178,12 +180,12 @@ func parseDDInput(t *testing.T, input string, w *datadogWriter) {
178180
require.NoError(t, err)
179181
ts, err := strconv.ParseInt(nameValueTimestamp[3], 10, 64)
180182
require.NoError(t, err)
181-
data.Points = append(data.Points, DatadogPoint{
182-
Value: value,
183-
Timestamp: ts,
183+
data.Points = append(data.Points, datadogV2.MetricPoint{
184+
Value: &value,
185+
Timestamp: &ts,
184186
})
185187
}
186-
_, err := w.emitDataDogMetrics([]DatadogSeries{*data})
188+
_, err := w.emitDataDogMetrics([]datadogV2.MetricSeries{*data})
187189
require.NoError(t, err)
188190
}
189191

@@ -193,7 +195,17 @@ func TestTsDumpFormatsDataDriven(t *testing.T) {
193195
defer testutils.TestingHook(&getCurrentTime, func() time.Time {
194196
return time.Date(2024, 11, 14, 0, 0, 0, 0, time.UTC)
195197
})()
196-
198+
var testReqs []*http.Request
199+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
200+
r2 := r.Clone(r.Context())
201+
// Clone the body so that it can be read again
202+
body, err := io.ReadAll(r.Body)
203+
require.NoError(t, err)
204+
r2.Body = io.NopCloser(bytes.NewReader(body))
205+
testReqs = append(testReqs, r2)
206+
w.WriteHeader(http.StatusOK)
207+
}))
208+
defer server.Close()
197209
datadriven.Walk(t, "testdata/tsdump", func(t *testing.T, path string) {
198210
datadriven.RunTest(t, path, func(t *testing.T, d *datadriven.TestData) string {
199211
var w tsWriter
@@ -204,28 +216,25 @@ func TestTsDumpFormatsDataDriven(t *testing.T) {
204216
debugTimeSeriesDumpOpts.zendeskTicket = "zd-test"
205217
debugTimeSeriesDumpOpts.organizationName = "test-org"
206218
debugTimeSeriesDumpOpts.userName = "test-user"
207-
var testReqs []*http.Request
208219
var series int
209220
d.ScanArgs(t, "series-threshold", &series)
210-
var ddwriter = makeDatadogWriter(
211-
"https://example.com/data", d.Cmd == "format-datadog-init", "api-key", series, func(req *http.Request,
212-
) error {
213-
testReqs = append(testReqs, req)
214-
return nil
215-
})
221+
var ddwriter, err = makeDatadogWriter(
222+
defaultDDSite, d.Cmd == "format-datadog-init", "api-key", series,
223+
server.Listener.Addr().String(),
224+
)
225+
require.NoError(t, err)
216226

217227
parseDDInput(t, d.Input, ddwriter)
218228

219229
out := strings.Builder{}
220230
for _, tr := range testReqs {
221-
rc, err := tr.GetBody()
222-
require.NoError(t, err)
223-
zipR, err := gzip.NewReader(rc)
231+
reader, err := gzip.NewReader(tr.Body)
224232
require.NoError(t, err)
225-
body, err := io.ReadAll(zipR)
233+
body, err := io.ReadAll(reader)
226234
require.NoError(t, err)
227235
out.WriteString(fmt.Sprintf("%s: %s\nDD-API-KEY: %s\nBody: %s", tr.Method, tr.URL, tr.Header.Get("DD-API-KEY"), body))
228236
}
237+
testReqs = testReqs[:0] // reset the slice
229238
return out.String()
230239
case "format-json":
231240
debugTimeSeriesDumpOpts.clusterLabel = "test-cluster"

0 commit comments

Comments
 (0)