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

RUMM-409 Unify service, env and version across all SDKs #102

Merged
merged 6 commits into from
May 12, 2020

Conversation

ncreated
Copy link
Member

@ncreated ncreated commented May 11, 2020

What and why?

📦 This PR unifies 3 common attributes across all Datadog SDKs. Similar changes were already applied to Android SDK (#248, #241, #240).

1/ Environment:

This attribute is specified by the user when initializing the SDK and cannot be overwritten any later:

let confBuilder = Datadog.Configuration.builderUsing(clientToken:environment:)

It is sent to Datadog as default tag in log JSON, i.e.:

{
   /* ... */
   ddtags: ["env:production"]
}

💡 NOTE: this changes the public API by introducing mandatory environment: argument.

2/ Service Name:

The default value of this attribute can be optionally specified by the user when initializing the SDK:

let confBuilder = Datadog.Configuration.builderUsing(clientToken:environment:)
confBuilder.set(serviceName: "my-default-service-name")

If not given, it defaults to the app bundle identifier (i.e. com.datadoghq.app).

The service name can be overwritten per Logger instance using Logger.Builder:

let logger = Logger.builder
   .set(serviceName: "custom-service-name")
   .build()

It is sent do Datadog as .service attribute in log JSON, i.e.:

{
   /* ... */
   service: "my-default-service-name"
}

💡 NOTE: this changes the service default value, which previously was evaluated to "ios".

3/ Application version:

This attribute is automatically inferred from application Bundle. It is sent to Datadog as as .version attribute in log JSON, i.e.:

{
   /* ... */
   version: "3.1.4"
}

💡 NOTE: this changes the coding key for application version (before, it was application.version).

How?

All three attributes are resolved using both arguments from the public Datadog.initialize() API:

// Datadog.swift

public static func initialize(appContext: AppContext, configuration: Configuration) {
   // ...
}

Their resolution can lead to many corner cases, i.e.:

  • configuration.environment contains invalid characters (e.x. "*(#@").
  • when configuration.serviceName is not given, it should be inferred from appContext.bundleIdentifier, which can also be nil.
  • appContext.bundleVertsion can be nil so fallback must be provided.

To not leak this corner cases to other SDK components, I created a type-safe representation of valid SDK configuration:

/// Valid SDK configuration, passed to the features.
///
/// It takes two types received from the user: `Datadog.Configuration` and `AppContext` and blends them together
/// with resolving defaults and ensuring the configuration consistency.
internal struct ValidConfiguration {
        internal let applicationName: String
        internal let applicationVersion: String
        internal let applicationBundleIdentifier: String
        internal let serviceName: String
        internal let environment: String

        internal let logsUploadURLWithClientToken: URL

        init(configuration: Datadog.Configuration, appContext: AppContext) throws {
            // defaults resolution, consistency and input validation
        }
}

The ValidConfiguration is now the only dependency passed down to features, which cuts off many edge cases consideration and centralizes unit testing to ValidConfiguration.

Other things done in this PR

It was possible to make LogBuilder independent of the public AppContext. Now it consumes only plain, non-optional values:

internal struct LogBuilder {
    let applicationVersion: String
    let environment: String
    let serviceName: String
    let loggerName: String

    // ...
}

This turned out to be highly effective, as the LoggerBuilderTests do not require full-feature mocking and assertions can be made on LogOutput and LogBuilder.

Newly introduced LoggerBuilderTests unrevealed one bug that we had:

// Logger
public func sendNetworkInfo(_ enabled: Bool) -> Builder {
-    sendNetworkInfo = true
+    sendNetworkInfo = enabled
    return self
}

It's also fixed now 👍.

Review checklist

  • Feature or bugfix MUST have appropriate tests (unit, integration)
  • Make sure each commit and the PR mention the Issue number or JIRA reference
  • Update documentation in docs/ folder, get it reviewed

@ncreated ncreated added this to the tracing milestone May 11, 2020
@ncreated ncreated requested a review from a team as a code owner May 11, 2020 11:21
@ncreated ncreated self-assigned this May 11, 2020
Copy link
Contributor

@buranmert buranmert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the general design is as we discussed before ✅
there are just a few minor things that i wanted to point out

Sources/Datadog/DatadogConfiguration.swift Outdated Show resolved Hide resolved
Sources/Datadog/DatadogConfiguration.swift Show resolved Hide resolved
Sources/Datadog/DatadogConfiguration.swift Show resolved Hide resolved
@ncreated ncreated requested a review from buranmert May 12, 2020 10:35
@ncreated ncreated merged commit ca3cc71 into master May 12, 2020
@ncreated ncreated deleted the ncreated/RUMM-409-update-service-env-and-version branch May 12, 2020 11:17
@ncreated ncreated modified the milestones: tracing, next-version May 12, 2020
@ncreated ncreated removed this from the next-version milestone May 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants