Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions src/Bot/Bot.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,24 @@

<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App"/>
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.51.0"/>
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="2.1.0"/>
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues" Version="5.5.3"/>
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.7"/>
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.23.0"/>
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="2.50.0"/>
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="10.0.2"/>
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="10.0.3"/>

<PackageReference Include="Microsoft.Azure.Functions.Worker.OpenTelemetry" Version="1.1.0"/>

<PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.15.0"/>
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.15.0"/>
<PackageReference Include="OpenTelemetry.Instrumentation.Runtime" Version="1.15.0"/>

<PackageReference Include="Azure.Monitor.OpenTelemetry.Exporter" Version="1.6.0"/>
</ItemGroup>

<ItemGroup>
<Compile Include="Mappings.fs" />
<Compile Include="Mappings.fs"/>
<Compile Include="Observability.fs"/>
<Compile Include="Functions.fs"/>
<Compile Include="Program.fs"/>
</ItemGroup>
Expand Down
63 changes: 37 additions & 26 deletions src/Bot/Functions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

open System.Diagnostics
open System.Threading.Tasks
open Bot
open Bot.Mappings
open Infrastructure.Queue
open Microsoft.ApplicationInsights
open Microsoft.ApplicationInsights.DataContracts
open Microsoft.AspNetCore.Http
open Microsoft.Azure.Functions.Worker
open Microsoft.Azure.Functions.Worker.Http
Expand All @@ -18,7 +17,7 @@ open Domain.Core
type ConverterResultMessage =
{ Id: string; Result: ConversionResult }

type Functions(telemetryClient: TelemetryClient, ffMpegBot: IFFMpegBot, logger: ILogger<Functions>) =
type Functions(ffMpegBot: IFFMpegBot, logger: ILogger<Functions>) =

[<Function("HandleUpdate")>]
member this.HandleUpdate
Expand All @@ -27,6 +26,9 @@ type Functions(telemetryClient: TelemetryClient, ffMpegBot: IFFMpegBot, logger:
>
=
task {
use activity =
Observability.ActivitySource.StartActivity("HandleUpdate", ActivityKind.Internal)

try
do! ffMpegBot.ProcessUpdate(update.ToBot())
with e ->
Expand All @@ -39,72 +41,81 @@ type Functions(telemetryClient: TelemetryClient, ffMpegBot: IFFMpegBot, logger:
(
[<QueueTrigger("%Workers:Downloader:Queue%", Connection = "Workers:ConnectionString")>] message:
BaseMessage<DownloaderMessage>,
_: FunctionContext
ctx: FunctionContext
) : Task<unit> =
let data = message.Data

task {
use activity = (new Activity("Downloader")).SetParentId(message.OperationId)
use operation = telemetryClient.StartOperation<RequestTelemetry>(activity)
use activity =
Observability.ActivitySource.StartActivity(
"Downloader",
ActivityKind.Consumer,
Activity.Current.Context,
links = [ ActivityLink(ActivityContext.Parse(message.Context["traceparent"], null)) ]
)

do! ffMpegBot.PrepareConversion(data.ConversionId, data.File)

operation.Telemetry.Success <- true
}

[<Function("Converter")>]
member this.Converter
(
[<QueueTrigger("%Workers:Converter:Output:Queue%", Connection = "Workers:ConnectionString")>] message:
BaseMessage<ConverterResultMessage>,
_: FunctionContext
ctx: FunctionContext
) : Task<unit> =
let data = message.Data

task {
use activity = (new Activity("Converter")).SetParentId(message.OperationId)

use operation = telemetryClient.StartOperation<RequestTelemetry>(activity)
use activity =
Observability.ActivitySource.StartActivity(
"Converter",
ActivityKind.Consumer,
Activity.Current.Context,
links = [ ActivityLink(ActivityContext.Parse(message.Context["traceparent"], null)) ]
)

do! ffMpegBot.SaveVideo(ConversionId data.Id, data.Result)

operation.Telemetry.Success <- true
}

[<Function("Thumbnailer")>]
member this.Thumbnailer
(
[<QueueTrigger("%Workers:Thumbnailer:Output:Queue%", Connection = "Workers:ConnectionString")>] message:
BaseMessage<ConverterResultMessage>,
_: FunctionContext
ctx: FunctionContext
) : Task<unit> =
let data = message.Data

task {
use activity = (new Activity("Thumbnailer")).SetParentId(message.OperationId)

use operation = telemetryClient.StartOperation<RequestTelemetry>(activity)
use activity =
Observability.ActivitySource.StartActivity(
"Thumbnailer",
ActivityKind.Consumer,
Activity.Current.Context,
links = [ ActivityLink(ActivityContext.Parse(message.Context["traceparent"], null)) ]
)

do! ffMpegBot.SaveThumbnail(ConversionId data.Id, data.Result)

operation.Telemetry.Success <- true
}

[<Function("Uploader")>]
member this.Uploader
(
[<QueueTrigger("%Workers:Uploader:Queue%", Connection = "Workers:ConnectionString")>] message:
BaseMessage<UploaderMessage>,
_: FunctionContext
ctx: FunctionContext
) : Task =
let conversionId = message.Data.ConversionId |> ConversionId

task {
use activity = (new Activity("Uploader")).SetParentId(message.OperationId)

use operation = telemetryClient.StartOperation<RequestTelemetry>(activity)
use activity =
Observability.ActivitySource.StartActivity(
"Uploader",
ActivityKind.Consumer,
Activity.Current.Context,
links = [ ActivityLink(ActivityContext.Parse(message.Context["traceparent"], null)) ]
)

do! ffMpegBot.UploadConversion conversionId

operation.Telemetry.Success <- true
}
21 changes: 21 additions & 0 deletions src/Bot/Observability.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[<RequireQualifiedAccess>]
module internal Bot.Observability

open System.Diagnostics
open System.Reflection
open Infrastructure.Helpers
open OpenTelemetry.Context.Propagation

let private assembly = Assembly.GetExecutingAssembly()

let ActivitySource = new ActivitySource(assembly.FullName)

let extractContext (context: Observability.TraceContext) =
Propagators.DefaultTextMapPropagator.Extract(
PropagationContext(),
context,
fun h k ->
match h.TryGetValue(k) with
| true, v -> [ v ]
| _ -> []
)
23 changes: 17 additions & 6 deletions src/Bot/Program.fs
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
namespace Bot

open System
open Azure.Monitor.OpenTelemetry.Exporter
open OpenTelemetry
open System.Reflection
open System.Text.Json
open System.Text.Json.Serialization
open Infrastructure.Helpers
open Microsoft.Azure.Functions.Worker.OpenTelemetry
open Microsoft.Extensions.Configuration
open Microsoft.Extensions.DependencyInjection
open Microsoft.Extensions.Hosting
open Microsoft.Azure.Functions.Worker
open Microsoft.Extensions.Logging
open Microsoft.Extensions.Logging.ApplicationInsights
open Infrastructure
open OpenTelemetry.Metrics
open OpenTelemetry.Trace
open Telegram.Infrastructure
open Domain
open Telegram
Expand All @@ -31,15 +34,23 @@ module Startup =
()

let configureLogging (builder: ILoggingBuilder) =
builder.AddFilter<ApplicationInsightsLoggerProvider>(String.Empty, LogLevel.Information)

builder.AddFilter<ApplicationInsightsLoggerProvider>("MongoDB.Command", LogLevel.Debug)
builder.AddOpenTelemetry(fun b ->
b.IncludeScopes <- true
b.IncludeFormattedMessage <- true
())

()

let private configureServices (ctx: HostBuilderContext) (services: IServiceCollection) =
services.AddApplicationInsightsTelemetryWorkerService()
services.ConfigureFunctionsApplicationInsights()
services
.AddOpenTelemetry()
.UseFunctionsWorkerDefaults()
.WithTracing(fun builder ->
builder.AddSource(Observability.ActivitySource.Name, "Azure.Storage.*")
builder.AddHttpClientInstrumentation()
())
.UseAzureMonitorExporter()

services
|> Startup.addDomain
Expand Down
1 change: 1 addition & 0 deletions src/Bot/host.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"version": "2.0",
"telemetryMode": "OpenTelemetry",
"functionTimeout": "00:01:00",
"logging": {
"logLevel": {
Expand Down
4 changes: 2 additions & 2 deletions src/Domain.Tests/Domain.Tests.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@

<ItemGroup>
<PackageReference Include="FsUnit.xUnit" Version="7.1.1"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="xunit" Version="2.9.3"/>
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<PackageReference Include="coverlet.collector" Version="8.0.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
4 changes: 2 additions & 2 deletions src/Domain/Domain.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.3" />
<PackageReference Include="otsom.fs.Extensions" Version="0.0.52" />
<PackageReference Include="shortid" Version="4.0.0"/>
<PackageReference Include="otsom.fs.Extensions.DependencyInjection" Version="0.0.26"/>
<PackageReference Include="otsom.fs.Extensions.DependencyInjection" Version="0.0.28"/>
</ItemGroup>

</Project>
21 changes: 20 additions & 1 deletion src/Infrastructure/Helpers.fs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
namespace Infrastructure

open System.Collections.Generic
open System.Diagnostics
open System.Text.Json
open System.Text.Json.Serialization
open Azure.Storage.Blobs
open Infrastructure.Settings
open OpenTelemetry
open OpenTelemetry.Context.Propagation

module Helpers =
[<RequireQualifiedAccess>]
Expand All @@ -27,4 +31,19 @@ module Helpers =

let blobClient = containerClient.GetBlobClient(name)

blobClient.OpenWriteAsync(true)
blobClient.OpenWriteAsync(true)

[<RequireQualifiedAccess>]
module Observability =
type TraceContext = IDictionary<string, string>

let getTraceContext () : TraceContext =
let activity = Activity.Current

let propagationContext = PropagationContext(activity.Context, Baggage.Current)

let headers = Dictionary<string, string>()

Propagators.DefaultTextMapPropagator.Inject(propagationContext, headers, fun h k v -> h.Add(k, v))

headers
7 changes: 4 additions & 3 deletions src/Infrastructure/Infrastructure.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@
<ItemGroup>
<PackageReference Include="Azure.Storage.Blobs" Version="12.27.0"/>
<PackageReference Include="Azure.Storage.Queues" Version="12.25.0"/>
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.2"/>
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.3"/>
<PackageReference Include="FSharp.SystemTextJson" Version="1.4.36"/>
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="10.0.2"/>
<PackageReference Include="Microsoft.Extensions.Http.Polly" Version="10.0.3"/>
<PackageReference Include="MongoDB.Driver" Version="3.6.0"/>
<PackageReference Include="Telegram.Bot" Version="22.8.1"/>
<PackageReference Include="Telegram.Bot" Version="22.9.5.2"/>
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.15.0"/>
</ItemGroup>

<ItemGroup>
Expand Down
6 changes: 5 additions & 1 deletion src/Infrastructure/Queue.fs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
namespace Infrastructure

open System.Diagnostics
open Domain.Core
open Infrastructure.Helpers
open Microsoft.FSharp.Core
open Infrastructure.Core

module Queue =
[<CLIMutable>]
type BaseMessage<'a> = { OperationId: string; Data: 'a }
type BaseMessage<'a> =
{ Context: Observability.TraceContext
Data: 'a }

[<CLIMutable>]
type UploaderMessage = { ConversionId: string }
Expand Down
8 changes: 4 additions & 4 deletions src/Infrastructure/Repos.fs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ type ConversionRepo
let queueClient = queueServiceClient.GetQueueClient(settings.Converter.Input.Queue)

let message: BaseMessage<Conversion.Prepared.ConverterMessage> =
{ OperationId = Activity.Current.ParentId
{ Context = Observability.getTraceContext ()
Data =
{ Id = conversion.Id.Value
Name = conversion.InputFile } }
Expand All @@ -77,7 +77,7 @@ type ConversionRepo
queueServiceClient.GetQueueClient(settings.Thumbnailer.Input.Queue)

let message: BaseMessage<Conversion.Prepared.ConverterMessage> =
{ OperationId = Activity.Current.ParentId
{ Context = Observability.getTraceContext ()
Data =
{ Id = conversion.Id.Value
Name = conversion.InputFile } }
Expand Down Expand Up @@ -126,7 +126,7 @@ type ConversionRepo

let messageBody =
JSON.serialize
{ OperationId = Activity.Current.ParentId
{ Context = Observability.getTraceContext ()
Data = { ConversionId = conversion.Id.Value } }

queueClient.SendMessageAsync(messageBody) |> Task.ignore
Expand All @@ -135,7 +135,7 @@ type ConversionRepo
let queueClient = queueServiceClient.GetQueueClient(settings.Downloader.Queue)

let message =
{ OperationId = Activity.Current.ParentId
{ Context = Observability.getTraceContext ()
Data =
{ ConversionId = conversionId
File = inputFile } }
Expand Down
Loading