Skip to content

Commit 6b7ccdc

Browse files
Monitor Query UX Study Feedback (Azure#19771)
* remove ColumnLookup * rename workspaces to additionalworkspaces * rename render to visualization * timespan * timespan struct * added ISO8601TimeInterval type * change batch names * doc updates * readme updates * docs * Update sdk/monitor/azquery/README.md Co-authored-by: Scott Addie <10702007+scottaddie@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Scott Addie <10702007+scottaddie@users.noreply.github.com> * iso8601 timeinterval * updated test recordings * fix linter errors * fix linting part 2 * charles suggestions * more doc comments * options update * test updates * joel feedback * prep for release * fix year to 2023 Co-authored-by: Scott Addie <10702007+scottaddie@users.noreply.github.com>
1 parent 7ead9e8 commit 6b7ccdc

27 files changed

+1298
-1150
lines changed

sdk/monitor/azquery/CHANGELOG.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
# Release History
22

3-
## 0.3.1 (Unreleased)
3+
## 0.4.0 (2023-01-12)
44

55
### Features Added
6+
* Added `TimeInterval` type with constructor to aid with timespan creation
7+
* Added `NewBatchQueryRequest` constructor to aid with logs batch requests
8+
* Added `LogsQueryOptions` model for easier setting of logs options
69

710
### Breaking Changes
8-
9-
### Bugs Fixed
11+
* Changed type of `Body.Timespan`, `MetricsClientQueryResourceOptions.Timespan`, `Response.Timespan` from *string to *TimeInterval
12+
* Remove `ColumnIndexLookup` field from Table struct
13+
* Renamed `Body.Workspaces` to `Body.AdditionalWorkspaces`
14+
* Renamed `Results.Render` and `BatchResponse.Render` to `Results.Visualization` and `BatchResponse.Visualization`
1015

1116
### Other Changes
17+
* Doc and example updates
1218

1319
## 0.3.0 (2022-11-08)
1420

sdk/monitor/azquery/README.md

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

sdk/monitor/azquery/autorest.md

Lines changed: 73 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,43 @@ directive:
6868
from: MetricNamespaces_List
6969
to: Metrics_ListNamespaces
7070

71+
# rename Body.Workspaces to Body.AdditionalWorkspaces
72+
- from: swagger-document
73+
where: $.definitions.queryBody.properties.workspaces
74+
transform: $["x-ms-client-name"] = "AdditionalWorkspaces"
75+
76+
# rename Render to Visualization
77+
- from: swagger-document
78+
where: $.definitions.queryResults.properties.render
79+
transform: $["x-ms-client-name"] = "Visualization"
80+
- from: swagger-document
81+
where: $.definitions.batchQueryResults.properties.render
82+
transform: $["x-ms-client-name"] = "Visualization"
83+
84+
# rename BatchQueryRequest.ID to BatchQueryRequest.CorrelationID
85+
- from: swagger-document
86+
where: $.definitions.batchQueryRequest.properties.id
87+
transform: $["x-ms-client-name"] = "CorrelationID"
88+
- from: swagger-document
89+
where: $.definitions.batchQueryResponse.properties.id
90+
transform: $["x-ms-client-name"] = "CorrelationID"
91+
92+
# rename BatchQueryRequest.Workspace to BatchQueryRequest.WorkspaceID
93+
- from: swagger-document
94+
where: $.definitions.batchQueryRequest.properties.workspace
95+
transform: $["x-ms-client-name"] = "WorkspaceID"
96+
97+
# rename Prefer to Options
98+
- from: swagger-document
99+
where: $.parameters.PreferHeaderParameter
100+
transform: $["x-ms-client-name"] = "Options"
101+
- from: models.go
102+
where: $
103+
transform: return $.replace(/Options \*string/g, "Options *LogsQueryOptions");
104+
- from: logs_client.go
105+
where: $
106+
transform: return $.replace(/\*options\.Options/, "options.Options.String()");
107+
71108
# add default values for batch request path and method attributes
72109
- from: swagger-document
73110
where: $.definitions.batchQueryRequest.properties.path
@@ -90,6 +127,23 @@ directive:
90127
where: $
91128
transform: return $.replace(/type ResultType string/, "//ResultType - Reduces the set of data collected. The syntax allowed depends on the operation. See the operation's description for details.\ntype ResultType string");
92129

130+
# update doc comments
131+
- from: swagger-document
132+
where: $.definitions.queryBody.properties.workspaces
133+
transform: $["description"] = "A list of workspaces to query in addition to the primary workspace."
134+
- from: swagger-document
135+
where: $.definitions.batchQueryRequest.properties.headers
136+
transform: $["description"] = "Optional. Headers of the request. Can use prefer header to set server timeout, query statistics and visualization information. For more information, see https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/monitor/azquery#readme-increase-wait-time-include-statistics-include-render-visualization"
137+
- from: swagger-document
138+
where: $.definitions.batchQueryRequest.properties.workspace
139+
transform: $["description"] = "Primary Workspace ID of the query"
140+
- from: swagger-document
141+
where: $.definitions.batchQueryRequest.properties.id
142+
transform: $["description"] = "Unique ID corresponding to each request in the batch"
143+
- from: swagger-document
144+
where: $.parameters.workspaceId
145+
transform: $["description"] = "Primary Workspace ID of the query. This is Workspace ID from the Properties blade in the Azure portal"
146+
93147
# delete unused error models
94148
- from: models.go
95149
where: $
@@ -104,14 +158,6 @@ directive:
104158
where: $
105159
transform: return $.replace(/(?:\/\/.*\s)+func \(\w \*?(?:ErrorInfo|ErrorDetail)\).*\{\s(?:.+\s)+\}\s/g, "");
106160

107-
# delete generated table struct, using custom one instead
108-
- from: models.go
109-
where: $
110-
transform: return $.replace(/(?:\/\/.*\s)+type (Table).+\{(?:\s.+\s)+\}\s/g, "");
111-
- from: models_serde.go
112-
where: $
113-
transform: return $.replace(/(?:\/\/.*\s)+func \(\w \*?(\*Table)\).*\{\s(?:.+\s)+\}\s/g, "");
114-
115161
# delete generated constructor and client
116162
- from: logs_client.go
117163
where: $
@@ -139,21 +185,37 @@ directive:
139185
where: $
140186
transform: return $.replace(/const host = "(.*?)"/, "");
141187

188+
# change Table.Rows from type [][]interface{} to type []Row
189+
- from: models.go
190+
where: $
191+
transform: return $.replace(/Rows \[\]\[\]interface{}/, "Rows []Row");
192+
142193
# change render and statistics type to []byte
143194
- from: models.go
144195
where: $
145-
transform: return $.replace(/interface{}/g, "[]byte");
196+
transform: return $.replace(/Statistics interface{}/g, "Statistics []byte");
197+
- from: models.go
198+
where: $
199+
transform: return $.replace(/Visualization interface{}/g, "Visualization []byte");
146200
- from: models_serde.go
147201
where: $
148202
transform: return
149203
$.replace(/err(.*)r\.Statistics\)/, "r.Statistics = val")
150204
- from: models_serde.go
151205
where: $
152-
transform: return $.replace(/err(.*)r\.Render\)/, "r.Render = val");
206+
transform: return $.replace(/err(.*)r\.Visualization\)/, "r.Visualization = val");
153207
- from: models_serde.go
154208
where: $
155209
transform: return
156210
$.replace(/err(.*)b\.Statistics\)/, "b.Statistics = val")
157211
- from: models_serde.go
158212
where: $
159-
transform: return $.replace(/err(.*)b\.Render\)/, "b.Render = val");
213+
transform: return $.replace(/err(.*)b\.Visualization\)/, "b.Visualization = val");
214+
215+
# change type of timespan from *string to *TimeInterval
216+
- from: models.go
217+
where: $
218+
transform: return $.replace(/Timespan \*string/g, "Timespan *TimeInterval");
219+
- from: metrics_client.go
220+
where: $
221+
transform: return $.replace(/reqQP\.Set\(\"timespan\", \*options\.Timespan\)/g, "reqQP.Set(\"timespan\", string(*options.Timespan))");

sdk/monitor/azquery/custom_client.go

Lines changed: 74 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import (
1313
"errors"
1414
"fmt"
1515
"reflect"
16+
"strings"
17+
"time"
1618

1719
"github.com/Azure/azure-sdk-for-go/sdk/azcore"
1820
"github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
@@ -109,47 +111,83 @@ func (e *ErrorInfo) Error() string {
109111
// Row of data in a table, types of data used by service specified in LogsColumnType
110112
type Row []any
111113

112-
// Table - Contains the columns and rows for one table in a query response.
113-
type Table struct {
114-
// REQUIRED; The list of columns in this table.
115-
Columns []*Column `json:"columns,omitempty"`
114+
// TimeInterval specifies the time range over which to query.
115+
// Use NewTimeInterval() for help formatting.
116+
// Follows the ISO8601 time interval standard with most common
117+
// format being startISOTime/endISOTime. ISO8601 durations also supported (ex "PT2H" for last two hours).
118+
// Use UTC for all times.
119+
type TimeInterval string
120+
121+
// NewTimeInterval creates a TimeInterval for use in a query.
122+
// Use UTC for start and end times.
123+
func NewTimeInterval(start time.Time, end time.Time) TimeInterval {
124+
return TimeInterval(start.Format(time.RFC3339) + "/" + end.Format(time.RFC3339))
125+
}
116126

117-
// REQUIRED; The name of the table.
118-
Name *string `json:"name,omitempty"`
127+
// Values returns the interval's start and end times if it's in the format startISOTime/endISOTime, else it will return an error.
128+
func (i TimeInterval) Values() (time.Time, time.Time, error) {
129+
// split into different start and end times
130+
times := strings.Split(string(i), "/")
131+
if len(times) != 2 {
132+
return time.Time{}, time.Time{}, errors.New("time interval should be in format startISOTime/endISOTime")
133+
}
134+
start, err := time.Parse(time.RFC3339, times[0])
135+
if err != nil {
136+
return time.Time{}, time.Time{}, errors.New("error parsing start time")
137+
}
138+
end, err := time.Parse(time.RFC3339, times[1])
139+
if err != nil {
140+
return time.Time{}, time.Time{}, errors.New("error parsing end time")
141+
}
142+
// return times
143+
return start, end, nil
144+
}
119145

120-
// REQUIRED; The resulting rows from this query.
121-
Rows []Row `json:"rows,omitempty"`
146+
// LogsQueryOptions sets server timeout, query statistics and visualization information
147+
type LogsQueryOptions struct {
148+
// Set Statistics to true to get logs query execution statistics,
149+
// such as CPU and memory consumption. Defaults to false.
150+
Statistics *bool
151+
152+
// Set Visualization to true to get visualization
153+
// data for logs queries. Defaults to false.
154+
Visualization *bool
155+
156+
// By default, the Azure Monitor Query service will run your
157+
// query for up to three minutes. To increase the default timeout,
158+
// set Wait to desired number of seconds.
159+
// Max wait time the service will allow is ten minutes (600 seconds).
160+
Wait *int
161+
}
122162

123-
// maps column name to index for easy lookup, helper for accessing Row data
124-
ColumnIndexLookup map[string]int `json:"-"`
163+
// String implements the fmt.Stringer interface for type LogsQueryOptions.
164+
func (l LogsQueryOptions) String() string {
165+
var options []string
166+
if l.Statistics != nil && *l.Statistics {
167+
options = append(options, "include-statistics=true")
168+
}
169+
if l.Visualization != nil && *l.Visualization {
170+
options = append(options, "include-render=true")
171+
}
172+
if l.Wait != nil {
173+
options = append(options, fmt.Sprintf("wait=%d", *l.Wait))
174+
}
175+
return strings.Join(options, ",")
125176
}
126177

127-
// UnmarshalJSON implements the json.Unmarshaller interface for type Table.
128-
func (t *Table) UnmarshalJSON(data []byte) error {
129-
var rawMsg map[string]json.RawMessage
130-
if err := json.Unmarshal(data, &rawMsg); err != nil {
131-
return fmt.Errorf("unmarshalling type %T: %v", t, err)
178+
// NewBatchQueryRequest creates a new BatchQueryRequest.
179+
func NewBatchQueryRequest(workspaceID string, query string, timespan TimeInterval, correlationID string, options LogsQueryOptions) BatchQueryRequest {
180+
var optionsMap map[string]*string
181+
if options.Statistics != nil || options.Visualization != nil || options.Wait != nil {
182+
optionsMap = make(map[string]*string)
183+
optionsString := options.String()
184+
optionsMap["prefer"] = &optionsString
132185
}
133-
for key, val := range rawMsg {
134-
var err error
135-
switch key {
136-
case "columns":
137-
err = unpopulate(val, "Columns", &t.Columns)
138-
delete(rawMsg, key)
139-
t.ColumnIndexLookup = map[string]int{}
140-
for i, v := range t.Columns {
141-
t.ColumnIndexLookup[*v.Name] = i
142-
}
143-
case "name":
144-
err = unpopulate(val, "Name", &t.Name)
145-
delete(rawMsg, key)
146-
case "rows":
147-
err = unpopulate(val, "Rows", &t.Rows)
148-
delete(rawMsg, key)
149-
}
150-
if err != nil {
151-
return fmt.Errorf("unmarshalling type %T: %v", t, err)
152-
}
186+
187+
return BatchQueryRequest{
188+
Body: &Body{Query: &query, Timespan: &timespan},
189+
CorrelationID: &correlationID,
190+
WorkspaceID: &workspaceID,
191+
Headers: optionsMap,
153192
}
154-
return nil
155193
}

0 commit comments

Comments
 (0)