Create user credentials in Locust subclass and pass to TaskSet - locust

I want to provision a user's credentials when locust runs, then pass those credentials to the tasks.
The idea is to provision a user as each user (client) is spawned by locust, and then deprovision the users when locust is stopped.
The user could be provisioned/deprovisioned in a backend system, read from a file or database table, etc.
Is there a way to do this?

I found a way to do this.
In the TaskSet subclass, implement on_start and on_stop. Set instance variables (self.whatever) to the values provisioned for the "user" (for example, username and password).
Use the decorator method of defining tasks. This makes the methods part of the TaskSet subclass, so you can refer to the instance variables with the provisioned values.
For example,
class MyTaskSet(TaskSet):
def on_start(self):
self.username = <however you want to get it>
#task(1)
def MyTask(self):
<wherever you need it> = self.username

Related

How inject dependency in custom TelemetryInitializer?

We are using Autofac 4 for DI and I started experimenting with AI a short while ago. Now I created a IdentityTelemetryInitializer class which needs and IIdentityProvider to be able to get the ID of the current authorized user and set it add it to the context. I cannot find a way in which to inject dependencies into a TelemetryInitializer. If I define a contructor that takes an IIdentityProvider, the custom initializer is skipped altogether.
Any ideas are welcome. I was thinking of having the user ID also set as the Thread Principal so that we can access it this way, but I was hoping I could use DI for this?
You cannot inject dependencies using a constructor as the initializer initialized internally using the default (empty) constructor. When you explicitly defined a new ctor you've actually 'removed' the default one, thus the initializer was skipped altogether, as you've mentioned.
Therefore, the only way is to resolve the dependencies during the 'Initialize' method, after registering them on application startup.
ctx.RegisterType<MyService>().As<IService>().AsSelf(); // on application startup
ctx.Resolve<IService>(); // during initializer 'Initialize' method
You might look at the question I asked here
How to have "Request" events with authenticated user id ?
because I had managed to have the TelemetryInitializer working, passing user id via the HttpContext as suggested by #yonisha.
Off course it's not as lean as what you try to achieve.
The Telemetry Initializer is called each time you instanciate a Telemetry class, so really depending of how you manage them. Btw I am looking for good advice/best pratice on that : for the moment I have one private instance on each Controller that need to track something, but that does not smell good due to lifetime of Controller.

How to use singelton (object) in Scala with parameters?

I want to build a role functionality for my application. So, I thought object would come in handy because I need a Singelton of all different roles.
Therefore, I have the following code:
trait Role {
def id: UUID
def name: String
}
object Admin extends Role {
val id = UUID.randomUUID()
val name = "admin"
}
object Pro extends Role {
val id = UUID.randomUUID()
val name = "pro"
}
However, after I persisted these roles in my database and restarted the application, I noticed that the id of the roles changed, meaning it's not the same role as I persisted them when I started the application in the first place. So, I would need to set the id if a role with the same name has already been stored in the database and set it to the Singelton object. I thought that I could use parameters to initialize the Admin and Pro object, but apparently this does not work.
How can this be done?
First, it is difficult to discuss the problem by only seeing this code, without knowing how you try to do the database persistence part.
Following your code, the id is initialised by calling randomUUID, so surely you get a new one with each start. System works as designed.
Second, I am not sure if we would agree about what a singleton is and what is the semantic of the two 'objects'.
To me it looks as if you indeed would like to have two different instances of the type Role, instead of one singleton type Admin and one different singleton type Pro, because the two differ only in the attributed values, not in structure.
A singleton object is already an object, indeed the sole object of its type. So the notion of setting its values from outside during some sort of construction, like you would do with classes during instantiation, is not really applicable here.
Take a look at the below code:
object Admin extends Role {
val id = getPersistedIDFromDatabase(name).getOrElse {
pesistID(name, UUID.randomUUID())
}
val name = "admin"
}
// getThePersistedIDFromDatabase => executes the `select` SQL query and returns an Optional ID, i.e., Some(id) if the admin already exists; Otherwise None.
Whenever you restart your application, its memory is wiped out. So it has no way to know about your previous ID.

Is it wise to keep a MongoDB session open for the lifetime of an object?

I have a struct that abstracts MongoDB for specific objects in my system, and during the factory function for it I set a few variables like hostname and other connection information. At the moment in each of the UserService's methods* it creates a new session, does what it needs to, then closes the session when it's done.
The system itself is the backend of a web application, so the lifetime of each UserService struct is usually only a few seconds at most, but more than one operation might be performed for each request that comes in. So I'm wondering whether to make session a member of the struct, initialise it when I create my UserService, and then ensure the request handler function that creates it calls a close function once it's done all the operations it needs to. I haven't been able to find anything that encourages or discourages this behaviour so I'm not really sure if the mgo package I'm using is designed that way.
This is my proposed code:
type UserService struct {
callingUserId id.ID //The ID of the user calling this service.
host string //The host name.
session mgo.Session //The active session.
}
func NewUserService(userId id.ID) *UserService {
nus := new(UserService)
nus.callingUserId = userId
nus.host = "localhost" //TODO change this to read from file or buffer.
nus.session, sessionErr = mgo.Dial(nos.host)
if sessionErr != nil {
//TODO log error.
}
return nus
}
func (us UserService) GetById(usrId id.ID) *users.User {
//TODO get a user from the database with the matching ID using the existing session.
}
There will also be a function called UserService.CloseSession, which as I mentioned, will be called after all the required operations are done by the handler function that creates the service.
Does anyone know if this is a sensible idea or should I just call mgo.Dial in every function on UserService?
Opening a connection to MongoDB or any other DB is an expensive task that should be done once and kept operative as much as possible inside your service.
You have three options:
A local package level MongoDB instance.
Using Contexts and Composing Handlers.
A method receiver which holds the MongoDB Instance.
This is a very informative blog post for handling DBs connections.
Take a look to this example, especially for MongoDB

Facing issues with sqlalchemy+postgresql session management

I am using sqlalchemy with PostgreSQL and the Pyramid web framework. Here is my models.py:
engine = create_engine(db_url, pool_recycle=3600,
isolation_level="READ UNCOMMITTED")
Session = scoped_session(sessionmaker(bind=engine))
session = Session()
Base = declarative_base()
Base.metadata.bind = engine
class _BaseMixin(object):
def save(self):
session.add(self)
session.commit()
def delete(self):
session.delete(self)
session.commit()
I am inheriting both the Base and _BaseMixin for my models. For example:
class MyModel(Base, _BaseMixin):
__tablename__ = 'MY_MODELS'
id = Column(Integer, primary_key=True, autoincrement=True)
The reason is that I would like to do something like
m = MyModel()
m.save()
I am facing weird issues with session all the time. Sample error messages include
InvalidRequestError: This session is in 'prepared' state; no further SQL can be emitted within this transaction.
InvalidRequestError: A transaction is already begun. Use subtransactions=True to allow subtransactions.
All I want to do is to commit what I have in the memory into the DB. But intermittently SQLAlchemy throws errors like described above and fails to commit.
Is there something wrong with my approach?
tl;dr The problems is that you're sharing one Session object between threads. It fails, because Session object is not thread-safe itself.
What happens?
You create a Session object, which is bound to current thread (let's call it Thread-1). Then you closure it inside your _BaseMixin. Incoming requests are handled in the different threads (let's call them Thread-2 and Thread-3). When request is handling, you call model.save(), which uses Session object created in Thread-1 from Thread-2 or Thread-3. Multiple requests can run concurrently, which together with thread-unsafe Session object gives you totally indeterministic behaviour.
How to handle?
When using scoped_session(), each time you create new object with Session() it will be bound to current thread. Furthermore if there is a session bound to current thread it will return you existing session instead of creating new one.
So you can move session = Session() from the module level to your save() and delete() methods. It will ensure, that you are always using session from current thread.
class _BaseMixin(object):
def save(self):
session = Session()
session.add(self)
session.commit()
def delete(self):
session = Session()
session.delete(self)
session.commit()
But it looks like duplication and also doesn't make sense to create Session object (it will always return the same object inside current thread). So SA provides you ability to implicitly access session for current thread. It produces clearer code.
class _BaseMixin(object):
def save(self):
Session.add(self)
Session.commit()
def delete(self):
Session.delete(self)
Session.commit()
Please, also note that for normal applications you never want to create Session objects explicitly. But want to use implicit access to thread-local session by using Session.some_method().
Further reading
Contextual/Thread-local Sessions.
When do I construct a Session, when do I commit it, and when do I close it?.

Logging user activity in another logical layer without global HttpContext

I'm looking for a good solution to log DB changes in a web application developed using Play/Scala/ReactiveMongo. I need to know who changed what.
I have a separate layer namely Services in which all data access and business logics happens. All saves/updates/removes are done by certain methods so I can log them safely in just 3 or 4 methods but I need user identity there.
I don't have access to current user in services! There is no global HttpContext or Request or something like that which let me get the user identity (I think this way of getting user identity was incorrect of course).
I have a solution:
Add an implicit parameter to all methods of services which have side effects (change DB) and pass user identity to them.
def save(model: A)(implicit userIdentity: Option[UserIndentity] = None) = { ... }
As I wrapped default request, it can extend UserIdentity trait so that the implicit request matches the implicit parameters.
class MyRequest[A](...) extends WrappedRequest[A](request) extends UserIdentity
Finally, actions can use services like this:
def index() = MyAction { implicit request =>
//...
defaultService.save(model)
//...
}
The bad thing is that I have to add implicit parameters to those service methods. Isn't there another solution to get current user without polluting method signatures.
What's the problem with simply adding UserIdentity as an argument to your functions? Knowing who the user is seems to be important for your business logic - after all, today you want to log who performed the operation, tomorrow you will want to make sure this particular user is allowed to do it.
And I would just use a real UserIdentity object, not some hack with WrappedRequest, your services don't need to mess with a WrappedRequest instance.