Skip to content

Commit c815e17

Browse files
author
Andrew Omondi
committed
Squash changes.
- Introduce base request adapter - Fix IUploadSession interface to use List instead of IEnumerable - Configure telemetry handler.
1 parent 5ad51c9 commit c815e17

14 files changed

Lines changed: 287 additions & 53 deletions

File tree

src/Microsoft.Graph.Core/CoreConstants.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ public static class Headers
2626
public const string SdkVersionHeaderName = "SdkVersion";
2727

2828
/// SDK Version header
29-
public const string SdkVersionHeaderValueFormatString = "{0}-dotnet-{1}.{2}.{3}";
29+
public const string SdkVersionHeaderValueFormatString = "graph-dotnet-core/{0}.{1}.{2}";
3030

3131
/// Content-Type header
3232
public const string FormUrlEncodedContentType = "application/x-www-form-urlencoded";

src/Microsoft.Graph.Core/Models/IUploadSession.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public interface IUploadSession: IParsable
2121
/// <summary>
2222
/// The ranges yet to be uploaded to the server
2323
/// </summary>
24-
IEnumerable<string> NextExpectedRanges { get; set; }
24+
List<string> NextExpectedRanges { get; set; }
2525

2626
/// <summary>
2727
/// The URL for upload

src/Microsoft.Graph.Core/Models/UploadSession.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ internal class UploadSession : IUploadSession
2222
/// <summary>
2323
/// The ranges yet to be uploaded to the server
2424
/// </summary>
25-
public IEnumerable<string> NextExpectedRanges { get; set; }
25+
public List<string> NextExpectedRanges { get; set; }
2626

2727
/// <summary>
2828
/// The URL for upload

src/Microsoft.Graph.Core/Requests/BaseClient.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ namespace Microsoft.Graph
1313
using Microsoft.Kiota.Authentication.Azure;
1414
using System.Linq;
1515
using Microsoft.Kiota.Abstractions;
16-
using Microsoft.Kiota.Http.HttpClientLibrary;
1716

1817
/// <summary>
1918
/// A default client implementation.
@@ -45,7 +44,7 @@ public BaseClient(
4544
public BaseClient(
4645
string baseUrl,
4746
IAuthenticationProvider authenticationProvider
48-
): this(new HttpClientRequestAdapter(authenticationProvider , httpClient: GraphClientFactory.Create()){ BaseUrl = baseUrl })
47+
): this(new BaseGraphRequestAdapter(authenticationProvider){ BaseUrl = baseUrl })
4948
{
5049
}
5150

@@ -70,7 +69,7 @@ public BaseClient(
7069
/// <param name="httpClient">The customized <see cref="HttpClient"/> to be used for making requests</param>
7170
public BaseClient(
7271
string baseUrl,
73-
HttpClient httpClient):this(new HttpClientRequestAdapter(new AnonymousAuthenticationProvider(), httpClient: httpClient) { BaseUrl = baseUrl })
72+
HttpClient httpClient):this(new BaseGraphRequestAdapter(new AnonymousAuthenticationProvider(), httpClient: httpClient) { BaseUrl = baseUrl })
7473
{
7574
}
7675

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// ------------------------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information.
3+
// ------------------------------------------------------------------------------
4+
5+
namespace Microsoft.Graph
6+
{
7+
using Microsoft.Kiota.Abstractions;
8+
using Microsoft.Kiota.Abstractions.Authentication;
9+
using Microsoft.Kiota.Abstractions.Serialization;
10+
using Microsoft.Kiota.Http.HttpClientLibrary;
11+
using System.Net.Http;
12+
13+
/// <summary>
14+
/// The <see cref="IRequestAdapter"/> instance for use with microsoft graph
15+
/// </summary>
16+
public class BaseGraphRequestAdapter : HttpClientRequestAdapter
17+
{
18+
/// <summary>
19+
/// The public constructor for <see cref="BaseGraphRequestAdapter"/>
20+
/// </summary>
21+
/// <param name="authenticationProvider">The authentication provider.</param>
22+
/// <param name="graphClientOptions">The options for the graph client</param>
23+
/// <param name="parseNodeFactory">The parse node factory.</param>
24+
/// <param name="serializationWriterFactory">The serialization writer factory.</param>
25+
/// <param name="httpClient">The native HTTP client.</param>
26+
public BaseGraphRequestAdapter(IAuthenticationProvider authenticationProvider, GraphClientOptions graphClientOptions = null, IParseNodeFactory parseNodeFactory = null, ISerializationWriterFactory serializationWriterFactory = null, HttpClient httpClient = null)
27+
: base(authenticationProvider, parseNodeFactory ?? ParseNodeFactoryRegistry.DefaultInstance, serializationWriterFactory ?? SerializationWriterFactoryRegistry.DefaultInstance, httpClient ?? GraphClientFactory.Create(graphClientOptions))
28+
{
29+
}
30+
}
31+
}

src/Microsoft.Graph.Core/Requests/GraphClientFactory.cs

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ------------------------------------------------------------------------------
1+
// ------------------------------------------------------------------------------
22
// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information.
33
// ------------------------------------------------------------------------------
44
namespace Microsoft.Graph
@@ -8,29 +8,14 @@ namespace Microsoft.Graph
88
using System.Linq;
99
using System.Net;
1010
using System.Net.Http;
11-
using System.Reflection;
1211
using System.Net.Http.Headers;
1312
using Microsoft.Kiota.Http.HttpClientLibrary.Middleware;
14-
using Microsoft.Kiota.Abstractions.Authentication;
13+
1514
/// <summary>
1615
/// GraphClientFactory class to create the HTTP client
1716
/// </summary>
1817
public static class GraphClientFactory
1918
{
20-
/// The key for the SDK version header.
21-
private static readonly string SdkVersionHeaderName = CoreConstants.Headers.SdkVersionHeaderName;
22-
23-
/// The version for current assembly.
24-
private static Version assemblyVersion = typeof(GraphClientFactory).GetTypeInfo().Assembly.GetName().Version;
25-
26-
/// The value for the SDK version header.
27-
private static string SdkVersionHeaderValue = string.Format(
28-
CoreConstants.Headers.SdkVersionHeaderValueFormatString,
29-
"Graph",
30-
assemblyVersion.Major,
31-
assemblyVersion.Minor,
32-
assemblyVersion.Build);
33-
3419
/// The default value for the overall request timeout.
3520
private static readonly TimeSpan defaultTimeout = TimeSpan.FromSeconds(100);
3621

@@ -60,17 +45,19 @@ public static class GraphClientFactory
6045
/// </summary>
6146
/// <param name="version">The graph version to use.</param>
6247
/// <param name="nationalCloud">The national cloud endpoint to use.</param>
48+
/// <param name="graphClientOptions">The <see cref="GraphClientOptions"/> to use with the client</param>
6349
/// <param name="proxy">The proxy to be used with created client.</param>
6450
/// <param name="finalHandler">The last HttpMessageHandler to HTTP calls.
6551
/// The default implementation creates a new instance of <see cref="HttpClientHandler"/> for each HttpClient.</param>
6652
/// <returns></returns>
6753
public static HttpClient Create(
54+
GraphClientOptions graphClientOptions = null,
6855
string version = "v1.0",
6956
string nationalCloud = Global_Cloud,
7057
IWebProxy proxy = null,
7158
HttpMessageHandler finalHandler = null)
7259
{
73-
IList<DelegatingHandler> handlers = CreateDefaultHandlers();
60+
IList<DelegatingHandler> handlers = CreateDefaultHandlers(graphClientOptions);
7461
return Create(handlers, version, nationalCloud, proxy, finalHandler);
7562
}
7663

@@ -109,7 +96,6 @@ public static HttpClient Create(
10996

11097
var pipelineWithFlags = CreatePipelineWithFeatureFlags(handlers, finalHandler);
11198
HttpClient client = new HttpClient(pipelineWithFlags.Pipeline);
112-
client.DefaultRequestHeaders.Add(SdkVersionHeaderName, SdkVersionHeaderValue);
11399
client.SetFeatureFlag(pipelineWithFlags.FeatureFlags);
114100
client.Timeout = defaultTimeout;
115101
client.BaseAddress = DetermineBaseAddress(nationalCloud, version);
@@ -120,10 +106,12 @@ public static HttpClient Create(
120106
/// <summary>
121107
/// Create a default set of middleware for calling Microsoft Graph
122108
/// </summary>
109+
/// <param name="graphClientOptions">The <see cref="GraphClientOptions"/> to use with the client</param>
123110
/// <returns></returns>
124-
public static IList<DelegatingHandler> CreateDefaultHandlers()
111+
public static IList<DelegatingHandler> CreateDefaultHandlers(GraphClientOptions graphClientOptions = null)
125112
{
126113
return new List<DelegatingHandler> {
114+
new GraphTelemetryHandler(graphClientOptions),
127115
new OdataQueryHandler(),
128116
new CompressionHandler(),
129117
new RetryHandler(),
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// ------------------------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information.
3+
// ------------------------------------------------------------------------------
4+
5+
namespace Microsoft.Graph
6+
{
7+
/// <summary>
8+
/// The options for setting up a given graph client
9+
/// </summary>
10+
public class GraphClientOptions
11+
{
12+
/// <summary>
13+
/// The target version of the api endpoint we are targeting (v1 or beta)
14+
/// </summary>
15+
public string GraphServiceTargetVersion { get; set; }
16+
17+
/// <summary>
18+
/// The version of the service library in use. Should be in the format `x.x.x` (Semantic version)
19+
/// </summary>
20+
public string GraphServiceLibraryClientVersion { get; set; }
21+
22+
/// <summary>
23+
/// The version of the core library in use. Should be in the format `x.x.x` (Semantic version).
24+
/// </summary>
25+
public string GraphCoreClientVersion { get; set; }
26+
27+
/// <summary>
28+
/// The product prefix to use in setting the telemetry headers.
29+
/// Will default to `graph-dotnet` if not set.
30+
/// </summary>
31+
public string GraphProductPrefix { get; set; }
32+
}
33+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// ------------------------------------------------------------------------------
2+
// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License in the project root for license information.
3+
// ------------------------------------------------------------------------------
4+
5+
namespace Microsoft.Graph
6+
{
7+
using System;
8+
using System.Net.Http;
9+
using System.Reflection;
10+
using System.Runtime.InteropServices;
11+
using System.Threading;
12+
using System.Threading.Tasks;
13+
14+
/// <summary>
15+
/// A <see cref="DelegatingHandler"/> implementation that telemetry for graph.
16+
/// </summary>
17+
public class GraphTelemetryHandler : DelegatingHandler
18+
{
19+
/// The version for current assembly.
20+
private static Version assemblyVersion = typeof(GraphTelemetryHandler).GetTypeInfo().Assembly.GetName().Version;
21+
22+
/// The value for the SDK version header.
23+
private static string SdkVersionHeaderValue = string.Format(
24+
CoreConstants.Headers.SdkVersionHeaderValueFormatString,
25+
assemblyVersion.Major,
26+
assemblyVersion.Minor,
27+
assemblyVersion.Build);
28+
29+
private readonly GraphClientOptions graphClientOptions;
30+
31+
/// <summary>
32+
/// The <see cref="GraphClientOptions"/> constructor.
33+
/// </summary>
34+
/// <param name="graphClientOptions"></param>
35+
public GraphTelemetryHandler(GraphClientOptions graphClientOptions = null)
36+
{
37+
this.graphClientOptions = graphClientOptions ?? new GraphClientOptions();
38+
}
39+
40+
/// <summary>
41+
/// Sends a HTTP request.
42+
/// </summary>
43+
/// <param name="httpRequest">The <see cref="HttpRequestMessage"/> to be sent.</param>
44+
/// <param name="cancellationToken">The <see cref="CancellationToken"/> for the request.</param>
45+
/// <returns></returns>
46+
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage httpRequest, CancellationToken cancellationToken)
47+
{
48+
if (httpRequest == null)
49+
throw new ArgumentNullException(nameof(httpRequest));
50+
51+
// Build the service library string from the options
52+
var serviceLibraryString = string.Empty;
53+
if (!string.IsNullOrEmpty(graphClientOptions?.GraphServiceLibraryClientVersion))
54+
{
55+
serviceLibraryString = graphClientOptions?.GraphProductPrefix ?? "graph-dotnet";
56+
if (!string.IsNullOrEmpty(graphClientOptions?.GraphServiceTargetVersion))
57+
serviceLibraryString += $"-{graphClientOptions?.GraphServiceTargetVersion}";
58+
serviceLibraryString += $"/{graphClientOptions?.GraphServiceLibraryClientVersion},";
59+
}
60+
61+
// Default to the version string we have, otherwise use the ope provided
62+
var coreLibraryString = SdkVersionHeaderValue;
63+
if (!string.IsNullOrEmpty(graphClientOptions?.GraphCoreClientVersion) && !string.IsNullOrEmpty(graphClientOptions?.GraphProductPrefix))
64+
{
65+
coreLibraryString = $"{graphClientOptions?.GraphProductPrefix}-core/{graphClientOptions?.GraphCoreClientVersion}";
66+
}
67+
68+
// Get the features section of the telemetry header
69+
var features = string.Empty;
70+
if (Environment.OSVersion != null)
71+
features += " hostOS=" + Environment.OSVersion + ";" + " hostArch=" + RuntimeInformation.OSArchitecture + ";"; ;
72+
features += " runtimeEnvironment=" + RuntimeInformation.FrameworkDescription + ";";
73+
74+
var telemetryString = $"{serviceLibraryString} {coreLibraryString} (featureUsage={Enum.Format(typeof(FeatureFlag), httpRequest.GetFeatureFlags(), "x")};{features})";
75+
httpRequest.Headers.Add(CoreConstants.Headers.SdkVersionHeaderName, telemetryString);
76+
httpRequest.Headers.Add(CoreConstants.Headers.ClientRequestId, Guid.NewGuid().ToString());
77+
78+
return base.SendAsync(httpRequest, cancellationToken);
79+
}
80+
81+
}
82+
}

src/Microsoft.Graph.Core/Requests/Middleware/Options/ODataQueryHandlerOption.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ namespace Microsoft.Graph
88
using System;
99
using System.Net.Http;
1010

11+
/// <summary>
12+
/// The <see cref="IRequestOption"/> to configure the <see cref="OdataQueryHandler"/>
13+
/// </summary>
1114
public class ODataQueryHandlerOption : IRequestOption
1215
{
1316
/// <summary>

tests/Microsoft.Graph.DotnetCore.Core.Test/Requests/BaseClientTests.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
namespace Microsoft.Graph.DotnetCore.Core.Test.Requests
66
{
77
using Microsoft.Graph.DotnetCore.Core.Test.Mocks;
8-
using Microsoft.Kiota.Http.HttpClientLibrary;
98
using Xunit;
109
public class BaseClientTests
1110
{
@@ -36,7 +35,7 @@ public void BaseClient_InitializeWithTokenCredential()
3635
var baseClient = new BaseClient(expectedBaseUrl, this.tokenCredential.Object);
3736

3837
Assert.Equal(expectedBaseUrl, baseClient.RequestAdapter.BaseUrl);
39-
Assert.IsType<HttpClientRequestAdapter>(baseClient.RequestAdapter);
38+
Assert.IsType<BaseGraphRequestAdapter>(baseClient.RequestAdapter);
4039

4140
}
4241
}

0 commit comments

Comments
 (0)