Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(metrics): Change adding set to string #3792

Merged
merged 5 commits into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Sentry.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
62262B8B2BA1C4C1004DA3DD /* EncodeMetrics.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62262B8A2BA1C4C1004DA3DD /* EncodeMetrics.swift */; };
62262B8D2BA1C4DB004DA3DD /* Metric.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62262B8C2BA1C4DB004DA3DD /* Metric.swift */; };
62262B912BA1C520004DA3DD /* CounterMetric.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62262B902BA1C520004DA3DD /* CounterMetric.swift */; };
6229416A2BB2F123004765D1 /* SentryNSDataUtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 622941692BB2F123004765D1 /* SentryNSDataUtilsTests.swift */; };
622C08D829E546F4002571D4 /* SentryTraceOrigins.h in Headers */ = {isa = PBXBuildFile; fileRef = 622C08D729E546F4002571D4 /* SentryTraceOrigins.h */; };
622C08DB29E554B9002571D4 /* SentrySpanContext+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 622C08D929E554B9002571D4 /* SentrySpanContext+Private.h */; };
62375FB92B47F9F000CC55F1 /* SentryDependencyContainerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62375FB82B47F9F000CC55F1 /* SentryDependencyContainerTests.swift */; };
Expand Down Expand Up @@ -998,6 +999,7 @@
62262B8C2BA1C4DB004DA3DD /* Metric.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Metric.swift; sourceTree = "<group>"; };
62262B902BA1C520004DA3DD /* CounterMetric.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CounterMetric.swift; sourceTree = "<group>"; };
62262B952BA1C564004DA3DD /* EncodeMetricTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncodeMetricTests.swift; sourceTree = "<group>"; };
622941692BB2F123004765D1 /* SentryNSDataUtilsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryNSDataUtilsTests.swift; sourceTree = "<group>"; };
622C08D729E546F4002571D4 /* SentryTraceOrigins.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryTraceOrigins.h; path = include/SentryTraceOrigins.h; sourceTree = "<group>"; };
622C08D929E554B9002571D4 /* SentrySpanContext+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "SentrySpanContext+Private.h"; path = "include/SentrySpanContext+Private.h"; sourceTree = "<group>"; };
62375FB82B47F9F000CC55F1 /* SentryDependencyContainerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryDependencyContainerTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2809,6 +2811,7 @@
children = (
7B6438A626A70DDB000D0F65 /* UIViewControllerSentryTests.swift */,
7B0DC73328869BF40039995F /* NSMutableDictionarySentryTests.swift */,
622941692BB2F123004765D1 /* SentryNSDataUtilsTests.swift */,
);
path = Categories;
sourceTree = "<group>";
Expand Down Expand Up @@ -4533,6 +4536,7 @@
7B2A70DF27D60904008B0D15 /* SentryTestThreadWrapper.swift in Sources */,
7BE912AF272166DD00E49E62 /* SentryNoOpSpanTests.swift in Sources */,
62991A8F2BAC24ED0078A8B8 /* SentryMetricsAPITests.swift in Sources */,
6229416A2BB2F123004765D1 /* SentryNSDataUtilsTests.swift in Sources */,
7B56D73524616E5600B842DA /* SentryConcurrentRateLimitsDictionaryTests.swift in Sources */,
7B7D8730248648AD00D2ECFF /* SentryStacktraceBuilderTests.swift in Sources */,
62E081AB29ED4322000F69FC /* SentryBreadcrumbTestDelegate.swift in Sources */,
Expand Down
7 changes: 7 additions & 0 deletions Sources/Sentry/SentryNSDataUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,11 @@
return mutable;
}

NSUInteger
sentry_crc32ofString(NSString *value)
{
NSData *data = [value dataUsingEncoding:NSUTF8StringEncoding];
return crc32(0, data.bytes, (uInt)[data length]);
}

NS_ASSUME_NONNULL_END
6 changes: 6 additions & 0 deletions Sources/Sentry/include/SentryNSDataUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,10 @@ NSData *_Nullable sentry_gzippedWithCompressionLevel(
*/
NSData *_Nullable sentry_nullTerminated(NSData *_Nullable data);

/**
* Calculates an CRC32 (Cyclic Redundancy Check 32) checksum for the string by first encoding it to
* UTF8Encoded data.
*/
NSUInteger sentry_crc32ofString(NSString *value);

NS_ASSUME_NONNULL_END
1 change: 1 addition & 0 deletions Sources/Sentry/include/SentryPrivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#import "SentryBaggage.h"
#import "SentryBaseIntegration.h"
#import "SentryDispatchQueueWrapper.h"
#import "SentryNSDataUtils.h"
#import "SentryRandom.h"
#import "SentrySdkInfo.h"
#import "SentryStatsdClient.h"
Expand Down
2 changes: 1 addition & 1 deletion Sources/Swift/Metrics/BucketsMetricsAggregator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class BucketMetricsAggregator: MetricsAggregator {
case .distribution:
return DistributionMetric(first: first, key: key, unit: unit, tags: tags)
case .set:
return SetMetric(first: Int32(first), key: key, unit: unit, tags: tags)
return SetMetric(first: UInt(first), key: key, unit: unit, tags: tags)
}
}

Expand Down
7 changes: 5 additions & 2 deletions Sources/Swift/Metrics/SentryMetricsAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,12 @@ import Foundation
/// - Parameter unit: The value for the metric see `MeasurementUnit`.
/// - Parameter tags: Tags to associate with the metric.
@objc
public func set(key: String, value: Int32, unit: MeasurementUnit = .none, tags: [String: String] = [:]) {
public func set(key: String, value: String, unit: MeasurementUnit = .none, tags: [String: String] = [:]) {
let mergedTags = mergeDefaultTagsInto(tags: tags)
aggregator.add(type: MetricType.set, key: key, value: Double(value), unit: unit, tags: mergedTags, localMetricsAggregator: delegate?.getLocalMetricsAggregator())

let crc32 = sentry_crc32ofString(value)

aggregator.add(type: MetricType.set, key: key, value: Double(crc32), unit: unit, tags: mergedTags, localMetricsAggregator: delegate?.getLocalMetricsAggregator())
}

@objc public func close() {
Expand Down
9 changes: 6 additions & 3 deletions Sources/Swift/Metrics/SetMetric.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,21 @@ import Foundation

class SetMetric: Metric {

private var set: Set<Int32>
private var set: Set<UInt>
var weight: UInt {
return UInt(set.count)
}

init(first: Int32, key: String, unit: MeasurementUnit, tags: [String: String]) {
init(first: UInt, key: String, unit: MeasurementUnit, tags: [String: String]) {
set = [first]
super.init(type: .set, key: key, unit: unit, tags: tags)
}

// This doesn't work with the full range of UInt.
// We still need to fix this.
func add(value: Double) {
set.insert(Int32(value))
if value >= Double(UInt.min) && value < Double(UInt.max) { set.insert(UInt(value))
}
}

func serialize() -> [String] {
Expand Down
19 changes: 19 additions & 0 deletions Tests/SentryTests/Categories/SentryNSDataUtilsTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Nimble
import Sentry
import XCTest

final class SentryNSDataUtilsTests: XCTestCase {

func testCRC32OfString_SameString_ReturnsSameResult() throws {
let result1 = sentry_crc32ofString("test-string")
let result2 = sentry_crc32ofString("test-string")
expect(result1) == result2
}

func testCRC32OfString_DifferentString_ReturnsDifferentResult() throws {
let result1 = sentry_crc32ofString("test-string")
let result2 = sentry_crc32ofString("test-string1")
expect(result1) != result2
}

}
9 changes: 5 additions & 4 deletions Tests/SentryTests/Swift/Metrics/SentryMetricsAPITests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ final class SentryMetricsAPITests: XCTestCase, SentryMetricsAPIDelegate {
sut.increment(key: "some", value: 1.0, unit: .none, tags: ["yeah": "sentry"])
sut.gauge(key: "some", value: 1.0, unit: .none, tags: ["yeah": "sentry"])
sut.distribution(key: "some", value: 1.0, unit: .none, tags: ["yeah": "sentry"])
sut.set(key: "some", value: 1, unit: .none, tags: ["yeah": "sentry"])
sut.set(key: "some", value: "value", unit: .none, tags: ["yeah": "sentry"])

sut.close()

Expand Down Expand Up @@ -92,8 +92,9 @@ final class SentryMetricsAPITests: XCTestCase, SentryMetricsAPIDelegate {
let sut = SentryMetricsAPI(enabled: true, client: metricsClient, currentDate: SentryCurrentDateProvider(), dispatchQueue: SentryDispatchQueueWrapper(), random: SentryRandom())
sut.setDelegate(self)

sut.set(key: "key", value: 1, unit: MeasurementUnitFraction.percent, tags: ["yeah": "sentry"])
sut.set(key: "key", value: 12, unit: MeasurementUnitFraction.percent, tags: ["yeah": "sentry"])
sut.set(key: "key", value: "value1", unit: MeasurementUnitFraction.percent, tags: ["yeah": "sentry"])
sut.set(key: "key", value: "value1", unit: MeasurementUnitFraction.percent, tags: ["yeah": "sentry"])
sut.set(key: "key", value: "value12", unit: MeasurementUnitFraction.percent, tags: ["yeah": "sentry"])

sut.flush()

Expand All @@ -105,7 +106,7 @@ final class SentryMetricsAPITests: XCTestCase, SentryMetricsAPIDelegate {
let metric = try XCTUnwrap(bucket.first as? SetMetric)

expect(metric.key) == "key"
expect(metric.serialize()).to(contain(["1", "12"]))
expect(metric.serialize()).to(contain(["2445898635", "2725604442"]))
expect(metric.unit.unit) == MeasurementUnitFraction.percent.unit
expect(metric.tags) == ["yeah": "sentry", "some": "tag"]
}
Expand Down
18 changes: 14 additions & 4 deletions Tests/SentryTests/Swift/Metrics/SetMetricTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,21 @@ final class SetMetricTests: XCTestCase {
let sut = SetMetric(first: 1, key: "key", unit: MeasurementUnitDuration.hour, tags: [:])

sut.add(value: 0.0)
sut.add(value: -1.0)
sut.add(value: -1.1)
sut.add(value: 1.1)
sut.add(value: 2.0)

expect(sut.serialize()).to(contain(["1", "0", "-1", "2"]))
// negative numbers are ignored
sut.add(value: -1.0)

expect(sut.serialize()).to(contain(["1", "0", "2"]))
}

func testAddUIntMax_GetsNotAdded() {
let sut = SetMetric(first: 1, key: "key", unit: MeasurementUnitDuration.hour, tags: [:])

sut.add(value: Double(UInt.max))

expect(sut.serialize()).to(contain(["1"]))
}

func testType() {
Expand All @@ -30,7 +40,7 @@ final class SetMetricTests: XCTestCase {
sut.add(value: 5.0)
}

sut.add(value: -1.0)
sut.add(value: 3.0)
sut.add(value: 2.0)

expect(sut.weight) == 4
Expand Down
Loading