You could try and get the GUID from the user’s Autodesk ID but that is quite difficult to parse across versions (you can do this with a Dynamo view extension), though this can be traced back to a user so it will look anonymous but only as much as a fingerprint is since you’ll be able to compare that GUID to a set of user GUIDs. Alternatively you try getting the worksharing ID from their Revit session (first part of a Revit element unique ID). The ‘trace’ to an individual user here pretty much impossible unless you collect every fingerprint from every worksharing session and tie that it a user… so any idea around ‘not having user identifiable information in a single database’ moot.
The double \ is because Dynamo has to escape the single \ when saving the code into the JSON format. Otherwise a string like this:
documents\revit
would be deserialized as this:
documents
evit
This is because \r is the string value to indicate a new line. After you save the Python and Dynamo graph with the single \ and open it back up in a text editor you’ll see they are doubled. Tabs also become \t, new lines become \r\n, and quotes become \”.
Just from the log file, it’s just for me to know how often (if at all) a script is used. Not about who uses it. That way I can optimize the amount of time I put into developping the pyRevit hosted toolbar
Gotcha. Often the next step is ‘finding groups who are not using the tools’, at which point you’ll want some manor of finger print back.
doc.Title might work, but I am not certain of that returns the username or not. If so the solution above from @Garbage_Collector would be the way I would go.
Because I am only one developping the toolbar and utilizing Dynamo to increase workflow efficiency but I don’t know if the amount of care and hours I put into it is even worth it if no activates any toolbar buttons
great then i think you should teach your team whatever you development ;), so its not only you there do it…and guess both you boss and your team get hooked good luck
Agreed!
Also prevents an enormous waste of time developing stuff nobody really needs I try to always discuss with a few coworkers what i plan to do to prevent myself from building a graph that only i use sporadically.
I did the same with my company/users, was very handy. For reference I’m happy to share my logger code (but I ran it from pyRevit scripts).
import os
import datetime
from pyrevit import revit
# Constants
PATH_LOGS = **your directory name to save to**
try:
REVIT_DOC = revit.doc
except:
REVIT_DOC = None
# Function to write logs
def log_write(script_name, myDoc = REVIT_DOC):
# Check if the user can see logging path
if os.path.exists(PATH_LOGS):
# Try to get doc title, if none it's no doc
if myDoc:
doc_title = myDoc.Title
else:
doc_title = 'zeroDoc'
# Try to get user and timestamps
date = datetime.datetime.today().strftime("%d/%m/%y")
time = datetime.datetime.today().strftime("%H:%M:%S")
user = os.environ.get("USERNAME")
# Try to identify journal path and row
path_log = PATH_LOGS + "pyRevitLog_" + user + ".csv"
data_log = '{},{},{},{}.py,{}.rvt\n'.format(date, time, user, script_name, doc_title)
# Try to write the next row to the logging file
try:
with open(path_log, "a") as f:
f.writelines(data_log)
return True
except:
# If not, return false
return False
# If not, return false
else:
return False
It’s more you can lead a horse to water… Over the past 2 years I’ve pointed out we have a fresh water pool oasis, where earlier this year with the pyRevit hosted toolbar, I’ve put a bottling station into even. Yet I don’t think anyone pressed the toolbar buttons like ever…
As far as I can tell it works a bit differently. Yours actually makes seperate csv for every user, correct?
doc_title = myDoc.Title is an import from pyRevit? Does that entail the local file or the central model file?
Overall the script doesn’t work. I tried running it and no .csv was created
Yes it is safer to separate journals and consolidate them later I think, and lends itself to different options in future such as collecting local journals at end of day to avoid dependence on servers etc. Better to have one journal not read properly than the entire text dump.
doc.Title should work for any variable that is a document, it uses this property. The script is built for pyRevit specifically, not Dynamo, but might lead to learning opportunities. Some of my tools can run without a model open so I check for this and set the title field to zeroDoc if not.
Do you also log ‘amount of time saved’ anywhere?
Or do you base that off of the script name in your log data?
Can imagine it’s very useful to see just how much time a script has saved per week/month/ever compared to doing things manually
I feel like just communicating with your coworkers would solve this, wouldn’t it?
I try to involve my coworkers with the things I build, and also build things on demand.
Besides that i tend to write small ‘news letters’ so to speak to inform my coworkers on new scripts. Most of the time the time saving speaks for itself and it gets used simply because its less of a hassle than doing repetitive tasks for half an hour straight.
Time saved is a difficult metric to determine, sometimes it’s a simple number and other times it depends on the scale of the task. E.g. if I make 1000 sheets vs 5 I will save a very different amount of time. My main measurement here was engagement vs time saved, but one could build in an extra input to the function that is calculated based on a list size/factor potentially.
Try communicating with 450 Revit users across 7 states in 3 time zones. Not everyone engages with social mediums distributed I’ve found, it can help to see the quieter users engaging with tools vs just assuming everyone is interested in talking to the creator. Data also talks more strongly than simple trust in larger orgs.
Yeah true. I’ve made a logger in Dynamo based on one of your videos where i simply count the amount of results at the end and multiply that by the time saved per item. Not completely accurate as ‘time saved’ doesn’t scale linearly like that in my opinion but its good enough
Try communicating with 450 Revit users across 7 states in 3 time zones. Not everyone engages with social mediums distributed I’ve found, it can help to see the quieter users engaging with tools vs just assuming everyone is interested in talking to the creator. Data also talks more strongly than simple trust in larger orgs.
It appears you have discovered I work at a smaller org haha. I can definitely imagine it wouldn’t work for a large organisation, especially on the scale you’ve mentioned. Here i am at an org with about 20 revit users… But even then, collecting usage data is never a bad thing and does give a lot of insight.
At smaller scale discussion/user group is definitely the right approach. Even just having 1 or 2 people on board out of 20 is a great achievement in my experience (the firm I worked at before this one had 15 Revit users, huge change!).
I have been, I’m quite proactive and communicative about it. This pyRevit hosted toolbar was a Eureka moment for me for sure.
However my colleagues are really set in their ways and don’t embrace change at all. I mean I can barely get them to start using DiRoots Prosheets instead of Docuflow
This has led me to create this logger so I have actual statistical proof and I can just manage the toolbar buttons for myself and update the toolbar to only contain the buttons that are actually used
But I think we are getting waaay off topic here.
I still need a method to extract the document name so I can make it anonymous. I’m doing this to learn about python as well. Which lines can I replace with what to get this?
current python code
import clr
import os
# Add references to Revit and Dynamo libraries
clr.AddReference('RevitServices')
from RevitServices.Persistence import DocumentManager
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *
clr.AddReference('DynamoRevitDS')
import Dynamo
clr.AddReference('DSCoreNodes')
import DSCore
from System.IO import Path
# Define the path to the text file within the script
tekstbestandpath = r"K:\S+K\Computer\01-Bibliotheek\Revit\0-Toolbar S+K\S+K.extension\gebruik stats.txt"
# Ensure the directory exists
os.makedirs(os.path.dirname(tekstbestandpath), exist_ok=True)
def remove_username_suffix(filename):
# Separate the base filename and the extension
base, ext = os.path.splitext(filename)
# Split the base filename by underscores
parts = base.split('_')
# Check if the last part is a valid username (assuming usernames are alphabetical)
if parts and parts[-1].isalpha():
# Remove the last part and join the remaining parts
base = '_'.join(parts[:-1])
# Recombine the cleaned base filename with the extension
return base + ext
try:
# Get the Dynamo workspace name
dynamoRevit = Dynamo.Applications.DynamoRevit()
currentWorkspace = dynamoRevit.RevitDynamoModel.CurrentWorkspace
dynamoname = currentWorkspace.Name
# Get the current Revit document
doc = DocumentManager.Instance.CurrentDBDocument
# Get the Revit user's name
username = doc.Application.Username
# Get the central model file path
if doc.IsWorkshared:
central_model_path = doc.GetWorksharingCentralModelPath()
filename = Path.GetFileName(central_model_path) if central_model_path else "Untitled"
else:
filename = Path.GetFileName(doc.PathName) if doc.PathName else "Untitled"
# Remove the username suffix from the filename
filename = remove_username_suffix(filename)
# Get the current date and time
current_datetime = DSCore.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")
# Create the log entry if the username is not "Thijs.vE"
if username != "Thijs.vE":
log_entry = f"{current_datetime} - {dynamoname}\n"
print(f"Log Entry: {log_entry}") # Print log entry for debugging
# Append the log entry to the text file
with open(tekstbestandpath, 'a') as file:
file.write(log_entry)
except Exception as e:
print(f"An error occurred: {e}")
import clr
clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
# Get the active Revit document
document = DocumentManager.Instance.CurrentDBDocument
document_name = document.Title.replace(document.Application.Username, "")