/// <summary> /// Loads the decision module based on the decision metadata /// </summary> /// <param name="decisionMetadata">The decision metadata.</param> /// <param name="workspaceWrapper">The workspace wrapper.</param> /// <param name="componentsAppDomain">The components app domain is the app domain which decision assembly is going to be loaded into.</param> /// <returns>Loaded decision</returns> internal static IDecisionModule LoadDecisionModule(DecisionMetadata decisionMetadata, IWorkspaceInternal workspaceWrapper, AppDomain componentsAppDomain) { DecisionLoader loader = ConstructDecisionModuleInComponentsAppDomain(decisionMetadata, workspaceWrapper, componentsAppDomain); return((IDecisionModule)loader.LoadedDecisionModule); }
/// <summary> /// Creates the Runnable node with a specific id based on the given metadata. /// </summary> /// <param name="nodeId">The node id.</param> /// <param name="metadata">The component metadata.</param> /// <param name="loggerNameRoot">The logger name root - needed so that the logs are specific per experiment and experiment window.</param> /// <param name="library">The library of components.</param> /// <param name="componentsAppDomain">The components app domain is the app domain which components assemblies are going to be loaded into.</param> /// <param name="terminateExperimentExecutionResetEvent">The event that allows signalling termination of the experiment; /// Needed for the composite components sublevel experiments, so that they hold the referance to the same termination event as top level experiment.</param> /// <returns> /// Created node /// </returns> public virtual RunnableNode CreateNode(String nodeId, Metadata metadata, LoggerNameRoot loggerNameRoot, ComponentsLibrary library, AppDomain componentsAppDomain, System.Threading.ManualResetEvent terminateExperimentExecutionResetEvent) { RunnableNode retNode; ComponentMetadata componentMetadata = metadata as ComponentMetadata; DecisionMetadata decisionMetadata = metadata as DecisionMetadata; StartNodeMetadata startNodeMetadata = metadata as StartNodeMetadata; EndNodeMetadata endNodeMetadata = metadata as EndNodeMetadata; ScopeBaseMetadata scopeMetadata = metadata as ScopeBaseMetadata; LoopScopeMetadata loopMetadata = metadata as LoopScopeMetadata; CompositeComponentMetadata compositeComponentMetadata = metadata as CompositeComponentMetadata; ExitDecisionMetadata exitDecisionMetadata = metadata as ExitDecisionMetadata; if (componentMetadata != null) { TraceLabSDK.ComponentLogger logger = TraceLab.Core.Components.LoggerFactory.CreateLogger(loggerNameRoot, nodeId, componentMetadata); IComponent component = library.LoadComponent(componentMetadata, Workspace, logger, componentsAppDomain); retNode = new RunnableComponentNode(nodeId, componentMetadata.Label, component, logger, library, componentMetadata.WaitsForAllPredecessors); } else if (decisionMetadata != null) { IDecisionModule decisionModule = DecisionModuleFactory.LoadDecisionModule(decisionMetadata, Workspace, componentsAppDomain); retNode = new RunnableDecisionNode(nodeId, decisionMetadata.Label, decisionModule, library, decisionMetadata.WaitsForAllPredecessors); } else if (startNodeMetadata != null) { retNode = new RunnableStartNode(nodeId); } else if (endNodeMetadata != null) { retNode = new RunnableEndNode(nodeId, endNodeMetadata.WaitsForAllPredecessors); } else if (loopMetadata != null) { retNode = CreateLoopNode(nodeId, loopMetadata, loggerNameRoot, library, componentsAppDomain, terminateExperimentExecutionResetEvent); } else if (scopeMetadata != null) { retNode = CreateScopeCompositeComponentNode(nodeId, scopeMetadata, loggerNameRoot, library, componentsAppDomain, terminateExperimentExecutionResetEvent); } else if (compositeComponentMetadata != null) { retNode = CreateCompositeComponentNode(nodeId, compositeComponentMetadata, loggerNameRoot, library, componentsAppDomain, terminateExperimentExecutionResetEvent); } else if (exitDecisionMetadata != null) { retNode = new RunnablePrimitiveNode(nodeId, exitDecisionMetadata.WaitsForAllPredecessors); } else { throw new Exceptions.InconsistentTemplateException("Could not identify node type."); } return(retNode); }
private DecisionMetadata CompileMockDecision(string decisionCode) { DecisionMetadata decisionMetadata = new DecisionMetadata("Decision"); decisionMetadata.DecisionCode = decisionCode; DecisionCompilationRunner_Accessor.BuildSourceAndCompileDecisionModule(decisionMetadata, null, null, AppContext.WorkspaceInstance.TypeDirectories, new LoggerNameRoot("Mock")); AppContext.DecisionsToClear.Add(decisionMetadata.UniqueDecisionID); return(decisionMetadata); }
private void CompileDecision(string code) { DecisionMetadata decisionMetadata = new DecisionMetadata("Decision"); Dictionary <string, string> mockSuccessorNodeLabelIdLookup = new Dictionary <string, string>(); mockSuccessorNodeLabelIdLookup.Add("node 1 label", "Fake node 1 id"); mockSuccessorNodeLabelIdLookup.Add("node 2 label", "Fake node 2 id"); Dictionary <string, string> mockPredeccessorsOutputsNameTypeLookup = new Dictionary <string, string>(); mockPredeccessorsOutputsNameTypeLookup.Add("test", "int"); mockPredeccessorsOutputsNameTypeLookup.Add("targetArtifacts", "TraceLabSDK.Types.TLArtifactsCollection"); mockPredeccessorsOutputsNameTypeLookup.Add("sourceArtifacts", "TraceLabSDK.Types.TLArtifactsCollection"); decisionMetadata.DecisionCode = code; DecisionCompilationRunner_Accessor.BuildSourceAndCompileDecisionModule(decisionMetadata, mockSuccessorNodeLabelIdLookup, mockPredeccessorsOutputsNameTypeLookup, AppContext.WorkspaceInstance.TypeDirectories, new LoggerNameRoot("Mock")); }
/// <summary> /// Create ImpressionEvent instance from ProjectConfig /// </summary> /// <param name="projectConfig">The ProjectConfig entity</param> /// <param name="activatedExperiment">The Experiment entity</param> /// <param name="variation">The variation entity</param> /// <param name="userId">The user Id</param> /// <param name="userAttributes">The user's attributes</param> /// <param name="flagKey">experiment key or feature key</param> /// <param name="ruleType">experiment or featureDecision source </param> /// <returns>ImpressionEvent instance</returns> public static ImpressionEvent CreateImpressionEvent(ProjectConfig projectConfig, Experiment activatedExperiment, Variation variation, string userId, UserAttributes userAttributes, string flagKey, string ruleType, bool enabled = false) { if ((ruleType == FeatureDecision.DECISION_SOURCE_ROLLOUT || variation == null) && !projectConfig.SendFlagDecisions) { return(null); } var eventContext = new EventContext.Builder() .WithProjectId(projectConfig.ProjectId) .WithAccountId(projectConfig.AccountId) .WithAnonymizeIP(projectConfig.AnonymizeIP) .WithRevision(projectConfig.Revision) .Build(); var variationKey = ""; var ruleKey = ""; if (variation != null) { variationKey = variation.Key; ruleKey = activatedExperiment?.Key ?? string.Empty; } var metadata = new DecisionMetadata(flagKey, ruleKey, ruleType, variationKey, enabled); return(new ImpressionEvent.Builder() .WithEventContext(eventContext) .WithBotFilteringEnabled(projectConfig.BotFiltering) .WithExperiment(activatedExperiment) .WithMetadata(metadata) .WithUserId(userId) .WithVariation(variation) .WithVisitorAttributes(EventFactory.BuildAttributeList(userAttributes, projectConfig)) .Build()); }
public void TestImpressionEventEqualsSerializedPayload() { var guid = Guid.NewGuid(); var timeStamp = TestData.SecondsSince1970(); var userId = "TestUserId"; var expectedPayload = new Dictionary <string, object> { { "visitors", new object[] { new Dictionary <string, object>() { { "snapshots", new object[] { new Dictionary <string, object> { { "decisions", new object[] { new Dictionary <string, object> { { "campaign_id", "7719770039" }, { "experiment_id", "7716830082" }, { "variation_id", "77210100090" } } } }, { "events", new object[] { new Dictionary <string, object> { { "entity_id", "7719770039" }, { "timestamp", timeStamp }, { "uuid", guid }, { "key", "campaign_activated" } } } } } } }, { "attributes", new object[] { new Dictionary <string, object> { { "entity_id", "7723280020" }, { "key", "device_type" }, { "type", "custom" }, { "value", "iPhone" } }, new Dictionary <string, object> { { "entity_id", ControlAttributes.BOT_FILTERING_ATTRIBUTE }, { "key", ControlAttributes.BOT_FILTERING_ATTRIBUTE }, { "type", "custom" }, { "value", true } } } }, { "visitor_id", userId } } } }, { "project_id", "7720880029" }, { "account_id", "1592310167" }, { "enrich_decisions", true }, { "client_name", "csharp-sdk" }, { "client_version", Optimizely.SDK_VERSION }, { "revision", "15" }, { "anonymize_ip", false } }; EventBatch.Builder builder = new EventBatch.Builder(); builder.WithAccountId("1592310167") .WithProjectID("7720880029") .WithClientVersion(Optimizely.SDK_VERSION) .WithRevision("15") .WithClientName("csharp-sdk") .WithAnonymizeIP(false) .WithEnrichDecisions(true); var visitorAttribute1 = new VisitorAttribute(entityId: "7723280020", type: "custom", value: "iPhone", key: "device_type"); var visitorAttribute2 = new VisitorAttribute(entityId: ControlAttributes.BOT_FILTERING_ATTRIBUTE, type: "custom", value: true, key: ControlAttributes.BOT_FILTERING_ATTRIBUTE); var snapshotEvent = new SnapshotEvent.Builder() .WithUUID(guid.ToString()) .WithEntityId("7719770039") .WithKey("campaign_activated") .WithValue(null) .WithRevenue(null) .WithTimeStamp(timeStamp) .WithEventTags(null) .Build(); var metadata = new DecisionMetadata("experiment", "experiment_key", "7716830082"); var decision = new Decision("7719770039", "7716830082", "77210100090"); var snapshot = new Snapshot(events: new SnapshotEvent[] { snapshotEvent }, decisions: new Decision[] { decision }); var visitor = new Visitor( snapshots: new Snapshot[] { snapshot }, attributes: new VisitorAttribute[] { visitorAttribute1, visitorAttribute2 }, visitorId: "test_user"); builder.WithVisitors(new Visitor[] { visitor }); EventBatch eventBatch = builder.Build(); // Single Conversion Event TestData.CompareObjects(expectedPayload, eventBatch); }