-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathStartup.cs
153 lines (129 loc) · 5.79 KB
/
Startup.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
// ------------------------------------------------------------
namespace MessageAnalyzer
{
using Dapr.Client;
using Dapr.Tests.Common.Models;
using Google.Protobuf.WellKnownTypes;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Prometheus;
using System;
using System.Text.Json;
using System.Threading.Tasks;
/// <summary>
/// Startup class.
/// </summary>
public class Startup
{
private static readonly Gauge PubSubDuration = Metrics.CreateGauge("lh_message_analyzer_pubsub_duration", "The time between the previous app's publish call and the time this app receives it");
private static readonly Gauge OutputBindingCallTime = Metrics.CreateGauge("lh_message_analyzer_output_binding_call_time", "The time it takes the binding api to return locally");
private static readonly Counter BindingApiFailureCount = Metrics.CreateCounter("lh_message_analyzer_binding_failure_count", "Output binding calls that throw");
private static string[] Sentiments = new string[]
{
"verynegative",
"negative",
"neutral",
"positive",
"verypositive"
};
/// <summary>
/// The name of the pubsub component. The name of the component and the topic happen to be the same here...
/// </summary>
public const string PubsubComponentName = "receivemediapost";
/// <summary>
/// The name of the topic to subscribe to.
/// </summary>
public const string PubsubTopicName = "receivemediapost";
/// <summary>
///
/// </summary>
public const string BindingName = "messagebinding";
/// <summary>
/// Initializes a new instance of the <see cref="Startup"/> class.
/// </summary>
/// <param name="configuration">Configuration.</param>
public Startup(IConfiguration configuration)
{
this.Configuration = configuration;
}
/// <summary>
/// Gets the configuration.
/// </summary>
public IConfiguration Configuration { get; }
/// <summary>
/// Configures Services.
/// </summary>
/// <param name="services">Service Collection.</param>
public void ConfigureServices(IServiceCollection services)
{
services.AddDaprClient();
services.AddSingleton(new JsonSerializerOptions()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
PropertyNameCaseInsensitive = true,
});
}
/// <summary>
/// Configures Application Builder and WebHost environment.
/// </summary>
/// <param name="app">Application builder.</param>
/// <param name="env">Webhost environment.</param>
/// <param name="serializerOptions">Options for JSON serialization.</param>
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, JsonSerializerOptions serializerOptions)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseCloudEvents();
app.UseEndpoints(endpoints =>
{
endpoints.MapSubscribeHandler();
endpoints.MapPost(PubsubTopicName, ReceiveMediaPost).WithTopic(PubsubComponentName, PubsubTopicName);
});
// Receive a "Post" object from the previous app in the pipeline.
async Task ReceiveMediaPost(HttpContext context, ILogger<Startup> logger)
{
logger.LogDebug("Enter ReceiveMediaPost");
var client = context.RequestServices.GetRequiredService<DaprClient>();
var message = await JsonSerializer.DeserializeAsync<SocialMediaMessage>(context.Request.Body, serializerOptions);
// record the time
TimeSpan durationFromPreviousApp = DateTime.UtcNow - message.PreviousAppTimestamp;
PubSubDuration.Set(durationFromPreviousApp.TotalSeconds);
// update with a sentiment
message.Sentiment = GenerateRandomSentiment();
logger.LogInformation("....Invoking binding {BindingName} with message {Message} and sentiment {Sentiment}", BindingName, message.Message, message.Sentiment);
// overwrite the timestamp so the next app can use it
message.PreviousAppTimestamp = DateTime.UtcNow;
try
{
using (OutputBindingCallTime.NewTimer())
{
await client.InvokeBindingAsync<SocialMediaMessage>(BindingName, "create", message);
logger.LogInformation("Invoke binding \"create\" completed successfully");
}
}
catch (Exception e)
{
logger.LogError(e, "Caught {Exception}", e);
BindingApiFailureCount.Inc();
}
}
}
internal string GenerateRandomSentiment()
{
Random random = new Random();
int i = random.Next(Sentiments.Length);
return Sentiments[i];
}
}
}