Different connection string for output or trigger - c#

Here i have a webjob function using servicebus triggers and outputs. I'd like to set a different configuration for output and input.
public static void OnPush(
[ServiceBusTrigger("%PushProcessor.InputTopicName%", "%PushProcessor.InputTopicSubscriptionName%", AccessRights.Listen)]
BrokeredMessage message,
[ServiceBus("%PushProcessor.OutputTopicName%", AccessRights.Send)]
out BrokeredMessage output
)
I see in latest api that one can control the job host with service bus extensions.
JobHostConfiguration config = new JobHostConfiguration
{
StorageConnectionString = ConfigHelpers.GetConfigValue("AzureWebJobsStorage"),
DashboardConnectionString = ConfigHelpers.GetConfigValue("AzureWebJobsDashboard"),
NameResolver = new ByAppSettingsNameResolver()
};
config.UseServiceBus(new ServiceBusConfiguration
{
MessageOptions = new OnMessageOptions {
MaxConcurrentCalls = 2,
AutoRenewTimeout = TimeSpan.FromMinutes(1),
AutoComplete = true,
},
ConnectionString = ConfigHelpers.GetConfigValue("InputServiceBusConnectionString"),
});
Unfortunately i see no control for the connection string for the output. I'd like a different connection string (different namespace/access rights) to be used for inputs versus outputs.
Perhaps the api can support registering named jobhostconfigurations to a jobhost, and referring to that name in the attributes for the trigger/output. Anyways if there is a way to do this let me know.

Yes, also in the latest beta1 release you'll see that there is now a ServiceBusAccountAttribute that you can apply along with the ServiceBusTrigger/ServiceBus attributes. For example:
public static void Test(
[ServiceBusTriggerAttribute("test"),
ServiceBusAccount("testaccount")] BrokeredMessage message)
{
. . .
}
We've done the same for all the other attribute types (Queue/Blob/Table) via StorageAccountAttribute. These account attributes can be applied at the class/method/parameter level. Please give this new feature a try and let us know how it works for you. Also, see the release notes for more details.

Related

How to push LSP Diagnostic using OmniSharp LanguageServer?

I'm using OmniSharp's C# LSP server to implement a simple parsing/language service for a VS Code plugin. I've managed to get the basics up and running, but I've not been able to figure out how to push diagnostic messages to VS Code (like in this typescript sample).
Does anyone have any sample code/hints that would be of use?
Thanks!
Having spoken with #david-driscoll, it turns out I needed to stash a reference to ILanguageServerFacade in my constructor and use the PublishDiagnostics extension method on TextDocument. Ie:
public class TextDocumentSyncHandler : ITextDocumentSyncHandler
{
private readonly ILanguageServerFacade _facade;
public TextDocumentSyncHandler(ILanguageServerFacade facade)
{
_facade = facade;
}
public Task<Unit> Handle(DidChangeTextDocumentParams request, CancellationToken cancellationToken)
{
// Parse your stuff here
// Diagnostics are sent a document at a time, this example is for demonstration purposes only
var diagnostics = ImmutableArray<Diagnostic>.Empty.ToBuilder();
diagnostics.Add(new Diagnostic()
{
Code = "ErrorCode_001",
Severity = DiagnosticSeverity.Error,
Message = "Something bad happened",
Range = new Range(0, 0, 0, 0),
Source = "XXX",
Tags = new Container<DiagnosticTag>(new DiagnosticTag[] { DiagnosticTag.Unnecessary })
});
_facade.TextDocument.PublishDiagnostics(new PublishDiagnosticsParams()
{
Diagnostics = new Container<Diagnostic>(diagnostics.ToArray()),
Uri = request.TextDocument.Uri,
Version = request.TextDocument.Version
});
return Unit.Task;
}
}
For real code, you would want a centralised array of Diagnostic objects, but this shows the basics of how to get it done.
Thank you David!

Start GCE instance via client API with environment variable

I'm trying to programmatically start up GCE instances from the C#/REST API (ie not using gcloud or the console). These instances must have values (identifying who started them, so will be different for each instance) passed to them during start-up, which will then get passed to the various applications running within. The obvious way of adding environment variables to the GCE request doesn't appear to be possible, so how does one provide dynamic configuration?
My current code for creating the instances which works fine:
public void CreateInstance(string name)
{
var credentials = GoogleCredential.GetApplicationDefault().CreateScoped(ComputeService.Scope.Compute);
var service = new ComputeService(new BaseClientService.Initializer
{
HttpClientInitializer = credentials,
ApplicationName = "Spin-up"
});
var spec = new Google.Apis.Compute.v1.Data.Instance
{
Name = name
};
var instanceTemplate = service.InstanceTemplates.Get(GCloudConfig.ProjectName, GCloudConfig.TemplateName).Execute();
var insertRequest = service.Instances.Insert(spec, GCloudConfig.ProjectName, GCloudConfig.Region);
insertRequest.SourceInstanceTemplate = instanceTemplate.SelfLink;
insertRequest.Execute();
}
You might use the API for Compute Engine Method: instances.start or instances.stop to trigger the start or stop of VM Instances with C# code requests.
Additional information about these API methods are described in documents: instances.start. and instances.stop.

Cannot update read/write attributes of UserPoolClient via C# SDK

When programmatically creating a Cognito user pool and app client, if the app client is to have read/write access to attributes of the user pool, that access must be explicitly given. I have been able to do so successfully for custom attributes but built-in attributes always return an error of "Invalid write attributes specified while creating a client" or "Invalid read attributes specified while creating a client".
Documentation is ... both voluminous and difficult to find. I have yet to see an example of this or an actual bit of useful documentation on the CreateUserPoolClientRequest type that says anything about this other than things like "ReadAttributes is a list of strings that are the attributes that can be read".
Here is the code I'm using that always ends up with that error message and failure to create the app client. _client is an AmazonCognitoIdentityProviderClient properly instantiated and credentialed and running in a lambda function.
var request = new CreateUserPoolClientRequest { UserPoolId = userPoolId, ClientName = $"{name}AppClient" };
var builtInAttributes = new List<string>()
{
"address","birthdate","email","family name","gender","given name","locale","middle name","name","nickname","phone number", "picture","preferred username","profile","zoneinfo","updated at","website"
};
var readAttributes = new List<string>();
var writeAttributes = new List<string>();
readAttributes.InsertRange(0,builtInAttributes);
writeAttributes.InsertRange(0, builtInAttributes);
var attributeConfig = ConfigurationHelper.GetListFromSection("UserPoolCustomAttributes");
foreach (var attribute in attributeConfig)
{
readAttributes.Add($"custom:{attribute.Key}");
writeAttributes.Add($"custom:{attribute.Key}");
}
request.ReadAttributes = readAttributes;
request.WriteAttributes = writeAttributes;
var result = await _client.CreateUserPoolClientAsync(request, CancellationToken.None);
Any help is greatly appreciated.
Figured it out. Though I have yet to find it documented anywhere, default attributes with a space in the name in the ui need to have that space replaced with an underscore when using their name in the api.

How can I stop NLog from double logging

I'm writing a WEB API call for NLog, so remote apps can log to my logging table.
In my controller I have (hard-coded for now as a sanity check):
NLogger.LogError("Some Error Message", "An exception", 5, "A computer name");
Then my static LogError method looks like this (I tried LogEventInfo() too):
public static void LogError(string msg, string ex, int appid, string machineName)
{
LogEventInfo logEvent = new LogEventInfo(LogLevel.Error, "Api Logger", "Another test msg");
logEvent.Properties["myMsg"] = msg;
logEvent.Properties["myEx"] = ex;
logEvent.Properties["myAppId"] = appid;
logEvent.Properties["myMachineName"] = machineName;
NLogManager.Instance.Log(logEvent);
}
Lastly, this is my code first config for that rule (there's 2 others with different db targets):
private static void ConfigureApiLog()
{
var dbApiErrorTarget = new DatabaseTarget
{
ConnectionString = ConnectionFactory.GetSqlConnection().ConnectionString,
CommandText = "usp_LogError",
CommandType = CommandType.StoredProcedure
};
dbApiErrorTarget.Parameters.Add(new DatabaseParameterInfo("#level",
new global::NLog.Layouts.SimpleLayout("${level}")));
dbApiErrorTarget.Parameters.Add(new DatabaseParameterInfo("#logger",
new global::NLog.Layouts.SimpleLayout("${logger}")));
dbApiErrorTarget.Parameters.Add(new DatabaseParameterInfo("#message",
new global::NLog.Layouts.SimpleLayout("${event-properties:item=myMsg}")));
dbApiErrorTarget.Parameters.Add(new DatabaseParameterInfo("#exception",
new global::NLog.Layouts.SimpleLayout("${event-properties:item=myEx}")));
dbApiErrorTarget.Parameters.Add(new DatabaseParameterInfo("#AppId",
new global::NLog.Layouts.SimpleLayout("${event-properties:item=myAppId}")));
dbApiErrorTarget.Parameters.Add(new DatabaseParameterInfo("#MachineName",
new global::NLog.Layouts.SimpleLayout("${event-properties:item=myMachineName}")));
Config.AddTarget("database", dbApiErrorTarget);
Config.LoggingRules.Add(new LoggingRule("*", LogLevel.Error, LogLevel.Fatal, dbApiErrorTarget));
}
I expect 1 log per log call to the logger instance, but I'm getting two and I'm not exactly sure why:
Id Date Level Logger Message Exception AppId MachineName
1 2017-03-03 22:43:20.557 Error Api Logger Another test msg 0 mylocalmachine
2 2017-03-03 22:43:20.603 Error Api Logger Some Error Message An exception 5 A computer name
AppId 0 is my Api, 5 is some remote app, hard coded at this point as POC.
Might be that it's Friday, but I can't seem to figure out what's wrong with the code. Any help would be appreciated!
I had this problem and found the problem, for my specific case. Problem was double entries everywhere on every target.
I had a .NET Core web application which used the UseNLog() inside the Program.cs IWebHostBuilder. This performs AddNLog() internally.
Then in the startup I manually did loggerInstance.AddNLog() which caused the dual insertion.
The latter must be removed since UseNLog is a far better and "sooner" time to enable NLog
Hope it helps!
Rules in NLog can be target specific, or it can write to all targets. The default rule(s) won't have any targets specified, so they will write to any you create. You're also adding your own rule, which writes specifically to your target and no others.
Thus, the double-logging.
You can remove the default rules to resolve the issue.
Config.LoggingRules.Clear();
before you add your rule.

How to configure Receiver batch size for Azure Functions EventHub listener?

In the latest Microsoft.Azure.WebJobs.ServiceBus package, it gives you the ability to receive batches of messages from eventhubs. I would like to set how many messages I want to receive in a batch.
The core ServiceBus library allows you to overload the Receive() function and provide the batch size.
How does one do this in the initial config of an EventHubs receiver, or is something else required?
You can do this in Functions via the eventHub configuration block in host.json as described here. E.g.:
{
"eventHub": {
"maxBatchSize": 500,
"prefetchCount": 100
}
}
We apply those configuration settings to the EventProcessorOptions when we create the EventProcessorHost (see here).
Steph,
The MaxBatchSize can be configured through EventProcessorOptions, you can pass it as a parameter when creating a new EventHubConfiguration.
var options = EventProcessorOptions.DefaultOptions;
options.MaxBatchSize = 50;
var eventHubConfig = new EventHubConfiguration(options);
string eventHubName = "MyHubName";
eventHubConfig.AddSender(eventHubName, "Endpoint=sb://test.servicebus.windows.net/;SharedAccessKeyName=SendRule;SharedAccessKey=xxxxxxxx");
eventHubConfig.AddReceiver(eventHubName, "Endpoint=sb://test.servicebus.windows.net/;SharedAccessKeyName=ReceiveRule;SharedAccessKey=yyyyyyy");
config.UseEventHub(eventHubConfig);
JobHost host = new JobHost(config);
As you can notice in the source code of EventHubConfiguration.cs if no EventProcessorOptions is specified, the MaxBatchSize is set to 1000 instead of 10 by default.
public EventHubConfiguration(
EventProcessorOptions options,
PartitionManagerOptions partitionOptions = null)
{
if (options == null)
{
options = EventProcessorOptions.DefaultOptions;
options.MaxBatchSize = 1000;
}
_partitionOptions = partitionOptions;
_options = options;
}

Categories

Resources