microsoft/teams.net

Public

mirrored fromhttps://github.com/microsoft/teams.netAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
docs/update-release-process

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

core/src/Microsoft.Teams.Apps/Diagnostics/AppsTelemetry.cs

190lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4using System.Diagnostics;
5using System.Diagnostics.Metrics;
6
7namespace Microsoft.Teams.Apps.Diagnostics;
8
9/// <summary>
10/// Singletons for the Apps-level <see cref="ActivitySource"/>, <see cref="Meter"/>, and instruments.
11/// Internal to <c>Microsoft.Teams.Apps</c>.
12/// </summary>
13internal static class AppsTelemetry
14{
15 private const string s_version = ThisAssembly.NuGetPackageVersion;
16
17 public static readonly ActivitySource Source =
18 new(TeamsBotApplicationTelemetry.ActivitySourceName, s_version);
19
20 public static readonly Meter Meter =
21 new(TeamsBotApplicationTelemetry.MeterName, s_version);
22
23 public static readonly Counter<long> HandlerDispatched =
24 Meter.CreateCounter<long>(Metrics.HandlerDispatched, description: "Total handler invocations dispatched by the router.");
25
26 public static readonly Histogram<double> HandlerDuration =
27 Meter.CreateHistogram<double>(Metrics.HandlerDuration, unit: "ms", description: "Duration of individual handler invocations.");
28
29 public static readonly Counter<long> HandlerFailures =
30 Meter.CreateCounter<long>(Metrics.HandlerFailures, description: "Total handler invocations that threw an exception.");
31
32 public static readonly Counter<long> HandlerUnmatched =
33 Meter.CreateCounter<long>(Metrics.HandlerUnmatched, description: "Total activities that found no matching route.");
34
35 // ── State instruments ────────────────────────────────────────────────
36
37 public static readonly Histogram<double> StateLoadDuration =
38 Meter.CreateHistogram<double>(Metrics.StateLoadDuration, unit: "ms", description: "Duration of state load from cache.");
39
40 public static readonly Histogram<double> StateSaveDuration =
41 Meter.CreateHistogram<double>(Metrics.StateSaveDuration, unit: "ms", description: "Duration of state save to cache.");
42
43 public static readonly Counter<long> StateCacheErrors =
44 Meter.CreateCounter<long>(Metrics.StateCacheErrors, description: "Total cache operation failures for turn state.");
45
46 public static readonly Histogram<long> StateBytesRead =
47 Meter.CreateHistogram<long>(Metrics.StateBytesRead, unit: "By", description: "Bytes read from cache per state load.");
48
49 public static readonly Histogram<long> StateBytesWritten =
50 Meter.CreateHistogram<long>(Metrics.StateBytesWritten, unit: "By", description: "Bytes written to cache per state save.");
51
52 // ── OAuth instruments ────────────────────────────────────────────────
53
54 public static readonly Counter<long> OAuthOperationCount =
55 Meter.CreateCounter<long>(Metrics.OAuthOperations, description: "Total OAuth flow operations attempted. For verify_state and signin_failure invokes, each per-flow attempt is counted independently in multi-connection deployments.");
56
57 public static readonly Histogram<double> OAuthOperationDuration =
58 Meter.CreateHistogram<double>(Metrics.OAuthOperationDuration, unit: "ms", description: "Duration of OAuth flow operations.");
59
60 public static readonly Counter<long> OAuthErrors =
61 Meter.CreateCounter<long>(Metrics.OAuthErrors, description: "Total OAuth flow operations that failed with an unexpected exception. Expected protocol fallbacks (HTTP 404/400/412 from the Token Service) are not counted here; they are recorded as oauth.result=failure on teams.oauth.operations instead.");
62
63 public static class Spans
64 {
65 public const string Handler = "handler";
66 public const string StateLoad = "state.load";
67 public const string StateSave = "state.save";
68 public const string StateDelete = "state.delete";
69
70 // OAuth spans
71 public const string OAuthSignIn = "oauth.signin";
72 public const string OAuthSignOut = "oauth.signout";
73 public const string OAuthGetToken = "oauth.get_token";
74 public const string OAuthTokenExchange = "oauth.token_exchange";
75 public const string OAuthVerifyState = "oauth.verify_state";
76 public const string OAuthSignInFailure = "oauth.signin_failure";
77 public const string OAuthConnectionStatus = "oauth.connection_status";
78 }
79
80 public static class Tags
81 {
82 public const string HandlerType = "handler.type";
83 public const string HandlerDispatch = "handler.dispatch";
84 public const string ActivityType = "activity.type";
85 public const string InvokeName = "invoke.name";
86
87 // State tags
88 public const string StateConversationHit = "state.conversation.hit";
89 public const string StateUserHit = "state.user.hit";
90 public const string StateConversationDirty = "state.conversation.dirty";
91 public const string StateUserDirty = "state.user.dirty";
92 public const string StateBytesRead = "state.bytes.read";
93 public const string StateBytesWritten = "state.bytes.written";
94 public const string Operation = "operation";
95
96 // OAuth tags
97 public const string OAuthConnection = "oauth.connection";
98 public const string OAuthOperation = "oauth.operation";
99 public const string OAuthResult = "oauth.result";
100 public const string OAuthErrorType = "oauth.error.type";
101 public const string OAuthFailureCode = "oauth.failure.code";
102 public const string OAuthCallbackInvoked = "oauth.callback.invoked";
103 public const string InvokeResponseStatus = "invoke.response.status";
104 }
105
106 public static class Metrics
107 {
108 public const string HandlerDispatched = "teams.handler.dispatched";
109 public const string HandlerDuration = "teams.handler.duration";
110 public const string HandlerFailures = "teams.handler.failures";
111 public const string HandlerUnmatched = "teams.handler.unmatched";
112
113 // State metrics
114 public const string StateLoadDuration = "teams.state.load.duration";
115 public const string StateSaveDuration = "teams.state.save.duration";
116 public const string StateCacheErrors = "teams.state.cache.errors";
117 public const string StateBytesRead = "teams.state.bytes.read";
118 public const string StateBytesWritten = "teams.state.bytes.written";
119
120 // OAuth metrics
121 public const string OAuthOperations = "teams.oauth.operations";
122 public const string OAuthOperationDuration = "teams.oauth.operation.duration";
123 public const string OAuthErrors = "teams.oauth.errors";
124 }
125
126 /// <summary>
127 /// Values used for the <see cref="Tags.OAuthOperation"/> tag.
128 /// Low cardinality: one of seven well-known operation names.
129 /// </summary>
130 public static class OAuthOperations
131 {
132 public const string SignIn = "signin";
133 public const string SignOut = "signout";
134 public const string GetToken = "get_token";
135 public const string TokenExchange = "token_exchange";
136 public const string VerifyState = "verify_state";
137 public const string SignInFailure = "signin_failure";
138 public const string ConnectionStatus = "connection_status";
139 }
140
141 /// <summary>
142 /// Values used for the <see cref="Tags.OAuthResult"/> tag.
143 /// </summary>
144 public static class OAuthResults
145 {
146 /// <summary>SignIn returned a cached token without sending an OAuthCard.</summary>
147 public const string Cached = "cached";
148 /// <summary>SignIn sent an OAuthCard because no cached token was found.</summary>
149 public const string CardSent = "card_sent";
150 /// <summary>GetToken found a cached token in the Token Store.</summary>
151 public const string Hit = "hit";
152 /// <summary>GetToken found no cached token in the Token Store.</summary>
153 public const string Miss = "miss";
154 /// <summary>Operation completed successfully.</summary>
155 public const string Success = "success";
156 /// <summary>Expected protocol failure (e.g., Token Service returned 404/400/412, or null state).</summary>
157 public const string Failure = "failure";
158 /// <summary>Duplicate signin/tokenExchange invoke; deduplicated to a 200 no-op.</summary>
159 public const string Duplicate = "duplicate";
160 /// <summary>verify_state attempted on a flow whose connection didn't match the code.</summary>
161 public const string NoToken = "no_token";
162 /// <summary>signin_failure invoke acknowledged and forwarded to the OnSignInFailure callback.</summary>
163 public const string Notified = "notified";
164 }
165
166 /// <summary>
167 /// Values used for the <see cref="Tags.OAuthErrorType"/> tag.
168 /// Set only on the <see cref="OAuthErrors"/> counter and on spans when an unexpected exception escapes.
169 /// </summary>
170 public static class OAuthErrorTypes
171 {
172 public const string HttpError = "http_error";
173 public const string InvalidOperation = "invalid_op";
174 public const string EmptyToken = "empty_token";
175 }
176
177 /// <summary>
178 /// Names of low-cardinality span events emitted by OAuth flows.
179 /// </summary>
180 public static class OAuthEvents
181 {
182 public const string CardSent = "oauth.card.sent";
183 }
184
185 /// <summary>
186 /// Special <see cref="Tags.OAuthConnection"/> value used by operations that span all connections
187 /// (e.g., <c>connection_status</c> returns the status of every registered OAuth connection).
188 /// </summary>
189 public const string OAuthAllConnections = "all";
190}
191