Skip to content

Commit 4fac3c1

Browse files
authored
Merge pull request #156 from TelemetryDeck/feature/update-api
Update API, models and TelemetryClient
2 parents 61d7c98 + 1b1e80c commit 4fac3c1

File tree

11 files changed

+105
-55
lines changed

11 files changed

+105
-55
lines changed

Services/MockData.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ struct MockData {
6060
groupID: UUID(),
6161
order: 0,
6262
title: "Preview",
63+
type: .timeseries,
6364
accentColor: nil,
6465
widgetable: false,
6566
customQuery: nil,

Services/QueryService.swift

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,23 @@ class QueryService: ObservableObject {
7474

7575
func getInsightQuery(ofInsightWithID insightID: DTOv2.Insight.ID) async throws -> CustomQuery {
7676
return try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<CustomQuery, Error>) in
77-
let url = api.urlForPath(apiVersion: .v3, "insights", insightID.uuidString, "query",
78-
Formatter.iso8601noFS.string(from: timeWindowBeginningDate),
79-
Formatter.iso8601noFS.string(from: timeWindowEndDate),
80-
"\(isTestingMode ? "true" : "live")")
81-
api.get(url) { (result: Result<CustomQuery, TransferError>) in
77+
let url = api.urlForPath(apiVersion: .v3, "insights", insightID.uuidString, "query")
78+
79+
struct ProduceQueryBody: Codable {
80+
/// Is Test Mode enabled? (nil means false)
81+
public var testMode: Bool?
82+
83+
/// Which time intervals are we looking at?
84+
public var relativeInterval: RelativeTimeInterval?
85+
public var interval: QueryTimeInterval?
86+
}
87+
88+
let produceQueryBody = ProduceQueryBody(testMode: isTestingMode, interval: .init(beginningDate: timeWindowBeginningDate, endDate: timeWindowEndDate))
89+
90+
91+
api.post(produceQueryBody, to: url) { (result: Result<CustomQuery, TransferError>) in
8292
switch result {
8393
case .success(let query):
84-
8594
continuation.resume(returning: query)
8695

8796
case .failure(let error):
@@ -94,6 +103,13 @@ class QueryService: ObservableObject {
94103

95104
func createTask(forQuery query: CustomQuery) async throws -> [String: String] {
96105
return try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<[String: String], Error>) in
106+
107+
// If the query has no specified interval, give it the default interval
108+
var query = query
109+
if query.relativeIntervals == nil && query.intervals == nil {
110+
query.intervals = [.init(beginningDate: timeWindowBeginningDate, endDate: timeWindowEndDate)]
111+
}
112+
97113
let url = api.urlForPath(apiVersion: .v3, "query", "calculate-async")
98114
api.post(query, to: url) { (result: Result<[String: String], TransferError>) in
99115
switch result {

SwiftUICharts/Charts/ChartHoverLabel.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import SwiftUI
1010

1111
struct ChartHoverLabel: View {
1212
let dataEntry: ChartDataPoint
13-
let interval: InsightGroupByInterval
13+
let interval: QueryGranularity
1414

1515
var body: some View {
1616
VStack(alignment: .leading) {

SwiftUICharts/Charts/RawChartView.swift

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,8 @@ public struct SingleValueView: View {
6666
VStack(alignment: .leading) {
6767
if let lastData = insightData.data.last,
6868
let doubleValue = lastData.yAxisValue,
69-
let dateValue = xAxisDefinition(insightData: lastData, groupBy: insightData.groupBy) {
69+
let dateValue = xAxisDefinition(insightData: lastData, groupBy: insightData.groupBy)
70+
{
7071
VStack(alignment: .leading) {
7172
ValueAndUnitView(value: Double(doubleValue), unit: "", shouldFormatBigNumbers: true)
7273
.foregroundColor(isSelected ? .cardBackground : .primary)
@@ -91,7 +92,7 @@ public struct SingleValueView: View {
9192
}
9293
}
9394

94-
func xAxisDefinition(insightData: ChartDataPoint, groupBy: InsightGroupByInterval? = .day) -> Text {
95+
func xAxisDefinition(insightData: ChartDataPoint, groupBy: QueryGranularity? = .day) -> Text {
9596
Text(dateString(from: insightData, groupedBy: groupBy))
9697
}
9798

@@ -166,7 +167,7 @@ public struct RawTableView: View {
166167
}
167168
}
168169

169-
func dateString(from chartDataPoint: ChartDataPoint, groupedBy groupByInterval: InsightGroupByInterval?) -> String {
170+
func dateString(from chartDataPoint: ChartDataPoint, groupedBy groupByInterval: QueryGranularity?) -> String {
170171
guard let date = chartDataPoint.xAxisDate else { return chartDataPoint.xAxisValue }
171172

172173
let formatter = DateFormatter()
@@ -189,6 +190,10 @@ func dateString(from chartDataPoint: ChartDataPoint, groupedBy groupByInterval:
189190
formatter.setLocalizedDateFormatFromTemplate("MMMM yyyy")
190191
formatter.timeZone = TimeZone(abbreviation: "UTC")
191192
return formatter.string(from: date)
193+
default:
194+
formatter.dateStyle = .long
195+
formatter.timeStyle = .long
196+
return formatter.string(from: date)
192197
}
193198
}
194199

SwiftUICharts/Models/ChartDataSet.swift

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,19 @@ public struct ChartDataSet {
1818
public let data: [ChartDataPoint]
1919
public let highestValue: Int64
2020
public let lowestValue: Int64
21-
public let groupBy: InsightGroupByInterval?
21+
public let groupBy: QueryGranularity?
2222

2323
public var isEmpty: Bool { data.isEmpty }
2424

25-
public init(data: [ChartDataPoint], groupBy: InsightGroupByInterval? = nil) {
25+
public init(data: [ChartDataPoint], groupBy: QueryGranularity? = nil) {
2626
self.data = data
2727
self.groupBy = groupBy
2828

2929
highestValue = self.data.reduce(0) { max($0, $1.yAxisValue ?? 0) }
3030
lowestValue = 0
3131
}
3232

33-
public init(fromQueryResultWrapper queryResultWrapper: QueryResultWrapper?, groupBy: InsightGroupByInterval? = nil) throws {
33+
public init(fromQueryResultWrapper queryResultWrapper: QueryResultWrapper?, groupBy: QueryGranularity? = nil) throws {
3434
guard let queryResult = queryResultWrapper?.result else { throw ChartDataSetError.conversionError(message: "QueryResult is nil.") }
3535

3636
switch queryResult {
@@ -42,7 +42,7 @@ public struct ChartDataSet {
4242
var data: [ChartDataPoint] = []
4343

4444
for row in timeSeriesRows {
45-
let yValue = row.result.values.first ?? 0
45+
let yValue = row.result.values.first?.value ?? 0
4646
let yInt = Int64(yValue)
4747
data.append(ChartDataPoint(xAxisDate: row.timestamp, yAxisValue: yInt))
4848
}
@@ -95,6 +95,22 @@ public struct ChartDataSet {
9595
return date.isInCurrentWeek
9696
case .month:
9797
return date.isInCurrentMonth
98+
case .all:
99+
return true
100+
case .none:
101+
return false
102+
case .second:
103+
return false
104+
case .minute:
105+
return date.isInCurrent(.minute)
106+
case .fifteen_minute:
107+
return date.isInCurrent(.hour)
108+
case .thirty_minute:
109+
return date.isInCurrent(.hour)
110+
case .quarter:
111+
return date.isInCurrent(.quarter)
112+
case .year:
113+
return date.isInCurrentYear
98114
}
99115
}
100116
}

SwiftUIChartsExtensions/ChartDataSet+InsightCalculationResult.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import DataTransferObjects
99
import Foundation
1010

1111
public extension ChartDataSet {
12-
init(data: [DTOv2.InsightCalculationResultRow], groupBy: DataTransferObjects.InsightGroupByInterval? = nil) {
12+
init(data: [DTOv2.InsightCalculationResultRow], groupBy: DataTransferObjects.QueryGranularity? = nil) {
1313
if let groupBy = groupBy {
14-
let groupBy: InsightGroupByInterval? = InsightGroupByInterval(rawValue: groupBy.rawValue)
14+
let groupBy: QueryGranularity? = QueryGranularity(rawValue: groupBy.rawValue)
1515

1616
self.init(
1717
data: data.map { ChartDataPoint(insightCalculationResultRow: $0) },
@@ -25,9 +25,9 @@ public extension ChartDataSet {
2525
}
2626
}
2727

28-
init(data: [DTOv1.InsightData], groupBy: DataTransferObjects.InsightGroupByInterval? = nil) {
28+
init(data: [DTOv1.InsightData], groupBy: DataTransferObjects.QueryGranularity? = nil) {
2929
if let groupBy = groupBy {
30-
let groupBy: InsightGroupByInterval? = InsightGroupByInterval(rawValue: groupBy.rawValue)
30+
let groupBy: QueryGranularity? = QueryGranularity(rawValue: groupBy.rawValue)
3131
self.init(
3232
data: data.map { ChartDataPoint(insightData: $0) },
3333
groupBy: groupBy

Telemetry Viewer.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@
55
"kind" : "remoteSourceControl",
66
"location" : "https://github.com/TelemetryDeck/models",
77
"state" : {
8-
"revision" : "92f900ec992c51a0f4a271489b4b6de1c6c8cac1",
9-
"version" : "1.5.0"
8+
"revision" : "4cb1a6a75add87086b522019e64532c3a460daea",
9+
"version" : "1.9.0"
1010
}
1111
},
1212
{
1313
"identity" : "swiftclient",
1414
"kind" : "remoteSourceControl",
1515
"location" : "https://github.com/AppTelemetry/SwiftClient",
1616
"state" : {
17-
"revision" : "3c38ccd09b6b4eaa76bb8c5490ecf587ad86c6c7",
18-
"version" : "1.3.0"
17+
"revision" : "f87b6b069ee8d9ae7a500cebcf3a6059695c5025",
18+
"version" : "1.4.1"
1919
}
2020
},
2121
{

Telemetry Viewer.xcodeproj/xcshareddata/xcschemes/Telemetry Viewer (macOS).xcscheme

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@
6060
ReferencedContainer = "container:Telemetry Viewer.xcodeproj">
6161
</BuildableReference>
6262
</BuildableProductRunnable>
63+
<EnvironmentVariables>
64+
<EnvironmentVariable
65+
key = "API_URL"
66+
value = "local"
67+
isEnabled = "YES">
68+
</EnvironmentVariable>
69+
</EnvironmentVariables>
6370
</LaunchAction>
6471
<ProfileAction
6572
buildConfiguration = "Release"

iOS/Components/CustomPickers.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,8 @@ struct DetailedPicker<Item: PickerItem, Summary: View>: View {
5858
struct GroupByPicker: View {
5959
let title: LocalizedStringKey?
6060

61-
@Binding var selection: InsightGroupByInterval
62-
let options: [InsightGroupByInterval]
61+
@Binding var selection: QueryGranularity
62+
let options: [QueryGranularity]
6363
let description: String
6464

6565
var body: some View {

iOS/Insights and Groups/Insights/EditorView.swift

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,22 @@ class EditorViewModel: ObservableObject {
2020
name: "Time Series",
2121
explanation: "A time series insight looks at discrete chunks of time and counts values in those times, " +
2222
"for example 'Signal counts for each day'. These are awesome for displaying in line charts or bar charts.",
23-
id: UUID())
23+
id: UUID()
24+
)
2425
static let breakdown = InsightType(
2526
name: "Breakdown",
2627
explanation: "A breakdown insights collects all signals, extracts a specific payload key from them, and then " +
2728
"gives you a list of which possible values are inside the payload key, and how often they occurred. " +
2829
"Ideal for seeing how many users use each version of your app for example, and well suited with donut charts.",
29-
id: UUID())
30+
id: UUID()
31+
)
3032
static let customQuery = InsightType(
3133
name: "Custom Query",
3234
explanation: "Custom queries allow you to write your query in a JSON based language. We'll add filters for " +
3335
"appID and your selected date range on the server. This is a very experimental early feature right now. " +
3436
"Trust nothing. Trust no one. Everything you found out, you want to forget.",
35-
id: UUID())
37+
id: UUID()
38+
)
3639
}
3740

3841
let groupService: GroupService
@@ -95,6 +98,7 @@ class EditorViewModel: ObservableObject {
9598
groupID: groupID,
9699
order: order,
97100
title: title,
101+
type: insightType != .breakdown ? .timeseries : .topN,
98102
accentColor: accentColor != "" ? accentColor : nil,
99103
signalType: signalType.isEmpty ? nil : signalType,
100104
uniqueUser: uniqueUser,
@@ -170,7 +174,7 @@ class EditorViewModel: ObservableObject {
170174
@Published var breakdownKey: String
171175

172176
/// If set, group and count found signals by this time interval. Incompatible with breakdownKey
173-
@Published var groupBy: InsightGroupByInterval
177+
@Published var groupBy: QueryGranularity
174178

175179
/// Which group should the insight belong to? (Only use this in update mode)
176180
@Published var groupID: UUID {
@@ -276,10 +280,10 @@ struct EditorView: View {
276280
GroupByPicker(title: "Group Values by",
277281
selection: $viewModel.groupBy,
278282
options: [
279-
InsightGroupByInterval.hour,
280-
InsightGroupByInterval.day,
281-
InsightGroupByInterval.week,
282-
InsightGroupByInterval.month
283+
QueryGranularity.hour,
284+
QueryGranularity.day,
285+
QueryGranularity.week,
286+
QueryGranularity.month
283287
],
284288
description: "Group signals by time interval. The more fine-grained the grouping, the more separate values you'll receive.")
285289
}
@@ -289,10 +293,10 @@ struct EditorView: View {
289293
var groupBySection: some View {
290294
CustomSection(header: Text("Group Values by"), summary: Text(viewModel.groupBy.rawValue), footer: Text(""), startCollapsed: true) {
291295
Picker(selection: $viewModel.groupBy, label: Text("")) {
292-
Text("Hour").tag(InsightGroupByInterval.hour)
293-
Text("Day").tag(InsightGroupByInterval.day)
294-
Text("Week").tag(InsightGroupByInterval.week)
295-
Text("Month").tag(InsightGroupByInterval.month)
296+
Text("Hour").tag(QueryGranularity.hour)
297+
Text("Day").tag(QueryGranularity.day)
298+
Text("Week").tag(QueryGranularity.week)
299+
Text("Month").tag(QueryGranularity.month)
296300
}
297301
.pickerStyle(SegmentedPickerStyle())
298302
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
@@ -366,20 +370,20 @@ struct EditorView: View {
366370
Button("Delete this Insight", role: .destructive, action: {
367371
showingAlert = true
368372
})
369-
.alert(isPresented: $showingAlert) {
370-
Alert(
371-
title: Text("Are you sure you want to delete the Insight \(viewModel.title)?"),
372-
message: Text("This will delete the Insight. Your signals are not affected."),
373-
primaryButton: .destructive(Text("Delete")) {
374-
viewModel.insightService.delete(insightID: viewModel.id) { _ in
375-
groupService.retrieveGroup(with: viewModel.groupID)
376-
selectedInsightID = nil
377-
dismiss()
378-
}
379-
},
380-
secondaryButton: .cancel()
381-
)
382-
}
373+
.alert(isPresented: $showingAlert) {
374+
Alert(
375+
title: Text("Are you sure you want to delete the Insight \(viewModel.title)?"),
376+
message: Text("This will delete the Insight. Your signals are not affected."),
377+
primaryButton: .destructive(Text("Delete")) {
378+
viewModel.insightService.delete(insightID: viewModel.id) { _ in
379+
groupService.retrieveGroup(with: viewModel.groupID)
380+
selectedInsightID = nil
381+
dismiss()
382+
}
383+
},
384+
secondaryButton: .cancel()
385+
)
386+
}
383387
}
384388
}
385389

macOS/Insights and Groups/EditorView.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ class EditorViewModel: ObservableObject {
103103
groupID: groupID,
104104
order: order,
105105
title: title,
106+
type: breakdownKey.isEmpty ? .timeseries : .topN,
106107
accentColor: accentColor != "" ? accentColor : nil,
107108
signalType: signalType.isEmpty ? nil : signalType,
108109
uniqueUser: uniqueUser,
@@ -188,7 +189,7 @@ class EditorViewModel: ObservableObject {
188189
@Published var breakdownKey: String { didSet { save() }}
189190

190191
/// If set, group and count found signals by this time interval. Incompatible with breakdownKey
191-
@Published var groupBy: InsightGroupByInterval { didSet { save() }}
192+
@Published var groupBy: QueryGranularity { didSet { save() }}
192193

193194
/// Which group should the insight belong to? (Only use this in update mode)
194195
@Published var groupID: UUID {
@@ -273,10 +274,10 @@ struct EditorView: View {
273274
startCollapsed: true)
274275
{
275276
Picker(selection: $viewModel.groupBy, label: Text("")) {
276-
Text("Hour").tag(InsightGroupByInterval.hour)
277-
Text("Day").tag(InsightGroupByInterval.day)
278-
Text("Week").tag(InsightGroupByInterval.week)
279-
Text("Month").tag(InsightGroupByInterval.month)
277+
Text("Hour").tag(QueryGranularity.hour)
278+
Text("Day").tag(QueryGranularity.day)
279+
Text("Week").tag(QueryGranularity.week)
280+
Text("Month").tag(QueryGranularity.month)
280281
}
281282
.pickerStyle(SegmentedPickerStyle())
282283
}

0 commit comments

Comments
 (0)