Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,16 @@ public static final class Broker {
*/
public static final String BROKER_SILENT_EXECUTOR_POOL_SIZE = "broker_silent_executor_pool_size";

/**
* Bundle key for the serialized broker telemetry request.
*/
public static final String BROKER_TELEMETRY_REQUEST = "broker_telemetry_request";

/**
* Bundle key for the serialized broker telemetry schema.
*/
public static final String BROKER_TELEMETRY_SCHEMA = "broker_telemetry_schema";

/**
* Broker application version name.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright (c) Microsoft Corporation.
// All rights reserved.
//
// This code is licensed under the MIT License.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package com.microsoft.identity.common.java.broker.telemetry

import java.time.Instant
import java.util.concurrent.CopyOnWriteArrayList

/**
* Thread-safe accumulator for [ExecutionEvent]s during an authentication flow.
*
* Create one instance per authentication request and call [addEvent] at each phase boundary.
* When the flow completes, call [toTelemetrySchema] to obtain the structured result.
*
* @param correlationId The correlation ID of the authentication request being tracked.
*/
class EventCollector(private val correlationId: String) {
private val events = CopyOnWriteArrayList<ExecutionEvent>()
private val startTimeMs: Long = System.currentTimeMillis()

companion object {
/**
* Offset applied to broker-side thread IDs to avoid collision with
* OneAuth client-side thread IDs when the two event streams are
* stitched in Kusto via correlation_id.
*/
const val BROKER_THREAD_ID_OFFSET = 10_000L
}

/**
* Records a new [ExecutionEvent] with the current elapsed time.
* Thread ID is offset by [BROKER_THREAD_ID_OFFSET] to avoid collision
* with client-side (OneAuth) thread IDs during Kusto stitching.
*
* @param tag The [EventTag] identifying this phase.
* @param diagnosticCode Optional diagnostic code for additional context.
* @param errorCode Optional error code if this event represents a failure.
*/
fun addEvent(tag: EventTag, diagnosticCode: Int? = null, errorCode: Int? = null) {
events.add(
ExecutionEvent(
tag = tag,
timestampMs = System.currentTimeMillis() - startTimeMs,
threadId = Thread.currentThread().id + BROKER_THREAD_ID_OFFSET,
diagnosticCode = diagnosticCode,
errorCode = errorCode
)
)
}

/**
* Builds a [TelemetrySchema] from all events collected so far.
*
* Snapshots the event list first, then captures the end time, ensuring
* that [PerformanceRecord.duration] is always >= the last event's timestamp.
*
* @return A [TelemetrySchema] containing a [PerformanceRecord] with all collected events.
*/
fun toTelemetrySchema(): TelemetrySchema {
// Snapshot events first, then capture end time — guarantees duration >= last event ts.
val eventSnapshot = events.toList()
val duration = System.currentTimeMillis() - startTimeMs
return TelemetrySchema(
correlationId = correlationId,
performanceRecord = PerformanceRecord(
startTime = Instant.ofEpochMilli(startTimeMs).toString(),
duration = duration,
executionFlow = eventSnapshot
)
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright (c) Microsoft Corporation.
// All rights reserved.
//
// This code is licensed under the MIT License.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package com.microsoft.identity.common.java.broker.telemetry

/**
* Enum of event tags representing phases of the broker authentication flow.
* Serialized as human-readable enum names (e.g., "BrokerCacheHit") on the IPC wire format.
* Compact JSON keys on [ExecutionEvent] fields (t, ts, tid, d, e) minimize payload size.
*/
enum class EventTag {
// BrokerEntry (5)
BrokerRequestReceived,
BrokerRequestDeserialized,
BrokerAccountLookupStart,
BrokerAccountLookupEnd,
BrokerRequestValidated,
// BrokerDispatch (3)
BrokerControllerSelected,
BrokerCommandQueued,
BrokerCommandExecutionStart,
// BrokerCache (6)
BrokerCacheCheckStart,
BrokerCacheCheckEnd,
BrokerCacheHit,
BrokerCacheMiss,
BrokerCacheWriteStart,
BrokerCacheWriteEnd,
// BrokerNetwork (5)
BrokerPrtLoadStart,
BrokerNetworkCallStart,
BrokerNetworkCallEnd,
BrokerTokenAcquired,
BrokerNetworkCallFailed,
// BrokerResponse (3)
BrokerResponseSerialized,
BrokerResponseSent,
BrokerRequestFailed,
// CommonStrategy (2)
CommonHttpRequestExecute,
CommonHttpResponseReceived
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) Microsoft Corporation.
// All rights reserved.
//
// This code is licensed under the MIT License.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package com.microsoft.identity.common.java.broker.telemetry

import com.google.gson.annotations.SerializedName

/**
* Represents a single timed event within the broker authentication flow.
*
* @param tag The [EventTag] identifying which phase this event captures.
* @param timestampMs Elapsed time in milliseconds from the start of the flow.
* @param threadId The ID of the thread that recorded this event.
* @param diagnosticCode Optional diagnostic code for additional context.
* @param errorCode Optional error code if the event represents a failure.
*/
data class ExecutionEvent(
@SerializedName("t") val tag: EventTag,
@SerializedName("ts") val timestampMs: Long,
@SerializedName("tid") val threadId: Long = Thread.currentThread().id,
@SerializedName("d") val diagnosticCode: Int? = null,
@SerializedName("e") val errorCode: Int? = null
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) Microsoft Corporation.
// All rights reserved.
//
// This code is licensed under the MIT License.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package com.microsoft.identity.common.java.broker.telemetry

/**
* Implemented by objects that can carry a [TelemetrySchema].
* Mainly used to pass the structured broker telemetry between broker and client.
*
* Thread-safety note: [telemetrySchema] must be set before the implementing object
* is shared across threads. The IPC boundary (Binder transaction) provides the
* memory barrier. This follows the same contract as [IBrokerPerformanceMetricsProvider].
*/
interface ITelemetrySchemaProvider {
var telemetrySchema: TelemetrySchema?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation.
// All rights reserved.
//
// This code is licensed under the MIT License.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package com.microsoft.identity.common.java.broker.telemetry

import com.google.gson.annotations.SerializedName

/**
* Aggregation container for the performance data captured during an authentication flow.
*
* @param version Schema version for this perf section. Independent of [TelemetrySchema.CURRENT_VERSION].
* @param startTime ISO 8601 UTC timestamp when the flow started.
* @param duration Total elapsed time in milliseconds for the authentication flow.
* @param executionFlow Ordered list of [ExecutionEvent]s captured during the flow.
*/
data class PerformanceRecord(
@SerializedName("version") val version: String = CURRENT_PERF_VERSION,
@SerializedName("start_time") val startTime: String,
@SerializedName("duration") val duration: Long,
@SerializedName("execution_flow") val executionFlow: List<ExecutionEvent>
) {
companion object {
/**
* Version of the perf section schema. Informational only — not used in
* version negotiation (which uses root-level [TelemetrySchema.CURRENT_VERSION]).
* Evolves independently from the top-level schema version.
*/
const val CURRENT_PERF_VERSION = "1.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) Microsoft Corporation.
// All rights reserved.
//
// This code is licensed under the MIT License.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
package com.microsoft.identity.common.java.broker.telemetry

/**
* Null-safe utility for recording events into an [EventCollector].
* Callers may hold a nullable collector reference and use this helper to avoid null checks.
*/
object TelemetryHelper {
/**
* Adds an event to the given [collector] if it is non-null; otherwise does nothing.
*
* @param collector The [EventCollector] to record the event into, or null.
* @param tag The [EventTag] identifying the phase.
* @param diagnosticCode Optional diagnostic code for additional context.
* @param errorCode Optional error code if this event represents a failure.
*/
@JvmStatic
fun addEventSafely(
collector: EventCollector?,
tag: EventTag,
diagnosticCode: Int? = null,
errorCode: Int? = null
) {
collector?.addEvent(tag, diagnosticCode, errorCode)
}
}
Loading
Loading