From 63d2be5f15c5b03819b329e69a01848a021934ff Mon Sep 17 00:00:00 2001 From: dvonthenen Date: Fri, 29 Mar 2024 19:13:02 -0700 Subject: [PATCH] Last Refactor of LiveClient --- Deepgram.Microphone/Constants.cs | 6 +- Deepgram.Microphone/Library.cs | 8 +- Deepgram.Microphone/Microphone.cs | 12 - .../LoggerExtension/LoggerExtensions.cs | 20 - .../ClientTests/AnalyzeClientTests.cs | 28 +- .../UnitTests/ClientTests/LiveClientTests.cs | 2 +- .../UnitTests/ClientTests/ManageClientTest.cs | 50 +- .../ClientTests/OnPremClientTests.cs | 8 +- .../ClientTests/PrerecordedClientTests.cs | 28 +- .../UnitTests/ClientTests/SpeakClientTests.cs | 10 +- .../LoggerProviderTests/LogProviderTest.cs | 23 - Deepgram/Abstractions/AbstractRestClient.cs | 149 ++++- Deepgram/Abstractions/Constants.cs | 2 +- .../Abstractions/LocalFileWithMetadata.cs | 5 +- Deepgram/Abstractions/NoopSchema.cs | 5 +- Deepgram/Abstractions/Utilities.cs | 4 +- Deepgram/AnalyzeClient.cs | 5 +- Deepgram/Clients/Analyze/v1/Client.cs | 99 +++- Deepgram/Clients/Live/v1/Client.cs | 535 +++++++++++++----- Deepgram/Clients/Manage/v1/Client.cs | 411 +++++++++++--- Deepgram/Clients/OnPrem/v1/Client.cs | 77 ++- Deepgram/Clients/PreRecorded/v1/Client.cs | 96 +++- Deepgram/Clients/Speak/v1/Client.cs | 70 ++- Deepgram/Clients/Speak/v1/Constants.cs | 2 +- Deepgram/Clients/Speak/v1/UriSegments.cs | 2 +- Deepgram/Deepgram.csproj | 3 + Deepgram/Factory/HttpClientFactory.cs | 5 +- Deepgram/GlobalSuppressions.cs | 14 - Deepgram/GlobalUsings.cs | 1 - Deepgram/Library.cs | 18 + Deepgram/Logger/Constants.cs | 47 ++ Deepgram/Logger/Log.cs | 138 +++-- Deepgram/Logger/LogProvider.cs | 31 - Deepgram/ManageClient.cs | 3 +- Deepgram/Models/Analyze/v1/AnalyzeSchema.cs | 2 +- Deepgram/Models/Analyze/v1/AsyncResponse.cs | 2 +- Deepgram/Models/Analyze/v1/Average.cs | 2 +- Deepgram/Models/Analyze/v1/Intent.cs | 2 +- Deepgram/Models/Analyze/v1/IntentGroup.cs | 2 +- Deepgram/Models/Analyze/v1/IntentsInfo.cs | 2 +- Deepgram/Models/Analyze/v1/Metadata.cs | 2 +- Deepgram/Models/Analyze/v1/Results.cs | 2 +- Deepgram/Models/Analyze/v1/Segment.cs | 2 +- Deepgram/Models/Analyze/v1/SentimentGroup.cs | 2 +- Deepgram/Models/Analyze/v1/SentimentInfo.cs | 2 +- Deepgram/Models/Analyze/v1/Summary.cs | 2 +- Deepgram/Models/Analyze/v1/SummaryInfo.cs | 2 +- Deepgram/Models/Analyze/v1/SyncResponse.cs | 2 +- Deepgram/Models/Analyze/v1/Topic.cs | 2 +- Deepgram/Models/Analyze/v1/TopicGroup.cs | 2 +- Deepgram/Models/Analyze/v1/TopicsInfo.cs | 2 +- Deepgram/Models/Analyze/v1/UrlSource.cs | 2 +- .../Authenticate/v1/DeepgramClientOptions.cs | 113 ---- .../v1/DeepgramHttpClientOptions.cs | 123 +++- .../v1/DeepgramWsClientOptions.cs | 103 +++- Deepgram/Models/Speak/v1/AsyncResponse.cs | 2 +- Deepgram/Models/Speak/v1/SpeakSchema.cs | 2 +- Deepgram/Models/Speak/v1/SyncResponse.cs | 2 +- Deepgram/Models/Speak/v1/TextSource.cs | 2 +- Deepgram/OnPremClient.cs | 3 +- Deepgram/PreRecordedClient.cs | 3 +- Deepgram/SpeakClient.cs | 5 +- Deepgram/Utilities/QueryParameterUtil.cs | 6 + Deepgram/Utilities/UserAgentUtil.cs | 1 - examples/prerecorded/file/Program.cs | 18 +- examples/speak/file/hello-world/Program.cs | 17 +- examples/streaming/file/Program.cs | 54 +- examples/streaming/microphone/Program.cs | 77 ++- .../streaming/microphone/Streaming.csproj | 1 - 69 files changed, 1715 insertions(+), 770 deletions(-) delete mode 100644 Deepgram.Tests/LoggerExtension/LoggerExtensions.cs delete mode 100644 Deepgram.Tests/UnitTests/LoggerProviderTests/LogProviderTest.cs create mode 100644 Deepgram/Library.cs create mode 100644 Deepgram/Logger/Constants.cs delete mode 100644 Deepgram/Logger/LogProvider.cs delete mode 100644 Deepgram/Models/Authenticate/v1/DeepgramClientOptions.cs diff --git a/Deepgram.Microphone/Constants.cs b/Deepgram.Microphone/Constants.cs index 967c841e..083c82db 100644 --- a/Deepgram.Microphone/Constants.cs +++ b/Deepgram.Microphone/Constants.cs @@ -1,4 +1,8 @@ -namespace Deepgram.Microphone; +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// SPDX-License-Identifier: MIT + +namespace Deepgram.Microphone; public static class Defaults { diff --git a/Deepgram.Microphone/Library.cs b/Deepgram.Microphone/Library.cs index 47ee10a0..ed94ad1b 100644 --- a/Deepgram.Microphone/Library.cs +++ b/Deepgram.Microphone/Library.cs @@ -1,18 +1,18 @@ - +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// SPDX-License-Identifier: MIT + namespace Deepgram.Microphone; public class Library { public static void Initialize() { - // TODO: logging - Console.WriteLine("Portaudio Version: {0}\n\n", PortAudio.VersionInfo.versionText); PortAudio.Initialize(); } public static void Terminate() { - // TODO: logging // Terminate PortAudio PortAudio.Terminate(); } diff --git a/Deepgram.Microphone/Microphone.cs b/Deepgram.Microphone/Microphone.cs index 3fcb2774..bb0da3f7 100644 --- a/Deepgram.Microphone/Microphone.cs +++ b/Deepgram.Microphone/Microphone.cs @@ -60,8 +60,6 @@ public bool Start() _device_index = PortAudio.DefaultInputDevice; if (_device_index == PortAudio.NoDevice) { - // TODO: logging - Console.WriteLine("No default input device found"); return false; } } @@ -100,15 +98,12 @@ private StreamCallbackResult _callback(nint input, nint output, uint frameCount, // Check if the input is null if (input == IntPtr.Zero) { - // TODO: logging - Console.WriteLine("Input is null"); return StreamCallbackResult.Continue; } // Check if the exit token is set if (_exitToken != null && _exitToken.IsCancellationRequested) { - Console.WriteLine("Exiting!"); return StreamCallbackResult.Abort; } @@ -117,7 +112,6 @@ private StreamCallbackResult _callback(nint input, nint output, uint frameCount, if (_isMuted) { - Console.WriteLine("Muted!"); buf = new byte[buf.Length]; } else @@ -126,7 +120,6 @@ private StreamCallbackResult _callback(nint input, nint output, uint frameCount, } // Push the data to the callback - Console.WriteLine("Sending buffer!"); _push_callback(buf); return StreamCallbackResult.Continue; @@ -136,11 +129,9 @@ public void Mute() { if (_stream != null) { - // TODO: logging return; } - // TODO: logging _isMuted = true; } @@ -148,11 +139,9 @@ public void Unmute() { if (_stream != null) { - // TODO: logging return; } - // TODO: logging _isMuted = false; } @@ -161,7 +150,6 @@ public void Stop() // Check if we have a stream if (_stream == null) { - // TODO: logging return; } diff --git a/Deepgram.Tests/LoggerExtension/LoggerExtensions.cs b/Deepgram.Tests/LoggerExtension/LoggerExtensions.cs deleted file mode 100644 index e3af55d2..00000000 --- a/Deepgram.Tests/LoggerExtension/LoggerExtensions.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. -// SPDX-License-Identifier: MIT - -using Microsoft.Extensions.Logging; - -namespace Deepgram.Tests.TestExtensions; - -public static class LoggerTestExtensions -{ - public static void AnyLogOfType(this ILogger logger, LogLevel level) where T : class - { - logger.Log( - level, - Arg.Any(), - Arg.Is(o => o != null), - Arg.Any(), - Arg.Any>()); - } -} \ No newline at end of file diff --git a/Deepgram.Tests/UnitTests/ClientTests/AnalyzeClientTests.cs b/Deepgram.Tests/UnitTests/ClientTests/AnalyzeClientTests.cs index 396cc75a..dac96580 100644 --- a/Deepgram.Tests/UnitTests/ClientTests/AnalyzeClientTests.cs +++ b/Deepgram.Tests/UnitTests/ClientTests/AnalyzeClientTests.cs @@ -32,7 +32,7 @@ public async Task AnalyzeUrl_Should_Call_PostAsync_Returning_SyncResponse() // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var analyzeClient = Substitute.For(_apiKey, _options); + var analyzeClient = Substitute.For(_apiKey, _options, null); // Mock methods analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -63,7 +63,7 @@ public async Task AnalyzeUrl_Should_Throw_ArgumentException_If_CallBack_Not_Null // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var analyzeClient = Substitute.For(_apiKey, _options); + var analyzeClient = Substitute.For(_apiKey, _options, null); // Mock methods analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -88,7 +88,7 @@ public async Task AnalyzeUrlCallBack_Should_Call_PostAsync_Returning_SyncRespons // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var analyzeClient = Substitute.For(_apiKey, _options); + var analyzeClient = Substitute.For(_apiKey, _options, null); // Mock methods analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -122,7 +122,7 @@ public async Task AnalyzeUrlCallBack_Should_Call_PostAsync_Returning_SyncRespons // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var analyzeClient = Substitute.For(_apiKey, _options); + var analyzeClient = Substitute.For(_apiKey, _options, null); // Mock methods analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -152,7 +152,7 @@ public async Task AnalyzeUrlCallBack_Should_Throw_ArgumentException_With_CallBac // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var analyzeClient = Substitute.For(_apiKey, _options); + var analyzeClient = Substitute.For(_apiKey, _options, null); // Mock methods analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -178,7 +178,7 @@ public async Task AnalyzeUrlCallBack_Should_Throw_ArgumentException_With_No_Call // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var analyzeClient = Substitute.For(_apiKey, _options); + var analyzeClient = Substitute.For(_apiKey, _options, null); // Mock methods analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -203,7 +203,7 @@ public async Task AnalyzeFile_With_Stream_Should_Call_PostAsync_Returning_SyncRe // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var analyzeClient = Substitute.For(_apiKey, _options); + var analyzeClient = Substitute.For(_apiKey, _options, null); // Mock methods analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -234,7 +234,7 @@ public async Task AnalyzeFile_With_Bytes_Should_Call_PostAsync_Returning_SyncRes // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var analyzeClient = Substitute.For(_apiKey, _options); + var analyzeClient = Substitute.For(_apiKey, _options, null); // Mock methods analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -264,7 +264,7 @@ public async Task AnalyzeFileCallBack_With_Stream_With_CallBack_Property_Should_ // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var analyzeClient = Substitute.For(_apiKey, _options); + var analyzeClient = Substitute.For(_apiKey, _options, null); // Mock methods analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -294,7 +294,7 @@ public async Task AnalyzeFileCallBack_With_Bytes_With_CallBack_Property_Should_C // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var analyzeClient = Substitute.For(_apiKey, _options); + var analyzeClient = Substitute.For(_apiKey, _options, null); // Mock methods analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -325,7 +325,7 @@ public async Task AnalyzeFileCallBack_With_Stream_With_CallBack_Parameter_Should // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var analyzeClient = Substitute.For(_apiKey, _options); + var analyzeClient = Substitute.For(_apiKey, _options, null); // Mock methods analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -359,7 +359,7 @@ public async Task AnalyzeFileCallBack_With_Bytes_With_CallBack_Parameter_Should_ // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var analyzeClient = Substitute.For(_apiKey, _options); + var analyzeClient = Substitute.For(_apiKey, _options, null); // Mock methods analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -393,7 +393,7 @@ public async Task AnalyzeFileCallBack_With_Stream_Throw_ArgumentException_With_C // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var analyzeClient = Substitute.For(_apiKey, _options); + var analyzeClient = Substitute.For(_apiKey, _options, null); // Mock methods analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -419,7 +419,7 @@ public async Task AnalyzeFileCallBack_With_Bytes_Should_Throw_ArgumentException_ // Fake Clients var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var analyzeClient = Substitute.For(_apiKey, _options); + var analyzeClient = Substitute.For(_apiKey, _options, null); // Mock methods analyzeClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); diff --git a/Deepgram.Tests/UnitTests/ClientTests/LiveClientTests.cs b/Deepgram.Tests/UnitTests/ClientTests/LiveClientTests.cs index d986b68d..9c0ee948 100644 --- a/Deepgram.Tests/UnitTests/ClientTests/LiveClientTests.cs +++ b/Deepgram.Tests/UnitTests/ClientTests/LiveClientTests.cs @@ -23,7 +23,7 @@ // _options = new DeepgramWsClientOptions(_apiKey, null, null, true); // _webSocketReceiveResult = new WebSocketReceiveResult(1, WebSocketMessageType.Text, true); -// _liveClient = new LiveClient(_apiKey, _options); +// _liveClient = new LiveClient(_apiKey, _options, null); // } // [TearDown] diff --git a/Deepgram.Tests/UnitTests/ClientTests/ManageClientTest.cs b/Deepgram.Tests/UnitTests/ClientTests/ManageClientTest.cs index 9f8240eb..308b177e 100644 --- a/Deepgram.Tests/UnitTests/ClientTests/ManageClientTest.cs +++ b/Deepgram.Tests/UnitTests/ClientTests/ManageClientTest.cs @@ -33,7 +33,7 @@ public async Task GetProjects_Should_Call_GetAsync_Returning_ProjectsResponse() // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); @@ -62,7 +62,7 @@ public async Task GetProject_Should_Call_GetAsync_Returning_ProjectResponse() // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); @@ -91,7 +91,7 @@ public async Task UpdateProject_Should_Call_PatchAsync_Returning_MessageResponse // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.PatchAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -119,7 +119,7 @@ public async Task LeaveProject_Should_Call_DeleteAsync_Returning_MessageResponse // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.DeleteAsync(Arg.Any())).DoNotCallBase(); @@ -148,7 +148,7 @@ public async Task DeleteProject_Should_Call_DeleteAsync() // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.DeleteAsync< MessageResponse>(Arg.Any())).DoNotCallBase(); @@ -173,7 +173,7 @@ public async Task GetKeys_Should_Call_GetAsync_Returning_KeysResponse() // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); @@ -202,7 +202,7 @@ public async Task GetKey_Should_Call_GetAsync_Returning_KeyResponse() // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); @@ -233,7 +233,7 @@ public async Task CreateKey_Should_Call_PostAsync_Returning_KeyResponse_Without_ // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -264,7 +264,7 @@ public async Task CreateKey_Should_Call_PostAsync_Returning_KeyResponse_With_Exp // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -295,7 +295,7 @@ public async Task CreateKey_Should_Return_KeyResponse_Without_TimeToLive_Set() // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -323,7 +323,7 @@ public async Task CreateKey_Should_Throw_ArgumentException_When_Both_Expiration_ var createKeySchema = new AutoFaker().Generate(); // Fake Client - var manageClient = new ManageClient(_apiKey, _options); + var manageClient = new ManageClient(_apiKey, _options, null); //Act & Assert await manageClient.Invoking(y => y.CreateKey(url, createKeySchema)) @@ -340,7 +340,7 @@ public async Task DeleteKey_Should_Call_DeleteAsync() // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.DeleteAsync(Arg.Any())).DoNotCallBase(); @@ -365,7 +365,7 @@ public async Task GetInvites_Should_Call_GetAsync_Returning_InvitesResponse() // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); @@ -394,7 +394,7 @@ public async Task SendInvite_Should_Call_PostAsync_Returning_MessageResponse() // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -423,7 +423,7 @@ public async Task DeleteInvite_Should_Call_DeleteAsync() // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.DeleteAsync(Arg.Any())).DoNotCallBase(); @@ -448,7 +448,7 @@ public async Task GetMembers_Should_Call_GetAsync_Returning_MembersResponse() // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); @@ -477,7 +477,7 @@ public async Task GetMemberScopes_Should_Call_GetAsync_Returning_MemberScopesRes // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); @@ -507,7 +507,7 @@ public async Task UpdateMemberScope_Should_Call_PutAsync_Returning_MessageRespon // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.PutAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -536,7 +536,7 @@ public async Task RemoveMember_Should_Call_DeleteAsync() // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.DeleteAsync(Arg.Any())).DoNotCallBase(); @@ -562,7 +562,7 @@ public async Task GetUsageRequests_Should_Call_GetAsync_Returning_UsageRequestsR // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.GetAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -592,7 +592,7 @@ public async Task GetsUsageRequest_Should_Call_GetAsync_Returning_UsageRequestRe // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); @@ -621,7 +621,7 @@ public async Task GetsUsageSummary_Should_Call_GetAsync_Returning_UsageSummaryRe // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.GetAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -651,7 +651,7 @@ public async Task GetUsageFields_Should_GetAsync_Returning_UsageSummaryResponse( // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.GetAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -684,7 +684,7 @@ public async Task GetBalances_Should_Call_GetAsync_Returning_BalancesResponse() // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); @@ -713,7 +713,7 @@ public async Task GetBalance_Should_Call_GetAsync_Returning_BalanceResponse() // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var manageClient = Substitute.For(_apiKey, _options); + var manageClient = Substitute.For(_apiKey, _options, null); // Mock methods manageClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); diff --git a/Deepgram.Tests/UnitTests/ClientTests/OnPremClientTests.cs b/Deepgram.Tests/UnitTests/ClientTests/OnPremClientTests.cs index 8b778694..577436f8 100644 --- a/Deepgram.Tests/UnitTests/ClientTests/OnPremClientTests.cs +++ b/Deepgram.Tests/UnitTests/ClientTests/OnPremClientTests.cs @@ -30,7 +30,7 @@ public async Task ListCredentials_Should_Call_GetAsync_Returning_CredentialsResp // Fake client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var onPremClient = Substitute.For(_apiKey, _options); + var onPremClient = Substitute.For(_apiKey, _options, null); // Mock methods onPremClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); @@ -59,7 +59,7 @@ public async Task GetCredentials_Should_Call_GetAsync_Returning_CredentialRespon // Fake client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var onPremClient = Substitute.For(_apiKey, _options); + var onPremClient = Substitute.For(_apiKey, _options, null); // Mock methods onPremClient.When(x => x.GetAsync(Arg.Any())).DoNotCallBase(); @@ -88,7 +88,7 @@ public async Task DeleteCredentials_Should_Call_DeleteAsync_Returning_MessageRes // Fake client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var onPremClient = Substitute.For(_apiKey, _options); + var onPremClient = Substitute.For(_apiKey, _options, null); // Mock methods onPremClient.When(x => x.DeleteAsync(Arg.Any())).DoNotCallBase(); @@ -118,7 +118,7 @@ public async Task CreateCredentials_Should_Return_CredentialResponse() // Fake client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var onPremClient = Substitute.For(_apiKey, _options); + var onPremClient = Substitute.For(_apiKey, _options, null); // Mock methods onPremClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); diff --git a/Deepgram.Tests/UnitTests/ClientTests/PrerecordedClientTests.cs b/Deepgram.Tests/UnitTests/ClientTests/PrerecordedClientTests.cs index a19a39ed..5e1a5200 100644 --- a/Deepgram.Tests/UnitTests/ClientTests/PrerecordedClientTests.cs +++ b/Deepgram.Tests/UnitTests/ClientTests/PrerecordedClientTests.cs @@ -32,7 +32,7 @@ public async Task TranscribeUrl_Should_Call_PostAsync_Returning_SyncResponse() // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var prerecordedClient = Substitute.For(_apiKey, _options); + var prerecordedClient = Substitute.For(_apiKey, _options, null); // Mock Methods prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -63,7 +63,7 @@ public async Task TranscribeUrl_Should_Throw_ArgumentException_If_CallBack_Not_N // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var prerecordedClient = Substitute.For(_apiKey, _options); + var prerecordedClient = Substitute.For(_apiKey, _options, null); // Mock Methods prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -87,7 +87,7 @@ public async Task TranscribeUrlCallBack_Should_Call_PostAsync_Returning_SyncResp // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var prerecordedClient = Substitute.For(_apiKey, _options); + var prerecordedClient = Substitute.For(_apiKey, _options, null); // Mock Methods prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -121,7 +121,7 @@ public async Task TranscribeUrlCallBack_Should_Call_PostAsync_Returning_SyncResp // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var prerecordedClient = Substitute.For(_apiKey, _options); + var prerecordedClient = Substitute.For(_apiKey, _options, null); // Mock Methods prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -151,7 +151,7 @@ public async Task TranscribeUrlCallBack_Should_Throw_ArgumentException_With_Call // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var prerecordedClient = Substitute.For(_apiKey, _options); + var prerecordedClient = Substitute.For(_apiKey, _options, null); // Mock Methods prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -178,7 +178,7 @@ public async Task TranscribeUrlCallBack_Should_Throw_ArgumentException_With_No_C // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var prerecordedClient = Substitute.For(_apiKey, _options); + var prerecordedClient = Substitute.For(_apiKey, _options, null); // Mock Methods prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -203,7 +203,7 @@ public async Task TranscribeFile_With_Stream_Should_Call_PostAsync_Returning_Syn // Fake Client var source = GetFakeStream(GetFakeByteArray()); var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var prerecordedClient = Substitute.For(_apiKey, _options); + var prerecordedClient = Substitute.For(_apiKey, _options, null); // Mock Methods prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -234,7 +234,7 @@ public async Task TranscribeFile_With_Bytes_Should_Call_PostAsync_Returning_Sync // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var prerecordedClient = Substitute.For(_apiKey, _options); + var prerecordedClient = Substitute.For(_apiKey, _options, null); // Mock Methods prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -264,7 +264,7 @@ public async Task TranscribeFileCallBack_With_Stream_With_CallBack_Property_Shou // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var prerecordedClient = Substitute.For(_apiKey, _options); + var prerecordedClient = Substitute.For(_apiKey, _options, null); // Mock Methods prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -294,7 +294,7 @@ public async Task TranscribeFileCallBack_With_Bytes_With_CallBack_Property_Shoul // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var prerecordedClient = Substitute.For(_apiKey, _options); + var prerecordedClient = Substitute.For(_apiKey, _options, null); // Mock Methods prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -325,7 +325,7 @@ public async Task TranscribeFileCallBack_With_Stream_With_CallBack_Parameter_Sho // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var prerecordedClient = Substitute.For(_apiKey, _options); + var prerecordedClient = Substitute.For(_apiKey, _options, null); // Mock Methods prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -359,7 +359,7 @@ public async Task TranscribeFileCallBack_With_Bytes_With_CallBack_Parameter_Shou // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var prerecordedClient = Substitute.For(_apiKey, _options); + var prerecordedClient = Substitute.For(_apiKey, _options, null); // Mock Methods prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -393,7 +393,7 @@ public async Task TranscribeFileCallBack_With_Stream_Throw_ArgumentException_Wit // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var prerecordedClient = Substitute.For(_apiKey, _options); + var prerecordedClient = Substitute.For(_apiKey, _options, null); // Mock Methods prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -419,7 +419,7 @@ public async Task TranscribeFileCallBack_With_Bytes_Should_Throw_ArgumentExcepti // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var prerecordedClient = Substitute.For(_apiKey, _options); + var prerecordedClient = Substitute.For(_apiKey, _options, null); // Mock Methods prerecordedClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); diff --git a/Deepgram.Tests/UnitTests/ClientTests/SpeakClientTests.cs b/Deepgram.Tests/UnitTests/ClientTests/SpeakClientTests.cs index 27565252..f340bc55 100644 --- a/Deepgram.Tests/UnitTests/ClientTests/SpeakClientTests.cs +++ b/Deepgram.Tests/UnitTests/ClientTests/SpeakClientTests.cs @@ -33,7 +33,7 @@ public void Setup() // // Fake Client // var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - // var speakClient = Substitute.For(_apiKey, _options); + // var speakClient = Substitute.For(_apiKey, _options, null); // // Mock Methods // speakClient.When(x => x.PostRetrieveLocalFileAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -63,7 +63,7 @@ public async Task StreamCallBack_With_CallBack_Property_Should_Call_PostAsync_Re // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var speakClient = Substitute.For(_apiKey, _options); + var speakClient = Substitute.For(_apiKey, _options, null); // Mock Methods speakClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -93,7 +93,7 @@ public async Task StreamCallBack_With_CallBack_Parameter_Should_Call_PostAsync_R // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var speakClient = Substitute.For(_apiKey, _options); + var speakClient = Substitute.For(_apiKey, _options, null); // Mock Methods speakClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -127,7 +127,7 @@ public async Task StreamCallBack_Throw_ArgumentException_With_CallBack_Property_ // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var speakClient = Substitute.For(_apiKey, _options); + var speakClient = Substitute.For(_apiKey, _options, null); // Mock Methods speakClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); @@ -152,7 +152,7 @@ public async Task StreamCallBack_Should_Throw_ArgumentException_With_No_CallBack // Fake Client var httpClient = MockHttpClient.CreateHttpClientWithResult(expectedResponse); - var speakClient = Substitute.For(_apiKey, _options); + var speakClient = Substitute.For(_apiKey, _options, null); // Mock Methods speakClient.When(x => x.PostAsync(Arg.Any(), Arg.Any(), Arg.Any())).DoNotCallBase(); diff --git a/Deepgram.Tests/UnitTests/LoggerProviderTests/LogProviderTest.cs b/Deepgram.Tests/UnitTests/LoggerProviderTests/LogProviderTest.cs deleted file mode 100644 index 551bd783..00000000 --- a/Deepgram.Tests/UnitTests/LoggerProviderTests/LogProviderTest.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. -// SPDX-License-Identifier: MIT - -using Deepgram.Logger; -using Microsoft.Extensions.Logging; - -namespace Deepgram.Tests.UnitTests.LoggerProviderTests; -public class LogProviderTest -{ - [Test] - public void SetLogFactory_Should_Set_LoggerFactory() - { - // Input and Output - var loggerFactory = Substitute.For(); - - //Act - LogProvider.SetLogFactory(loggerFactory); - - //Assert - LogProvider._loggerFactory.Should().NotBeNull(); - } -} diff --git a/Deepgram/Abstractions/AbstractRestClient.cs b/Deepgram/Abstractions/AbstractRestClient.cs index 6eec2b63..1b29ce1f 100644 --- a/Deepgram/Abstractions/AbstractRestClient.cs +++ b/Deepgram/Abstractions/AbstractRestClient.cs @@ -13,11 +13,6 @@ public abstract class AbstractRestClient /// HttpClient created by the factory internal HttpClient _httpClient; - /// - /// get the logger of category type of _clientName - /// - internal ILogger _logger => LogProvider.GetLogger(this.GetType().Name); - /// /// Copy of the options for the client /// @@ -28,12 +23,20 @@ public abstract class AbstractRestClient /// /// Options for the Deepgram client - internal AbstractRestClient(string? apiKey = null, DeepgramHttpClientOptions? options = null) + internal AbstractRestClient(string? apiKey = null, DeepgramHttpClientOptions? options = null, string? httpId = null) { + Log.Verbose("AbstractRestClient", "ENTER"); + options ??= new DeepgramHttpClientOptions(apiKey); - _httpClient = HttpClientFactory.Create(); + _httpClient = HttpClientFactory.Create(httpId); _httpClient = HttpClientFactory.ConfigureDeepgram(_httpClient, options); _options = options; + + Log.Debug("AbstractRestClient", $"APIVersion: {options.APIVersion}"); + Log.Debug("AbstractRestClient", $"BaseAddress: {options.BaseAddress}"); + Log.Debug("AbstractRestClient", $"KeepAlive: {options.KeepAlive}"); + Log.Debug("AbstractRestClient", $"options: {options.OnPrem}"); + Log.Verbose("AbstractRestClient", "LEAVE"); } /// @@ -45,11 +48,16 @@ internal AbstractRestClient(string? apiKey = null, DeepgramHttpClientOptions? op public virtual async Task GetAsync(string uriSegment, CancellationTokenSource? cancellationToken = null, Dictionary? addons = null, Dictionary? headers = null) { + Log.Verbose("GetAsync", "ENTER"); + Log.Debug("GetAsync", $"uriSegment: {uriSegment}"); + Log.Debug("GetAsync", $"addons: {addons}"); + try { // if not defined, use default timeout if (cancellationToken == null) { + Log.Information("GetAsync", $"Using default timeout: {Constants.DefaultRESTTimeout}"); cancellationToken = new CancellationTokenSource(); cancellationToken.CancelAfter(Constants.DefaultRESTTimeout); } @@ -63,20 +71,25 @@ public virtual async Task GetAsync(string uriSegment, CancellationTokenSou { foreach (var header in headers) { + Log.Debug("GetAsync", $"Add Header {header.Key}={header.Value}"); request.Headers.Add(header.Key, header.Value); } } // do the request + Log.Verbose("GetAsync", "Calling _httpClient.SendAsync..."); var response = await _httpClient.SendAsync(request, cancellationToken.Token); response.EnsureSuccessStatusCode(); var result = await HttpRequestUtil.DeserializeAsync(response); + Log.Debug("GetAsync", "Succeeded"); + Log.Verbose("GetAsync", "LEAVE"); return result; } catch (Exception ex) { - Log.Exception(_logger, "GET", ex); + Log.Error("GetAsync", $"Exception: {ex}"); + Log.Verbose("GetAsync", "LEAVE"); throw; } } @@ -84,11 +97,17 @@ public virtual async Task GetAsync(string uriSegment, CancellationTokenSou public virtual async Task GetAsync(string uriSegment, S? parameter, CancellationTokenSource? cancellationToken = null, Dictionary? addons = null, Dictionary? headers = null) { + Log.Verbose("GetAsync", "ENTER"); + Log.Debug("GetAsync", $"uriSegment: {uriSegment}"); + Log.Debug("GetAsync", $"parameter: {parameter}"); + Log.Debug("GetAsync", $"addons: {addons}"); + try { // if not defined, use default timeout if (cancellationToken == null) { + Log.Information("GetAsync", $"Using default timeout: {Constants.DefaultRESTTimeout}"); cancellationToken = new CancellationTokenSource(); cancellationToken.CancelAfter(Constants.DefaultRESTTimeout); } @@ -101,20 +120,26 @@ public virtual async Task GetAsync(string uriSegment, S? parameter, Can { foreach (var header in headers) { + Log.Debug("GetAsync", $"Add Header {header.Key}={header.Value}"); request.Headers.Add(header.Key, header.Value); } } // do the request + Log.Verbose("GetAsync", "Calling _httpClient.SendAsync..."); var response = await _httpClient.SendAsync(request, cancellationToken.Token); response.EnsureSuccessStatusCode(); var result = await HttpRequestUtil.DeserializeAsync(response); + Log.Debug("GetAsync", "Succeeded"); + Log.Verbose("GetAsync", "LEAVE"); + return result; } catch (Exception ex) { - Log.Exception(_logger, "GET", ex); + Log.Error("GetAsync", $"Exception: {ex}"); + Log.Verbose("GetAsync", "LEAVE"); throw; } } @@ -131,11 +156,18 @@ public virtual async Task PostRetrieveLocalFileAsync? headers = null ) { + Log.Verbose("PostRetrieveLocalFileAsync", "ENTER"); + Log.Debug("PostRetrieveLocalFileAsync", $"uriSegment: {uriSegment}"); + Log.Debug("PostRetrieveLocalFileAsync", $"parameter: {parameter}"); + Log.Debug("PostRetrieveLocalFileAsync", $"keys: {keys}"); + Log.Debug("PostRetrieveLocalFileAsync", $"addons: {addons}"); + try { // if not defined, use default timeout if (cancellationToken == null) { + Log.Information("PostRetrieveLocalFileAsync", $"Using default timeout: {Constants.DefaultRESTTimeout}"); cancellationToken = new CancellationTokenSource(); cancellationToken.CancelAfter(Constants.DefaultRESTTimeout); } @@ -151,11 +183,13 @@ public virtual async Task PostRetrieveLocalFileAsync", $"Add Header {header.Key}={header.Value}"); request.Headers.Add(header.Key, header.Value); } } // do the request + Log.Verbose("PostRetrieveLocalFileAsync", "Calling _httpClient.SendAsync..."); var response = await _httpClient.SendAsync(request, cancellationToken.Token); response.EnsureSuccessStatusCode(); @@ -203,6 +237,9 @@ public virtual async Task PostRetrieveLocalFileAsync", "Succeeded"); + Log.Verbose("PostRetrieveLocalFileAsync", "LEAVE"); + return new LocalFileWithMetadata() { Metadata = result, @@ -212,7 +249,8 @@ public virtual async Task PostRetrieveLocalFileAsync", $"Exception: {ex}"); + Log.Verbose("PostRetrieveLocalFileAsync", "LEAVE"); throw; } } @@ -227,11 +265,17 @@ public virtual async Task PostRetrieveLocalFileAsync PostAsync(string uriSegment, S? parameter, CancellationTokenSource? cancellationToken = null, Dictionary? addons = null, Dictionary? headers = null) { + Log.Verbose("PostAsync", "ENTER"); + Log.Debug("PostAsync", $"uriSegment: {uriSegment}"); + Log.Debug("PostAsync", $"parameter: {parameter}"); + Log.Debug("PostAsync", $"addons: {addons}"); + try { // if not defined, use default timeout if (cancellationToken == null) { + Log.Information("PostAsync", $"Using default timeout: {Constants.DefaultRESTTimeout}"); cancellationToken = new CancellationTokenSource(); cancellationToken.CancelAfter(Constants.DefaultRESTTimeout); } @@ -247,20 +291,26 @@ public virtual async Task PostAsync(string uriSegment, S? parameter, Ca { foreach (var header in headers) { + Log.Debug("PostAsync", $"Add Header {header.Key}={header.Value}"); request.Headers.Add(header.Key, header.Value); } } // do the request + Log.Verbose("PostAsync", "Calling _httpClient.SendAsync..."); var response = await _httpClient.SendAsync(request, cancellationToken.Token); response.EnsureSuccessStatusCode(); var result = await HttpRequestUtil.DeserializeAsync(response); + Log.Debug("PostAsync", $"Succeeded. Result: {result}"); + Log.Verbose("PostAsync", "LEAVE"); + return result; } catch (Exception ex) { - Log.Exception(_logger, "POST", ex); + Log.Error("PostAsync", $"Exception: {ex}"); + Log.Verbose("PostAsync", "LEAVE"); throw; } } @@ -268,11 +318,17 @@ public virtual async Task PostAsync(string uriSegment, S? parameter, Ca public virtual async Task PostAsync(string uriSegment, S? parameter, R? content, CancellationTokenSource? cancellationToken = null, Dictionary? addons = null, Dictionary? headers = null) { + Log.Verbose("PostAsync", "ENTER"); + Log.Debug("PostAsync", $"uriSegment: {uriSegment}"); + Log.Debug("PostAsync", $"parameter: {parameter}"); + Log.Debug("PostAsync", $"addons: {addons}"); + try { // if not defined, use default timeout if (cancellationToken == null) { + Log.Information("PostAsync", $"Using default timeout: {Constants.DefaultRESTTimeout}"); cancellationToken = new CancellationTokenSource(); cancellationToken.CancelAfter(Constants.DefaultRESTTimeout); } @@ -298,20 +354,26 @@ public virtual async Task PostAsync(string uriSegment, S? parameter, { foreach (var header in headers) { + Log.Debug("PostAsync", $"Add Header {header.Key}={header.Value}"); request.Headers.Add(header.Key, header.Value); } } // do the request + Log.Verbose("PostAsync", "Calling _httpClient.SendAsync..."); var response = await _httpClient.SendAsync(request, cancellationToken.Token); response.EnsureSuccessStatusCode(); var result = await HttpRequestUtil.DeserializeAsync(response); + Log.Debug("PostAsync", $"Succeeded. Result: {result}"); + Log.Verbose("PostAsync", "LEAVE"); + return result; } catch (Exception ex) { - Log.Exception(_logger, "POST", ex); + Log.Error("PostAsync", $"Exception: {ex}"); + Log.Verbose("PostAsync", "LEAVE"); throw; } } @@ -325,11 +387,17 @@ public virtual async Task PostAsync(string uriSegment, S? parameter, public virtual async Task PatchAsync(string uriSegment, S? parameter, CancellationTokenSource? cancellationToken = null, Dictionary? addons = null, Dictionary? headers = null) { + Log.Verbose("PatchAsync", "ENTER"); + Log.Debug("PatchAsync", $"uriSegment: {uriSegment}"); + Log.Debug("PatchAsync", $"parameter: {parameter}"); + Log.Debug("PatchAsync", $"addons: {addons}"); + try { // if not defined, use default timeout if (cancellationToken == null) { + Log.Information("PatchAsync", $"Using default timeout: {Constants.DefaultRESTTimeout}"); cancellationToken = new CancellationTokenSource(); cancellationToken.CancelAfter(Constants.DefaultRESTTimeout); } @@ -352,21 +420,27 @@ public virtual async Task PatchAsync(string uriSegment, S? parameter, C { foreach (var header in headers) { + Log.Debug("PatchAsync", $"Add Header {header.Key}={header.Value}"); request.Headers.Add(header.Key, header.Value); } } // do the request + Log.Verbose("PatchAsync", "Calling _httpClient.SendAsync..."); var response = await _httpClient.SendAsync(request, cancellationToken.Token); response.EnsureSuccessStatusCode(); var result = await HttpRequestUtil.DeserializeAsync(response); + Log.Debug("PatchAsync", $"Succeeded. Result: {result}"); + Log.Verbose("PatchAsync", "LEAVE"); + return result; } catch (Exception ex) { - Log.Exception(_logger, "PATCH", ex); + Log.Error("PatchAsync", $"Exception: {ex}"); + Log.Verbose("PatchAsync", "LEAVE"); throw; } @@ -381,11 +455,17 @@ public virtual async Task PatchAsync(string uriSegment, S? parameter, C public virtual async Task PutAsync(string uriSegment, S? parameter, CancellationTokenSource? cancellationToken = null, Dictionary? addons = null, Dictionary? headers = null) { + Log.Verbose("PutAsync", "ENTER"); + Log.Debug("PutAsync", $"uriSegment: {uriSegment}"); + Log.Debug("PutAsync", $"parameter: {parameter}"); + Log.Debug("PutAsync", $"addons: {addons}"); + try { // if not defined, use default timeout if (cancellationToken == null) { + Log.Information("PutAsync", $"Using default timeout: {Constants.DefaultRESTTimeout}"); cancellationToken = new CancellationTokenSource(); cancellationToken.CancelAfter(Constants.DefaultRESTTimeout); } @@ -401,20 +481,30 @@ public virtual async Task PutAsync(string uriSegment, S? parameter, Can { foreach (var header in headers) { + var tmp = header.Key.ToLower(); + if ( !(tmp.Contains("password") || tmp.Contains("token") || tmp.Contains("authorization") || tmp.Contains("auth")) ) + { + Log.Debug("PutAsync", $"Add Header {header.Key}={header.Value}"); + } request.Headers.Add(header.Key, header.Value); } } // do the request + Log.Verbose("PutAsync", "Calling _httpClient.SendAsync..."); var response = await _httpClient.SendAsync(request, cancellationToken.Token); response.EnsureSuccessStatusCode(); var result = await HttpRequestUtil.DeserializeAsync(response); + Log.Debug("PutAsync", $"Succeeded. Result: {result}"); + Log.Verbose("PutAsync", "LEAVE"); + return result; } catch (Exception ex) { - Log.Exception(_logger, "PUT", ex); + Log.Error("PutAsync", $"Exception: {ex}"); + Log.Verbose("PutAsync", "LEAVE"); throw; } } @@ -423,14 +513,19 @@ public virtual async Task PutAsync(string uriSegment, S? parameter, Can /// Delete Method for use with calls that do not expect a response /// /// Uri for the api including the query parameters - public virtual async Task DeleteAsync(string uriSegment, CancellationTokenSource? cancellationToken = null, Dictionary? addons = null, - Dictionary? headers = null) + public virtual async Task DeleteAsync(string uriSegment, CancellationTokenSource? cancellationToken = null, + Dictionary? addons = null, Dictionary? headers = null) { + Log.Verbose("DeleteAsync", "ENTER"); + Log.Debug("DeleteAsync", $"uriSegment: {uriSegment}"); + Log.Debug("DeleteAsync", $"addons: {addons}"); + try { // if not defined, use default timeout if (cancellationToken == null) { + Log.Information("DeleteAsync", $"Using default timeout: {Constants.DefaultRESTTimeout}"); cancellationToken = new CancellationTokenSource(); cancellationToken.CancelAfter(Constants.DefaultRESTTimeout); } @@ -443,20 +538,26 @@ public virtual async Task DeleteAsync(string uriSegment, CancellationToken { foreach (var header in headers) { + Log.Debug("DeleteAsync", $"Add Header {header.Key}={header.Value}"); request.Headers.Add(header.Key, header.Value); } } // do the request + Log.Verbose("DeleteAsync", "Calling _httpClient.SendAsync..."); var response = await _httpClient.SendAsync(request, cancellationToken.Token); response.EnsureSuccessStatusCode(); var result = await HttpRequestUtil.DeserializeAsync(response); + Log.Debug("DeleteAsync", $"Succeeded. Result: {result}"); + Log.Verbose("DeleteAsync", "LEAVE"); + return result; } catch (Exception ex) { - Log.Exception(_logger, "DELETE", ex); + Log.Error("DeleteAsync", $"Exception: {ex}"); + Log.Verbose("DeleteAsync", "LEAVE"); throw; } } @@ -470,11 +571,17 @@ public virtual async Task DeleteAsync(string uriSegment, CancellationToken public virtual async Task DeleteAsync(string uriSegment, S? parameter, CancellationTokenSource? cancellationToken = null, Dictionary? addons = null, Dictionary? headers = null) { + Log.Verbose("DeleteAsync", "ENTER"); + Log.Debug("DeleteAsync", $"uriSegment: {uriSegment}"); + Log.Debug("DeleteAsync", $"parameter: {parameter}"); + Log.Debug("DeleteAsync", $"addons: {addons}"); + try { // if not defined, use default timeout if (cancellationToken == null) { + Log.Information("DeleteAsync", $"Using default timeout: {Constants.DefaultRESTTimeout}"); cancellationToken = new CancellationTokenSource(); cancellationToken.CancelAfter(Constants.DefaultRESTTimeout); } @@ -487,20 +594,26 @@ public virtual async Task DeleteAsync(string uriSegment, S? parameter, { foreach (var header in headers) { + Log.Debug("DeleteAsync", $"Add Header {header.Key}={header.Value}"); request.Headers.Add(header.Key, header.Value); } } // do the request + Log.Verbose("DeleteAsync", "Calling _httpClient.SendAsync..."); var response = await _httpClient.SendAsync(request, cancellationToken.Token); response.EnsureSuccessStatusCode(); var result = await HttpRequestUtil.DeserializeAsync(response); + Log.Debug("DeleteAsync", $"Succeeded. Result: {result}"); + Log.Verbose("DeleteAsync", "LEAVE"); + return result; } catch (Exception ex) { - Log.Exception(_logger, "DELETE ASYNC", ex); + Log.Error("DeleteAsync", $"Exception: {ex}"); + Log.Verbose("DeleteAsync", "LEAVE"); throw; } } diff --git a/Deepgram/Abstractions/Constants.cs b/Deepgram/Abstractions/Constants.cs index fa730a45..3f8cc885 100644 --- a/Deepgram/Abstractions/Constants.cs +++ b/Deepgram/Abstractions/Constants.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Abstractions/LocalFileWithMetadata.cs b/Deepgram/Abstractions/LocalFileWithMetadata.cs index 5cbb5008..9035750d 100644 --- a/Deepgram/Abstractions/LocalFileWithMetadata.cs +++ b/Deepgram/Abstractions/LocalFileWithMetadata.cs @@ -1,9 +1,12 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT namespace Deepgram.Abstractions; +/// +/// LocalFileWithMetadata is a class that represents a file with metadata. +/// public class LocalFileWithMetadata { public Dictionary Metadata { get; set; } diff --git a/Deepgram/Abstractions/NoopSchema.cs b/Deepgram/Abstractions/NoopSchema.cs index 6d72526a..4af49920 100644 --- a/Deepgram/Abstractions/NoopSchema.cs +++ b/Deepgram/Abstractions/NoopSchema.cs @@ -1,9 +1,12 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT namespace Deepgram.Abstractions; +/// +/// Just a NoopSchema where you dont need to marshall JSON into a Async function. +/// public class NoopSchema { } diff --git a/Deepgram/Abstractions/Utilities.cs b/Deepgram/Abstractions/Utilities.cs index 050efb3a..1a4e8b38 100644 --- a/Deepgram/Abstractions/Utilities.cs +++ b/Deepgram/Abstractions/Utilities.cs @@ -4,11 +4,13 @@ namespace Deepgram.Abstractions; +/// +/// Helper funcitons for HttpRequests +/// internal static class HttpRequestUtil { public const string DEFAULT_CONTENT_TYPE = "application/json"; - static ILogger logger => LogProvider.GetLogger(nameof(HttpRequestUtil)); static readonly JsonSerializerOptions _jsonSerializerOptions = new() { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, diff --git a/Deepgram/AnalyzeClient.cs b/Deepgram/AnalyzeClient.cs index f089f86d..8393b98c 100644 --- a/Deepgram/AnalyzeClient.cs +++ b/Deepgram/AnalyzeClient.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT @@ -12,7 +12,8 @@ namespace Deepgram; /// public class AnalyzeClient : Client { - public AnalyzeClient(string apiKey = "", DeepgramHttpClientOptions? deepgramClientOptions = null) : base(apiKey, deepgramClientOptions) + public AnalyzeClient(string apiKey = "", DeepgramHttpClientOptions? deepgramClientOptions = null, + string? httpId = null) : base(apiKey, deepgramClientOptions, httpId) { } } diff --git a/Deepgram/Clients/Analyze/v1/Client.cs b/Deepgram/Clients/Analyze/v1/Client.cs index 810d7953..d1a15a11 100644 --- a/Deepgram/Clients/Analyze/v1/Client.cs +++ b/Deepgram/Clients/Analyze/v1/Client.cs @@ -2,6 +2,7 @@ // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT +using System; using Deepgram.Models.Analyze.v1; using Deepgram.Models.Authenticate.v1; @@ -12,8 +13,8 @@ namespace Deepgram.Clients.Analyze.v1; /// /// Required DeepgramApiKey /// for HttpClient Configuration -public class Client(string? apiKey = null, DeepgramHttpClientOptions? deepgramClientOptions = null) - : AbstractRestClient(apiKey, deepgramClientOptions) +public class Client(string? apiKey = null, DeepgramHttpClientOptions? deepgramClientOptions = null, string? httpId = null) + : AbstractRestClient(apiKey, deepgramClientOptions, httpId) { #region NoneCallBacks /// @@ -24,11 +25,22 @@ public class Client(string? apiKey = null, DeepgramHttpClientOptions? deepgramCl /// public async Task AnalyzeUrl(UrlSource source, AnalyzeSchema? analyzeSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { + Log.Verbose("AnalyzeClient.AnalyzeUrl", "ENTER"); + Log.Information("AnalyzeUrl", $"source: {source}"); + Log.Information("AnalyzeUrl", $"analyzeSchema: {analyzeSchema}"); + VerifyNoCallBack(nameof(AnalyzeUrl), analyzeSchema); - return await PostAsync( - GetUri(_options, UriSegments.READ), analyzeSchema, source, cancellationToken, addons, headers + var uri = GetUri(_options, UriSegments.READ); + var result = await PostAsync( + uri, analyzeSchema, source, cancellationToken, addons, headers ); + + Log.Information("AnalyzeUrl", $"{uri} Succeeded"); + Log.Debug("AnalyzeUrl", $"result: {result}"); + Log.Verbose("AnalyzeClient.AnalyzeUrl", "LEAVE"); + + return result; } @@ -52,13 +64,23 @@ public async Task AnalyzeFile(byte[] source, AnalyzeSchema? analyz /// public async Task AnalyzeFile(Stream source, AnalyzeSchema? analyzeSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { + Log.Verbose("AnalyzeClient.AnalyzeFile", "ENTER"); + Log.Information("AnalyzeFile", $"source: {source}"); + Log.Information("AnalyzeFile", $"analyzeSchema: {analyzeSchema}"); + VerifyNoCallBack(nameof(AnalyzeFile), analyzeSchema); - return await PostAsync( - GetUri(_options, UriSegments.READ), analyzeSchema, source, cancellationToken, addons, headers - ); - } + var uri = GetUri(_options, UriSegments.READ); + var result = await PostAsync( + uri, analyzeSchema, source, cancellationToken, addons, headers + ); + + Log.Information("AnalyzeFile", $"{uri} Succeeded"); + Log.Debug("AnalyzeFile", $"result: {result}"); + Log.Verbose("AnalyzeClient.AnalyzeFile", "LEAVE"); + return result; + } #endregion #region CallBack Methods @@ -84,13 +106,25 @@ public async Task AnalyzeFileCallBack(byte[] source, string? call /// public async Task AnalyzeFileCallBack(Stream source, string? callBack, AnalyzeSchema? analyzeSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { + Log.Verbose("AnalyzeClient.AnalyzeFileCallBack", "ENTER"); + Log.Information("AnalyzeFileCallBack", $"source: {source}"); + Log.Information("AnalyzeFileCallBack", $"callBack: {callBack}"); + Log.Information("AnalyzeFileCallBack", $"analyzeSchema: {analyzeSchema}"); + VerifyOneCallBackSet(nameof(AnalyzeFileCallBack), callBack, analyzeSchema); if (callBack != null) analyzeSchema.CallBack = callBack; - return await PostAsync( - GetUri(_options, UriSegments.READ), analyzeSchema, source, cancellationToken, addons, headers + var uri = GetUri(_options, UriSegments.READ); + var result = await PostAsync( + uri, analyzeSchema, source, cancellationToken, addons, headers ); + + Log.Information("AnalyzeFileCallBack", $"{uri} Succeeded"); + Log.Debug("AnalyzeFileCallBack", $"result: {result}"); + Log.Verbose("AnalyzeClient.AnalyzeFileCallBack", "LEAVE"); + + return result; } /// @@ -102,39 +136,58 @@ public async Task AnalyzeFileCallBack(Stream source, string? call /// public async Task AnalyzeUrlCallBack(UrlSource source, string? callBack, AnalyzeSchema? analyzeSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { + Log.Verbose("AnalyzeClient.AnalyzeUrlCallBack", "ENTER"); + Log.Information("AnalyzeUrlCallBack", $"source: {source}"); + Log.Information("AnalyzeUrlCallBack", $"callBack: {callBack}"); + Log.Information("AnalyzeUrlCallBack", $"analyzeSchema: {analyzeSchema}"); + VerifyOneCallBackSet(nameof(AnalyzeUrlCallBack), callBack, analyzeSchema); if (callBack != null) analyzeSchema.CallBack = callBack; - return await PostAsync( - GetUri(_options, UriSegments.READ), analyzeSchema, source, cancellationToken, addons, headers + var uri = GetUri(_options, UriSegments.READ); + var result = await PostAsync( + uri, analyzeSchema, source, cancellationToken, addons, headers ); + + Log.Information("AnalyzeUrlCallBack", $"{uri} Succeeded"); + Log.Debug("AnalyzeUrlCallBack", $"result: {result}"); + Log.Verbose("AnalyzeClient.AnalyzeUrlCallBack", "LEAVE"); + + return result; } #endregion #region CallbackChecks private void VerifyNoCallBack(string method, AnalyzeSchema? analyzeSchema) { - // TODO: think about logging here based on coderabbit feedback + Log.Debug("VerifyNoCallBack", $"method: {method}"); + if (analyzeSchema != null && analyzeSchema.CallBack != null) - throw new ArgumentException($"CallBack cannot be provided as schema option to a synchronous transcription when calling {method}. Use {nameof(AnalyzeFileCallBack)} or {nameof(AnalyzeUrlCallBack)}"); + { + var exStr = $"CallBack cannot be provided as schema option to a synchronous transcription when calling {method}. Use {nameof(AnalyzeFileCallBack)} or {nameof(AnalyzeUrlCallBack)}"; + Log.Error("VerifyNoCallBack", $"Exception: {exStr}"); + throw new ArgumentException(exStr); + } } - private void VerifyOneCallBackSet(string callingMethod, string? callBack, AnalyzeSchema? analyzeSchema) + private void VerifyOneCallBackSet(string method, string? callBack, AnalyzeSchema? analyzeSchema) { - // TODO: think about logging here based on coderabbit feedback + Log.Debug("VerifyOneCallBackSet", $"method: {method}"); + if (analyzeSchema.CallBack == null && callBack == null) - { //check if no CallBack set in either callBack parameter or AnalyzeSchema - var ex = new ArgumentException($"Either provide a CallBack url or set AnalyzeSchema.CallBack. If no CallBack needed either {nameof(AnalyzeUrl)} or {nameof(AnalyzeFile)}"); - Log.Exception(_logger, $"While calling {callingMethod} no callback set", ex); - throw ex; + { + //check if no CallBack set in either callBack parameter or AnalyzeSchema + var exStr = $"Either provide a CallBack url or set AnalyzeSchema.CallBack. If no CallBack needed either {nameof(AnalyzeUrl)} or {nameof(AnalyzeFile)}"; + Log.Error("VerifyNoCallBack", $"Exception: {exStr}"); + throw new ArgumentException(exStr); } else if (!string.IsNullOrEmpty(analyzeSchema.CallBack) && !string.IsNullOrEmpty(callBack)) { //check that only one CallBack is set in either callBack parameter or AnalyzeSchema - var ex = new ArgumentException("CallBack should be set in either the CallBack parameter or AnalyzeSchema.CallBack not in both."); - Log.Exception(_logger, $"While calling {callingMethod}, callback set in both parameter and property", ex); - throw ex; + var exStr = "CallBack should be set in either the CallBack parameter or AnalyzeSchema.CallBack not in both."; + Log.Error("VerifyNoCallBack", $"Exceptions: {exStr}"); + throw new ArgumentException(exStr); } } #endregion diff --git a/Deepgram/Clients/Live/v1/Client.cs b/Deepgram/Clients/Live/v1/Client.cs index 3f9e159e..c4cda267 100644 --- a/Deepgram/Clients/Live/v1/Client.cs +++ b/Deepgram/Clients/Live/v1/Client.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics.Tracing; +using System.Net.WebSockets; using Deepgram.Models.Authenticate.v1; using Deepgram.Models.Live.v1; @@ -15,19 +16,26 @@ namespace Deepgram.Clients.Live.v1; public class Client : Attribute, IDisposable { #region Fields - internal ILogger logger => LogProvider.GetLogger(this.GetType().Name); - internal readonly DeepgramWsClientOptions _deepgramClientOptions; + private readonly DeepgramWsClientOptions _deepgramClientOptions; - internal ClientWebSocket? _clientWebSocket; - internal CancellationTokenSource _cancellationTokenSource; + private ClientWebSocket? _clientWebSocket; + private CancellationTokenSource _cancellationTokenSource; #endregion /// Required DeepgramApiKey /// for HttpClient Configuration public Client(string? apiKey = null, DeepgramWsClientOptions? options = null) { + Log.Verbose("LiveClient", "ENTER"); + options ??= new DeepgramWsClientOptions(apiKey); _deepgramClientOptions = options; + + Log.Debug("LiveClient", $"APIVersion: {options.APIVersion}"); + Log.Debug("LiveClient", $"BaseAddress: {options.BaseAddress}"); + Log.Debug("LiveClient", $"KeepAlive: {options.KeepAlive}"); + Log.Debug("LiveClient", $"options: {options.OnPrem}"); + Log.Verbose("LiveClient", "LEAVE"); } #region Subscribe Events @@ -44,34 +52,40 @@ public Client(string? apiKey = null, DeepgramWsClientOptions? options = null) public event EventHandler? _errorReceived; #endregion - //TODO when a response is received check if it is a transcript(LiveTranscriptionEvent) or metadata (LiveMetadataEvent) response - /// /// Connect to a Deepgram API Web Socket to begin transcribing audio /// /// Options to use when transcribing audio /// The task object representing the asynchronous operation. - public async Task Connect(LiveSchema options, CancellationTokenSource? cancellationToken = null, Dictionary? addons = null, Dictionary? headers = null) + public async Task Connect(LiveSchema options, CancellationTokenSource? cancellationToken = null, Dictionary? addons = null, + Dictionary? headers = null) { + Log.Verbose("LiveClient.Connect", "ENTER"); + Log.Information("Connect", $"options: {options}"); + Log.Debug("Connect", $"addons: {addons}"); + // check if the client is disposed if (_clientWebSocket != null) { // client has already connected - // TODO: logging - var ex = new Exception("Client has already been initialized"); - ProcessException("Connect", ex); - throw ex; + var exStr = "Client has already been initialized"; + Log.Error("Connect", exStr); + throw new InvalidOperationException(exStr); } // create client _clientWebSocket = new ClientWebSocket(); // set headers - _clientWebSocket.Options.SetRequestHeader("Authorization", $"token {_deepgramClientOptions.ApiKey}"); if (_deepgramClientOptions.Headers is not null) { foreach (var header in _deepgramClientOptions.Headers) { + var tmp = header.Key.ToLower(); + if (!(tmp.Contains("password") || tmp.Contains("token") || tmp.Contains("authorization") || tmp.Contains("auth"))) + { + Log.Debug("PutAsync", $"Add Header {header.Key}={header.Value}"); + } _clientWebSocket.Options.SetRequestHeader(header.Key, header.Value); } } @@ -79,30 +93,60 @@ public async Task Connect(LiveSchema options, CancellationTokenSource? cancellat { foreach (var header in headers) { + var tmp = header.Key.ToLower(); + if (!(tmp.Contains("password") || tmp.Contains("token") || tmp.Contains("authorization") || tmp.Contains("auth"))) + { + Log.Debug("PutAsync", $"Add Header {header.Key}={header.Value}"); + } _clientWebSocket.Options.SetRequestHeader(header.Key, header.Value); } } // cancelation token if (cancellationToken != null) - { + { + Log.Information("Connect", "Using provided cancellation token"); _cancellationTokenSource = cancellationToken; } else { + Log.Information("Connect", "Using default cancellation token"); _cancellationTokenSource = new CancellationTokenSource(); } try { var _uri = GetUri(_deepgramClientOptions, options, addons); - Console.WriteLine(_uri); // TODO: logging + Log.Debug("Connect", $"uri: {_uri}"); + + Log.Debug("Connect", "Connecting to Deepgram API..."); await _clientWebSocket.ConnectAsync(_uri, _cancellationTokenSource.Token).ConfigureAwait(false); + + Log.Debug("Connect", "Starting Sender Thread..."); StartSenderBackgroundThread(); + + Log.Debug("Connect", "Starting Receiver Thread..."); StartReceiverBackgroundThread(); + + if (_deepgramClientOptions.KeepAlive) + { + Log.Debug("Connect", "Starting KeepAlive Thread..."); + StartKeepAliveBackgroundThread(); + } + + // send a OpenResponse event + if (_openReceived != null) + { + Log.Debug("Connect", "Sending OpenResponse event..."); + var data = new OpenResponse(); + data.Type = LiveType.Open; + _openReceived.Invoke(null, data); + } + + Log.Debug("Connect", "Connect Succeeded"); } catch (Exception ex) { - ProcessException("Connect", ex); + Log.Error("Connect", $"Excepton: {ex}"); } void StartSenderBackgroundThread() => _ = Task.Factory.StartNew( @@ -112,6 +156,12 @@ void StartSenderBackgroundThread() => _ = Task.Factory.StartNew( void StartReceiverBackgroundThread() => _ = Task.Factory.StartNew( _ => ProcessReceiveQueue(), TaskCreationOptions.LongRunning); + + void StartKeepAliveBackgroundThread() => _ = Task.Factory.StartNew( + _ => ProcessKeepAlive(), + TaskCreationOptions.LongRunning); + + Log.Verbose("LiveClient.Connect", "LEAVE"); } //// TODO: convienence method for subscribing to events @@ -160,46 +210,107 @@ internal void EnqueueSendMessage(WebSocketMessage message) } catch (Exception ex) { - ProcessException("Enqueue Message", ex); + Log.Error("EnqueueSendMessage", $"Excepton: {ex}"); } } internal async Task ProcessSendQueue() { + Log.Verbose("ProcessSendQueue", "ENTER"); + if (_clientWebSocket == null) { - var ex = new Exception( - "Attempting to start a sender queue when the WebSocket has been disposed is not allowed."); - ProcessException("ProcessSendQueue", ex); - throw ex; + var exStr = "Attempting to start a sender queue when the WebSocket has been disposed is not allowed."; + Log.Error("EnqueueSendMessage", exStr); + Log.Verbose("ProcessSendQueue", "LEAVE"); + + throw new InvalidOperationException(exStr); } try { while (await _sendChannel.Reader.WaitToReadAsync(_cancellationTokenSource.Token)) { + Log.Verbose("ProcessSendQueue", "Reading message of queue..."); while (_sendChannel.Reader.TryRead(out var message)) { + Log.Verbose("ProcessSendQueue", $"Sending message..."); // TODO: dump this message await _clientWebSocket.SendAsync(message.Message, message.MessageType, true, _cancellationTokenSource.Token).ConfigureAwait(false); + } + } + + Log.Verbose("ProcessSendQueue", "Succeeded"); + Log.Verbose("ProcessSendQueue", "LEAVE"); + return; + } + catch (OperationCanceledException ex) + { + Log.Debug("ProcessSendQueue", $"SendThread cancelled."); + Log.Verbose("ProcessSendQueue", $"SendThread cancelled. Info: {ex}"); + } + catch (Exception ex) + { + Log.Error("ProcessSendQueue", $"Excepton: {ex}"); + Log.Verbose("ProcessSendQueue", "LEAVE"); + throw; + } + + Log.Verbose("ProcessSendQueue", "LEAVE"); + } + internal async void ProcessKeepAlive() + { + Log.Verbose("ProcessKeepAlive", "ENTER"); + + try + { + while(true) + { + Log.Verbose("ProcessKeepAlive", "Waiting for KeepAlive..."); + await Task.Delay(5000, _cancellationTokenSource.Token); + + if (_cancellationTokenSource.Token.IsCancellationRequested) + { + Log.Information("ProcessKeepAlive", "KeepAliveThread cancelled"); + break; } + + Log.Debug("ProcessKeepAlive", "Sending KeepAlive"); + byte[] array = Encoding.ASCII.GetBytes("{\"type\": \"KeepAlive\"}"); + await _clientWebSocket.SendAsync(new ArraySegment(array), WebSocketMessageType.Text, true, _cancellationTokenSource.Token) + .ConfigureAwait(false); } + + Log.Verbose("ProcessKeepAlive", "Exiting"); + Log.Verbose("ProcessKeepAlive", "LEAVE"); + return; + } + catch (TaskCanceledException ex) + { + Log.Debug("ProcessKeepAlive", $"KeepAliveThread cancelled."); + Log.Verbose("ProcessKeepAlive", $"KeepAliveThread cancelled. Info: {ex}"); } catch (Exception ex) { - ProcessException("Process sender queue", ex); + Log.Error("ProcessKeepAlive", $"Excepton: {ex}"); + Log.Verbose("ProcessKeepAlive", "LEAVE"); + throw; } + + Log.Verbose("ProcessKeepAlive", "LEAVE"); } internal async Task ProcessReceiveQueue() { + Log.Verbose("ProcessReceiveQueue", "ENTER"); + while (_clientWebSocket?.State == WebSocketState.Open) { try { if (_cancellationTokenSource.Token.IsCancellationRequested) { - // TODO: logging + Log.Information("ProcessReceiveQueue", "ReceiveThread cancelled"); break; } @@ -222,137 +333,241 @@ internal async Task ProcessReceiveQueue() if (result.MessageType == WebSocketMessageType.Close) { - Log.RequestedSocketClose(logger, result.CloseStatusDescription!); + Log.Information("ProcessReceiveQueue", "Received Close message"); break; } - // TODO: replace with fine grained event handling + Log.Verbose("ProcessReceiveQueue", $"Received message: {result} / {ms}"); ProcessDataReceived(result, ms); } if (result.MessageType == WebSocketMessageType.Close) { + Log.Information("ProcessReceiveQueue", "Received WebSocket Close"); await Stop(); break; } } + catch (TaskCanceledException ex) + { + Log.Debug("ProcessReceiveQueue", $"ReceiveThread cancelled."); + Log.Verbose("ProcessReceiveQueue", $"ReceiveThread cancelled. Info: {ex}"); + } catch (Exception ex) { - ProcessException("ProcessReceiveQueue", ex); - break; + Log.Error("ProcessReceiveQueue", $"Excepton: {ex}"); + Log.Verbose("ProcessReceiveQueue", "LEAVE"); + throw; } } + + Log.Verbose("ProcessReceiveQueue", "Succeeded"); + Log.Verbose("ProcessReceiveQueue", "LEAVE"); } internal void ProcessDataReceived(WebSocketReceiveResult result, MemoryStream ms) { + Log.Verbose("ProcessDataReceived", "ENTER"); + ms.Seek(0, SeekOrigin.Begin); - if (result.MessageType == WebSocketMessageType.Text) + if (result.MessageType != WebSocketMessageType.Text) { - var response = Encoding.UTF8.GetString(ms.ToArray()); + Log.Warning("ProcessDataReceived", "Received a text message. This is not supported."); + Log.Verbose("ProcessDataReceived", "LEAVE"); + return; + } - if (response != null) - { - try - { + var response = Encoding.UTF8.GetString(ms.ToArray()); + if (response == null) + { + Log.Warning("ProcessDataReceived", "Response is null"); + Log.Verbose("ProcessDataReceived", "LEAVE"); + return; + } - var data = JsonDocument.Parse(response); - var val = Enum.Parse(typeof(LiveType), data.RootElement.GetProperty("type").GetString()!); - - switch (val) - { - case LiveType.Open: - //var openResponse = new ResponseEvent(data.Deserialize()); - var openResponse = data.Deserialize(); - if (_openReceived == null || openResponse == null) - { - return; - } - _openReceived.Invoke(null, data.Deserialize()); - //InvokeResponseReceived(_openReceived, openResponse); - break; - case LiveType.Results: - //var eventResponse = new ResponseEvent(data.Deserialize()); - var eventResponse = data.Deserialize(); - if (_resultsReceived == null || eventResponse == null) - { - return; - } - _resultsReceived.Invoke(null, data.Deserialize()); - //InvokeResponseReceived(_resultsReceived, eventResponse); - break; - case LiveType.Metadata: - //var metadataResponse = new ResponseEvent(data.Deserialize()); - var metadataResponse = data.Deserialize(); - if (_metadataReceived == null || metadataResponse == null) - { - return; - } - _metadataReceived.Invoke(null, data.Deserialize()); - //InvokeResponseReceived(_metadataReceived, metadataResponse); - break; - case LiveType.UtteranceEnd: - //var utteranceEndResponse = new ResponseEvent(data.Deserialize()); - var utteranceEndResponse = data.Deserialize(); - if (_utteranceEndReceived == null || utteranceEndResponse == null) - { - return; - } - _utteranceEndReceived.Invoke(null, data.Deserialize()); - //InvokeResponseReceived(_utteranceEndReceived, utteranceEndResponse); - break; - case LiveType.SpeechStarted: - //var speechStartedResponse = new ResponseEvent(data.Deserialize()); - var speechStartedResponse = data.Deserialize(); - if (_speechStartedReceived == null || speechStartedResponse == null) - { - return; - } - _speechStartedReceived.Invoke(null, data.Deserialize()); - //InvokeResponseReceived(_speechStartedReceived, speechStartedResponse); - break; - case LiveType.Close: - //var closeResponse = new ResponseEvent(data.Deserialize()); - var closeResponse = data.Deserialize(); - if (_closeReceived == null || closeResponse == null) - { - return; - } - _closeReceived.Invoke(null, data.Deserialize()); - //InvokeResponseReceived(_closeReceived, closeResponse); - break; - case LiveType.Error: - //var errorResponse = new ResponseEvent(data.Deserialize()); - var errorResponse = data.Deserialize(); - if (_errorReceived == null || errorResponse == null) - { - return; - } - _errorReceived.Invoke(null, data.Deserialize()); - //InvokeResponseReceived(_errorReceived, errorResponse); - break; - default: - if (_unhandledReceived == null) - { - return; - } - //var unhandledResponse = new ResponseEvent(data.Deserialize()); - var unhandledResponse = new UnhandledResponse(); - unhandledResponse.Type = LiveType.Unhandled; - unhandledResponse.Raw = response; - - _unhandledReceived.Invoke(null, unhandledResponse); - //InvokeResponseReceived(_unhandledReceived, unhandledResponse); - break; + try + { + Log.Verbose("ProcessDataReceived", $"raw response: {response}"); + var data = JsonDocument.Parse(response); + var val = Enum.Parse(typeof(LiveType), data.RootElement.GetProperty("type").GetString()!); + + Log.Verbose("ProcessDataReceived", $"Type: {val}"); + switch (val) + { + case LiveType.Open: + //var openResponse = new ResponseEvent(data.Deserialize()); + var openResponse = data.Deserialize(); + if (_openReceived == null) + { + Log.Debug("ProcessDataReceived", "_openReceived has no listeners"); + Log.Verbose("ProcessDataReceived", "LEAVE"); + return; } - } - catch (Exception ex) - { - ProcessException("Live response received", ex); - } + if (openResponse == null) + { + Log.Warning("ProcessDataReceived", "OpenResponse is invalid"); + Log.Verbose("ProcessDataReceived", "LEAVE"); + return; + } + + Log.Debug("ProcessDataReceived", $"Invoking OpenResponse. event: {openResponse}"); + _openReceived.Invoke(null, openResponse); + //InvokeResponseReceived(_openReceived, openResponse); + break; + case LiveType.Results: + //var eventResponse = new ResponseEvent(data.Deserialize()); + var resultResponse = data.Deserialize(); + if (_resultsReceived == null) + { + Log.Debug("ProcessDataReceived", "_resultsReceived has no listeners"); + Log.Verbose("ProcessDataReceived", "LEAVE"); + return; + } + if ( resultResponse == null) + { + Log.Warning("ProcessDataReceived", "ResultResponse is invalid"); + Log.Verbose("ProcessDataReceived", "LEAVE"); + return; + } + + Log.Debug("ProcessDataReceived", $"Invoking ResultsResponse. event: {resultResponse}"); + _resultsReceived.Invoke(null, resultResponse); + //InvokeResponseReceived(_resultsReceived, eventResponse); + break; + case LiveType.Metadata: + //var metadataResponse = new ResponseEvent(data.Deserialize()); + var metadataResponse = data.Deserialize(); + if (_metadataReceived == null) + { + Log.Debug("ProcessDataReceived", "_metadataReceived has no listeners"); + Log.Verbose("ProcessDataReceived", "LEAVE"); + return; + } + if (metadataResponse == null) + { + Log.Warning("ProcessDataReceived", "MetadataResponse is invalid"); + Log.Verbose("ProcessDataReceived", "LEAVE"); + return; + } + + Log.Debug("ProcessDataReceived", $"Invoking MetadataResponse. event: {metadataResponse}"); + _metadataReceived.Invoke(null, metadataResponse); + //InvokeResponseReceived(_metadataReceived, metadataResponse); + break; + case LiveType.UtteranceEnd: + //var utteranceEndResponse = new ResponseEvent(data.Deserialize()); + var utteranceEndResponse = data.Deserialize(); + if (_utteranceEndReceived == null) + { + Log.Debug("ProcessDataReceived", "_utteranceEndReceived has no listeners"); + Log.Verbose("ProcessDataReceived", "LEAVE"); + return; + } + if ( utteranceEndResponse == null) + { + Log.Warning("ProcessDataReceived", "UtteranceEndResponse is invalid"); + Log.Verbose("ProcessDataReceived", "LEAVE"); + return; + } + + Log.Debug("ProcessDataReceived", $"Invoking UtteranceEndResponse. event: {utteranceEndResponse}"); + _utteranceEndReceived.Invoke(null, utteranceEndResponse); + //InvokeResponseReceived(_utteranceEndReceived, utteranceEndResponse); + break; + case LiveType.SpeechStarted: + //var speechStartedResponse = new ResponseEvent(data.Deserialize()); + var speechStartedResponse = data.Deserialize(); + if (_speechStartedReceived == null) + { + Log.Debug("ProcessDataReceived", "_speechStartedReceived has no listeners"); + Log.Verbose("ProcessDataReceived", "LEAVE"); + return; + } + if (speechStartedResponse == null) + { + Log.Warning("ProcessDataReceived", "SpeechStartedResponse is invalid"); + Log.Verbose("ProcessDataReceived", "LEAVE"); + return; + } + + Log.Debug("ProcessDataReceived", $"Invoking SpeechStartedResponse. event: {speechStartedResponse}"); + _speechStartedReceived.Invoke(null, speechStartedResponse); + //InvokeResponseReceived(_speechStartedReceived, speechStartedResponse); + break; + case LiveType.Close: + //var closeResponse = new ResponseEvent(data.Deserialize()); + var closeResponse = data.Deserialize(); + if (_closeReceived == null) + { + Log.Debug("ProcessDataReceived", "_closeReceived has no listeners"); + Log.Verbose("ProcessDataReceived", "LEAVE"); + return; + } + if (closeResponse == null) + { + Log.Warning("ProcessDataReceived", "CloseResponse is invalid"); + Log.Verbose("ProcessDataReceived", "LEAVE"); + return; + } + + Log.Debug("ProcessDataReceived", $"Invoking CloseResponse. event: {closeResponse}"); + _closeReceived.Invoke(null, closeResponse); + //InvokeResponseReceived(_closeReceived, closeResponse); + break; + case LiveType.Error: + //var errorResponse = new ResponseEvent(data.Deserialize()); + var errorResponse = data.Deserialize(); + if (_errorReceived == null) + { + Log.Debug("ProcessDataReceived", "_errorReceived has no listeners"); + Log.Verbose("ProcessDataReceived", "LEAVE"); + return; + } + if (errorResponse == null) + { + Log.Warning("ProcessDataReceived", "ErrorResponse is invalid"); + Log.Verbose("ProcessDataReceived", "LEAVE"); + return; + } + + Log.Debug("ProcessDataReceived", $"Invoking ErrorResponse. event: {errorResponse}"); + _errorReceived.Invoke(null, errorResponse); + //InvokeResponseReceived(_errorReceived, errorResponse); + break; + default: + if (_unhandledReceived == null) + { + Log.Debug("ProcessDataReceived", "_unhandledReceived has no listeners"); + Log.Verbose("ProcessDataReceived", "LEAVE"); + return; + } + + //var unhandledResponse = new ResponseEvent(data.Deserialize()); + var unhandledResponse = new UnhandledResponse(); + unhandledResponse.Type = LiveType.Unhandled; + unhandledResponse.Raw = response; + + Log.Debug("ProcessDataReceived", $"Invoking UnhandledResponse. event: {unhandledResponse}"); + _unhandledReceived.Invoke(null, unhandledResponse); + //InvokeResponseReceived(_unhandledReceived, unhandledResponse); + break; } + + Log.Debug("ProcessDataReceived", "Succeeded"); + Log.Verbose("ProcessDataReceived", "LEAVE"); + return; + } + catch (JsonException ex) + { + Log.Error("ProcessDataReceived", $"JsonException: {ex}"); } + catch (Exception ex) + { + Log.Error("ProcessDataReceived", $"Excepton: {ex}"); + } + + Log.Verbose("ProcessDataReceived", "LEAVE"); } /// @@ -361,36 +576,47 @@ internal void ProcessDataReceived(WebSocketReceiveResult result, MemoryStream ms /// The task object representing the asynchronous operation. public async Task Stop(CancellationTokenSource? cancellationToken = null) { + Log.Verbose("Stop", "ENTER"); + var cancelToken = _cancellationTokenSource.Token; if (cancellationToken != null) { + Log.Verbose("Stop", "Using provided cancellation token"); cancelToken = cancellationToken.Token; } // client is already disposed if (_clientWebSocket == null) { - // TODO: logging + Log.Warning("Stop", "Client has already been disposed"); + Log.Verbose("Stop", "LEAVE"); return; } // send the close message and flush transcription message - if (_clientWebSocket!.State == WebSocketState.Open) - { - await _clientWebSocket.SendAsync(new ArraySegment([]), WebSocketMessageType.Binary, true, cancelToken) - .ConfigureAwait(false); - } - - // attempt to stop the connection - try - { - if (_clientWebSocket!.CloseStatus.HasValue) + try { + if (_clientWebSocket!.State == WebSocketState.Open) { - Log.ClosingSocket(logger); + Log.Debug("Stop", "Sending Close message..."); + + // send a close to Deepgram + await _clientWebSocket.SendAsync(new ArraySegment([]), WebSocketMessageType.Binary, true, cancelToken) + .ConfigureAwait(false); + + // send a CloseResponse event + if (_closeReceived != null) + { + Log.Debug("Stop", "Sending CloseResponse event..."); + var data = new CloseResponse(); + data.Type = LiveType.Close; + _closeReceived.Invoke(null, data); + } } + // attempt to stop the connection if (_clientWebSocket!.State != WebSocketState.Closed) { + Log.Debug("Stop", "Closing WebSocket connection..."); await _clientWebSocket.CloseOutputAsync( WebSocketCloseStatus.NormalClosure, string.Empty, @@ -401,14 +627,29 @@ await _clientWebSocket.CloseOutputAsync( // Always request cancellation to the local token source, if some function has been called without a token if (cancellationToken != null) { + Log.Debug("Stop", "Cancelling provided cancellation token..."); cancellationToken.Cancel(); } + + Log.Debug("Stop", "Disposing WebSocket connection..."); _cancellationTokenSource.Cancel(); + + Log.Debug("Stop", "Succeeded"); + Log.Verbose("Stop", "LEAVE"); + return; + } + catch (TaskCanceledException ex) + { + Log.Debug("Stop", $"Stop cancelled."); + Log.Verbose("Stop", $"Stop cancelled. Info: {ex}"); } catch (Exception ex) { - ProcessException("Stop Connection ", ex); + Log.Error("Stop", $"Excepton: {ex}"); } + + _clientWebSocket = null; + Log.Verbose("Stop", "LEAVE"); } #region Helpers @@ -425,13 +666,13 @@ await _clientWebSocket.CloseOutputAsync( public bool IsConnected() => _clientWebSocket.State == WebSocketState.Open; /// - /// TODO + /// Handle channel options /// internal readonly Channel _sendChannel = System.Threading.Channels.Channel .CreateUnbounded(new UnboundedChannelOptions { SingleReader = true, SingleWriter = true, }); /// - /// TODO + /// Get the URI for the WebSocket connection /// internal static Uri GetUri(DeepgramWsClientOptions options, LiveSchema parameter, Dictionary? addons = null) { @@ -443,23 +684,11 @@ internal static Uri GetUri(DeepgramWsClientOptions options, LiveSchema parameter return new Uri($"{options.BaseAddress}/{UriSegments.LISTEN}?{queryString}"); } - - /// - /// TODO - /// - private void ProcessException(string action, Exception ex) - { - if (_clientWebSocket == null) - Log.SocketDisposed(logger, action, ex); - else - Log.Exception(logger, action, ex); - //EventResponseReceived?.Invoke(null, new ResponseEventArgs(new EventResponse() { Error = ex })); - } #endregion #region Dispose /// - /// TODO + /// Disposes of the resources used by the client /// public void Dispose() { diff --git a/Deepgram/Clients/Manage/v1/Client.cs b/Deepgram/Clients/Manage/v1/Client.cs index f7184233..fc73772c 100644 --- a/Deepgram/Clients/Manage/v1/Client.cs +++ b/Deepgram/Clients/Manage/v1/Client.cs @@ -2,6 +2,7 @@ // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT +using System; using Deepgram.Models.Authenticate.v1; using Deepgram.Models.Manage.v1; @@ -12,8 +13,8 @@ namespace Deepgram.Clients.Manage.v1; /// /// Required DeepgramApiKey /// for HttpClient Configuration -public class Client(string? apiKey = null, DeepgramHttpClientOptions? deepgramClientOptions = null) - : AbstractRestClient(apiKey, deepgramClientOptions) +public class Client(string? apiKey = null, DeepgramHttpClientOptions? deepgramClientOptions = null, string? httpId = null) + : AbstractRestClient(apiKey, deepgramClientOptions, httpId) { #region Projects /// @@ -21,8 +22,19 @@ public class Client(string? apiKey = null, DeepgramHttpClientOptions? deepgramCl /// /// public async Task GetProjects(CancellationTokenSource? cancellationToken = default, - Dictionary? addons = null, Dictionary? headers = null) => - await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}"), cancellationToken, addons, headers); + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("ManageClient.GetProjects", "ENTER"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}"); + var result = await GetAsync(uri, cancellationToken, addons, headers); + + Log.Information("GetProjects", $"{uri} Succeeded"); + Log.Debug("GetProjects", $"result: {result}"); + Log.Verbose("ManageClient.GetProjects", "LEAVE"); + + return result; + } /// /// Gets project associated with project Id @@ -30,10 +42,20 @@ public async Task GetProjects(CancellationTokenSource? cancell /// Id of Project /// public async Task GetProject(string projectId, CancellationTokenSource? cancellationToken = default, - Dictionary? addons = null, Dictionary? headers = null) => - await GetAsync( - GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}"), cancellationToken, addons, headers - ); + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("ManageClient.GetProject", "ENTER"); + Log.Information("GetProject", $"projectId: {projectId}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}"); + var result = await GetAsync(uri, cancellationToken, addons, headers); + + Log.Information("GetProject", $"{uri} Succeeded"); + Log.Debug("GetProject", $"result: {result}"); + Log.Verbose("ManageClient.GetProject", "LEAVE"); + + return result; + } /// /// Update a project associated with the projectID @@ -43,10 +65,21 @@ await GetAsync( /// // USES PATCH public async Task UpdateProject(string projectId, ProjectSchema updateProjectSchema, CancellationTokenSource? cancellationToken = default, - Dictionary? addons = null, Dictionary? headers = null) => - await PatchAsync( - GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}"), updateProjectSchema, cancellationToken, addons, headers - ); + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("ManageClient.UpdateProject", "ENTER"); + Log.Information("UpdateProject", $"projectId: {projectId}"); + Log.Information("UpdateProject", $"updateProjectSchema: {updateProjectSchema}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}"); + var result = await PatchAsync(uri, updateProjectSchema, cancellationToken, addons, headers); + + Log.Information("UpdateProject", $"{uri} Succeeded"); + Log.Debug("UpdateProject", $"result: {result}"); + Log.Verbose("ManageClient.UpdateProject", "LEAVE"); + + return result; + } /// /// Deletes a project, no response will be returned @@ -54,10 +87,20 @@ await PatchAsync( /// Id of project // No response expected public async Task DeleteProject(string projectId, CancellationTokenSource? cancellationToken = default, - Dictionary? addons = null, Dictionary? headers = null) => - await DeleteAsync( - GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}"), cancellationToken, addons, headers - ); + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("ManageClient.DeleteProject", "ENTER"); + Log.Information("DeleteProject", $"projectId: {projectId}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}"); + var result = await DeleteAsync(uri, cancellationToken, addons, headers); + + Log.Information("DeleteProject", $"{uri} Succeeded"); + Log.Debug("DeleteProject", $"result: {result}"); + Log.Verbose("ManageClient.DeleteProject", "LEAVE"); + + return result; + } /// /// leave project associated with the project Id @@ -65,10 +108,20 @@ await DeleteAsync( /// Id of project /// public async Task LeaveProject(string projectId, CancellationTokenSource? cancellationToken = default, - Dictionary? addons = null, Dictionary? headers = null) => - await DeleteAsync( - GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/leave"), cancellationToken, addons, headers - ); + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("ManageClient.LeaveProject", "ENTER"); + Log.Information("LeaveProject", $"projectId: {projectId}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/leave"); + var result = await DeleteAsync(uri, cancellationToken, addons, headers); + + Log.Information("LeaveProject", $"{uri} Succeeded"); + Log.Debug("LeaveProject", $"result: {result}"); + Log.Verbose("ManageClient.LeaveProject", "LEAVE"); + + return result; + } #endregion #region ProjectKeys @@ -78,10 +131,21 @@ await DeleteAsync( /// /// Id of project /// - public async Task GetKeys(string projectId, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) => - await GetAsync( - GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.KEYS}"), cancellationToken, addons, headers - ); + public async Task GetKeys(string projectId, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("ManageClient.GetKeys", "ENTER"); + Log.Information("GetKeys", $"projectId: {projectId}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.KEYS}"); + var result = await GetAsync(uri, cancellationToken, addons, headers); + + Log.Information("GetKeys", $"{uri} Succeeded"); + Log.Debug("GetKeys", $"result: {result}"); + Log.Verbose("ManageClient.GetKeys", "LEAVE"); + + return result; + } /// /// Get details of key associated with the key ID @@ -89,10 +153,22 @@ await GetAsync( /// Id of project /// Id of key /// - public async Task GetKey(string projectId, string keyId, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) => - await GetAsync( - GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.KEYS}/{keyId}"), cancellationToken, addons, headers - ); + public async Task GetKey(string projectId, string keyId, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("ManageClient.GetKey", "ENTER"); + Log.Information("GetKey", $"projectId: {projectId}"); + Log.Information("GetKey", $"keyId: {keyId}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.KEYS}/{keyId}"); + var result = await GetAsync(uri, cancellationToken, addons, headers); + + Log.Information("GetKey", $"{uri} Succeeded"); + Log.Debug("GetKey", $"result: {result}"); + Log.Verbose("ManageClient.GetKey", "LEAVE"); + + return result; + } /// /// Create a key in the associated project @@ -100,21 +176,29 @@ await GetAsync( /// Id of project /// for the key to be created /// - public async Task CreateKey(string projectId, KeySchema createKeySchema, CancellationTokenSource? cancellationToken = default, + public async Task CreateKey(string projectId, KeySchema keySchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { - // TODO: think about logging here based on coderabbit feedback - if (createKeySchema.ExpirationDate is not null && createKeySchema.TimeToLiveInSeconds is not null) + Log.Verbose("ManageClient.CreateKey", "ENTER"); + Log.Information("CreateKey", $"projectId: {projectId}"); + Log.Information("CreateKey", $"keySchema: {keySchema}"); + + if (keySchema.ExpirationDate is not null && keySchema.TimeToLiveInSeconds is not null) { - Log.CreateKeyError(_logger, createKeySchema); - throw new ArgumentException("Both ExpirationDate and TimeToLiveInSeconds is set. set either one but not both"); + var exStr = "Both ExpirationDate and TimeToLiveInSeconds is set. set either one but not both"; + Log.Error("CreateKey", $"Exception: {exStr}"); + throw new ArgumentException(exStr); } - return await PostAsync( - GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/keys"), createKeySchema, cancellationToken, addons, headers - ); - } + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/keys"); + var result = await PostAsync(uri, keySchema, cancellationToken, addons, headers); + + Log.Information("CreateKey", $"{uri} Succeeded"); + Log.Debug("CreateKey", $"result: {result}"); + Log.Verbose("ManageClient.CreateKey", "LEAVE"); + return result; + } /// /// Remove key from project, No response returned @@ -122,9 +206,22 @@ public async Task CreateKey(string projectId, KeySchema createKeySc /// Id of project /// Id of key // Nothing being returned - public async Task DeleteKey(string projectId, string keyId, CancellationTokenSource? cancellationToken = default, - Dictionary? addons = null, Dictionary? headers = null) => - await DeleteAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/keys/{keyId}"), cancellationToken, addons, headers); + public async Task DeleteKey(string projectId, string keyId, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("ManageClient.DeleteKey", "ENTER"); + Log.Information("DeleteKey", $"projectId: {projectId}"); + Log.Information("DeleteKey", $"keyId: {keyId}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/keys/{keyId}"); + var result = await DeleteAsync(uri , cancellationToken, addons, headers); + + Log.Information("DeleteKey", $"{uri} Succeeded"); + Log.Debug("DeleteKey", $"result: {result}"); + Log.Verbose("ManageClient.DeleteKey", "LEAVE"); + + return result; + } #endregion #region ProjectInvites @@ -134,8 +231,20 @@ public async Task DeleteKey(string projectId, string keyId, CancellationTokenSou /// Id of project /// public async Task GetInvites(string projectId, CancellationTokenSource? cancellationToken = default, - Dictionary? addons = null, Dictionary? headers = null) => - await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.INVITES}"), cancellationToken, addons, headers); + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("ManageClient.GetInvites", "ENTER"); + Log.Information("GetInvites", $"projectId: {projectId}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.INVITES}"); + var result = await GetAsync(uri, cancellationToken, addons, headers); + + Log.Information("GetInvites", $"{uri} Succeeded"); + Log.Debug("GetInvites", $"result: {result}"); + Log.Verbose("ManageClient.GetInvites", "LEAVE"); + + return result; + } /// /// Delete a project invite that has been sent @@ -143,10 +252,22 @@ public async Task GetInvites(string projectId, CancellationToke /// Id of project /// email of the invite to be removed //no response expected - public async Task DeleteInvite(string projectId, string email, CancellationTokenSource? cancellationToken = default, - Dictionary? addons = null, Dictionary? headers = null) => - await DeleteAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.INVITES}/{email}"), - cancellationToken, addons, headers); + public async Task DeleteInvite(string projectId, string email, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("ManageClient.DeleteInvite", "ENTER"); + Log.Information("DeleteInvite", $"projectId: {projectId}"); + Log.Information("DeleteInvite", $"email: {email}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.INVITES}/{email}"); + var result = await DeleteAsync(uri, cancellationToken, addons, headers); + + Log.Information("DeleteInvite", $"{uri} Succeeded"); + Log.Debug("DeleteInvite", $"result: {result}"); + Log.Verbose("ManageClient.DeleteInvite", "LEAVE"); + + return result; + } /// /// Send a invite to the associated project @@ -155,10 +276,21 @@ await DeleteAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{pr /// for a invite to project /// public async Task SendInvite(string projectId, InviteSchema inviteSchema, CancellationTokenSource? cancellationToken = default, - Dictionary? addons = null, Dictionary? headers = null) => - await PostAsync( - GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.INVITES}"), inviteSchema, cancellationToken, addons, headers - ); + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("ManageClient.SendInvite", "ENTER"); + Log.Information("SendInvite", $"projectId: {projectId}"); + Log.Information("SendInvite", $"inviteSchema: {inviteSchema}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.INVITES}"); + var result = await PostAsync(uri, inviteSchema, cancellationToken, addons, headers); + + Log.Information("SendInvite", $"{uri} Succeeded"); + Log.Debug("SendInvite", $"result: {result}"); + Log.Verbose("ManageClient.SendInvite", "LEAVE"); + + return result; + } #endregion #region Members @@ -168,8 +300,20 @@ await PostAsync( /// Id of project /// public async Task GetMembers(string projectId, CancellationTokenSource? cancellationToken = default, - Dictionary? addons = null, Dictionary? headers = null) => - await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.MEMBERS}"), cancellationToken, addons, headers); + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("ManageClient.GetMembers", "ENTER"); + Log.Information("GetMembers", $"projectId: {projectId}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.MEMBERS}"); + var result = await GetAsync(uri, cancellationToken, addons, headers); + + Log.Information("GetMembers", $"{uri} Succeeded"); + Log.Debug("GetMembers", $"result: {result}"); + Log.Verbose("ManageClient.GetMembers", "LEAVE"); + + return result; + } /// /// Get the scopes associated with member @@ -178,10 +322,20 @@ public async Task GetMembers(string projectId, CancellationToke /// Id of member /// public async Task GetMemberScopes(string projectId, string memberId, CancellationTokenSource? cancellationToken = default, - Dictionary? addons = null, Dictionary? headers = null) => - await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.MEMBERS}/{memberId}/{UriSegments.SCOPES}"), - cancellationToken, addons, headers - ); + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("ManageClient.GetMemberScopes", "ENTER"); + Log.Information("GetMemberScopes", $"projectId: {projectId}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.MEMBERS}/{memberId}/{UriSegments.SCOPES}"); + var result = await GetAsync(uri, cancellationToken, addons, headers); + + Log.Information("GetMemberScopes", $"{uri} Succeeded"); + Log.Debug("GetMemberScopes", $"result: {result}"); + Log.Verbose("ManageClient.GetMemberScopes", "LEAVE"); + + return result; + } /// /// Update the scopes fot the member @@ -190,12 +344,24 @@ await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{ /// Id of member /// updates scope options for member /// - public async Task UpdateMemberScope(string projectId, string memberId, MemberScopeSchema memberScopeSchema, - CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) => - await PutAsync( - GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.MEMBERS}/{memberId}/{UriSegments.SCOPES}"), memberScopeSchema, - cancellationToken, addons, headers - ); + public async Task UpdateMemberScope(string projectId, string memberId, MemberScopeSchema scopeSchema, + CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, + Dictionary? headers = null) + { + Log.Verbose("ManageClient.UpdateMemberScope", "ENTER"); + Log.Information("UpdateMemberScope", $"projectId: {projectId}"); + Log.Information("UpdateMemberScope", $"memberId: {memberId}"); + Log.Information("UpdateMemberScope", $"projectId: {scopeSchema}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.MEMBERS}/{memberId}/{UriSegments.SCOPES}"); + var result = await PutAsync(uri,scopeSchema, cancellationToken, addons, headers); + + Log.Information("UpdateMemberScope", $"{uri} Succeeded"); + Log.Debug("UpdateMemberScope", $"result: {result}"); + Log.Verbose("ManageClient.UpdateMemberScope", "LEAVE"); + + return result; + } /// /// Remove member from project, there is no response @@ -203,11 +369,22 @@ await PutAsync( /// Id of project /// Id of member //No response expected - public async Task RemoveMember(string projectId, string memberId, CancellationTokenSource? cancellationToken = default, - Dictionary? addons = null, Dictionary? headers = null) => - await DeleteAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.MEMBERS}/{memberId}"), - cancellationToken, addons, headers - ); + public async Task RemoveMember(string projectId, string memberId, CancellationTokenSource? cancellationToken = default, + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("ManageClient.RemoveMember", "ENTER"); + Log.Information("RemoveMember", $"projectId: {projectId}"); + Log.Information("RemoveMember", $"memberId: {memberId}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.MEMBERS}/{memberId}"); + var result = await DeleteAsync(uri, cancellationToken, addons, headers); + + Log.Information("RemoveMember", $"{uri} Succeeded"); + Log.Debug("RemoveMember", $"result: {result}"); + Log.Verbose("ManageClient.RemoveMember", "LEAVE"); + + return result; + } #endregion #region Usage @@ -221,9 +398,18 @@ await DeleteAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{pr public async Task GetUsageRequests(string projectId, UsageRequestsSchema usageRequestsSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { - return await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.REQUESTS}"), - usageRequestsSchema, cancellationToken, addons, headers - ); + Log.Verbose("ManageClient.GetUsageRequests", "ENTER"); + Log.Information("GetUsageRequests", $"projectId: {projectId}"); + Log.Information("GetUsageRequests", $"usageRequestsSchema: {usageRequestsSchema}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.REQUESTS}"); + var result = await GetAsync(uri, usageRequestsSchema, cancellationToken, addons, headers); + + Log.Information("GetUsageRequests", $"{uri} Succeeded"); + Log.Debug("GetUsageRequests", $"result: {result}"); + Log.Verbose("ManageClient.GetUsageRequests", "LEAVE"); + + return result; } /// @@ -233,10 +419,21 @@ public async Task GetUsageRequests(string projectId, Usag /// Id of request /// public async Task GetUsageRequest(string projectId, string requestId, CancellationTokenSource? cancellationToken = default, - Dictionary? addons = null, Dictionary? headers = null) => - await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.REQUESTS}/{requestId}"), - cancellationToken, addons, headers - ); + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("ManageClient.GetUsageRequest", "ENTER"); + Log.Information("GetUsageRequest", $"projectId: {projectId}"); + Log.Information("GetUsageRequest", $"requestId: {requestId}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.REQUESTS}/{requestId}"); + var result = await GetAsync(uri, cancellationToken, addons, headers); + + Log.Information("GetUsageRequest", $"{uri} Succeeded"); + Log.Debug("GetUsageRequest", $"result: {result}"); + Log.Verbose("ManageClient.GetUsageRequest", "LEAVE"); + + return result; + } /// /// Gets a summary of usage @@ -244,12 +441,21 @@ await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{ /// Id of project /// Usage summary options /// - public async Task GetUsageSummary(string projectId, UsageSummarySchema usageSummarySchema, + public async Task GetUsageSummary(string projectId, UsageSummarySchema summarySchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { - return await GetAsync( - GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.USAGE}"), usageSummarySchema, cancellationToken, addons, headers - ); + Log.Verbose("ManageClient.GetUsageSummary", "ENTER"); + Log.Information("GetUsageSummary", $"projectId: {projectId}"); + Log.Information("GetUsageSummary", $"summarySchema: {summarySchema}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.USAGE}"); + var result = await GetAsync(uri, summarySchema, cancellationToken, addons, headers); + + Log.Information("GetUsageSummary", $"{uri} Succeeded"); + Log.Debug("GetUsageSummary", $"result: {result}"); + Log.Verbose("ManageClient.GetUsageSummary", "LEAVE"); + + return result; } /// @@ -258,11 +464,21 @@ public async Task GetUsageSummary(string projectId, UsageS /// Id of project /// Project usage request field options /// - public async Task GetUsageFields(string projectId, UsageFieldsSchema usageFieldsSchema, + public async Task GetUsageFields(string projectId, UsageFieldsSchema fieldsSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { - return await GetAsync( - GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.USAGE}/fields"), usageFieldsSchema, cancellationToken, addons, headers); + Log.Verbose("ManageClient.GetUsageFields", "ENTER"); + Log.Information("GetUsageFields", $"projectId: {projectId}"); + Log.Information("GetUsageFields", $"summarySchema: {fieldsSchema}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.USAGE}/fields"); + var result = await GetAsync(uri, fieldsSchema, cancellationToken, addons, headers); + + Log.Information("GetUsageFields", $"{uri} Succeeded"); + Log.Debug("GetUsageFields", $"result: {result}"); + Log.Verbose("ManageClient.GetUsageFields", "LEAVE"); + + return result; } #endregion @@ -273,8 +489,20 @@ public async Task GetUsageFields(string projectId, UsageFie /// Id of project /// public async Task GetBalances(string projectId, CancellationTokenSource? cancellationToken = default, - Dictionary? addons = null, Dictionary? headers = null) => - await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.BALANCES}"), cancellationToken, addons, headers); + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("ManageClient.GetBalances", "ENTER"); + Log.Information("GetBalances", $"projectId: {projectId}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.BALANCES}"); + var result = await GetAsync(uri, cancellationToken, addons, headers); + + Log.Information("GetBalances", $"{uri} Succeeded"); + Log.Debug("GetBalances", $"result: {result}"); + Log.Verbose("ManageClient.GetBalances", "LEAVE"); + + return result; + } /// /// Get the balance details associated with the balance id @@ -283,7 +511,20 @@ public async Task GetBalances(string projectId, CancellationTo /// Id of balance /// public async Task GetBalance(string projectId, string balanceId, CancellationTokenSource? cancellationToken = default, - Dictionary? addons = null, Dictionary? headers = null) => - await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.BALANCES}/{balanceId}"), cancellationToken, addons, headers); + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("ManageClient.GetBalance", "ENTER"); + Log.Information("GetBalance", $"projectId: {projectId}"); + Log.Information("GetBalance", $"balanceId: {balanceId}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.BALANCES}/{balanceId}"); + var result = await GetAsync(uri, cancellationToken, addons, headers); + + Log.Information("GetBalances", $"{uri} Succeeded"); + Log.Debug("GetBalance", $"result: {result}"); + Log.Verbose("ManageClient.GetBalance", "LEAVE"); + + return result; + } #endregion } diff --git a/Deepgram/Clients/OnPrem/v1/Client.cs b/Deepgram/Clients/OnPrem/v1/Client.cs index 4dd4d70a..6cbe0a43 100644 --- a/Deepgram/Clients/OnPrem/v1/Client.cs +++ b/Deepgram/Clients/OnPrem/v1/Client.cs @@ -2,6 +2,7 @@ // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT +using System; using Deepgram.Models.Authenticate.v1; using Deepgram.Models.OnPrem.v1; @@ -12,8 +13,8 @@ namespace Deepgram.Clients.OnPrem.v1; /// /// Required DeepgramApiKey /// for HttpClient Configuration -public class Client(string? apiKey = null, DeepgramHttpClientOptions? deepgramClientOptions = null) - : AbstractRestClient(apiKey, deepgramClientOptions) +public class Client(string? apiKey = null, DeepgramHttpClientOptions? deepgramClientOptions = null, string? httpId = null) + : AbstractRestClient(apiKey, deepgramClientOptions, httpId) { /// /// get a list of credentials associated with project @@ -21,8 +22,20 @@ public class Client(string? apiKey = null, DeepgramHttpClientOptions? deepgramCl /// Id of project /// public async Task ListCredentials(string projectId, CancellationTokenSource? cancellationToken = default, - Dictionary? addons = null, Dictionary? headers = null) => - await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.ONPREM}"), cancellationToken, addons, headers); + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("OnPremClient.ListCredentials", "ENTER"); + Log.Debug("ListCredentials", $"projectId: {projectId}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.ONPREM}"); + var result = await GetAsync(uri, cancellationToken, addons, headers); + + Log.Information("ListCredentials", $"{uri} Succeeded"); + Log.Debug("ListCredentials", $"result: {result}"); + Log.Verbose("OnPremClient.ListCredentials", "LEAVE"); + + return result; + } /// /// Get credentials for the project that is associated with credential ID @@ -31,10 +44,21 @@ public async Task ListCredentials(string projectId, Cancell /// Id of credentials /// public async Task GetCredentials(string projectId, string credentialsId, CancellationTokenSource? cancellationToken = default, - Dictionary? addons = null, Dictionary? headers = null) => - await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.ONPREM}/{credentialsId}"), - cancellationToken, addons, headers - ); + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("OnPremClient.GetCredentials", "ENTER"); + Log.Debug("GetCredentials", $"projectId: {projectId}"); + Log.Debug("GetCredentials", $"credentialsId: {credentialsId}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.ONPREM}/{credentialsId}"); + var result = await GetAsync(uri, cancellationToken, addons, headers); + + Log.Information("GetCredentials", $"{uri} Succeeded"); + Log.Debug("GetCredentials", $"result: {result}"); + Log.Verbose("OnPremClient.GetCredentials", "LEAVE"); + + return result; + } /// /// Remove credentials in the project associated with the credentials ID @@ -43,10 +67,21 @@ await GetAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{pr /// Id of credentials /// public async Task DeleteCredentials(string projectId, string credentialsId, CancellationTokenSource? cancellationToken = default, - Dictionary? addons = null, Dictionary? headers = null) => - await DeleteAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.ONPREM}/{credentialsId}"), - cancellationToken, addons, headers - ); + Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("OnPremClient.DeleteCredentials", "ENTER"); + Log.Debug("DeleteCredentials", $"projectId: {projectId}"); + Log.Debug("DeleteCredentials", $"credentialsId: {credentialsId}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.ONPREM}/{credentialsId}"); + var result = await DeleteAsync(uri, cancellationToken, addons, headers); + + Log.Information("DeleteCredentials", $"{uri} Succeeded"); + Log.Debug("DeleteCredentials", $"result: {result}"); + Log.Verbose("OnPremClient.DeleteCredentials", "LEAVE"); + + return result; + } /// /// Create credentials for the associated projects @@ -55,9 +90,19 @@ await DeleteAsync(GetUri(_options, $"{UriSegments.PROJECTS}/{pr /// for credentials to be created /// public async Task CreateCredentials(string projectId, CredentialsSchema credentialsSchema, - CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) => - await PostAsync( - GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.ONPREM}"), credentialsSchema, cancellationToken, addons, headers - ); + CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) + { + Log.Verbose("OnPremClient.CreateCredentials", "ENTER"); + Log.Debug("CreateCredentials", $"projectId: {projectId}"); + Log.Debug("CreateCredentials", $"credentialsSchema: {credentialsSchema}"); + + var uri = GetUri(_options, $"{UriSegments.PROJECTS}/{projectId}/{UriSegments.ONPREM}"); + var result = await PostAsync(uri, credentialsSchema, cancellationToken, addons, headers); + + Log.Information("CreateCredentials", $"{uri} Succeeded"); + Log.Debug("CreateCredentials", $"result: {result}"); + Log.Verbose("OnPremClient.CreateCredentials", "LEAVE"); + return result; + } } diff --git a/Deepgram/Clients/PreRecorded/v1/Client.cs b/Deepgram/Clients/PreRecorded/v1/Client.cs index 11791670..defc6c92 100644 --- a/Deepgram/Clients/PreRecorded/v1/Client.cs +++ b/Deepgram/Clients/PreRecorded/v1/Client.cs @@ -2,6 +2,7 @@ // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT +using System; using Deepgram.Models.Authenticate.v1; using Deepgram.Models.PreRecorded.v1; @@ -12,8 +13,8 @@ namespace Deepgram.Clients.PreRecorded.v1; /// /// Required DeepgramApiKey /// for HttpClient Configuration -public class Client(string? apiKey = null, DeepgramHttpClientOptions? deepgramClientOptions = null) - : AbstractRestClient(apiKey, deepgramClientOptions) +public class Client(string? apiKey = null, DeepgramHttpClientOptions? deepgramClientOptions = null, string? httpId = null) + : AbstractRestClient(apiKey, deepgramClientOptions, httpId) { #region NoneCallBacks @@ -26,12 +27,22 @@ public class Client(string? apiKey = null, DeepgramHttpClientOptions? deepgramCl public async Task TranscribeUrl(UrlSource source, PrerecordedSchema? prerecordedSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { + Log.Verbose("PreRecordedClient.TranscribeUrl", "ENTER"); + Log.Information("TranscribeUrl", $"source: {source}"); + Log.Information("TranscribeUrl", $"prerecordedSchema: {prerecordedSchema}"); + VerifyNoCallBack(nameof(TranscribeUrl), prerecordedSchema); - return await PostAsync( - GetUri(_options, $"{UriSegments.LISTEN}"), prerecordedSchema, source, cancellationToken, addons, headers - ); + var uri = GetUri(_options, $"{UriSegments.LISTEN}"); + var result = await PostAsync( uri, prerecordedSchema, source, cancellationToken, addons, headers); + + Log.Information("TranscribeUrl", $"{uri} Succeeded"); + Log.Debug("TranscribeUrl", $"result: {result}"); + Log.Verbose("PreRecordedClient.TranscribeUrl", "LEAVE"); + + return result; } + /// /// Transcribes a file using the provided byte array /// @@ -53,11 +64,20 @@ public async Task TranscribeFile(byte[] source, PrerecordedSchema? /// public async Task TranscribeFile(Stream source, PrerecordedSchema? prerecordedSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { + Log.Verbose("PreRecordedClient.TranscribeFile", "ENTER"); + Log.Information("TranscribeFile", $"source: {source}"); + Log.Information("TranscribeFile", $"prerecordedSchema: {prerecordedSchema}"); + VerifyNoCallBack(nameof(TranscribeFile), prerecordedSchema); - return await PostAsync( - GetUri(_options, $"{UriSegments.LISTEN}"), prerecordedSchema, source, cancellationToken, addons, headers - ); + var uri = GetUri(_options, $"{UriSegments.LISTEN}"); + var result = await PostAsync(uri, prerecordedSchema, source, cancellationToken, addons, headers); + + Log.Information("TranscribeFile", $"{uri} Succeeded"); + Log.Debug("TranscribeFile", $"result: {result}"); + Log.Verbose("PreRecordedClient.TranscribeFile", "LEAVE"); + + return result; } #endregion @@ -85,13 +105,23 @@ public async Task TranscribeFileCallBack(byte[] source, string? c /// public async Task TranscribeFileCallBack(Stream source, string? callBack, PrerecordedSchema? prerecordedSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { + Log.Verbose("PreRecordedClient.TranscribeFileCallBack", "ENTER"); + Log.Information("TranscribeFileCallBack", $"source: {source}"); + Log.Information("TranscribeFileCallBack", $"callBack: {callBack}"); + Log.Information("TranscribeFileCallBack", $"prerecordedSchema: {prerecordedSchema}"); + VerifyOneCallBackSet(nameof(TranscribeFileCallBack), callBack, prerecordedSchema); if (callBack != null) prerecordedSchema.CallBack = callBack; - return await PostAsync( - GetUri(_options, $"{UriSegments.LISTEN}"), prerecordedSchema, source, cancellationToken, addons, headers - ); + var uri = GetUri(_options, $"{UriSegments.LISTEN}"); + var result = await PostAsync(uri, prerecordedSchema, source, cancellationToken, addons, headers); + + Log.Information("TranscribeFileCallBack", $"{uri} Succeeded"); + Log.Debug("TranscribeFileCallBack", $"result: {result}"); + Log.Verbose("PreRecordedClient.TranscribeFileCallBack", "LEAVE"); + + return result; } /// @@ -103,39 +133,57 @@ public async Task TranscribeFileCallBack(Stream source, string? c /// public async Task TranscribeUrlCallBack(UrlSource source, string? callBack, PrerecordedSchema? prerecordedSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { + Log.Verbose("PreRecordedClient.TranscribeUrlCallBack", "ENTER"); + Log.Information("TranscribeUrlCallBack", $"source: {source}"); + Log.Information("TranscribeUrlCallBack", $"callBack: {callBack}"); + Log.Information("TranscribeUrlCallBack", $"prerecordedSchema: {prerecordedSchema}"); + VerifyOneCallBackSet(nameof(TranscribeUrlCallBack), callBack, prerecordedSchema); if (callBack != null) prerecordedSchema.CallBack = callBack; - return await PostAsync( - GetUri(_options, $"{UriSegments.LISTEN}"), prerecordedSchema, source, cancellationToken, addons, headers - ); + var uri = GetUri(_options, $"{UriSegments.LISTEN}"); + var result = await PostAsync(uri, prerecordedSchema, source, cancellationToken, addons, headers); + + Log.Information("TranscribeUrlCallBack", $"{uri} Succeeded"); + Log.Debug("TranscribeUrlCallBack", $"result: {result}"); + Log.Verbose("PreRecordedClient.TranscribeUrlCallBack", "LEAVE"); + + return result; } #endregion #region CallbackChecks private void VerifyNoCallBack(string method, PrerecordedSchema? prerecordedSchema) { + Log.Debug("VerifyNoCallBack", $"method: {method}"); + if (prerecordedSchema != null && prerecordedSchema.CallBack != null) - throw new ArgumentException($"CallBack cannot be provided as schema option to a synchronous transcription when calling {method}. Use {nameof(TranscribeFileCallBack)} or {nameof(TranscribeUrlCallBack)}"); + { + var exStr = $"CallBack cannot be provided as schema option to a synchronous transcription when calling {method}. Use {nameof(TranscribeFileCallBack)} or {nameof(TranscribeUrlCallBack)}"; + Log.Error("VerifyNoCallBack", $"Exception: {exStr}"); + throw new ArgumentException(exStr); + } } - private void VerifyOneCallBackSet(string callingMethod, string? callBack, PrerecordedSchema? prerecordedSchema) + private void VerifyOneCallBackSet(string method, string? callBack, PrerecordedSchema? prerecordedSchema) { + Log.Debug("VerifyOneCallBackSet", $"method: {method}"); if (prerecordedSchema.CallBack == null && callBack == null) - { //check if no CallBack set in either callBack parameter or PrerecordedSchema - var ex = new ArgumentException($"Either provide a CallBack url or set PrerecordedSchema.CallBack. If no CallBack needed either {nameof(TranscribeUrl)} or {nameof(TranscribeFile)}"); - Log.Exception(_logger, $"While calling {callingMethod} no callback set", ex); - throw ex; + { + //check if no CallBack set in either callBack parameter or AnalyzeSchema + var exStr = $"Either provide a CallBack url or set PreRecordedSchema.CallBack. If no CallBack needed either {nameof(TranscribeUrl)} or {nameof(TranscribeFile)}"; + Log.Error("VerifyNoCallBack", $"Exception: {exStr}"); + throw new ArgumentException(exStr); } else if (!string.IsNullOrEmpty(prerecordedSchema.CallBack) && !string.IsNullOrEmpty(callBack)) { - //check that only one CallBack is set in either callBack parameter or PrerecordedSchema - var ex = new ArgumentException("CallBack should be set in either the CallBack parameter or PrerecordedSchema.CallBack not in both."); - Log.Exception(_logger, $"While calling {callingMethod}, callback set in both parameter and property", ex); - throw ex; + //check that only one CallBack is set in either callBack parameter or AnalyzeSchema + var exStr = "CallBack should be set in either the CallBack parameter or PreRecordedSchema.CallBack not in both."; + Log.Error("VerifyNoCallBack", $"Exceptions: {exStr}"); + throw new ArgumentException(exStr); } } #endregion diff --git a/Deepgram/Clients/Speak/v1/Client.cs b/Deepgram/Clients/Speak/v1/Client.cs index e6dc56c0..79933e27 100644 --- a/Deepgram/Clients/Speak/v1/Client.cs +++ b/Deepgram/Clients/Speak/v1/Client.cs @@ -1,9 +1,10 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT using Deepgram.Models.Speak.v1; using Deepgram.Models.Authenticate.v1; +using System; namespace Deepgram.Clients.Speak.v1; @@ -12,8 +13,8 @@ namespace Deepgram.Clients.Speak.v1; /// /// Required DeepgramApiKey /// for HttpClient Configuration -public class Client(string? apiKey = null, DeepgramHttpClientOptions? deepgramClientOptions = null) - : AbstractRestClient(apiKey, deepgramClientOptions) +public class Client(string? apiKey = null, DeepgramHttpClientOptions? deepgramClientOptions = null, string? httpId = null) + : AbstractRestClient(apiKey, deepgramClientOptions, httpId) { #region NoneCallBacks /// @@ -25,6 +26,10 @@ public class Client(string? apiKey = null, DeepgramHttpClientOptions? deepgramCl public async Task ToStream(TextSource source, SpeakSchema? speakSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { + Log.Verbose("SpeakClient.ToStream", "ENTER"); + Log.Information("ToStream", $"source: {source}"); + Log.Information("ToStream", $"analyzeSchema: {speakSchema}"); + VerifyNoCallBack(nameof(ToStream), speakSchema); List keys = new List { @@ -37,8 +42,9 @@ public async Task ToStream(TextSource source, SpeakSchema? speakSc Constants.Date, }; + var uri = GetUri(_options, $"{UriSegments.SPEAK}"); var localFileResult = await PostRetrieveLocalFileAsync( - GetUri(_options, $"{UriSegments.SPEAK}"), speakSchema, source, keys, cancellationToken, addons, headers + uri, speakSchema, source, keys, cancellationToken, addons, headers ); SyncResponse response = new SyncResponse(); @@ -77,6 +83,10 @@ public async Task ToStream(TextSource source, SpeakSchema? speakSc } } + Log.Information("ToStream", $"{uri} Succeeded"); + Log.Debug("ToStream", $"response: {response}"); + Log.Verbose("Client.ToStream", "LEAVE"); + // add stream to response response.Stream = localFileResult.Content; @@ -87,6 +97,10 @@ public async Task ToFile(TextSource source, string filename, Speak Dictionary? addons = null, Dictionary? headers = null ) { + Log.Verbose("Client.ToFile", "ENTER"); + Log.Information("ToFile", $"source: {source}"); + Log.Information("ToFile", $"filename: {filename}"); + var response = await ToStream(source, speakSchema, cancellationToken, addons, headers); // save the file @@ -99,6 +113,8 @@ public async Task ToFile(TextSource source, string filename, Speak // clear the stream response.Stream = null; + Log.Verbose("Client.ToFile", "LEAVE"); + return response; } #endregion @@ -114,38 +130,56 @@ public async Task ToFile(TextSource source, string filename, Speak public async Task StreamCallBack(TextSource source, string? callBack, SpeakSchema? speakSchema, CancellationTokenSource? cancellationToken = default, Dictionary? addons = null, Dictionary? headers = null) { + Log.Verbose("SpeakClient.StreamCallBack", "ENTER"); + Log.Information("StreamCallBack", $"source: {source}"); + Log.Information("StreamCallBack", $"callBack: {callBack}"); + Log.Information("StreamCallBack", $"speakSchema: {speakSchema}"); + VerifyOneCallBackSet(nameof(StreamCallBack), callBack, speakSchema); if (callBack != null) speakSchema.CallBack = callBack; - return await PostAsync( - GetUri(_options, $"{UriSegments.SPEAK}"), speakSchema, source, cancellationToken, addons, headers); + var uri = GetUri(_options, $"{UriSegments.SPEAK}"); + var result = await PostAsync(uri, speakSchema, source, cancellationToken, addons, headers); + + Log.Information("StreamCallBack", $"{uri} Succeeded"); + Log.Debug("StreamCallBack", $"result: {result}"); + Log.Verbose("Client.StreamCallBack", "LEAVE"); + + return result; } #endregion #region CallbackChecks private void VerifyNoCallBack(string method, SpeakSchema? speakSchema) { - // TODO: think about logging here based on coderabbit feedback + Log.Debug("VerifyNoCallBack", $"method: {method}"); + if (speakSchema != null && speakSchema.CallBack != null) - throw new ArgumentException($"CallBack cannot be provided as schema option to a synchronous transcription when calling {method}. Use {nameof(StreamCallBack)}"); + { + var exStr = $"CallBack cannot be provided as schema option to a synchronous transcription when calling {method}. Use {nameof(StreamCallBack)}"; + Log.Error("VerifyNoCallBack", $"Exception: {exStr}"); + throw new ArgumentException(exStr); + } } - private void VerifyOneCallBackSet(string callingMethod, string? callBack, SpeakSchema? speakSchema) + private void VerifyOneCallBackSet(string method, string? callBack, SpeakSchema? speakSchema) { - // TODO: think about logging here based on coderabbit feedback + Log.Debug("VerifyOneCallBackSet", $"method: {method}"); + if (speakSchema.CallBack == null && callBack == null) - { //check if no CallBack set in either callBack parameter or SpeakSchema - var ex = new ArgumentException($"Either provide a CallBack url or set SpeakSchema.CallBack. If no CallBack needed either {nameof(Stream)}"); - Log.Exception(_logger, $"While calling {callingMethod} no callback set", ex); - throw ex; + { + //check if no CallBack set in either callBack parameter or AnalyzeSchema + var exStr = $"Either provide a CallBack url or set SpeakSchema.CallBack. Use {nameof(ToStream)}"; + Log.Error("VerifyNoCallBack", $"Exception: {exStr}"); + throw new ArgumentException(exStr); } else if (!string.IsNullOrEmpty(speakSchema.CallBack) && !string.IsNullOrEmpty(callBack)) { - //check that only one CallBack is set in either callBack parameter or SpeakSchema - var ex = new ArgumentException("CallBack should be set in either the CallBack parameter or SpeakSchema.CallBack not in both."); - Log.Exception(_logger, $"While calling {callingMethod}, callback set in both parameter and property", ex); - throw ex; + //check that only one CallBack is set in either callBack parameter or AnalyzeSchema + var exStr = "CallBack should be set in either the CallBack parameter or SpeakSchema.CallBack not in both."; + Log.Error("VerifyNoCallBack", $"Exceptions: {exStr}"); + throw new ArgumentException(exStr); } } #endregion diff --git a/Deepgram/Clients/Speak/v1/Constants.cs b/Deepgram/Clients/Speak/v1/Constants.cs index 8e4accc8..ff2cfdd0 100644 --- a/Deepgram/Clients/Speak/v1/Constants.cs +++ b/Deepgram/Clients/Speak/v1/Constants.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Clients/Speak/v1/UriSegments.cs b/Deepgram/Clients/Speak/v1/UriSegments.cs index 661ddd6a..838aa400 100644 --- a/Deepgram/Clients/Speak/v1/UriSegments.cs +++ b/Deepgram/Clients/Speak/v1/UriSegments.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Deepgram.csproj b/Deepgram/Deepgram.csproj index 39a2c19c..f9de39bb 100644 --- a/Deepgram/Deepgram.csproj +++ b/Deepgram/Deepgram.csproj @@ -125,6 +125,9 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all + + + \ No newline at end of file diff --git a/Deepgram/Factory/HttpClientFactory.cs b/Deepgram/Factory/HttpClientFactory.cs index d18d7017..58529793 100644 --- a/Deepgram/Factory/HttpClientFactory.cs +++ b/Deepgram/Factory/HttpClientFactory.cs @@ -11,8 +11,11 @@ internal class HttpClientFactory public const int DEFAULT_HTTP_TINEOUT_IN_MINUTES = 5; public const string HTTPCLIENT_NAME = "DEEPGRAM_HTTP_CLIENT"; - public static HttpClient Create(string httpId = HTTPCLIENT_NAME) + public static HttpClient Create(string? httpId = null) { + if (string.IsNullOrWhiteSpace(httpId)) + httpId = HTTPCLIENT_NAME; + var services = new ServiceCollection(); services.AddHttpClient(httpId) .AddTransientHttpErrorPolicy(policyBuilder => diff --git a/Deepgram/GlobalSuppressions.cs b/Deepgram/GlobalSuppressions.cs index 120a2d21..4b8cecd1 100644 --- a/Deepgram/GlobalSuppressions.cs +++ b/Deepgram/GlobalSuppressions.cs @@ -10,7 +10,6 @@ using System.Diagnostics.CodeAnalysis; [assembly: SuppressMessage("Spellchecker", "CRRSP08:A misspelled word has been found", Justification = "", Scope = "member", Target = "~F:Deepgram.Constants.AudioEncoding.OggSpeex")] -[assembly: SuppressMessage("Spellchecker", "CRRSP08:A misspelled word has been found", Justification = "", Scope = "namespace", Target = "~N:Deepgram.DeepgramEventArgs")] [assembly: SuppressMessage("Spellchecker", "CRRSP08:A misspelled word has been found", Justification = "", Scope = "member", Target = "~P:Deepgram.Models.Manage.v1.Config.Diarize")] [assembly: SuppressMessage("Spellchecker", "CRRSP08:A misspelled word has been found", Justification = "", Scope = "member", Target = "~P:Deepgram.Models.Manage.v1.UsageSummarySchema.Diarize")] [assembly: SuppressMessage("Spellchecker", "CRRSP08:A misspelled word has been found", Justification = "", Scope = "type", Target = "~T:Deepgram.Models.OnPrem.v1.CredentialsSchema")] @@ -19,19 +18,6 @@ [assembly: SuppressMessage("Spellchecker", "CRRSP08:A misspelled word has been found", Justification = "", Scope = "type", Target = "~T:Deepgram.Models.PreRecorded.v1.AsyncResponse")] [assembly: SuppressMessage("Spellchecker", "CRRSP08:A misspelled word has been found", Justification = "", Scope = "type", Target = "~T:Deepgram.Models.PreRecorded.v1.PrerecordedSchema")] [assembly: SuppressMessage("Spellchecker", "CRRSP08:A misspelled word has been found", Justification = "", Scope = "type", Target = "~T:Deepgram.Models.PreRecorded.v1.SyncResponse")] -[assembly: SuppressMessage("Spellchecker", "CRRSP08:A misspelled word has been found", Justification = "", Scope = "member", Target = "~P:Deepgram.Models.PreRecorded.v1.TranscriptionSchema.Diarize")] -[assembly: SuppressMessage("Spellchecker", "CRRSP08:A misspelled word has been found", Justification = "", Scope = "member", Target = "~P:Deepgram.Models.Live.v1.TranscriptionSchema.Diarize")] -[assembly: SuppressMessage("Spellchecker", "CRRSP08:A misspelled word has been found", Justification = "", Scope = "member", Target = "~P:Deepgram.Models.PreRecorded.v1.TranscriptionSchema.DiarizeVersion")] -[assembly: SuppressMessage("Spellchecker", "CRRSP08:A misspelled word has been found", Justification = "", Scope = "member", Target = "~P:Deepgram.Models.Live.v1.TranscriptionSchema.DiarizeVersion")] [assembly: SuppressMessage("Performance", "SYSLIB1045:Convert to 'GeneratedRegexAttribute'.", Justification = "", Scope = "member", Target = "~M:Deepgram.Utilities.UserAgentUtil.GetInfo~System.String")] -[assembly: SuppressMessage("Performance", "SYSLIB1045:Convert to 'GeneratedRegexAttribute'.", Justification = "", Scope = "member", Target = "~M:Deepgram.Extensions.HttpClientExtensions.SetBaseUrl(System.Net.Http.HttpClient,Deepgram.Models.Shared.v1.DeepgramClientOptions)")] -[assembly: SuppressMessage("Performance", "SYSLIB1045:Convert to 'GeneratedRegexAttribute'.", Justification = "", Scope = "member", Target = "~M:Deepgram.LiveClient.GetBaseUrl(Deepgram.Models.Shared.v1.DeepgramClientOptions)~System.String")] -[assembly: SuppressMessage("Style", "IDE0057:Use range operator", Justification = "", Scope = "member", Target = "~M:Deepgram.Models.PreRecorded.v1.SyncResponse.SecondsToTimestamp(System.Decimal)~System.String")] -[assembly: SuppressMessage("Spellchecker", "CRRSP09:A misspelled word has been found", Justification = "", Scope = "member", Target = "~F:Deepgram.LiveClient._deepgramClientOptions")] -[assembly: SuppressMessage("Spellchecker", "CRRSP09:A misspelled word has been found", Justification = "", Scope = "member", Target = "~M:Deepgram.Extensions.HttpClientExtensions.ConfigureDeepgram(System.Net.Http.HttpClient,System.String,Deepgram.Models.Shared.v1.DeepgramClientOptions)~System.Net.Http.HttpClient")] [assembly: SuppressMessage("Spellchecker", "CRRSP08:A misspelled word has been found", Justification = "", Scope = "namespace", Target = "~N:Deepgram")] -[assembly: SuppressMessage("Spellchecker", "CRRSP08:A misspelled word has been found", Justification = "", Scope = "namespace", Target = "~N:Deepgram.HttpClient")] -[assembly: SuppressMessage("Spellchecker", "CRRSP09:A misspelled word has been found", Justification = "", Scope = "type", Target = "~T:Deepgram.HttpClient.HttpClientFactory")] -[assembly: SuppressMessage("Spellchecker", "CRRSP08:A misspelled word has been found", Justification = "", Scope = "type", Target = "~T:Deepgram.Models.Authenticate.v1.DeepgramClientOptions")] [assembly: SuppressMessage("Spellchecker", "CRRSP08:A misspelled word has been found", Justification = "", Scope = "type", Target = "~T:Deepgram.OnPremClient")] -[assembly: SuppressMessage("Spellchecker", "CRRSP08:A misspelled word has been found", Justification = "", Scope = "type", Target = "~T:Deepgram.PrerecordedClient")] diff --git a/Deepgram/GlobalUsings.cs b/Deepgram/GlobalUsings.cs index dc312f5c..a33d6c16 100644 --- a/Deepgram/GlobalUsings.cs +++ b/Deepgram/GlobalUsings.cs @@ -18,6 +18,5 @@ global using Deepgram.Utilities; global using Microsoft.Extensions.DependencyInjection; global using Microsoft.Extensions.Logging; -global using Microsoft.Extensions.Logging.Abstractions; global using Polly; global using Polly.Contrib.WaitAndRetry; diff --git a/Deepgram/Library.cs b/Deepgram/Library.cs new file mode 100644 index 00000000..e034a9a3 --- /dev/null +++ b/Deepgram/Library.cs @@ -0,0 +1,18 @@ +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// SPDX-License-Identifier: MIT + +namespace Deepgram; + +public class Library +{ + public static void Initialize(Logger.LogLevel level = Logger.LogLevel.Default, string? filename = "log.txt") + { + Log.Initialize(level, filename); + } + + public static void Terminate() + { + // No-op + } +} diff --git a/Deepgram/Logger/Constants.cs b/Deepgram/Logger/Constants.cs new file mode 100644 index 00000000..48fc9f3f --- /dev/null +++ b/Deepgram/Logger/Constants.cs @@ -0,0 +1,47 @@ +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// SPDX-License-Identifier: MIT + +namespace Deepgram.Logger; + +/// +/// Specifies the meaning and relative importance of a log event. +/// +public enum LogLevel +{ + /// + /// Anything and everything you might want to know about + /// a running block of code. + /// + Verbose = Serilog.Events.LogEventLevel.Verbose, + + /// + /// Internal system events that aren't necessarily + /// observable from the outside. + /// + Debug = Serilog.Events.LogEventLevel.Debug, + + /// + /// The lifeblood of operational intelligence - things + /// happen. + /// + Information = Serilog.Events.LogEventLevel.Information, + Default = Serilog.Events.LogEventLevel.Information, + + /// + /// Service is degraded or endangered. + /// + Warning = Serilog.Events.LogEventLevel.Warning, + + /// + /// Functionality is unavailable, invariants are broken + /// or data is lost. + /// + Error = Serilog.Events.LogEventLevel.Error, + + /// + /// If you have a pager, it goes off when one of these + /// occurs. + /// + Fatal = Serilog.Events.LogEventLevel.Fatal, +} diff --git a/Deepgram/Logger/Log.cs b/Deepgram/Logger/Log.cs index ebe96c2e..04482baa 100644 --- a/Deepgram/Logger/Log.cs +++ b/Deepgram/Logger/Log.cs @@ -1,53 +1,99 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT -using Deepgram.Models.Manage.v1; +using Serilog; namespace Deepgram.Logger; -internal static partial class Log + +public sealed class Log { - [LoggerMessage( - EventId = 0002, - Level = LogLevel.Error, - Message = "`{requestType}` threw exception ")] - internal static partial void Exception(this ILogger logger, string requestType, Exception ex); - - [LoggerMessage( - EventId = 0005, - Level = LogLevel.Information, - Message = "Whilst creating RestClient there was no ApiKey ")] - internal static partial void ApiKeyNotPresent(this ILogger logger); - - - [LoggerMessage( - EventId = 0006, - Level = LogLevel.Warning, - Message = "Trying to send message when the socket is `{state}`. Ack for this message will fail shortly.")] - internal static partial void LiveSendWarning(this ILogger logger, WebSocketState state); - - - [LoggerMessage( - EventId = 0009, - Level = LogLevel.Error, - Message = "Unable to perform `{action}` Socket disposed")] - internal static partial void SocketDisposed(this ILogger logger, string action, Exception ex); - - [LoggerMessage( - EventId = 0014, - Level = LogLevel.Error, - Message = "Closing WebSocket")] - internal static partial void ClosingSocket(this ILogger logger); - - [LoggerMessage( - EventId = 0016, - Level = LogLevel.Information, - Message = "WebSocket is being closed : `{closeStatusDescription}`")] - internal static partial void RequestedSocketClose(this ILogger logger, string closeStatusDescription); - - [LoggerMessage( - EventId = 0018, - Level = LogLevel.Error, - Message = "Error creating project key both ExpirationDate and TimeToLiveInSeconds are set: `{createProjectKeySchema}`")] - internal static partial void CreateKeyError(this ILogger logger, KeySchema createProjectKeySchema); + private static Serilog.ILogger? instance = null; + + // Prevent instantiation + static Log() + { + // Do nothing + } + + /// + /// Initializes the logger with the specified log level and filename. + /// + public static Serilog.ILogger Initialize(LogLevel level = LogLevel.Information, string? filename = "log.txt") + { + if (filename != null) + { + instance = new LoggerConfiguration() + .MinimumLevel.Is((Serilog.Events.LogEventLevel) level) + .WriteTo.Console() + .WriteTo.File(filename) + .CreateLogger(); + return instance; + } + instance = new LoggerConfiguration() + .MinimumLevel.Is((Serilog.Events.LogEventLevel)level) + .WriteTo.Console() + .CreateLogger(); + return instance; + } + + /// + /// Gets the logger instance + /// + public static Serilog.ILogger GetLogger() + { + if (instance == null) + { + return Initialize(); + } + return instance; + } + + /// + /// Logs a verbose message + /// + public static void Verbose(string identifier, string trace) + { + GetLogger().Verbose($"{identifier}: {trace}"); + } + + /// + /// Logs a debug message + /// + public static void Debug(string identifier, string trace) + { + GetLogger().Debug($"{identifier}: {trace}"); + } + + /// + /// Logs an information message + /// + public static void Information(string identifier, string trace) + { + GetLogger().Information($"{identifier}: {trace}"); + } + + /// + /// Logs an warning message + /// + public static void Warning(string identifier, string trace) + { + GetLogger().Warning($"{identifier}: {trace}"); + } + + /// + /// Logs an error message + /// + public static void Error(string identifier, string trace) + { + GetLogger().Error($"{identifier}: {trace}"); + } + + /// + /// Logs an fatal message + /// + public static void Fatal(string identifier, string trace) + { + GetLogger().Fatal($"{identifier}: {trace}"); + } } diff --git a/Deepgram/Logger/LogProvider.cs b/Deepgram/Logger/LogProvider.cs deleted file mode 100644 index da1afbc7..00000000 --- a/Deepgram/Logger/LogProvider.cs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. -// SPDX-License-Identifier: MIT - -namespace Deepgram.Logger; - -public sealed class LogProvider -{ - internal static readonly ConcurrentDictionary _loggers = new(); - internal static ILoggerFactory? _loggerFactory = NullLoggerFactory.Instance; - - public static void SetLogFactory(ILoggerFactory factory) - { - _loggerFactory?.Dispose(); - _loggerFactory = factory; - _loggers.Clear(); - } - - public static ILogger GetLogger(string category) - { - // Try to get the logger from the dictionary - if (!_loggers.TryGetValue(category, out var logger)) - { - // If not found, create a new logger and add it to the dictionary - logger = _loggerFactory?.CreateLogger(category) ?? NullLogger.Instance; - _loggers[category] = logger; - } - // Return the logger - return logger; - } -} diff --git a/Deepgram/ManageClient.cs b/Deepgram/ManageClient.cs index c39fe7bb..f58845fd 100644 --- a/Deepgram/ManageClient.cs +++ b/Deepgram/ManageClient.cs @@ -12,7 +12,8 @@ namespace Deepgram; /// public class ManageClient : Client { - public ManageClient(string apiKey = "", DeepgramHttpClientOptions? deepgramClientOptions = null) : base(apiKey, deepgramClientOptions) + public ManageClient(string apiKey = "", DeepgramHttpClientOptions? deepgramClientOptions = null, + string? httpId = null) : base(apiKey, deepgramClientOptions, httpId) { } } diff --git a/Deepgram/Models/Analyze/v1/AnalyzeSchema.cs b/Deepgram/Models/Analyze/v1/AnalyzeSchema.cs index c84b123f..f2fb3afe 100644 --- a/Deepgram/Models/Analyze/v1/AnalyzeSchema.cs +++ b/Deepgram/Models/Analyze/v1/AnalyzeSchema.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Analyze/v1/AsyncResponse.cs b/Deepgram/Models/Analyze/v1/AsyncResponse.cs index b2ec1d7a..65f0d93f 100644 --- a/Deepgram/Models/Analyze/v1/AsyncResponse.cs +++ b/Deepgram/Models/Analyze/v1/AsyncResponse.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Analyze/v1/Average.cs b/Deepgram/Models/Analyze/v1/Average.cs index 21df5014..74e6f045 100644 --- a/Deepgram/Models/Analyze/v1/Average.cs +++ b/Deepgram/Models/Analyze/v1/Average.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Analyze/v1/Intent.cs b/Deepgram/Models/Analyze/v1/Intent.cs index fa1405bf..1f8eb689 100644 --- a/Deepgram/Models/Analyze/v1/Intent.cs +++ b/Deepgram/Models/Analyze/v1/Intent.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Analyze/v1/IntentGroup.cs b/Deepgram/Models/Analyze/v1/IntentGroup.cs index 3c948dbb..6d062b01 100644 --- a/Deepgram/Models/Analyze/v1/IntentGroup.cs +++ b/Deepgram/Models/Analyze/v1/IntentGroup.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Analyze/v1/IntentsInfo.cs b/Deepgram/Models/Analyze/v1/IntentsInfo.cs index a13529e7..0eefedad 100644 --- a/Deepgram/Models/Analyze/v1/IntentsInfo.cs +++ b/Deepgram/Models/Analyze/v1/IntentsInfo.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Analyze/v1/Metadata.cs b/Deepgram/Models/Analyze/v1/Metadata.cs index 17bb3b86..42129dea 100644 --- a/Deepgram/Models/Analyze/v1/Metadata.cs +++ b/Deepgram/Models/Analyze/v1/Metadata.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Analyze/v1/Results.cs b/Deepgram/Models/Analyze/v1/Results.cs index 9dabf516..15049564 100644 --- a/Deepgram/Models/Analyze/v1/Results.cs +++ b/Deepgram/Models/Analyze/v1/Results.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Analyze/v1/Segment.cs b/Deepgram/Models/Analyze/v1/Segment.cs index a92e9db7..e31d946e 100644 --- a/Deepgram/Models/Analyze/v1/Segment.cs +++ b/Deepgram/Models/Analyze/v1/Segment.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Analyze/v1/SentimentGroup.cs b/Deepgram/Models/Analyze/v1/SentimentGroup.cs index ebb51c3d..b1ddee0d 100644 --- a/Deepgram/Models/Analyze/v1/SentimentGroup.cs +++ b/Deepgram/Models/Analyze/v1/SentimentGroup.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Analyze/v1/SentimentInfo.cs b/Deepgram/Models/Analyze/v1/SentimentInfo.cs index 79d59318..991a9ee2 100644 --- a/Deepgram/Models/Analyze/v1/SentimentInfo.cs +++ b/Deepgram/Models/Analyze/v1/SentimentInfo.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Analyze/v1/Summary.cs b/Deepgram/Models/Analyze/v1/Summary.cs index 9b73efab..700a45b3 100644 --- a/Deepgram/Models/Analyze/v1/Summary.cs +++ b/Deepgram/Models/Analyze/v1/Summary.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Analyze/v1/SummaryInfo.cs b/Deepgram/Models/Analyze/v1/SummaryInfo.cs index 52863c3b..881ee448 100644 --- a/Deepgram/Models/Analyze/v1/SummaryInfo.cs +++ b/Deepgram/Models/Analyze/v1/SummaryInfo.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Analyze/v1/SyncResponse.cs b/Deepgram/Models/Analyze/v1/SyncResponse.cs index 22acd686..91d6b898 100644 --- a/Deepgram/Models/Analyze/v1/SyncResponse.cs +++ b/Deepgram/Models/Analyze/v1/SyncResponse.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Analyze/v1/Topic.cs b/Deepgram/Models/Analyze/v1/Topic.cs index 948f8eeb..be96b3f8 100644 --- a/Deepgram/Models/Analyze/v1/Topic.cs +++ b/Deepgram/Models/Analyze/v1/Topic.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Analyze/v1/TopicGroup.cs b/Deepgram/Models/Analyze/v1/TopicGroup.cs index 90cb6fba..265b154b 100644 --- a/Deepgram/Models/Analyze/v1/TopicGroup.cs +++ b/Deepgram/Models/Analyze/v1/TopicGroup.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Analyze/v1/TopicsInfo.cs b/Deepgram/Models/Analyze/v1/TopicsInfo.cs index f8679eaf..d49ee495 100644 --- a/Deepgram/Models/Analyze/v1/TopicsInfo.cs +++ b/Deepgram/Models/Analyze/v1/TopicsInfo.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Analyze/v1/UrlSource.cs b/Deepgram/Models/Analyze/v1/UrlSource.cs index b37d52a2..2eb4d64d 100644 --- a/Deepgram/Models/Analyze/v1/UrlSource.cs +++ b/Deepgram/Models/Analyze/v1/UrlSource.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Authenticate/v1/DeepgramClientOptions.cs b/Deepgram/Models/Authenticate/v1/DeepgramClientOptions.cs deleted file mode 100644 index dce5d1f4..00000000 --- a/Deepgram/Models/Authenticate/v1/DeepgramClientOptions.cs +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. -// Use of this source code is governed by a MIT license that can be found in the LICENSE file. -// SPDX-License-Identifier: MIT - -namespace Deepgram.Models.Authenticate.v1; - -/// -/// Configuration for the Deepgram client -/// -public class DeepgramClientOptions -{ - /*****************************/ - // General Options - /*****************************/ - /// - /// Deepgram API KEY - /// - public string ApiKey { get; set; } - - /// - /// BaseAddress of the server :defaults to api.deepgram.com - /// no need to attach the protocol it will be added internally - /// - public string BaseAddress { get; set; } = Defaults.DEFAULT_URI; - - /// - /// Api endpoint version - /// - public string APIVersion { get; set; } = Defaults.DEFAULT_API_VERSION; - - /// - /// Global headers to always be added to the request - /// - public Dictionary Headers { get; set; } - - /*****************************/ - // Prerecorded - /*****************************/ - - /*****************************/ - // Live - /*****************************/ - /// - /// Enable sending KeepAlives for Streaming - /// - public bool KeepAlive { get; set; } = false; - - /*****************************/ - // OnPrem - /*****************************/ - /// - /// Enable when using OnPrem mode - /// - public bool OnPrem { get; set; } = false; - - /*****************************/ - // Manage - /*****************************/ - - /*****************************/ - // Analyze - /*****************************/ - - /*****************************/ - // Constructor - /*****************************/ - public DeepgramClientOptions(string? apiKey = null, string? baseAddress = null, bool? keepAlive = null, bool? onPrem = null, Dictionary? headers = null, string? apiVersion = null) - { - ApiKey = apiKey ?? ""; - BaseAddress = baseAddress ?? Defaults.DEFAULT_URI; - KeepAlive = keepAlive ?? false; - OnPrem = onPrem ?? false; - Headers = headers ?? new Dictionary(); - APIVersion = apiVersion ?? Defaults.DEFAULT_API_VERSION; - - // user provided takes precedence - if (string.IsNullOrWhiteSpace(ApiKey)) - { - // then try the environment variable - // TODO: log - ApiKey = Environment.GetEnvironmentVariable(variable: Defaults.DEEPGRAM_API_KEY) ?? ""; - if (string.IsNullOrEmpty(ApiKey)) - { - // TODO: log - } - } - if (!OnPrem && string.IsNullOrEmpty(ApiKey)) - { - // TODO: log - throw new ArgumentException("Deepgram API Key is invalid"); - } - - // base url - Regex regex = new Regex(@"\b(\/v[0-9]+)\b", RegexOptions.IgnoreCase); - if (!regex.IsMatch(BaseAddress)) - { - //Console.WriteLine($"REST BaseAddress: {BaseAddress}"); // TODO: logging - BaseAddress = $"{BaseAddress}/{APIVersion}/"; - } - // TODO: log - - //checks for http:// https:// http https - https:// is include to ensure it is all stripped out and correctly formatted - regex = new Regex(@"\b(http:\/\/|https:\/\/|http|https)\b", RegexOptions.IgnoreCase); - if (!regex.IsMatch(BaseAddress)) - { - //if no protocol in the address then https:// is added - //Console.WriteLine($"REST BaseAddress: {BaseAddress}"); // TODO: logging - BaseAddress = $"https://{BaseAddress}"; - } - BaseAddress = BaseAddress.TrimEnd('/'); - //Console.WriteLine($"REST BaseAddress (Final): {BaseAddress}"); // TODO: logging - } -} diff --git a/Deepgram/Models/Authenticate/v1/DeepgramHttpClientOptions.cs b/Deepgram/Models/Authenticate/v1/DeepgramHttpClientOptions.cs index 5b355ac4..85bac4a8 100644 --- a/Deepgram/Models/Authenticate/v1/DeepgramHttpClientOptions.cs +++ b/Deepgram/Models/Authenticate/v1/DeepgramHttpClientOptions.cs @@ -7,9 +7,128 @@ namespace Deepgram.Models.Authenticate.v1; /// /// Configuration for the Deepgram client /// -public class DeepgramHttpClientOptions : DeepgramClientOptions +public class DeepgramHttpClientOptions { - public DeepgramHttpClientOptions(string? apiKey = null, string? baseAddress = null, bool? keepAlive = null, bool? onPrem = null, Dictionary? headers = null, string? apiVersion = null) : base(apiKey, baseAddress, keepAlive, onPrem, headers, apiVersion) + /*****************************/ + // General Options + /*****************************/ + /// + /// Deepgram API KEY + /// + public string ApiKey { get; set; } + + /// + /// BaseAddress of the server :defaults to api.deepgram.com + /// no need to attach the protocol it will be added internally + /// + public string BaseAddress { get; set; } = Defaults.DEFAULT_URI; + + /// + /// Api endpoint version + /// + public string APIVersion { get; set; } = Defaults.DEFAULT_API_VERSION; + + /// + /// Global headers to always be added to the request + /// + public Dictionary Headers { get; set; } + + /*****************************/ + // Prerecorded + /*****************************/ + + /*****************************/ + // Live + /*****************************/ + /// + /// Enable sending KeepAlives for Streaming + /// + public bool KeepAlive { get; set; } = false; + + /*****************************/ + // OnPrem + /*****************************/ + /// + /// Enable when using OnPrem mode + /// + public bool OnPrem { get; set; } = false; + + /*****************************/ + // Manage + /*****************************/ + + /*****************************/ + // Analyze + /*****************************/ + + /*****************************/ + // Constructor + /*****************************/ + public DeepgramHttpClientOptions(string? apiKey = null, string? baseAddress = null, bool? keepAlive = null, bool? onPrem = null, Dictionary? headers = null, string? apiVersion = null) { + Log.Verbose("DeepgramHttpClientOptions", "ENTER"); + Log.Debug("DeepgramHttpClientOptions", apiKey == null ? "API KEY is null" : "API KEY provided"); + Log.Debug("DeepgramHttpClientOptions", baseAddress == null ? "BaseAddress is null" : "BaseAddress provided"); + Log.Debug("DeepgramHttpClientOptions", keepAlive == null ? "KeepAlive is null" : "KeepAlive provided"); + Log.Debug("DeepgramHttpClientOptions", onPrem == null ? "OnPrem is null" : "OnPrem provided"); + Log.Debug("DeepgramHttpClientOptions", headers == null ? "Headers is null" : "Headers provided"); + Log.Debug("DeepgramHttpClientOptions", apiVersion == null ? "API Version is null" : "API Version provided"); + + ApiKey = apiKey ?? ""; + BaseAddress = baseAddress ?? Defaults.DEFAULT_URI; + KeepAlive = keepAlive ?? false; + OnPrem = onPrem ?? false; + Headers = headers ?? new Dictionary(); + APIVersion = apiVersion ?? Defaults.DEFAULT_API_VERSION; + + Log.Information("DeepgramHttpClientOptions", $"KeepAlive: {KeepAlive}"); + Log.Information("DeepgramHttpClientOptions", $"OnPrem: {OnPrem}"); + Log.Information("DeepgramHttpClientOptions", $"APIVersion: {APIVersion}"); + + // user provided takes precedence + if (string.IsNullOrWhiteSpace(ApiKey)) + { + // then try the environment variable + Log.Debug("DeepgramHttpClientOptions", "API KEY is not set"); + ApiKey = Environment.GetEnvironmentVariable(variable: Defaults.DEEPGRAM_API_KEY) ?? ""; + if (!string.IsNullOrEmpty(ApiKey)) + { + Log.Information("DeepgramHttpClientOptions", "API KEY set from environment variable"); + } + else + { + Log.Warning("DeepgramHttpClientOptions", "API KEY environment variable not set"); + } + } + if (!OnPrem && string.IsNullOrEmpty(ApiKey)) + { + var exStr = "Deepgram API Key is invalid"; + Log.Error("DeepgramHttpClientOptions", exStr); + throw new ArgumentException(exStr); + } + + // base url + Log.Debug("DeepgramHttpClientOptions", $"REST BaseAddress: {BaseAddress}"); + + Regex regex = new Regex(@"\b(\/v[0-9]+)\b", RegexOptions.IgnoreCase); + if (!regex.IsMatch(BaseAddress)) + { + Log.Information("DeepgramHttpClientOptions", $"REST BaseAddress does not contain API version: {BaseAddress}"); + BaseAddress = $"{BaseAddress}/{APIVersion}"; + Log.Debug("DeepgramHttpClientOptions", $"BaseAddress: {BaseAddress}"); + } + + //checks for http:// https:// http https - https:// is include to ensure it is all stripped out and correctly formatted + regex = new Regex(@"\b(http:\/\/|https:\/\/|http|https)\b", RegexOptions.IgnoreCase); + if (!regex.IsMatch(BaseAddress)) + { + Log.Information("DeepgramHttpClientOptions", $"BaseAddress contains no protocol: {BaseAddress}"); + BaseAddress = $"https://{BaseAddress}"; + Log.Debug("DeepgramHttpClientOptions", $"BaseAddress: {BaseAddress}"); + } + BaseAddress = BaseAddress.TrimEnd('/'); + + Log.Information("DeepgramHttpClientOptions", $"BaseAddress: {BaseAddress}"); + Log.Verbose("DeepgramHttpClientOptions", "LEAVE"); } } diff --git a/Deepgram/Models/Authenticate/v1/DeepgramWsClientOptions.cs b/Deepgram/Models/Authenticate/v1/DeepgramWsClientOptions.cs index b0a1398d..f95c251f 100644 --- a/Deepgram/Models/Authenticate/v1/DeepgramWsClientOptions.cs +++ b/Deepgram/Models/Authenticate/v1/DeepgramWsClientOptions.cs @@ -7,10 +7,73 @@ namespace Deepgram.Models.Authenticate.v1; /// /// Configuration for the Deepgram client /// -public class DeepgramWsClientOptions : DeepgramClientOptions +public class DeepgramWsClientOptions { + /*****************************/ + // General Options + /*****************************/ + /// + /// Deepgram API KEY + /// + public string ApiKey { get; set; } + + /// + /// BaseAddress of the server :defaults to api.deepgram.com + /// no need to attach the protocol it will be added internally + /// + public string BaseAddress { get; set; } = Defaults.DEFAULT_URI; + + /// + /// Api endpoint version + /// + public string APIVersion { get; set; } = Defaults.DEFAULT_API_VERSION; + + /// + /// Global headers to always be added to the request + /// + public Dictionary Headers { get; set; } + + /*****************************/ + // Prerecorded + /*****************************/ + + /*****************************/ + // Live + /*****************************/ + /// + /// Enable sending KeepAlives for Streaming + /// + public bool KeepAlive { get; set; } = false; + + /*****************************/ + // OnPrem + /*****************************/ + /// + /// Enable when using OnPrem mode + /// + public bool OnPrem { get; set; } = false; + + /*****************************/ + // Manage + /*****************************/ + + /*****************************/ + // Analyze + /*****************************/ + + /*****************************/ + // Constructor + /*****************************/ public DeepgramWsClientOptions(string? apiKey = null, string? baseAddress = null, bool? keepAlive = null, bool? onPrem = null, Dictionary? headers = null, string? apiVersion = null) { + Log.Verbose("DeepgramWsClientOptions", "ENTER"); + Log.Debug("DeepgramWsClientOptions", apiKey == null ? "API KEY is null" : "API KEY provided"); + Log.Debug("DeepgramWsClientOptions", baseAddress == null ? "BaseAddress is null" : "BaseAddress provided"); + Log.Debug("DeepgramWsClientOptions", keepAlive == null ? "KeepAlive is null" : "KeepAlive provided"); + Log.Debug("DeepgramWsClientOptions", onPrem == null ? "OnPrem is null" : "OnPrem provided"); + Log.Debug("DeepgramWsClientOptions", headers == null ? "Headers is null" : "Headers provided"); + Log.Debug("DeepgramWsClientOptions", apiVersion == null ? "API Version is null" : "API Version provided"); + ApiKey = apiKey ?? ""; BaseAddress = baseAddress ?? Defaults.DEFAULT_URI; KeepAlive = keepAlive ?? false; @@ -18,51 +81,61 @@ public DeepgramWsClientOptions(string? apiKey = null, string? baseAddress = null Headers = headers ?? new Dictionary(); APIVersion = apiVersion ?? Defaults.DEFAULT_API_VERSION; + Log.Information("DeepgramWsClientOptions", $"KeepAlive: {KeepAlive}"); + Log.Information("DeepgramWsClientOptions", $"OnPrem: {OnPrem}"); + Log.Information("DeepgramWsClientOptions", $"APIVersion: {APIVersion}"); + // user provided takes precedence if (string.IsNullOrWhiteSpace(ApiKey)) { // then try the environment variable - // TODO: log + Log.Debug("DeepgramWsClientOptions", "API KEY is not set"); ApiKey = Environment.GetEnvironmentVariable(variable: Defaults.DEEPGRAM_API_KEY) ?? ""; - if (string.IsNullOrEmpty(ApiKey)) + if (!string.IsNullOrEmpty(ApiKey)) { - // TODO: log + Log.Information("DeepgramWsClientOptions", "API KEY set from environment variable"); + } else { + Log.Warning("DeepgramWsClientOptions", "API KEY environment variable not set"); } } if (!OnPrem && string.IsNullOrEmpty(ApiKey)) { - // TODO: log - throw new ArgumentException("Deepgram API Key is invalid"); + var exStr = "Deepgram API Key is invalid"; + Log.Error("DeepgramWsClientOptions", exStr); + throw new ArgumentException(exStr); } // base url + Log.Debug("DeepgramWsClientOptions", $"REST BaseAddress: {BaseAddress}"); + Regex regex = new Regex(@"\b(\/v[0-9]+)\b", RegexOptions.IgnoreCase); if (!regex.IsMatch(BaseAddress)) { - //Console.WriteLine($"WS BaseAddress: {BaseAddress}"); // TODO: logging + Log.Information("DeepgramWsClientOptions", $"REST BaseAddress does not contain API version: {BaseAddress}"); BaseAddress = $"{BaseAddress}/{APIVersion}"; + Log.Debug("DeepgramWsClientOptions", $"BaseAddress: {BaseAddress}"); } - // TODO: log - //checks for ws:// wss:// ws wss - wss:// is include to ensure it is all stripped out and correctly formatted + //checks for http:// https:// http https - https:// is include to ensure it is all stripped out and correctly formatted regex = new Regex(@"\b(http:\/\/|https:\/\/|http|https)\b", RegexOptions.IgnoreCase); if (regex.IsMatch(BaseAddress)) { - // if protocol https/http is in the address, remove it - //Console.WriteLine($"WS BaseAddress (Remove https/http): {BaseAddress}"); // TODO: logging + Log.Information("DeepgramWsClientOptions", $"BaseAddress contains HTTP(s) protocol. Remove: {BaseAddress}"); BaseAddress = BaseAddress.Substring(BaseAddress.IndexOf("/") + 2); + Log.Debug("DeepgramWsClientOptions", $"BaseAddress: {BaseAddress}"); } //checks for ws:// wss:// ws wss - wss:// is include to ensure it is all stripped out and correctly formatted regex = new Regex(@"\b(ws:\/\/|wss:\/\/|ws|wss)\b", RegexOptions.IgnoreCase); if (!regex.IsMatch(BaseAddress)) { - // if no protocol in the address then https:// is added - //Console.WriteLine($"WS BaseAddress (Add wss/ws): {BaseAddress}"); // TODO: logging + Log.Information("DeepgramWsClientOptions", $"BaseAddress does not contain protocol: {BaseAddress}"); BaseAddress = $"wss://{BaseAddress}"; + Log.Debug("DeepgramWsClientOptions", $"BaseAddress: {BaseAddress}"); } - BaseAddress = BaseAddress.TrimEnd('/'); - //Console.WriteLine($"WS BaseAddress (Final): {BaseAddress}"); // TODO: logging + + Log.Information("DeepgramWsClientOptions", $"BaseAddress: {BaseAddress}"); + Log.Verbose("DeepgramWsClientOptions", "LEAVE"); } } diff --git a/Deepgram/Models/Speak/v1/AsyncResponse.cs b/Deepgram/Models/Speak/v1/AsyncResponse.cs index ffaba3ed..4c93a67a 100644 --- a/Deepgram/Models/Speak/v1/AsyncResponse.cs +++ b/Deepgram/Models/Speak/v1/AsyncResponse.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Speak/v1/SpeakSchema.cs b/Deepgram/Models/Speak/v1/SpeakSchema.cs index a107ad83..242fbda5 100644 --- a/Deepgram/Models/Speak/v1/SpeakSchema.cs +++ b/Deepgram/Models/Speak/v1/SpeakSchema.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Speak/v1/SyncResponse.cs b/Deepgram/Models/Speak/v1/SyncResponse.cs index 9acddff6..fb7dd5e8 100644 --- a/Deepgram/Models/Speak/v1/SyncResponse.cs +++ b/Deepgram/Models/Speak/v1/SyncResponse.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/Models/Speak/v1/TextSource.cs b/Deepgram/Models/Speak/v1/TextSource.cs index 8ce90f8b..40b88f7f 100644 --- a/Deepgram/Models/Speak/v1/TextSource.cs +++ b/Deepgram/Models/Speak/v1/TextSource.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT diff --git a/Deepgram/OnPremClient.cs b/Deepgram/OnPremClient.cs index 4d69880f..f1d6d868 100644 --- a/Deepgram/OnPremClient.cs +++ b/Deepgram/OnPremClient.cs @@ -12,7 +12,8 @@ namespace Deepgram; /// public class OnPremClient : Client { - public OnPremClient(string apiKey = "", DeepgramHttpClientOptions? deepgramClientOptions = null) : base(apiKey, deepgramClientOptions) + public OnPremClient(string apiKey = "", DeepgramHttpClientOptions? deepgramClientOptions = null, + string? httpId = null) : base(apiKey, deepgramClientOptions, httpId) { } } diff --git a/Deepgram/PreRecordedClient.cs b/Deepgram/PreRecordedClient.cs index 195d93b3..f9456ff9 100644 --- a/Deepgram/PreRecordedClient.cs +++ b/Deepgram/PreRecordedClient.cs @@ -12,7 +12,8 @@ namespace Deepgram; /// public class PreRecordedClient : Client { - public PreRecordedClient(string apiKey = "", DeepgramHttpClientOptions? deepgramClientOptions = null) : base(apiKey, deepgramClientOptions) + public PreRecordedClient(string apiKey = "", DeepgramHttpClientOptions? deepgramClientOptions = null, + string? httpId = null) : base(apiKey, deepgramClientOptions, httpId) { } } diff --git a/Deepgram/SpeakClient.cs b/Deepgram/SpeakClient.cs index 7f38c10f..81d8775f 100644 --- a/Deepgram/SpeakClient.cs +++ b/Deepgram/SpeakClient.cs @@ -1,4 +1,4 @@ -// Copyright 2021-2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. // Use of this source code is governed by a MIT license that can be found in the LICENSE file. // SPDX-License-Identifier: MIT @@ -12,7 +12,8 @@ namespace Deepgram; /// public class SpeakClient : Client { - public SpeakClient(string apiKey = "", DeepgramHttpClientOptions? deepgramClientOptions = null) : base(apiKey, deepgramClientOptions) + public SpeakClient(string apiKey = "", DeepgramHttpClientOptions? deepgramClientOptions = null, + string? httpId = null) : base(apiKey, deepgramClientOptions, httpId) { } } diff --git a/Deepgram/Utilities/QueryParameterUtil.cs b/Deepgram/Utilities/QueryParameterUtil.cs index 45830833..cee89707 100644 --- a/Deepgram/Utilities/QueryParameterUtil.cs +++ b/Deepgram/Utilities/QueryParameterUtil.cs @@ -11,6 +11,9 @@ namespace Deepgram.Utilities; internal static class QueryParameterUtil { + /// + /// Formats a URL with the specified parameters + /// public static string FormatURL(string uriSegment, S? parameter, Dictionary? addons = null) { //checks for http:// https:// http https - https:// is include to ensure it is all stripped out and correctly formatted @@ -42,6 +45,9 @@ public static string FormatURL(string uriSegment, S? parameter, Dictionary + /// Encodes the specified parameters into a URL + /// internal static string UrlEncode(T parameters, IEnumerable? propertyInfoList, Dictionary? addons = null) { var sb = new StringBuilder(); diff --git a/Deepgram/Utilities/UserAgentUtil.cs b/Deepgram/Utilities/UserAgentUtil.cs index dc001b7d..91cbbea5 100644 --- a/Deepgram/Utilities/UserAgentUtil.cs +++ b/Deepgram/Utilities/UserAgentUtil.cs @@ -9,7 +9,6 @@ internal static class UserAgentUtil /// /// determines the UserAgent Library version /// - /// public static string GetInfo() { var libraryVersion = Assembly.GetExecutingAssembly().GetName().Version; diff --git a/examples/prerecorded/file/Program.cs b/examples/prerecorded/file/Program.cs index f2876fac..e2950393 100644 --- a/examples/prerecorded/file/Program.cs +++ b/examples/prerecorded/file/Program.cs @@ -1,13 +1,24 @@ -using Deepgram; -using Deepgram.Models.PreRecorded.v1; +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// SPDX-License-Identifier: MIT + using System.Text.Json; +using Deepgram.Logger; +using Deepgram.Models.PreRecorded.v1; + namespace PreRecorded { class Program { static async Task Main(string[] args) { + // Initialize Library with default logging + // Normal logging is "Info" level + Library.Initialize(); + // OR very chatty logging + //Library.Initialize(LogLevel.Debug); // LogLevel.Default, LogLevel.Debug, LogLevel.Verbose + // Set "DEEPGRAM_API_KEY" environment variable to your Deepgram API Key var deepgramClient = new PreRecordedClient(); @@ -21,6 +32,9 @@ static async Task Main(string[] args) //Console.WriteLine(response); Console.WriteLine(JsonSerializer.Serialize(response)); Console.ReadKey(); + + // Teardown Library + Library.Terminate(); } } } \ No newline at end of file diff --git a/examples/speak/file/hello-world/Program.cs b/examples/speak/file/hello-world/Program.cs index c97a21af..d21f999c 100644 --- a/examples/speak/file/hello-world/Program.cs +++ b/examples/speak/file/hello-world/Program.cs @@ -1,6 +1,12 @@ +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// SPDX-License-Identifier: MIT + +using System.Text.Json; + using Deepgram; using Deepgram.Models.Speak.v1; -using System.Text.Json; +using Deepgram.Logger; namespace SampleApp { @@ -8,6 +14,12 @@ class Program { static async Task Main(string[] args) { + // Initialize Library with default logging + // Normal logging is "Info" level + Library.Initialize(); + // OR very chatty logging + //Library.Initialize(LogLevel.Debug); // LogLevel.Default, LogLevel.Debug, LogLevel.Verbose + // Set "DEEPGRAM_API_KEY" environment variable to your Deepgram API Key var deepgramClient = new SpeakClient(); @@ -22,6 +34,9 @@ static async Task Main(string[] args) //Console.WriteLine(response); Console.WriteLine(JsonSerializer.Serialize(response)); Console.ReadKey(); + + // Teardown Library + Library.Terminate(); } } } \ No newline at end of file diff --git a/examples/streaming/file/Program.cs b/examples/streaming/file/Program.cs index cee9b468..866a1855 100644 --- a/examples/streaming/file/Program.cs +++ b/examples/streaming/file/Program.cs @@ -1,11 +1,9 @@ -using Deepgram; -using Deepgram.Constants; -using Deepgram.Models.Authenticate.v1; +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// SPDX-License-Identifier: MIT + using Deepgram.Models.Live.v1; -using System; -using System.IO; -using System.Text.Json; -using System.Threading.Tasks; +using Deepgram.Logger; namespace SampleApp { @@ -13,6 +11,12 @@ class Program { static async Task Main(string[] args) { + // Initialize Library with default logging + // Normal logging is "Info" level + Library.Initialize(); + // OR very chatty logging + //Library.Initialize(LogLevel.Debug); // LogLevel.Default, LogLevel.Debug, LogLevel.Verbose + // Set "DEEPGRAM_API_KEY" environment variable to your Deepgram API Key var liveClient = new LiveClient(); @@ -21,48 +25,19 @@ static async Task Main(string[] args) { if (e.Channel.Alternatives[0].Transcript == "") { - Console.WriteLine("Empty transcription received."); return; } // Console.WriteLine("Transcription received: " + JsonSerializer.Serialize(e.Response.Transcription)); Console.WriteLine($"Speaker: {e.Channel.Alternatives[0].Transcript}"); }; - //liveClient.EventResponseReceived += (sender, e) => - //{ - // if (e.Response.Transcription != null) - // { - // if (e.Response.Transcription.Channel.Alternatives[0].Transcript == "") - // { - // Console.WriteLine("Empty transcription received."); - // return; - // } - - // // Console.WriteLine("Transcription received: " + JsonSerializer.Serialize(e.Response.Transcription)); - // Console.WriteLine($"Speaker: {e.Response.Transcription.Channel.Alternatives[0].Transcript}"); - // } - // else if (e.Response.SpeechStarted != null) - // { - // Console.WriteLine("SpeechStarted received: " + JsonSerializer.Serialize(e.Response.SpeechStarted)); - // } - // else if (e.Response.UtteranceEnd != null) - // { - // Console.WriteLine("UtteranceEnd received: " + JsonSerializer.Serialize(e.Response.UtteranceEnd)); - // } - // else if (e.Response.MetaData != null) - // { - // Console.WriteLine("Metadata received: " + JsonSerializer.Serialize(e.Response.MetaData)); - // } - // else if (e.Response.Error != null) - // { - // Console.WriteLine("Error: " + JsonSerializer.Serialize(e.Response.Error.Message)); - // } - //}; // Start the connection var liveSchema = new LiveSchema() { Model = "nova-2", + Punctuate = true, + SmartFormat = true, }; await liveClient.Connect(liveSchema); @@ -78,6 +53,9 @@ static async Task Main(string[] args) // Dispose the client liveClient.Dispose(); + + // Teardown Library + Library.Terminate(); } } } diff --git a/examples/streaming/microphone/Program.cs b/examples/streaming/microphone/Program.cs index d951997f..17e2e26f 100644 --- a/examples/streaming/microphone/Program.cs +++ b/examples/streaming/microphone/Program.cs @@ -1,6 +1,14 @@ +// Copyright 2024 Deepgram .NET SDK contributors. All Rights Reserved. +// Use of this source code is governed by a MIT license that can be found in the LICENSE file. +// SPDX-License-Identifier: MIT + +using System.Text.Json; + +using Deepgram.Models.Authenticate.v1; using Deepgram.Models.Live.v1; +using Deepgram.Logger; using Deepgram.Microphone; -using System.Text.Json; +using System.Threading; namespace SampleApp { @@ -8,23 +16,63 @@ class Program { static async Task Main(string[] args) { - Library.Initialize(); + // Initialize Library with default logging + // Normal logging is "Info" level + //Deepgram.Library.Initialize(); + // OR very chatty logging + Deepgram.Library.Initialize(LogLevel.Debug); // LogLevel.Default, LogLevel.Debug, LogLevel.Verbose + Deepgram.Microphone.Library.Initialize(); + + Console.WriteLine("\n\nPress any key to stop and exit...\n\n\n"); // Set "DEEPGRAM_API_KEY" environment variable to your Deepgram API Key - var liveClient = new LiveClient(); + DeepgramWsClientOptions options = new DeepgramWsClientOptions(null, null, true); + var liveClient = new LiveClient("", options); + // OR + //var liveClient = new LiveClienkt("set your DEEPGRAM_API_KEY here"); // Subscribe to the EventResponseReceived event + liveClient._openReceived += (sender, e) => + { + Console.WriteLine($"{e.Type} received"); + }; + liveClient._metadataReceived += (sender, e) => + { + Console.WriteLine($"{e.Type} received: {JsonSerializer.Serialize(e)}"); + }; liveClient._resultsReceived += (sender, e) => { if (e.Channel.Alternatives[0].Transcript == "") { - Console.WriteLine("Empty transcription received."); return; } - // Console.WriteLine("Transcription received: " + JsonSerializer.Serialize(e.Response.Transcription)); - Console.WriteLine($"Speaker: {e.Channel.Alternatives[0].Transcript}"); + // Console.WriteLine("Transcription received: " + JsonSerializer.Serialize(e.Transcription)); + Console.WriteLine($"\n\n\nSpeaker: {e.Channel.Alternatives[0].Transcript}\n\n\n"); + }; + liveClient._speechStartedReceived += (sender, e) => + { + Console.WriteLine($"{e.Type} received"); }; + liveClient._utteranceEndReceived += (sender, e) => + { + Console.WriteLine($"{e.Type} received"); + }; + liveClient._closeReceived += (sender, e) => + { + Console.WriteLine($"{e.Type} received"); + }; + liveClient._unhandledReceived += (sender, e) => + { + Console.WriteLine($"{e.Type} received. Raw: {e.Raw}"); + }; + liveClient._errorReceived += (sender, e) => + { + Console.WriteLine($"{e.Type} received. Error: {e.Message}"); + }; + + // my own cancellation token + //var cancellationToken = new CancellationTokenSource(); // Start the connection var liveSchema = new LiveSchema() @@ -32,10 +80,13 @@ static async Task Main(string[] args) Model = "nova-2", Encoding = "linear16", SampleRate = 16000, + Punctuate = true, + SmartFormat = true, InterimResults = true, UtteranceEnd = "1000", VadEvents = true, }; + //await liveClient.Connect(liveSchema, cancellationToken); await liveClient.Connect(liveSchema); // Microphone streaming @@ -43,17 +94,25 @@ static async Task Main(string[] args) microphone.Start(); // Wait for the user to press a key - Console.WriteLine("Press any key to stop the microphone streaming..."); Console.ReadKey(); + Console.WriteLine("Stopping the microphone streaming..."); + microphone.Stop(); + + //// START: test an external cancellation + //cancellationToken.Cancel(); + //Thread.Sleep(10000); // wait 10 seconds to cancel externally + //// END: test an external cancellation + // Stop the connection await liveClient.Stop(); // Dispose the client liveClient.Dispose(); - // Terminate PortAudio - Library.Terminate(); + // Terminate Libraries + Deepgram.Microphone.Library.Terminate(); + Deepgram.Library.Terminate(); } } } diff --git a/examples/streaming/microphone/Streaming.csproj b/examples/streaming/microphone/Streaming.csproj index a7cf3923..91d69f95 100644 --- a/examples/streaming/microphone/Streaming.csproj +++ b/examples/streaming/microphone/Streaming.csproj @@ -10,7 +10,6 @@ -