Skip to content

Commit

Permalink
Merge pull request #156 from TelemetryDeck/feature/update-api
Browse files Browse the repository at this point in the history
Update API, models and TelemetryClient
  • Loading branch information
winsmith authored Feb 3, 2023
2 parents 61d7c98 + 1b1e80c commit 4fac3c1
Show file tree
Hide file tree
Showing 11 changed files with 105 additions and 55 deletions.
1 change: 1 addition & 0 deletions Services/MockData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ struct MockData {
groupID: UUID(),
order: 0,
title: "Preview",
type: .timeseries,
accentColor: nil,
widgetable: false,
customQuery: nil,
Expand Down
28 changes: 22 additions & 6 deletions Services/QueryService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,23 @@ class QueryService: ObservableObject {

func getInsightQuery(ofInsightWithID insightID: DTOv2.Insight.ID) async throws -> CustomQuery {
return try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<CustomQuery, Error>) in
let url = api.urlForPath(apiVersion: .v3, "insights", insightID.uuidString, "query",
Formatter.iso8601noFS.string(from: timeWindowBeginningDate),
Formatter.iso8601noFS.string(from: timeWindowEndDate),
"\(isTestingMode ? "true" : "live")")
api.get(url) { (result: Result<CustomQuery, TransferError>) in
let url = api.urlForPath(apiVersion: .v3, "insights", insightID.uuidString, "query")

struct ProduceQueryBody: Codable {
/// Is Test Mode enabled? (nil means false)
public var testMode: Bool?

/// Which time intervals are we looking at?
public var relativeInterval: RelativeTimeInterval?
public var interval: QueryTimeInterval?
}

let produceQueryBody = ProduceQueryBody(testMode: isTestingMode, interval: .init(beginningDate: timeWindowBeginningDate, endDate: timeWindowEndDate))


api.post(produceQueryBody, to: url) { (result: Result<CustomQuery, TransferError>) in
switch result {
case .success(let query):

continuation.resume(returning: query)

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

func createTask(forQuery query: CustomQuery) async throws -> [String: String] {
return try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<[String: String], Error>) in

// If the query has no specified interval, give it the default interval
var query = query
if query.relativeIntervals == nil && query.intervals == nil {
query.intervals = [.init(beginningDate: timeWindowBeginningDate, endDate: timeWindowEndDate)]
}

let url = api.urlForPath(apiVersion: .v3, "query", "calculate-async")
api.post(query, to: url) { (result: Result<[String: String], TransferError>) in
switch result {
Expand Down
2 changes: 1 addition & 1 deletion SwiftUICharts/Charts/ChartHoverLabel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import SwiftUI

struct ChartHoverLabel: View {
let dataEntry: ChartDataPoint
let interval: InsightGroupByInterval
let interval: QueryGranularity

var body: some View {
VStack(alignment: .leading) {
Expand Down
11 changes: 8 additions & 3 deletions SwiftUICharts/Charts/RawChartView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ public struct SingleValueView: View {
VStack(alignment: .leading) {
if let lastData = insightData.data.last,
let doubleValue = lastData.yAxisValue,
let dateValue = xAxisDefinition(insightData: lastData, groupBy: insightData.groupBy) {
let dateValue = xAxisDefinition(insightData: lastData, groupBy: insightData.groupBy)
{
VStack(alignment: .leading) {
ValueAndUnitView(value: Double(doubleValue), unit: "", shouldFormatBigNumbers: true)
.foregroundColor(isSelected ? .cardBackground : .primary)
Expand All @@ -91,7 +92,7 @@ public struct SingleValueView: View {
}
}

func xAxisDefinition(insightData: ChartDataPoint, groupBy: InsightGroupByInterval? = .day) -> Text {
func xAxisDefinition(insightData: ChartDataPoint, groupBy: QueryGranularity? = .day) -> Text {
Text(dateString(from: insightData, groupedBy: groupBy))
}

Expand Down Expand Up @@ -166,7 +167,7 @@ public struct RawTableView: View {
}
}

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

let formatter = DateFormatter()
Expand All @@ -189,6 +190,10 @@ func dateString(from chartDataPoint: ChartDataPoint, groupedBy groupByInterval:
formatter.setLocalizedDateFormatFromTemplate("MMMM yyyy")
formatter.timeZone = TimeZone(abbreviation: "UTC")
return formatter.string(from: date)
default:
formatter.dateStyle = .long
formatter.timeStyle = .long
return formatter.string(from: date)
}
}

Expand Down
24 changes: 20 additions & 4 deletions SwiftUICharts/Models/ChartDataSet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,19 @@ public struct ChartDataSet {
public let data: [ChartDataPoint]
public let highestValue: Int64
public let lowestValue: Int64
public let groupBy: InsightGroupByInterval?
public let groupBy: QueryGranularity?

public var isEmpty: Bool { data.isEmpty }

public init(data: [ChartDataPoint], groupBy: InsightGroupByInterval? = nil) {
public init(data: [ChartDataPoint], groupBy: QueryGranularity? = nil) {
self.data = data
self.groupBy = groupBy

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

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

switch queryResult {
Expand All @@ -42,7 +42,7 @@ public struct ChartDataSet {
var data: [ChartDataPoint] = []

for row in timeSeriesRows {
let yValue = row.result.values.first ?? 0
let yValue = row.result.values.first?.value ?? 0
let yInt = Int64(yValue)
data.append(ChartDataPoint(xAxisDate: row.timestamp, yAxisValue: yInt))
}
Expand Down Expand Up @@ -95,6 +95,22 @@ public struct ChartDataSet {
return date.isInCurrentWeek
case .month:
return date.isInCurrentMonth
case .all:
return true
case .none:
return false
case .second:
return false
case .minute:
return date.isInCurrent(.minute)
case .fifteen_minute:
return date.isInCurrent(.hour)
case .thirty_minute:
return date.isInCurrent(.hour)
case .quarter:
return date.isInCurrent(.quarter)
case .year:
return date.isInCurrentYear
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import DataTransferObjects
import Foundation

public extension ChartDataSet {
init(data: [DTOv2.InsightCalculationResultRow], groupBy: DataTransferObjects.InsightGroupByInterval? = nil) {
init(data: [DTOv2.InsightCalculationResultRow], groupBy: DataTransferObjects.QueryGranularity? = nil) {
if let groupBy = groupBy {
let groupBy: InsightGroupByInterval? = InsightGroupByInterval(rawValue: groupBy.rawValue)
let groupBy: QueryGranularity? = QueryGranularity(rawValue: groupBy.rawValue)

self.init(
data: data.map { ChartDataPoint(insightCalculationResultRow: $0) },
Expand All @@ -25,9 +25,9 @@ public extension ChartDataSet {
}
}

init(data: [DTOv1.InsightData], groupBy: DataTransferObjects.InsightGroupByInterval? = nil) {
init(data: [DTOv1.InsightData], groupBy: DataTransferObjects.QueryGranularity? = nil) {
if let groupBy = groupBy {
let groupBy: InsightGroupByInterval? = InsightGroupByInterval(rawValue: groupBy.rawValue)
let groupBy: QueryGranularity? = QueryGranularity(rawValue: groupBy.rawValue)
self.init(
data: data.map { ChartDataPoint(insightData: $0) },
groupBy: groupBy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/TelemetryDeck/models",
"state" : {
"revision" : "92f900ec992c51a0f4a271489b4b6de1c6c8cac1",
"version" : "1.5.0"
"revision" : "4cb1a6a75add87086b522019e64532c3a460daea",
"version" : "1.9.0"
}
},
{
"identity" : "swiftclient",
"kind" : "remoteSourceControl",
"location" : "https://github.com/AppTelemetry/SwiftClient",
"state" : {
"revision" : "3c38ccd09b6b4eaa76bb8c5490ecf587ad86c6c7",
"version" : "1.3.0"
"revision" : "f87b6b069ee8d9ae7a500cebcf3a6059695c5025",
"version" : "1.4.1"
}
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@
ReferencedContainer = "container:Telemetry Viewer.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<EnvironmentVariables>
<EnvironmentVariable
key = "API_URL"
value = "local"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
Expand Down
4 changes: 2 additions & 2 deletions iOS/Components/CustomPickers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ struct DetailedPicker<Item: PickerItem, Summary: View>: View {
struct GroupByPicker: View {
let title: LocalizedStringKey?

@Binding var selection: InsightGroupByInterval
let options: [InsightGroupByInterval]
@Binding var selection: QueryGranularity
let options: [QueryGranularity]
let description: String

var body: some View {
Expand Down
56 changes: 30 additions & 26 deletions iOS/Insights and Groups/Insights/EditorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,22 @@ class EditorViewModel: ObservableObject {
name: "Time Series",
explanation: "A time series insight looks at discrete chunks of time and counts values in those times, " +
"for example 'Signal counts for each day'. These are awesome for displaying in line charts or bar charts.",
id: UUID())
id: UUID()
)
static let breakdown = InsightType(
name: "Breakdown",
explanation: "A breakdown insights collects all signals, extracts a specific payload key from them, and then " +
"gives you a list of which possible values are inside the payload key, and how often they occurred. " +
"Ideal for seeing how many users use each version of your app for example, and well suited with donut charts.",
id: UUID())
id: UUID()
)
static let customQuery = InsightType(
name: "Custom Query",
explanation: "Custom queries allow you to write your query in a JSON based language. We'll add filters for " +
"appID and your selected date range on the server. This is a very experimental early feature right now. " +
"Trust nothing. Trust no one. Everything you found out, you want to forget.",
id: UUID())
id: UUID()
)
}

let groupService: GroupService
Expand Down Expand Up @@ -95,6 +98,7 @@ class EditorViewModel: ObservableObject {
groupID: groupID,
order: order,
title: title,
type: insightType != .breakdown ? .timeseries : .topN,
accentColor: accentColor != "" ? accentColor : nil,
signalType: signalType.isEmpty ? nil : signalType,
uniqueUser: uniqueUser,
Expand Down Expand Up @@ -170,7 +174,7 @@ class EditorViewModel: ObservableObject {
@Published var breakdownKey: String

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

/// Which group should the insight belong to? (Only use this in update mode)
@Published var groupID: UUID {
Expand Down Expand Up @@ -276,10 +280,10 @@ struct EditorView: View {
GroupByPicker(title: "Group Values by",
selection: $viewModel.groupBy,
options: [
InsightGroupByInterval.hour,
InsightGroupByInterval.day,
InsightGroupByInterval.week,
InsightGroupByInterval.month
QueryGranularity.hour,
QueryGranularity.day,
QueryGranularity.week,
QueryGranularity.month
],
description: "Group signals by time interval. The more fine-grained the grouping, the more separate values you'll receive.")
}
Expand All @@ -289,10 +293,10 @@ struct EditorView: View {
var groupBySection: some View {
CustomSection(header: Text("Group Values by"), summary: Text(viewModel.groupBy.rawValue), footer: Text(""), startCollapsed: true) {
Picker(selection: $viewModel.groupBy, label: Text("")) {
Text("Hour").tag(InsightGroupByInterval.hour)
Text("Day").tag(InsightGroupByInterval.day)
Text("Week").tag(InsightGroupByInterval.week)
Text("Month").tag(InsightGroupByInterval.month)
Text("Hour").tag(QueryGranularity.hour)
Text("Day").tag(QueryGranularity.day)
Text("Week").tag(QueryGranularity.week)
Text("Month").tag(QueryGranularity.month)
}
.pickerStyle(SegmentedPickerStyle())
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
Expand Down Expand Up @@ -366,20 +370,20 @@ struct EditorView: View {
Button("Delete this Insight", role: .destructive, action: {
showingAlert = true
})
.alert(isPresented: $showingAlert) {
Alert(
title: Text("Are you sure you want to delete the Insight \(viewModel.title)?"),
message: Text("This will delete the Insight. Your signals are not affected."),
primaryButton: .destructive(Text("Delete")) {
viewModel.insightService.delete(insightID: viewModel.id) { _ in
groupService.retrieveGroup(with: viewModel.groupID)
selectedInsightID = nil
dismiss()
}
},
secondaryButton: .cancel()
)
}
.alert(isPresented: $showingAlert) {
Alert(
title: Text("Are you sure you want to delete the Insight \(viewModel.title)?"),
message: Text("This will delete the Insight. Your signals are not affected."),
primaryButton: .destructive(Text("Delete")) {
viewModel.insightService.delete(insightID: viewModel.id) { _ in
groupService.retrieveGroup(with: viewModel.groupID)
selectedInsightID = nil
dismiss()
}
},
secondaryButton: .cancel()
)
}
}
}

Expand Down
11 changes: 6 additions & 5 deletions macOS/Insights and Groups/EditorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class EditorViewModel: ObservableObject {
groupID: groupID,
order: order,
title: title,
type: breakdownKey.isEmpty ? .timeseries : .topN,
accentColor: accentColor != "" ? accentColor : nil,
signalType: signalType.isEmpty ? nil : signalType,
uniqueUser: uniqueUser,
Expand Down Expand Up @@ -188,7 +189,7 @@ class EditorViewModel: ObservableObject {
@Published var breakdownKey: String { didSet { save() }}

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

/// Which group should the insight belong to? (Only use this in update mode)
@Published var groupID: UUID {
Expand Down Expand Up @@ -273,10 +274,10 @@ struct EditorView: View {
startCollapsed: true)
{
Picker(selection: $viewModel.groupBy, label: Text("")) {
Text("Hour").tag(InsightGroupByInterval.hour)
Text("Day").tag(InsightGroupByInterval.day)
Text("Week").tag(InsightGroupByInterval.week)
Text("Month").tag(InsightGroupByInterval.month)
Text("Hour").tag(QueryGranularity.hour)
Text("Day").tag(QueryGranularity.day)
Text("Week").tag(QueryGranularity.week)
Text("Month").tag(QueryGranularity.month)
}
.pickerStyle(SegmentedPickerStyle())
}
Expand Down

0 comments on commit 4fac3c1

Please sign in to comment.