internal HttpMessage CreatePostUsageEventRequest(UsageEvent body, Guid?requestId, Guid?correlationId) { var message = _pipeline.CreateMessage(); var request = message.Request; request.Method = RequestMethod.Post; var uri = new RawRequestUriBuilder(); uri.Reset(endpoint); uri.AppendPath("/usageEvent", false); uri.AppendQuery("api-version", apiVersion, true); request.Uri = uri; if (requestId != null) { request.Headers.Add("x-ms-requestid", requestId.Value); } if (correlationId != null) { request.Headers.Add("x-ms-correlationid", correlationId.Value); } request.Headers.Add("Accept", "application/json"); request.Headers.Add("Content-Type", "application/json"); var content = new Utf8JsonRequestContent(); content.JsonWriter.WriteObjectValue(body); request.Content = content; return(message); }
public CsvUsageEvent(UsageEvent usageEvent) { CustomerId = usageEvent.CustomerId; ItemId = usageEvent.ItemId; EventType = usageEvent.EventType.ToString(); CreatedDate = usageEvent.CreatedDate.ToString("s"); }
/// <summary> /// Manage Subscription Usage. /// </summary> /// <param name="subscriptionUsageRequest">The subscription usage request.</param> /// <returns> /// Subscription Usage. /// </returns> public async Task <MeteringUsageResult> EmitUsageEventAsync(MeteringUsageRequest subscriptionUsageRequest) { this.Logger?.Info($"Inside ManageSubscriptionUsageAsync() of FulfillmentApiClient, trying to Manage Subscription Usage :: {subscriptionUsageRequest.ResourceId}"); var usage = new UsageEvent() { ResourceId = subscriptionUsageRequest.ResourceId, PlanId = subscriptionUsageRequest.PlanId, Dimension = subscriptionUsageRequest.Dimension, Quantity = subscriptionUsageRequest.Quantity, EffectiveStartTime = subscriptionUsageRequest.EffectiveStartTime, }; try { var updateResult = (await this.meteringClient.Metering.PostUsageEventAsync(usage)).Value; return(new MeteringUsageResult() { Dimension = updateResult.Dimension, MessageTime = updateResult.MessageTime.Value.UtcDateTime, PlanId = updateResult.PlanId, Quantity = (long)updateResult.Quantity, ResourceId = updateResult.ResourceId.Value, Status = updateResult.Status.ToString(), UsagePostedDate = updateResult.EffectiveStartTime.Value.UtcDateTime, UsageEventId = updateResult.UsageEventId.Value }); } catch (Exception ex) { this.ProcessErrorResponse(MarketplaceActionEnum.SUBSCRIPTION_USAGEEVENT, ex); return(null); } }
public virtual Response <UsageEventOkResponse> PostUsageEvent(UsageEvent body, Guid?requestId = null, Guid?correlationId = null, CancellationToken cancellationToken = default) { using var scope = _clientDiagnostics.CreateScope("MeteringOperations.PostUsageEvent"); scope.Start(); try { return(RestClient.PostUsageEvent(body, requestId, correlationId, cancellationToken)); } catch (Exception e) { scope.Failed(e); throw; } }
public async Task <IActionResult> SubscriptionDimensionUsage(DimensionEventViewModel model, CancellationToken cancellationToken) { if (model == null) { throw new ArgumentNullException(nameof(model)); } var usage = new UsageEvent() { ResourceId = model.SubscriptionId, PlanId = model.PlanId, Dimension = model.SelectedDimension, Quantity = model.Quantity, EffectiveStartTime = model.EventTime, }; var updateResult = await this.meteringClient.MeteringOperations.PostUsageEventAsync(usage, null, null, cancellationToken).ConfigureAwait(false); DimensionUsageRecord dimRecord = new DimensionUsageRecord(usage.ResourceId?.ToString(), DateTime.Now.ToString("o")); bool errorMessage = true; if (updateResult != null) { dimRecord.UsageEventId = updateResult.UsageEventId; dimRecord.Status = updateResult.Status.ToString(); dimRecord.Quantity = updateResult.Quantity; dimRecord.Dimension = updateResult.Dimension; dimRecord.EffectiveStartTime = updateResult.MessageTime; dimRecord.PlanId = updateResult.PlanId; errorMessage = false; } else { dimRecord.Status = UsageEventStatusEnum.InvalidDimensionBadArgument.ToString(); dimRecord.Quantity = usage.Quantity; dimRecord.Dimension = usage.Dimension; dimRecord.EffectiveStartTime = usage.EffectiveStartTime; dimRecord.PlanId = usage.PlanId; } await this.dimensionUsageStore.RecordAsync(model.SubscriptionId, dimRecord, cancellationToken).ConfigureAwait(false); return(this.RedirectToAction("SubscriptionDimensionUsage", new { model.SubscriptionId, errorMessage })); }
public virtual UsageEvent ToModel(UsageEvent usageEvent) { if (usageEvent == null) { throw new ArgumentNullException("usageEvent"); } usageEvent.Id = Id; usageEvent.CreatedBy = CreatedBy; usageEvent.CreatedDate = CreatedDate; usageEvent.ModifiedBy = ModifiedBy; usageEvent.ModifiedDate = ModifiedDate; usageEvent.CustomerId = CustomerId; usageEvent.StoreId = StoreId; usageEvent.ItemId = ItemId; usageEvent.EventType = (UsageEventType)Enum.Parse(typeof(UsageEventType), EventType); return(usageEvent); }
public async Task <Response <UsageEventOkResponse> > PostUsageEventAsync(UsageEvent body, Guid?requestId = null, Guid?correlationId = null, CancellationToken cancellationToken = default) { if (body == null) { throw new ArgumentNullException(nameof(body)); } using var message = CreatePostUsageEventRequest(body, requestId, correlationId); await _pipeline.SendAsync(message, cancellationToken).ConfigureAwait(false); switch (message.Response.Status) { case 200: { UsageEventOkResponse value = default; using var document = await JsonDocument.ParseAsync(message.Response.ContentStream, default, cancellationToken).ConfigureAwait(false); value = UsageEventOkResponse.DeserializeUsageEventOkResponse(document.RootElement); return(Response.FromValue(value, message.Response)); }
public virtual UsageEventEntity FromModel(UsageEvent usageEvent, PrimaryKeyResolvingMap pkMap) { if (usageEvent == null) { throw new ArgumentNullException("usageEvent"); } pkMap.AddPair(usageEvent, this); Id = usageEvent.Id; CreatedBy = usageEvent.CreatedBy; CreatedDate = usageEvent.CreatedDate; ModifiedBy = usageEvent.ModifiedBy; ModifiedDate = usageEvent.ModifiedDate; CustomerId = usageEvent.CustomerId; StoreId = usageEvent.StoreId; ItemId = usageEvent.ItemId; EventType = usageEvent.EventType.ToString(); return(this); }
public static void AddUsageEvent(string userName, string homeOrgName, string partnerName, string certFile, string validationStatus, TimeSpan executionTime, string testFileName, string service, IDalManager dal) { // Hardcoded order since we don't create order during sign up yet. Order order = new Order() { Id = Guid.Parse("75654e42-c3fe-482b-b52a-024d073e1ea7"), OfferId = Guid.Parse("5ddd32f3-1783-4bbe-854f-4c5d5955df7f"), SeatCount = 1, TenantId = "GCom", UserId = userName, }; UsageEvent usageEvent = new UsageEvent() { Id = Guid.NewGuid(), OrderId = order.Id, ResourceId = "EdiValidation", TenantId = order.TenantId, Timestamp = DateTime.UtcNow, WhenConsumed = DateTime.UtcNow, UserId = order.UserId, AmountConsumed = 1.0d, HomeOrgName = homeOrgName, PartnerName = partnerName, SpecCertName = certFile, InstanceFileName = testFileName, ValidationStatus = validationStatus, TimeOfValidationInMs = (int)executionTime.TotalMilliseconds, Service = service, }; // For unit tests dal will be null if (dal != null) { dal.TrackUsage(usageEvent); } }
public bool TrackUsage(UsageEvent usage) { int statusCode = -1; BillingCycle currentBillingCyle = this.manager.FetchOrCreateCurrentBillingCycle(); usage.BillingCycleId = currentBillingCyle.Id; //PartitionKey = orderId + billingCycleId //RowKey = NewGuid usage.PartitionKey = string.Format("{0}-{1}", usage.OrderId.ToString(), usage.BillingCycleId.ToString()); usage.RowKey = Guid.NewGuid().ToString(); //locking to reduce contention for aggregate update if multiple events for same order are coming at the same time //this is not foolproff though. TODO - when updates happen from different servers. check what error Azure //returns when server1 read, server2 updated, server1 updated //based on that tweak the business logic lock (lockObject) { //step1 - fetchORcreate and increment aggregate usage UsageAggregateByBillingCycle aggregate = GetUsageAggregateByBillingCycle(usage.OrderId, usage.BillingCycleId, usage.ResourceId); bool isNew = false; if (aggregate == null) { aggregate = new UsageAggregateByBillingCycle { OrderId = usage.OrderId, BillingCycleId = usage.BillingCycleId, ResourceId = usage.ResourceId }; aggregate.PartitionKey = string.Format("{0}-{1}", usage.OrderId.ToString(), usage.BillingCycleId.ToString()); aggregate.RowKey = usage.ResourceId; isNew = true; } aggregate.AmountConsumed += usage.AmountConsumed; //step2 - save raw usage this.tableContext.AddObject(RawUsageTableName, usage); if (isNew) { this.aggregateTableServiceContext.AddObject(AggregateUsageTableName, aggregate); } else { this.aggregateTableServiceContext.UpdateObject(aggregate); } //Now add logic for per user aggregate UsageAggregatePerUserByBillingCycle aggregatePerUser = GetUsageAggregatePerUserByBillingCycle(usage.OrderId, usage.BillingCycleId, usage.ResourceId, usage.UserId); isNew = false; if (aggregatePerUser == null) { aggregatePerUser = new UsageAggregatePerUserByBillingCycle { OrderId = usage.OrderId, BillingCycleId = usage.BillingCycleId, ResourceId = usage.ResourceId, UserId = usage.UserId }; aggregatePerUser.PartitionKey = string.Format("{0}-{1}", usage.OrderId.ToString(), usage.BillingCycleId.ToString()); aggregatePerUser.RowKey = string.Format("{0}-{1}", usage.ResourceId, usage.UserId); isNew = true; } aggregatePerUser.AmountConsumed += usage.AmountConsumed; if (isNew) { this.aggregatePerUserTableServiceContext.AddObject(AggregatePerUserUsageTableName, aggregatePerUser); } else { this.aggregatePerUserTableServiceContext.UpdateObject(aggregatePerUser); } //end DataServiceResponse response = this.tableContext.SaveChangesWithRetries(SaveChangesOptions.Batch); response = this.aggregateTableServiceContext.SaveChangesWithRetries(SaveChangesOptions.Batch); statusCode = response.BatchStatusCode; } return(statusCode == Http200 || statusCode == 202); }
public bool TrackUsage(UsageEvent usageEvent) { DalUsageEvent dal = new DalUsageEvent(this, this.storageAccount); return(dal.TrackUsage(usageEvent)); }