Skip to content

Commit

Permalink
Merge pull request #96 from DataDog/buranmert/RUMM-437-iso8601-milise…
Browse files Browse the repository at this point in the history
…conds-fix

RUMM-437 Encoding doesn't ignore miliseconds anymore
  • Loading branch information
buranmert authored May 5, 2020
2 parents 2364512 + f9a6884 commit 9beeb56
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 34 deletions.
12 changes: 12 additions & 0 deletions Datadog/Datadog.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@
9E08587A242519FF001A3583 /* NetworkPathMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E085879242519FF001A3583 /* NetworkPathMonitor.swift */; };
9E2FB2722447660E001C9B7B /* Datadog.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 61133B82242393DE00786299 /* Datadog.framework */; };
9E36D92224373EA700BFBDB7 /* SwiftExtensionsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E36D92124373EA700BFBDB7 /* SwiftExtensionsTests.swift */; };
9E58E8DF24615B89008E5063 /* ISO8601DateFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E58E8DE24615B89008E5063 /* ISO8601DateFormatter.swift */; };
9E58E8E124615C75008E5063 /* JSONEncoder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E58E8E024615C75008E5063 /* JSONEncoder.swift */; };
9E58E8E324615EDA008E5063 /* EncodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E58E8E224615EDA008E5063 /* EncodingTests.swift */; };
9E68FB55244707FD0013A8AA /* ObjcExceptionHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E68FB53244707FD0013A8AA /* ObjcExceptionHandler.m */; };
9E68FB56244707FD0013A8AA /* ObjcExceptionHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 9E68FB54244707FD0013A8AA /* ObjcExceptionHandler.h */; settings = {ATTRIBUTES = (Private, ); }; };
9EA6A539244897A900621535 /* LoggingIOBenchmarkTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EA6A538244897A900621535 /* LoggingIOBenchmarkTests.swift */; };
Expand Down Expand Up @@ -254,6 +257,9 @@
9E36D92124373EA700BFBDB7 /* SwiftExtensionsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftExtensionsTests.swift; sourceTree = "<group>"; };
9E4195742449D739000AB0DB /* app-target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "app-target.xcconfig"; sourceTree = "<group>"; };
9E4195752449D739000AB0DB /* unit-tests-target.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "unit-tests-target.xcconfig"; sourceTree = "<group>"; };
9E58E8DE24615B89008E5063 /* ISO8601DateFormatter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ISO8601DateFormatter.swift; sourceTree = "<group>"; };
9E58E8E024615C75008E5063 /* JSONEncoder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JSONEncoder.swift; sourceTree = "<group>"; };
9E58E8E224615EDA008E5063 /* EncodingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EncodingTests.swift; sourceTree = "<group>"; };
9E68FB53244707FD0013A8AA /* ObjcExceptionHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjcExceptionHandler.m; sourceTree = "<group>"; };
9E68FB54244707FD0013A8AA /* ObjcExceptionHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjcExceptionHandler.h; sourceTree = "<group>"; };
9E9EB37624468CE90002C80B /* Datadog.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; path = Datadog.modulemap; sourceTree = "<group>"; };
Expand Down Expand Up @@ -372,6 +378,8 @@
isa = PBXGroup;
children = (
61133BA02423979B00786299 /* EncodableValue.swift */,
9E58E8DE24615B89008E5063 /* ISO8601DateFormatter.swift */,
9E58E8E024615C75008E5063 /* JSONEncoder.swift */,
);
path = Utils;
sourceTree = "<group>";
Expand Down Expand Up @@ -627,6 +635,7 @@
children = (
61133C362423990D00786299 /* InternalLoggersTests.swift */,
9E36D92124373EA700BFBDB7 /* SwiftExtensionsTests.swift */,
9E58E8E224615EDA008E5063 /* EncodingTests.swift */,
);
path = Utils;
sourceTree = "<group>";
Expand Down Expand Up @@ -1008,12 +1017,14 @@
61133BCF2423979B00786299 /* FileWriter.swift in Sources */,
61133BCC2423979B00786299 /* MobileDevice.swift in Sources */,
9E08587A242519FF001A3583 /* NetworkPathMonitor.swift in Sources */,
9E58E8E124615C75008E5063 /* JSONEncoder.swift in Sources */,
61133BCA2423979B00786299 /* EncodableValue.swift in Sources */,
9E68FB55244707FD0013A8AA /* ObjcExceptionHandler.m in Sources */,
61C3638524361E9200C4D4E6 /* Globals.swift in Sources */,
61133BE62423979B00786299 /* LogSanitizer.swift in Sources */,
61133BDF2423979B00786299 /* SwiftExtensions.swift in Sources */,
61133BEA2423979B00786299 /* LogConsoleOutput.swift in Sources */,
9E58E8DF24615B89008E5063 /* ISO8601DateFormatter.swift in Sources */,
61133BE32423979B00786299 /* UserInfo.swift in Sources */,
61133BE02423979B00786299 /* Datadog.swift in Sources */,
61133BCB2423979B00786299 /* CarrierInfoProvider.swift in Sources */,
Expand Down Expand Up @@ -1067,6 +1078,7 @@
61133C6A2423990D00786299 /* DatadogTests.swift in Sources */,
61133C5E2423990D00786299 /* LogsUploadDelayTests.swift in Sources */,
61133C5C2423990D00786299 /* DataUploadWorkerTests.swift in Sources */,
9E58E8E324615EDA008E5063 /* EncodingTests.swift in Sources */,
61133C692423990D00786299 /* LogFileOutputTests.swift in Sources */,
61133C682423990D00786299 /* LogUtilityOutputsTests.swift in Sources */,
61133C6E2423990D00786299 /* DatadogExtensions.swift in Sources */,
Expand Down
6 changes: 1 addition & 5 deletions Sources/Datadog/Core/Persistence/FileWriter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,7 @@ internal final class FileWriter {
init(orchestrator: FilesOrchestrator, queue: DispatchQueue) {
self.orchestrator = orchestrator
self.queue = queue
self.jsonEncoder = JSONEncoder()
jsonEncoder.dateEncodingStrategy = .iso8601
if #available(iOS 13.0, OSX 10.15, *) {
jsonEncoder.outputFormatting = [.withoutEscapingSlashes]
}
self.jsonEncoder = JSONEncoder.default()
}

// MARK: - Writing data
Expand Down
24 changes: 24 additions & 0 deletions Sources/Datadog/Core/Utils/ISO8601DateFormatter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
* This product includes software developed at Datadog (https://www.datadoghq.com/).
* Copyright 2019-2020 Datadog, Inc.
*/

import Foundation

extension ISO8601DateFormatter {
static func `default`() -> ISO8601DateFormatter {
let formatter = ISO8601DateFormatter()
formatter.formatOptions.insert(.withFractionalSeconds)
return formatter
}

static var encodingStrategy: JSONEncoder.DateEncodingStrategy {
let formatter = Self.default()
return .custom { date, encoder in
var container = encoder.singleValueContainer()
let formatted = formatter.string(from: date)
try container.encode(formatted)
}
}
}
18 changes: 18 additions & 0 deletions Sources/Datadog/Core/Utils/JSONEncoder.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
* This product includes software developed at Datadog (https://www.datadoghq.com/).
* Copyright 2019-2020 Datadog, Inc.
*/

import Foundation

extension JSONEncoder {
static func `default`() -> JSONEncoder {
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = ISO8601DateFormatter.encodingStrategy
if #available(iOS 13.0, OSX 10.15, *) {
encoder.outputFormatting = [.withoutEscapingSlashes]
}
return encoder
}
}
21 changes: 9 additions & 12 deletions Sources/Datadog/Logs/LogOutputs/LogConsoleOutput.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@ internal protocol ConsoleLogFormatter {
/// `LogOutput` which prints logs to console.
internal struct LogConsoleOutput: LogOutput {
/// Time formatter used for `.short` output format.
static func shortTimeFormatter(calendar: Calendar = .current, timeZone: TimeZone = .current) -> DateFormatter {
let formatter = DateFormatter()
formatter.calendar = calendar
formatter.timeZone = timeZone
formatter.dateFormat = "HH:mm:ss"
static func shortTimeFormatter(calendar: Calendar = .current, timeZone: TimeZone = .current) -> Formatter {
let formatter = ISO8601DateFormatter.default()
formatter.formatOptions = [.withFractionalSeconds, .withFullTime]
return formatter
}

Expand All @@ -30,7 +28,7 @@ internal struct LogConsoleOutput: LogOutput {
logBuilder: LogBuilder,
format: Logger.Builder.ConsoleLogFormat,
printingFunction: @escaping (String) -> Void = { consolePrint($0) },
timeFormatter: DateFormatter = LogConsoleOutput.shortTimeFormatter()
timeFormatter: Formatter = LogConsoleOutput.shortTimeFormatter()
) {
switch format {
case .short:
Expand Down Expand Up @@ -60,8 +58,7 @@ private struct JSONLogFormatter: ConsoleLogFormatter {
private let prefix: String

init(prefix: String = "") {
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
let encoder = JSONEncoder.default()
encoder.outputFormatting = .prettyPrinted
self.encoder = encoder
self.prefix = prefix
Expand All @@ -79,17 +76,17 @@ private struct JSONLogFormatter: ConsoleLogFormatter {

/// Formats log as custom short string.
private struct ShortLogFormatter: ConsoleLogFormatter {
private let timeFormatter: DateFormatter
private let timeFormatter: Formatter
private let prefix: String

init(timeFormatter: DateFormatter, prefix: String = "") {
init(timeFormatter: Formatter, prefix: String = "") {
self.timeFormatter = timeFormatter
self.prefix = prefix
}

func format(log: Log) -> String {
let time = timeFormatter.string(from: log.date)
let time = timeFormatter.string(for: log.date)
let status = log.status.rawValue.uppercased()
return "\(prefix)\(time) [\(status)] \(log.message)"
return "\(prefix)\(time ?? "null") [\(status)] \(log.message)"
}
}
4 changes: 2 additions & 2 deletions Sources/Datadog/Utils/InternalLoggers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ internal var userLogger = createSDKUserLogger()
internal func createSDKDeveloperLogger(
consolePrintFunction: @escaping (String) -> Void = { consolePrint($0) },
dateProvider: DateProvider = SystemDateProvider(),
timeFormatter: DateFormatter = LogConsoleOutput.shortTimeFormatter()
timeFormatter: Formatter = LogConsoleOutput.shortTimeFormatter()
) -> Logger? {
if CompilationConditions.isSDKCompiledForDevelopment == false {
return nil
Expand Down Expand Up @@ -54,7 +54,7 @@ internal func createSDKDeveloperLogger(
internal func createSDKUserLogger(
consolePrintFunction: @escaping (String) -> Void = { consolePrint($0) },
dateProvider: DateProvider = SystemDateProvider(),
timeFormatter: DateFormatter = LogConsoleOutput.shortTimeFormatter()
timeFormatter: Formatter = LogConsoleOutput.shortTimeFormatter()
) -> Logger {
guard let loggingFeature = LoggingFeature.instance else {
return Logger(logOutput: NoOpLogOutput(), identifier: "no-op")
Expand Down
6 changes: 3 additions & 3 deletions Tests/DatadogTests/Datadog/LoggerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class LoggerTests: XCTestCase {
"logger.name" : "com.datadoghq.ios-sdk",
"logger.version": "\(sdkVersion)",
"logger.thread_name" : "main",
"date" : "2019-12-15T10:00:00Z",
"date" : "2019-12-15T10:00:00.000Z",
"application.version": "1.0.0"
}
""")
Expand Down Expand Up @@ -310,8 +310,8 @@ class LoggerTests: XCTestCase {
logMatcher.assertValue(forKey: "uint-8", equals: UInt8(10))
logMatcher.assertValue(forKey: "double", equals: 10.5)
logMatcher.assertValue(forKey: "array-of-int", equals: [1, 2, 3])
logMatcher.assertValue(forKeyPath: "dictionary-of-date.date1", equals: "2019-12-15T10:00:00Z")
logMatcher.assertValue(forKeyPath: "dictionary-of-date.date2", equals: "2019-12-15T11:00:00Z")
logMatcher.assertValue(forKeyPath: "dictionary-of-date.date1", equals: "2019-12-15T10:00:00.000Z")
logMatcher.assertValue(forKeyPath: "dictionary-of-date.date2", equals: "2019-12-15T11:00:00.000Z")
logMatcher.assertValue(forKeyPath: "person.name", equals: "Adam")
logMatcher.assertValue(forKeyPath: "person.age", equals: 30)
logMatcher.assertValue(forKeyPath: "person.nationality", equals: "Polish")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class LogConsoleOutputTests: XCTestCase {
timeFormatter: LogConsoleOutput.shortTimeFormatter(calendar: .gregorian, timeZone: .UTC)
)
output1.writeLogWith(level: .info, message: "Info message.", attributes: [:], tags: [])
XCTAssertEqual(messagePrinted, "10:00:00 [INFO] Info message.")
XCTAssertEqual(messagePrinted, "10:00:00.000Z [INFO] Info message.")

let output2 = LogConsoleOutput(
logBuilder: .mockWith(date: .mockDecember15th2019At10AMUTC()),
Expand All @@ -28,7 +28,7 @@ class LogConsoleOutputTests: XCTestCase {
timeFormatter: LogConsoleOutput.shortTimeFormatter(calendar: .gregorian, timeZone: .UTC)
)
output2.writeLogWith(level: .info, message: "Info message.", attributes: [:], tags: [])
XCTAssertEqual(messagePrinted, "🐶 10:00:00 [INFO] Info message.")
XCTAssertEqual(messagePrinted, "🐶 10:00:00.000Z [INFO] Info message.")
}

func testItPrintsLogsUsingJSONFormat() throws {
Expand Down
33 changes: 33 additions & 0 deletions Tests/DatadogTests/Datadog/Utils/EncodingTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
* This product includes software developed at Datadog (https://www.datadoghq.com/).
* Copyright 2019-2020 Datadog, Inc.
*/

import XCTest
@testable import Datadog

class DateFormatterTests: XCTestCase {
func testISO8601FormatWithSubSecondPrecision() throws {
let dateFormatter = ISO8601DateFormatter.default()

let knownDate: Date = .mockDecember15th2019At10AMUTC(addingTimeInterval: 0.123)
let formattedDate = dateFormatter.string(from: knownDate)

XCTAssertEqual(formattedDate, "2019-12-15T10:00:00.123Z")
}
}

class EncodingTests: XCTestCase {
func testEncodingDateWithSubSecondPrecision() throws {
let jsonEncoder = JSONEncoder.default()

let knownDate: Date = .mockDecember15th2019At10AMUTC(addingTimeInterval: 0.123)
let encodedKnownDate = try jsonEncoder.encode(knownDate)

let jsonDecoder = JSONDecoder()
let knownDateDecodedString = try jsonDecoder.decode(String.self, from: encodedKnownDate)

XCTAssertEqual(knownDateDecodedString, "2019-12-15T10:00:00.123Z")
}
}
14 changes: 7 additions & 7 deletions Tests/DatadogTests/Datadog/Utils/InternalLoggersTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,12 @@ class InternalLoggersTests: XCTestCase {
}

private let expectedMessages = [
"[DATADOG SDK] 🐶 → 10:00:00 [DEBUG] message",
"[DATADOG SDK] 🐶 → 10:00:00 [INFO] message",
"[DATADOG SDK] 🐶 → 10:00:00 [NOTICE] message",
"[DATADOG SDK] 🐶 → 10:00:00 [WARN] message",
"[DATADOG SDK] 🐶 → 10:00:00 [ERROR] message",
"[DATADOG SDK] 🐶 → 10:00:00 [CRITICAL] message"
"[DATADOG SDK] 🐶 → 10:00:00.000Z [DEBUG] message",
"[DATADOG SDK] 🐶 → 10:00:00.000Z [INFO] message",
"[DATADOG SDK] 🐶 → 10:00:00.000Z [NOTICE] message",
"[DATADOG SDK] 🐶 → 10:00:00.000Z [WARN] message",
"[DATADOG SDK] 🐶 → 10:00:00.000Z [ERROR] message",
"[DATADOG SDK] 🐶 → 10:00:00.000Z [CRITICAL] message"
]

func testUserLoggerDoesNothingWithDefaultVerbosityLevel() {
Expand Down Expand Up @@ -120,6 +120,6 @@ class InternalLoggersTests: XCTestCase {
developerLogger?.info("It works.")

XCTAssertNotNil(developerLogger)
XCTAssertEqual(printedMessage, "🐶 → 10:00:00 [INFO] It works.")
XCTAssertEqual(printedMessage, "🐶 → 10:00:00.000Z [INFO] It works.")
}
}
4 changes: 2 additions & 2 deletions Tests/DatadogTests/DatadogObjc/DDLoggerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ class DDLoggerTests: XCTestCase {
logMatcher.assertValue(forKeyPath: "nsnull", isTypeOf: Optional<Any>.self)
logMatcher.assertValue(forKey: "nsurl", equals: "http://apple.com")
logMatcher.assertValue(forKey: "nsarray-of-int", equals: [1, 2, 3])
logMatcher.assertValue(forKeyPath: "nsdictionary-of-date.date1", equals: "2019-12-15T10:00:00Z")
logMatcher.assertValue(forKeyPath: "nsdictionary-of-date.date2", equals: "2019-12-15T11:00:00Z")
logMatcher.assertValue(forKeyPath: "nsdictionary-of-date.date1", equals: "2019-12-15T10:00:00.000Z")
logMatcher.assertValue(forKeyPath: "nsdictionary-of-date.date2", equals: "2019-12-15T11:00:00.000Z")
}
}
// swiftlint:enable multiline_arguments_brackets
Expand Down
6 changes: 5 additions & 1 deletion Tests/DatadogTests/Matchers/LogMatcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import XCTest
/// Provides set of assertions for Log JSON object.
/// Note: this file is individually referenced by integration tests project, so no dependency on other source files should be introduced.
struct LogMatcher {
private static let dateFormatter = ISO8601DateFormatter()
private static let dateFormatter: ISO8601DateFormatter = {
let formatter = ISO8601DateFormatter()
formatter.formatOptions.insert(.withFractionalSeconds)
return formatter
}()

/// Log JSON keys.
struct JSONKey {
Expand Down

0 comments on commit 9beeb56

Please sign in to comment.