Is you closely observe the Exception methods here especially for DMLException, you will see that there is no method that would return the name of Object.
Now in your case, one option could have been using the method - getDmlId(). This will return ID of the failed record. But since your code has 2 Insert DMLs i.e. account and Contact, its impossible to differentiate between them using this method as getDMLid() will always be NULL.
Next method you can explore is getDmlFieldNames() which will return the list of field, so in this case you will have to apply logic to detect on which object the fields with error are present. So again this is not much maintainable. So I would suggest applying atleast 2 try catch block on for one. Split Account/Opportunity and Contact and also introduce a boolean (if required) that will ensure contact DML will happen only if Account/Oppty is Successful like below -
boolean insertContactFlag = false;
Savepoint sp = Database.setSavepoint();
try {
insertContactFlag = true;
Account[] accts = someList;
Opportunity[] opps = yetAnotherList;
Database.insert(accts);
Database.update(opps);
} catch(Exception e){
insertContactFlag = false;
if(e.getTypeName() == 'DmlException'){
//if getDMLId() is not Null,its Opportunity ELSE its Account
//log an error based on the dml message
} else {
//log a general error
}
Database.rollback(sp);
}
if(insertContactFlag){
try {
Contact[] conts = someOtherList;
Database.insert(conts);
} catch(Exception e){
insertContactFlag = false;
if(e.getTypeName() == 'DmlException'){
//log an error based on the dml message [Contact]
} else {
//log a general error
}
Database.rollback(sp);
}
}