Skip to content

Commit

Permalink
Hotfix(metrics): CNX-9196 add object type event tracking for mixpanel…
Browse files Browse the repository at this point in the history
… in autocad, rhino, and revit (#3257)

* adds events on send

* adds logging to receive

* changes event name and no longer passes default account

* removes unnecessary usings

* Update ConnectorBindingsRevit.Send.cs

* refactors payload to be an array capped at 250 entries

* oops capped it at 25 accidentally

* minor refactors

* changes type list to be capped at 200 instead of 250
  • Loading branch information
clairekuang authored Apr 10, 2024
1 parent b025200 commit 118f6bb
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ string id
var conversionProgressDict = new ConcurrentDictionary<string, int>();
conversionProgressDict["Conversion"] = 0;

// track object types for mixpanel logging
Dictionary<string, int> typeCountDict = new();

// create a commit prefix: used for layers and block definition names
var commitPrefix = Formatting.CommitInfo(stream.name, state.BranchName, id);

Expand Down Expand Up @@ -217,18 +220,22 @@ string id
return;
}

if (StoredObjects.TryGetValue(commitObj.OriginalId, out Base commitBaseObj))
{
// log received object type
typeCountDict.TryGetValue(commitBaseObj.speckle_type, out var currentCount);
typeCountDict[commitBaseObj.speckle_type] = ++currentCount;
}
else
{
commitObj.Update(status: ApplicationObject.State.Failed, logItem: "Object not found in StoredObjects");
}

// convert base (or base fallback values) and store in appobj converted prop
if (commitObj.Convertible)
{
if (StoredObjects.TryGetValue(commitObj.OriginalId, out Base obj))
{
converter.Report.Log(commitObj); // Log object so converter can access
commitObj.Converted = ConvertObject(obj, converter);
}
else
{
commitObj.Update(status: ApplicationObject.State.Failed, logItem: "Object not found in StoredObjects");
}
converter.Report.Log(commitObj); // Log object so converter can access
commitObj.Converted = ConvertObject(commitBaseObj, converter);
}
else
{
Expand Down Expand Up @@ -271,6 +278,20 @@ string id
}
progress.Report.Merge(converter.Report);

// track the object type counts as an event before we try to receive
// this will tell us the composition of a commit the user is trying to receive, even if it's not successfully received
// we are capped at 255 properties for mixpanel events, so we need to check dict entries
var typeCountList = typeCountDict
.Select(o => new { TypeName = o.Key, Count = o.Value })
.OrderBy(pair => pair.Count)
.Reverse()
.Take(200);

Analytics.TrackEvent(
Analytics.Events.ConvertToNative,
new Dictionary<string, object>() { { "typeCount", typeCountList } }
);

// add applicationID xdata before bake
if (!ApplicationIdManager.AddApplicationIdXDataToDoc(Doc, tr))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ ref int convertedCount
var commitLayerObjects = new Dictionary<string, List<Base>>();
var commitCollections = new Dictionary<string, Collection>();

// track object types for mixpanel logging
Dictionary<string, int> typeCountDict = new();

foreach (var autocadObjectHandle in state.SelectedObjectIds)
{
// handle user cancellation
Expand All @@ -201,6 +204,11 @@ ref int convertedCount
continue;
}

// log selection object type
var objectType = obj.GetType().ToString();
typeCountDict.TryGetValue(objectType, out var currentCount);
typeCountDict[objectType] = ++currentCount;

// create applicationobject for reporting
Base converted = null;
var descriptor = ObjectDescriptor(obj);
Expand Down Expand Up @@ -342,6 +350,20 @@ bool isOldApplicationId(string appId)

#endregion

// track the object type counts as an event before we try to send
// this will tell us the composition of a commit the user is trying to convert and send, even if it's not successfully converted or sent
// we are capped at 255 properties for mixpanel events, so we need to check dict entries
var typeCountList = typeCountDict
.Select(o => new { TypeName = o.Key, Count = o.Value })
.OrderBy(pair => pair.Count)
.Reverse()
.Take(200);

Analytics.TrackEvent(
Analytics.Events.ConvertToSpeckle,
new Dictionary<string, object>() { { "typeCount", typeCountList } }
);

tr.Commit();
}
}
Expand Down
22 changes: 22 additions & 0 deletions ConnectorRevit/ConnectorRevit/UI/ConnectorBindingsRevit.Receive.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ public override async Task<StreamState> ReceiveStream(StreamState state, Progres

converter.SetConverterSettings(settings);

// track object types for mixpanel logging
Dictionary<string, int> typeCountDict = new();

Commit myCommit = await ConnectorHelpers.GetCommitFromState(state, progress.CancellationToken);
state.LastCommit = myCommit;
Base commitObject = await ConnectorHelpers.ReceiveCommit(myCommit, state, progress);
Expand All @@ -70,8 +73,27 @@ await ConnectorHelpers.TryCommitReceived(
foreach (var previewObj in Preview)
{
progress.Report.Log(previewObj);
if (StoredObjects.TryGetValue(previewObj.OriginalId, out Base previewBaseObj))
{
typeCountDict.TryGetValue(previewBaseObj.speckle_type, out var currentCount);
typeCountDict[previewBaseObj.speckle_type] = ++currentCount;
}
}

// track the object type counts as an event before we try to receive
// this will tell us the composition of a commit the user is trying to convert and receive, even if it's not successfully converted or received
// we are capped at 255 properties for mixpanel events, so we need to check dict entries
var typeCountList = typeCountDict
.Select(o => new { TypeName = o.Key, Count = o.Value })
.OrderBy(pair => pair.Count)
.Reverse()
.Take(200);

Analytics.TrackEvent(
Analytics.Events.ConvertToNative,
new Dictionary<string, object>() { { "typeCount", typeCountList } }
);

converter.ReceiveMode = state.ReceiveMode;
// needs to be set for editing to work
var previousObjects = new StreamStateCache(state);
Expand Down
24 changes: 24 additions & 0 deletions ConnectorRevit/ConnectorRevit/UI/ConnectorBindingsRevit.Send.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ public override async Task<string> SendStream(StreamState state, ProgressViewMod
var conversionProgressDict = new ConcurrentDictionary<string, int> { ["Conversion"] = 0 };
var convertedCount = 0;

// track object types for mixpanel logging
Dictionary<string, int> typeCountDict = new();

await APIContext
.Run(() =>
{
Expand All @@ -114,6 +117,11 @@ await APIContext
break;
}

// log selection object type
var revitObjectType = revitElement.GetType().ToString();
typeCountDict.TryGetValue(revitObjectType, out var currentCount);
typeCountDict[revitObjectType] = ++currentCount;

bool isAlreadyConverted = GetOrCreateApplicationObject(
revitElement,
converter.Report,
Expand All @@ -136,10 +144,12 @@ out ApplicationObject reportObj

Base result = ConvertToSpeckle(revitElement, converter);

// log converted object
reportObj.Update(
status: ApplicationObject.State.Created,
logItem: $"Sent as {ConnectorRevitUtils.SimplifySpeckleType(result.speckle_type)}"
);

if (result.applicationId != reportObj.applicationId)
{
SpeckleLog.Logger.Information(
Expand Down Expand Up @@ -180,6 +190,20 @@ out ApplicationObject reportObj
throw new SpeckleException("Zero objects converted successfully. Send stopped.");
}

// track the object type counts as an event before we try to send
// this will tell us the composition of a commit the user is trying to convert and send, even if it's not successfully converted or sent
// we are capped at 255 properties for mixpanel events, so we need to check dict entries
var typeCountList = typeCountDict
.Select(o => new { TypeName = o.Key, Count = o.Value })
.OrderBy(pair => pair.Count)
.Reverse()
.Take(200);

Analytics.TrackEvent(
Analytics.Events.ConvertToSpeckle,
new Dictionary<string, object>() { { "typeCount", typeCountList } }
);

commitObjectBuilder.BuildCommitObject(commitObject);

var transports = new List<ITransport>() { new ServerTransport(client.Account, streamId) };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ public override async Task<StreamState> ReceiveStream(StreamState state, Progres
var conversionProgressDict = new ConcurrentDictionary<string, int>();
conversionProgressDict["Conversion"] = 0;

// track object types for mixpanel logging
Dictionary<string, int> typeCountDict = new();

Base commitObject = null;
if (Preview.Count == 0)
{
Expand Down Expand Up @@ -161,6 +164,7 @@ await ConnectorHelpers.TryCommitReceived(
.Where(o => !string.IsNullOrEmpty(o))
.OrderBy(path => path.Count(c => c == ':'))
.ToList();

// if on create mode, make sure the parent commit layer is created first
if (state.ReceiveMode == ReceiveMode.Create)
{
Expand All @@ -185,6 +189,7 @@ await ConnectorHelpers.TryCommitReceived(
var collection = Preview
.Where(o => o.Container == container && o.Descriptor.Contains("Collection"))
.FirstOrDefault();

if (collection != null)
{
var storedCollection = StoredObjects[collection.OriginalId];
Expand Down Expand Up @@ -217,6 +222,13 @@ await ConnectorHelpers.TryCommitReceived(

foreach (var previewObj in Preview)
{
// log received object type
if (StoredObjects.TryGetValue(previewObj.OriginalId, out Base previewBaseObj))
{
typeCountDict.TryGetValue(previewBaseObj.speckle_type, out var currentCount);
typeCountDict[previewBaseObj.speckle_type] = ++currentCount;
}

if (previewObj.Status != ApplicationObject.State.Unknown)
{
continue; // this has already been converted and baked
Expand Down Expand Up @@ -303,6 +315,20 @@ await ConnectorHelpers.TryCommitReceived(

RhinoDoc.LayerTableEvent += RhinoDoc_LayerChange; // reactivate the layer handler

// track the object type counts as an event before we try to receive
// this will tell us the composition of a commit the user is trying to convert and receive, even if it's not successfully converted or received
// we are capped at 255 properties for mixpanel events, so we need to check dict entries
var typeCountList = typeCountDict
.Select(o => new { TypeName = o.Key, Count = o.Value })
.OrderBy(pair => pair.Count)
.Reverse()
.Take(200);

Speckle.Core.Logging.Analytics.TrackEvent(
Speckle.Core.Logging.Analytics.Events.ConvertToNative,
new Dictionary<string, object>() { { "typeCount", typeCountList } }
);

// undo notes edit
var segments = Doc.Notes.Split(new[] { "%%%" }, StringSplitOptions.None).ToList();
Doc.Notes = segments[0];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ public override async Task<string> SendStream(StreamState state, ProgressViewMod
var commitLayers = new Dictionary<string, Layer>();
var commitCollections = new Dictionary<string, Collection>();

// track object types for mixpanel logging
Dictionary<string, int> typeCountDict = new();

// convert all commit objs
foreach (var selectedId in state.SelectedObjectIds)
{
Expand All @@ -63,6 +66,11 @@ public override async Task<string> SendStream(StreamState state, ProgressViewMod
var reportObj = new ApplicationObject(selectedId, "Unknown");
if (Utils.FindObjectBySelectedId(Doc, selectedId, out object obj, out string descriptor))
{
// log selection object type
var objectType = obj.GetType().ToString();
typeCountDict.TryGetValue(objectType, out var currentCount);
typeCountDict[objectType] = ++currentCount;

// create applicationObject
reportObj = new ApplicationObject(selectedId, descriptor);
converter.Report.Log(reportObj); // Log object so converter can access
Expand Down Expand Up @@ -228,10 +236,25 @@ void AddParent(Layer childLayer)
throw new SpeckleException("Zero objects converted successfully. Send stopped.");
}

// track the object type counts as an event before we try to send
// this will tell us the composition of a commit the user is trying to convert and send, even if it's not successfully converted or sent
// we are capped at 255 properties for mixpanel events, so we need to check dict entries
var typeCountList = typeCountDict
.Select(o => new { TypeName = o.Key, Count = o.Value })
.OrderBy(pair => pair.Count)
.Reverse()
.Take(200);

Speckle.Core.Logging.Analytics.TrackEvent(
Speckle.Core.Logging.Analytics.Events.ConvertToSpeckle,
new Dictionary<string, object>() { { "typeCount", typeCountList } }
);

progress.CancellationToken.ThrowIfCancellationRequested();

progress.Max = objCount;

// send the commit
var transports = new List<ITransport> { new ServerTransport(client.Account, streamId) };

var objectId = await Operations.Send(
Expand Down Expand Up @@ -260,6 +283,7 @@ void AddParent(Layer childLayer)
}

var commitId = await ConnectorHelpers.CreateCommit(client, actualCommit, progress.CancellationToken);

return commitId;
}
}
12 changes: 11 additions & 1 deletion Core/Core/Logging/Analytics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,17 @@ public enum Events
/// <summary>
/// Event triggered by the Mapping Tool
/// </summary>
MappingsAction
MappingsAction,

/// <summary>
/// Event triggered when user selects object to convert to Speckle on Send
/// </summary>
ConvertToSpeckle,

/// <summary>
/// Event triggered when user selects object to convert to Native on Receive
/// </summary>
ConvertToNative
}

private const string MIXPANEL_TOKEN = "acd87c5a50b56df91a795e999812a3a4";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ public Base ConvertToSpeckle(object @object)
break;
case AcadDB.Polyline o:
@base = o.IsOnlyLines ? PolylineToSpeckle(o) : (Base)PolycurveToSpeckle(o);

break;
case AcadDB.Polyline3d o:
@base = PolylineToSpeckle(o);
Expand Down

0 comments on commit 118f6bb

Please sign in to comment.