Read function timeout of Azure Function App from C# code - azure

I set my function timeout for my Azure Function App in the host.json on deployment:
{
"version": "2.0",
"functionTimeout": "00:10:00", //max 10 minutes
...
}
But how I can I access the value (read it) from within my C# function code. This isn't an environment variable, is it?

Code to get host.json variables:
string jsonfile = "host.json";
string jsonText = GetFileJson(jsonfile);
JObject jsonObj = JObject.Parse(jsonText);
string value = ((JObject)jsonObj)["functionTimeout"].ToString();
GetFileJson Method:
public static string GetFileJson(string filepath)
{
string json = string.Empty;
using (FileStream fs = new FileStream(filepath, FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fs, Encoding.GetEncoding("utf-8")))
{
json = sr.ReadToEnd().ToString();
}
}
return json;
}
Namespaces added:
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using System.Text;
using System.IO;
Output:
My Function Class File:
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
namespace FunctionApp5
{
public static class Function1
{
[Function("Function1")]
public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger("Function1");
logger.LogInformation("C# HTTP trigger function processed a request.");
logger.LogInformation(GetEnvironmentVariable("functionTimeout"));
string jsonfile = "host.json";
string jsonText = GetFileJson(jsonfile);
JObject jsonObj = JObject.Parse(jsonText);
string value = ((JObject)jsonObj)["functionTimeout"].ToString();
var response = req.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
response.WriteString("Welcome to Azure Functions!");
return response;
}
public static string GetEnvironmentVariable(string name)
{
return name + ": " +
System.Environment.GetEnvironmentVariable(name, EnvironmentVariableTarget.Process);
}
public static string GetFileJson(string filepath)
{
string json = string.Empty;
using (FileStream fs = new FileStream(filepath, FileMode.Open, System.IO.FileAccess.Read, FileShare.ReadWrite))
{
using (StreamReader sr = new StreamReader(fs, Encoding.GetEncoding("utf-8")))
{
json = sr.ReadToEnd().ToString();
}
}
return json;
}
}
}

Related

How to send data from .net core api to azure log analytics

I am trying to send data from my .net core API 2.1 version to Azure Log Analytics.
Below is my code:
using System;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;
namespace xyz.Common
{
public class AzureLogAnalytics
{
public String WorkspaceId { get; set; }
public String SharedKey { get; set; }
public String ApiVersion { get; set; }
public String LogType { get; set; }
public AzureLogAnalytics(String workspaceId, String sharedKey, String logType, String apiVersion = "2015-03-20")
{
this.WorkspaceId = workspaceId;
this.SharedKey = sharedKey;
this.LogType = logType;
this.ApiVersion = apiVersion;
}
public void Post(string json)
{
string requestUriString = $"https://{WorkspaceId}.ods.opinsights.azure.com/api/logs?api-version={ApiVersion}";
DateTime dateTime = DateTime.UtcNow;
string dateString = dateTime.ToString("r");
string signature = GetSignature("POST", json.Length, "application/json", dateString, "/api/logs");
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUriString);
request.ContentType = "application/json";
request.Method = "POST";
request.Headers["Log-Type"] = LogType;
request.Headers["x-ms-date"] = dateString;
request.Headers["Authorization"] = signature;
byte[] content = Encoding.UTF8.GetBytes(json);
using (Stream requestStreamAsync = request.GetRequestStream())
{
requestStreamAsync.Write(content, 0, content.Length);
}
using (HttpWebResponse responseAsync = (HttpWebResponse)request.GetResponse())
{
if (responseAsync.StatusCode != HttpStatusCode.OK && responseAsync.StatusCode != HttpStatusCode.Accepted)
{
Stream responseStream = responseAsync.GetResponseStream();
if (responseStream != null)
{
using (StreamReader streamReader = new StreamReader(responseStream))
{
throw new Exception(streamReader.ReadToEnd());
}
}
}
}
}
private string GetSignature(string method, int contentLength, string contentType, string date, string resource)
{
string message = $"{method}\n{contentLength}\n{contentType}\nx-ms-date:{date}\n{resource}";
byte[] bytes = Encoding.UTF8.GetBytes(message);
using (HMACSHA256 encryptor = new HMACSHA256(Convert.FromBase64String(SharedKey)))
{
return $"SharedKey {WorkspaceId}:{Convert.ToBase64String(encryptor.ComputeHash(bytes))}";
}
}
}
}
In the above code while accessing the
URL "$"https://{WorkspaceId}.ods.opinsights.azure.com/api/logs?api-version={ApiVersion}";
I am getting this error:
And because of this, I am not able to get a response in line
using (HttpWebResponse responseAsync = (HttpWebResponse)request.GetResponse())
There was an issue with the authorization and API version.
I was using API Version 2015-03-20, I have changed it to 2016-04-01.
I have found out this link which works -
https://dejanstojanovic.net/aspnet/2018/february/send-data-to-azure-log-analytics-from-c-code/
Also, there are multiple links that I have gone through.
https://learn.microsoft.com/en-us/azure/azure-monitor/platform/data-collector-api

How to use dependency inject for TelemetryConfiguration in Azure Function

I try to use Dependency injection in Azure Functions for TelemetryConfiguration. In my function I will have it resolved when I inject TelemetryConfiguration in the functions constructor. I suppose I don't really understand how I will do with TelemetryConfiguration in StartUp, thats why I get an exception. How will I add the TelemetryConfiguration I already configured.
I have did an easy example here what I'm doing so far.
[assembly: FunctionsStartup(typeof(StartUp))]
public class StartUp : FunctionsStartup
{
private string OmsModule { get; } = "OMS.VA";
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.Configure<TelemetryConfiguration>(
(o) =>
{
o.InstrumentationKey = Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY");
o.TelemetryInitializers.Add(new OperationCorrelationTelemetryInitializer());
});
}
}
public class StopPlaceUpdateTimerTrigger
{
private TelemetryClient _telemetryClient;
private string _azureWebJobsStorage;
public StopPlaceUpdateTimerTrigger(TelemetryConfiguration telemetryConfiguration)
{
_telemetryClient = new TelemetryClient(telemetryConfiguration);
}
[FunctionName("StopPlaceLoader")]
public async Task StopPlaceLoaderMain([TimerTrigger("%CRON_EXPRESSION%", RunOnStartup = true)]TimerInfo myTimerInfo, ILogger log, ExecutionContext context)
{
SetConfig(context);
var cloudTable = await GetCloudTableAsync();
if (cloudTable == null)
{
//Do nothing
}
//Do nothing
}
private async Task<CloudTable> GetCloudTableAsync()
{
var storageAccount = CloudStorageAccount.Parse(_azureWebJobsStorage);
var tableClient = storageAccount.CreateCloudTableClient();
var table = tableClient.GetTableReference(nameof(StopPlaceLoaderCacheRecord));
if (!await table.ExistsAsync())
{
await table.CreateIfNotExistsAsync();
}
return table;
}
private void SetConfig(ExecutionContext context)
{
var config = new ConfigurationBuilder()
.SetBasePath(context.FunctionAppDirectory)
.AddJsonFile("local.settings.json", optional: true)
.AddEnvironmentVariables()
.Build();
_azureWebJobsStorage = config["AzureWebJobsStorage"];
}
}
//local.settings.json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "DefaultEndpointsProtocol...",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"EnableMSDeployAppOffline": "True",
"CRON_EXPRESSION": "0 */5 22-3 * * *",
"APPINSIGHTS_INSTRUMENTATIONKEY": "..."
}
}
I get the following Exception;
Microsoft.Extensions.DependencyInjection.Abstractions: Unable to resolve service for type 'Microsoft.ApplicationInsights.Extensibility.TelemetryConfiguration' while attempting to activate 'OMS.VA.RealTime.StopPlaceLoader.StopPlaceUpdateTimerTrigger'.
Update:
We can change this line of code var newConfig = TelemetryConfiguration.Active; to var newConfig = TelemetryConfiguration.CreateDefault(); , since TelemetryConfiguration.Active is deprecated.
Please use the code below for TelemetryConfiguration DI, I test it with a blob trigger function and works well:
using System.IO;
using System.Linq;
using Microsoft.ApplicationInsights;
using Microsoft.ApplicationInsights.Extensibility;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
[assembly: WebJobsStartup(typeof(FunctionApp17.MyStartup))]
namespace FunctionApp17
{
public class MyStartup : IWebJobsStartup
{
public void Configure(IWebJobsBuilder builder)
{
var configDescriptor = builder.Services.SingleOrDefault(tc => tc.ServiceType == typeof(TelemetryConfiguration));
if (configDescriptor?.ImplementationFactory != null)
{
var implFactory = configDescriptor.ImplementationFactory;
builder.Services.Remove(configDescriptor);
builder.Services.AddSingleton(provider =>
{
if (implFactory.Invoke(provider) is TelemetryConfiguration config)
{
var newConfig = TelemetryConfiguration.Active;
newConfig.ApplicationIdProvider = config.ApplicationIdProvider;
newConfig.InstrumentationKey = config.InstrumentationKey;
return newConfig;
}
return null;
});
}
}
}
public class Function1
{
private TelemetryClient _telemetryClient;
public Function1(TelemetryConfiguration telemetryConfiguration)
{
_telemetryClient = new TelemetryClient(telemetryConfiguration);
}
[FunctionName("Function1")]
public void Run([BlobTrigger("samples-workitems/{name}", Connection = "AzureWebJobsStorage")]Stream myBlob, string name, ILogger log)
{
log.LogInformation($"!!!!!!!!!! C# Blob trigger function Processed blob\n Name:{name} \n Size: {myBlob.Length} Bytes");
_telemetryClient.TrackTrace("this is a test message from DI of telemetry client !!!!!!!!!!!!!!");
}
}
}
the test result as below, I can see the logs in the application insights in azure portal:
And one more thing, I see you try to use ITelemetry Initializer in your code. You can follow this GitHub issue for your ITelemetry Initializer or Itelemetry Processor
If you use builder.Services.Configure<TelemetryConfiguration>() to configure, you are using Options pattern in ASP.NET Core.
To access the option, you need to do as following:
public StopPlaceUpdateTimerTrigger(IOptionsMonitor<TelemetryConfiguration> telemetryConfiguration)
{
_telemetryClient = new TelemetryClient(telemetryConfiguration.CurrentValue);
}
If you just want to directly use TelemetryConfiguration object, you need to add it in service collection:
builder.Services.AddSingleton<TelemetryConfiguration >(sp =>
{
var telemetryConfiguration = new TelemetryConfiguration();
telemetryConfiguration.InstrumentationKey = Environment.GetEnvironmentVariable("APPINSIGHTS_INSTRUMENTATIONKEY");
telemetryConfiguration.TelemetryInitializers.Add(new OperationCorrelationTelemetryInitializer());
return telemetryConfiguration;
}
Then you can :
public StopPlaceUpdateTimerTrigger(TelemetryConfiguration telemetryConfiguration)
{
_telemetryClient = new TelemetryClient(telemetryConfiguration);
}
Hope it helps.

Directline intermittently not giving responses or giving an echoed response

I have a code that is calling a bot through directline. The directline intermittently stops giving responses or starts giving the same input question as the output. I get only a single messages array and it contains only the same input request message and no response from the bot. I have attached the bot response that I am getting during debugging. Anyone having any clue on this?
using DirectLineConsole;
using DirectLineConsole.Models;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace DirectLineConsole
{
class RequestOrchestrator
{
Conversation objconversation = new Conversation();
public static string secret_key = "BotConnector abc";
public static string Service_URL = "https://directline.botframework.com/api/conversations/";
static void Main(string[] args)
{
RequestOrchestrator objprogram = new RequestOrchestrator();
var task = objprogram.PostMessage("how can i change my phone number?").GetAwaiter().GetResult();
Console.WriteLine("The get static message is " + objprogram.PostMessage("Its 93091").GetAwaiter().GetResult());
Console.ReadKey();
Console.ReadLine();
}
private async Task<bool> PostMessage(string message)
{
bool IsReplyReceived = false;
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://directline.botframework.com/api/conversations/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("BotConnector", "abc");
HttpResponseMessage response = await client.GetAsync("/api/tokens/");
if (response.IsSuccessStatusCode)
{
var conversation = new Conversation();
response = await client.PostAsJsonAsync("/api/conversations/", conversation);
if (response.IsSuccessStatusCode)
{
CathyDirectConversation ConversationInfo = response.Content.ReadAsAsync(typeof(CathyDirectConversation)).Result as CathyDirectConversation;
string conversationUrl = ConversationInfo.conversationID + "/messages/";
MessageNew msg = new MessageNew() { text = message };
response = await client.PostAsJsonAsync(conversationUrl, msg);
if (response.IsSuccessStatusCode)
{
response = await client.GetAsync(conversationUrl);
if (response.IsSuccessStatusCode)
{
MessageSetNew BotMessage = response.Content.ReadAsAsync(typeof(MessageSetNew)).Result as MessageSetNew;
foreach (Message responseMessage in BotMessage.messages)
{
Console.WriteLine("The response text " + responseMessage.text);
}
IsReplyReceived = true;
}
}
}
}
return IsReplyReceived;
}

sharepoint SPFarm.local.GetObject return null

I installed sharepoint foundation 2010 (in 'Standalone' type) on windows 2012 r2.
And I created a windows app project.
When Load , New Counter(farm) is success.
But, SPFarm.local.GetObject return null;
Does someone konw the reason,please help me.
source like this:
//-------source start-------
//Counter.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
namespace WinAppTest
{
class Counter : SPPersistedObject
{
public static String SettingName = "Counter";
public static String SettingGuid = "62648e50-8aee-42b2-b074-2f49ced85587";
[Persisted]
public String name;
[Persisted]
public String count;
public Counter()
{
}
public Counter(SPPersistedObject parent)
: base(SettingName, parent, new Guid(SettingGuid))
{
}
}
}
// Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.SharePoint.Administration;
namespace WinAppTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Write_Click(object sender, EventArgs e)
{
SPFarm farm = SPFarm.Local;
//------- *conf is null*-----
Counter conf = (Counter)farm.GetObject(new Guid(Counter.SettingGuid));
//------- *conf is null*-----
conf.Name = "pf1";
conf.count = "1";
conf.Update();
}
private void Form1_Load(object sender, EventArgs e)
{
SPFarm farm = SPFarm.Local;
Counter conf = (Counter)farm.GetObject(new Guid(Counter.SettingGuid));
if (conf == null)
{
conf = new Counter(farm);
}
//------- *conf is null*-----
conf = (Counter)farm.GetObject(new Guid(Counter.SettingGuid));
//------- *conf is null*-----
String name = conf.name;
String count = conf.count;
}
}
}
Finally , I think the source has error in it.
modify like this, It's OK.
private void Write_Click(object sender, EventArgs e)
{
SPFarm farm = SPFarm.Local;
Counter conf = (Counter)farm.GetObject(new Guid(Counter.SettingGuid));
if (conf == null)
{
conf = new Counter(farm);
}
conf.Name = "pf1";
conf.count = "1";
conf.Update();
}
private void Form1_Load(object sender, EventArgs e)
{
SPFarm farm = SPFarm.Local;
Counter conf = (Counter)farm.GetObject(new Guid(Counter.SettingGuid));
String name = conf.name;
String count = conf.count;
}

Asynchronous http listener c#

I am developing a small SMS server in C# and want to make an asynchronous listener that processes requests sent to an SMS object (username, message, etc.). I want to create the asynchronous listener as a class library. Here is the code:
using System;
using System.Net;
using System.Threading;
namespace AListener
{
public class CAListener
{
public CAListener()
{
Thread listener = new Thread(new ParameterizedThreadStart(RequestListener));
listener.Start(new string[] { "http://*:11600/" });
}
private ManualResetEvent stopListener = new ManualResetEvent(false);
private object lockListener = new object();
private bool newRequest = false;
public void StopListener()
{
stopListener.Set();
}
public void RequestListener(object parameter)
{
string[] prefixes = parameter as string[];
HttpListener listener = new HttpListener();
foreach (string prefix in prefixes)
{
listener.Prefixes.Add(prefix);
}
listener.Start();
IAsyncResult result = listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener);
while (!stopListener.WaitOne(10))
{
lock (lockListener)
{
if (newRequest)
{
result = listener.BeginGetContext(new AsyncCallback(ListenerCallback), listener);
newRequest = false;
}
}
result.AsyncWaitHandle.WaitOne(10);
}
listener.Close();
}
public void ListenerCallback(IAsyncResult result)
{
HttpListener listener = (HttpListener)result.AsyncState;
// Call EndGetContext to complete the asynchronous operation.
HttpListenerContext context = listener.EndGetContext(result);
HttpListenerRequest request = context.Request;
// Obtain a response object.
HttpListenerResponse response = context.Response;
// Construct a response.
string responseString = "<HTML><BODY> Hello world!</BODY></HTML>";
byte[] buffer = System.Text.Encoding.UTF8.GetBytes(responseString);
// Get a response stream and write the response to it.
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
// You must close the output stream.
output.Close();
lock (lockListener)
{
newRequest = true;
}
}
}
}
I have a UI form where I obtain AListener object and everything here is OK.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AListener;
namespace ZNSMS
{
public partial class ZNSMSServer : Form
{
public ZNSMSServer()
{
InitializeComponent();
}
CAListener ca = null;
private void button1_Click(object sender, EventArgs e)
{
ca.StopListener();
}
private void ZNSMSServer_Load(object sender, EventArgs e)
{
ca = new CAListener();
}
}
}
But when I press the Button (I just want to stop the listener) - for some reason listener.Stop() kills my main UI Form ZNSMSServer. When I comment listener.Stop() it's working, but I think that's not the proper way and I cannot understand why calling listener.Stop() can impact (in this case Close?) the calling object - in this case ZNSMSServer.
If anyone has dealt with this kind of issue before, I would really appreciate it.
Thanks in advance.

Resources