webapi to IoTHub not working from Azure deployment - azure

was: "Iot Hub diagnostics azure deployed app"
Strange issue. I have a very simple 4.5.2 based webapi application that acts as a field gateway; that is each method connects to IoT Hub on behalf of the consumer which are actual devices capable of only posting to HTTP endpoints.
When I run the code from my local development machine everything works as expected and my IoT Hub receives the data. so, then, I published the webapi application to azure and ran the same methods but there is no activity to the IoT Hub detected at all. weird. I went so far as to debug the application code in azure and everything is working without error. There's no external configuration to mess things up at the moment, its all in the code.
Is there are logical explanation for this behavior?
I'm new to IoT Hub so maybe this is a simple thing. Where can I turn on verbose diagnostics? Since I have code that I believe to be working where can I see the next logical information? Are there permissions of some sort that may be preventing the data to pass through?
WebApi method(s) basically call this code which is contained in a separate assembly
public static void SendTempData(string Name, string value)
{
var telemetryDataPoint = new
{
deviceId = HOME_TEMP_DEVICE,
DeviceName = Name,
TValue = value
};
var messageString = JsonConvert.SerializeObject(telemetryDataPoint);
var task = Task.Run(() =>
{
deviceClient = DeviceClient.Create(iotHubUri, new DeviceAuthenticationWithRegistrySymmetricKey(HOME_TEMP_DEVICE, HOME_TEMP_DEVICE_KEY), TransportType.Mqtt);
var message = new Message(Encoding.ASCII.GetBytes(messageString));
deviceClient.SendEventAsync(message);
});
WaitForTask(ref task);
CheckForFail(task);
}
private static void WaitForTask(ref Task task)
{
while (task.Status != TaskStatus.RanToCompletion)
{
if ((task.IsCanceled) || (task.IsFaulted))
break;
System.Diagnostics.Debug.WriteLine("Thread ID: {0}, Status: {1}", Thread.CurrentThread.ManagedThreadId, task.Status);
}
}
Bottom line is I have no visibility. Is there some verbose setting I can enable to see why IoTHub never sees a connection or data?

Related

Identify consumer of Azure Service Bus queue

I'm taking over responsibility for an Azure Service Bus deployment. Documentation is incomplete in that there are undocumented Queues and Topic Subscriptions present.
What information can Azure provide me about the function that is consuming messages sent to a queue/topic subscription? I'd like ultimately to be able to locate the source code which is processing the messages.
e.g. a class library name, class name or even just a namespace of the function that receives the messages. Something. Anything.
Or am I asking the wrong question?
Seems like an oversight on Azure that all information about Service Bus ends at the definition of the "inbox" and offers nothing about the functions that deal with received messages.
Problem is, the whole idea of using a Service Bus is to decouple (parts of) applications, so the sender does not have a tight relationship with the receiver of the message. From your story it seems your consumers are probably Azure Functions but in other situations receiver might be running on-premises or in an other cloud environment like AWS or Google Cloud. The Azure Service Bus does simply not know what kind of hosting environment is consuming the messages. Tools like Application Insights can generate this kind of information but only if enabled on the consuming side.
What information can Azure provide me about the function that is consuming messages sent to a queue/topic subscription? I'd like ultimately to be able to locate the source code which is processing the messages.
e.g. a class library name, class name or even just a namespace of the function that receives the messages. Something. Anything.
If the producing/consuming applications have an Application Insights integration the Application Map might reveal this information.
Enabling Azure Functions to consume Service Bus messages is all based on configuration so you could scan your code repositories based topic names but there are plenty of other locations where this configuration can be stored like Azure Function Application Settings, Azure Key Vault, Azure App Configuration etc.
Even a statement "There are no consumers on this queue/subscription" would be a help.
The closest you can get is see whether there are active messages waiting to be delivered:
If there is no (active) consuming subscription while messages are pushed I would expect an increasing value of the Active Message Count metric. But do mind the Message Time to Live for the specific topic.
Or am I asking the wrong question?
It is a valid question and I definitely feel your pain but there is no satisfying answer to your question. For loosly coupled systems you need documentation, distributed tracing and possibly infrastructure as code to tackle issues like this.
Getting a list of Azure Functions and their bindings
In your comments you mention that it would help to get a list of functions and their bindings. I do know how to do that using the management SDK:
using Azure.Identity;
using Azure.ResourceManager;
using Azure.ResourceManager.AppService;
internal class Program
{
private static async Task Main(string[] args)
{
var client = new ArmClient(new DefaultAzureCredential(new DefaultAzureCredentialOptions()
{
ExcludeVisualStudioCredential = true,
ExcludeVisualStudioCodeCredential = true
}));
var azureFunctions = new List<SiteFunctionResource>();
foreach (var subscription in client.GetSubscriptions())
{
var resourceGroups = subscription.GetResourceGroups();
await foreach (var resourceGroup in resourceGroups.GetAllAsync())
{
var websites = resourceGroup.GetWebSites();
azureFunctions.AddRange(
websites
.Where(ws => ws.Data.Kind.Contains("functionapp", StringComparison.InvariantCultureIgnoreCase))
.SelectMany(ws => ws.GetSiteFunctions().ToList())
);
}
}
foreach (var azureFunction in azureFunctions)
{
var bindings = azureFunction.Data.Config.ToObjectFromJson<Config>().bindings;
Console.WriteLine(azureFunction.Id);
Console.WriteLine("bindings:");
foreach (var binding in bindings)
{
Console.WriteLine($"\t{binding.name}: {binding.type}");
}
Console.WriteLine("-----------------------------------");
}
Console.ReadLine();
}
public class Binding
{
public string type { get; set; }
public string route { get; set; }
public List<string> methods { get; set; }
public string authLevel { get; set; }
public string name { get; set; }
}
public class Config
{
public List<Binding> bindings { get; set; }
}
}
It needs the following NuGet packages:
<PackageReference Include="Azure.Identity" Version="1.7.0-beta.1" />
<PackageReference Include="Azure.ResourceManager" Version="1.3.0" />
<PackageReference Include="Azure.ResourceManager.AppService" Version="1.0.0-beta.3" />
Sample output:

Azure App Service cannot connect to Azure Redis when calling from Web Browser

I have a REST API services application that is using Asp.net core, and hosted on Azure App Service.
I am adding Azure Redis as a cache mechanism.
I tested the application on my local machine using local redis and it is working fine.
I deployed the Web service To Azure App Service, and test it.
When I try to test the services using Postman, it is working fine, and it is populating the cache, and reading from the cache.
But when I run the Front-end application which is a JavaScript Single Page Application that is calling the back-end services.
I am not querying Redis from the front-end. but from the backend .net application.
The calls to the services fail with this error
Timeout performing EVAL, inst: 1,
clientName: <.....>, serverEndpoint: Unspecified/my-redis.redis.cache.windows.net:6380,
keyHashSlot: 15126 (Please take a look at this article for some common client-side issues that can cause timeouts: http://stackexchange.github.io/StackExchange.Redis/Timeouts)
As I said, I am calling the same EndPoint (which is my App service), with the same parameters, from Postman, and it is working.
But from the browser, it is not working
This is my configuration and code:
In the Startup.cs
public void ConfigureServices(IServiceCollection services)
{
...
services.AddDistributedRedisCache(options => {
options.Configuration = Configuration.GetConnectionString("AzureCache");
options.InstanceName = "master";
});
}
And in the controller (ProductController)
using Microsoft.Extensions.Caching.Distributed;
public class ProductController: ControllerBase
{
IDistributedCache _cashe;
IDataRepository _repo;
public ProductController (IDistributedCache cache, IDataRepository repo)
{
_cache = cache;
_repo = repo;
}
[HttpGet]
public Async Task<IActionResult> GetProductions([FormBody] DataRequest request)
{
string data = _cache.GetString(request.AsKey());
if (data == null)
{
data = _repo.getData(request);
_cache.SetString(request.AsKey());
}
return Ok(data);
}
}
}
The client side code is as follows:
const request = axios.post('https://mydata.myserver.azure.com', reqBody, headers);
request.then(res => {
.... process the data
});
P.S: the error mentioned an article online.
I read the article and nothing jumped out. All my services are less than 5k in size except one, which is between 250k and 300k, and all calls are failing for me.
Error itself describing 'Please take a look at this article for some common client-side issues'. Could you share your client side code through which you are making call?

getting an error trying to register device with Azure Notification Hub

I have a xamarin app That will send notifications via Azure functions and its notification hub out put binding.
In xamarin app i have an android service that gets the token and stores in cache
[Service]
[IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
public class MyFirebaseIIDService : FirebaseInstanceIdService
{
private App _app => (App)Xamarin.Forms.Application.Current;
private readonly ICachingService _cachingService;
public MyFirebaseIIDService()
{
var xx = typeof(ICachingService);
_cachingService = (CachingService)App.Instance.Container.Resolve(xx);
}
public override void OnTokenRefresh()
{
var refreshedToken = FirebaseInstanceId.Instance.Token;
_cachingService.FireBaseToken = refreshedToken;
Console.WriteLine($"Token received: {refreshedToken}");
// SendRegistrationToServerAsync(refreshedToken);
}
}
after the user is logged in i want to use its Id as tag and i call another android service that tries to register a device with this tag
var client = new MobileServiceClient(App.MobileServiceUrl);
var push = client.GetPush();
var reg = new Registration(token, tags);
await push.RegisterAsync(reg);
at this point i have token and tags list that contains userId because later i want that this user only gets notification meant for them only.
on the push.RegisterAsyn method i get an error.
The resource you are looking for has been removed, had its name changed, or is temporarily unavailable.
please note that the App.MobileServiceUrl is the url of Azure Mobile App that is connected to notification hub
Other than that this Azure Mobile App have just the default TODO controllers and everything that comes with the template. My sending notification code will be in azure functions using notification hub output binding.
I also updated all azure related nugets no diffrence
it tries to hit this url for registration.
https://xxxx.azurewebsites.net/push/registrations?deviceId=dTd4wba1KTU:APA91bHKOZRX9LFzEGD-yqyz4p-whqh6UsoEAlgpFHfBxu00MhLo-------yyyyyyyyyyyyyyyyeuoRmH4h9czeQbvGRgbwt4zMlrvRIlvLDZ-kTu_Dcu2iHx9I5u0gheQQ3Z2tYq66O&platform=gcm
i was using a wrong nuget. i had to use
Microsoft.Azure.Mobile.Client
instead i was using Azure Mobile Services nuget.
both have MobileServiceClient class thats why i got confused. now i dont get the exception.

Trace Telemetry not showing up on Azure Portal

I have an MVC app running on local IIS server. I have an existing App Insights resource on Azure where I want Telemetry from my app to show up. However, Trace messages are not showing up on Azure Portal. I have added ApplicationInsights to my project, specified the resource where Telemetry should show up in ApplicationInsights.config and also written a TelemetryWrapper that I use in my code to send out the actual Telemetry Info and Error messages.
I initialize the Telemetry service through the wrapper:
TelemetryWrapper.InitializeTelemetry("InstrumentationKey", "ApplicationName");
And send out messages from the wrapper too
TelemetryWrapper.TelemetryInfo(requestId, action, userId, ultimateId, systemId, payload);
An overview of the TelemetryWrapper:
public static void InitializeTelemetry(string apiKey, string appId)
{
bool postBackground = true;
_telemetry = new TelemetryHelper(apiKey, appId, false) { PostBackground = postBackground };
}
public static void TelemetryInfo(Guid requestId, string action, Guid userId, string ultimateId, string systemId,
string payload)
{
var telem = CreateInstance(requestId, action, ultimateId, userId, systemId, payload);
_telemetry.Info(telem);
}
What am I possibly doing wrong?
Need more information. all you've shown is your code, there's no AppInsights code here to look at. so it could be that your TelemetryHelper class isn't setting the ikey correctly, the ikey could be invalid.
However: The one thing that jumps out at me is your usage of the terms apiKey and appId in your code.
Those 2 things have specific meaning in application insights, but that is for reading data from the AI API services (and apiKey in that context is something you could consider a secret, as if someone has those keys they can read all of your data!) I'm not sure if you're using them in a different context here but that jumped out at me right away.
There's a different thing, "Instrumentation Key" or iKey that you use to send data to application insights. Are you possibly switching those things around and trying to use an AI appId and apiKey in place of an iKey?
One way to check is to use fiddler or some other tool locally to watch outbound http traffic. configure it to decrypt https, and watch for outbound calls to dc.services.visualstudio.com, which is where your telemetry is going. If you have outbound calls, then it is at least trying to send your telemetry. If those calls are failing, the response might tell you that the iKey you are using is invalid, if this is the case.
You do not need

WCF Discovery with multithreading - The caller was not authenticated by the service

I try to implement WCF Discovery service using multithreading.
static void InvokeService()
{
var Services = discoveryClient.Find(new FindCriteria(typeof(WCFDiscoveryContract.IService1)));
discoveryClient.Close();
ServiceClient.ServiceReference1.Service1Client client = new ServiceClient.ServiceReference1.Service1Client();
client.Endpoint.Address = Services.Endpoints[0].Address;
var loanResponses = new MultiThreadedServiceCall<IService1, int, string>()
.CallMethod((service, request) => service.GetData(request))
.AttachService(new ServiceClient.ServiceReference1.Service1Client())
.GetResults(111);
string ss = client.GetData(1);
Console.WriteLine("Data is " + ss);
}
When i discover a service hosted in the same machine, it is working fine with the output.
But when i use the service hosted in another machine in the same network, it throws error in the following line.
string ss = client.GetData(1);
Error is
SecurityNegotiationException was unhandled
The caller was not authenticated by the service.
The request for security token could not be satisfied because authentication failed.
I use wsHttpBinding.
Please note wcf discovery service is working fine for service hosted in another machine.

Resources