Fair warning: Coming up with a scheme like this will require governance in order to keep the scheme useful.
I have been on a number of projects that use a similar scheme as what you're describing. It's very helpful for help desk, L2, and L3 when the scheme is enforced. One of the big advantages is HD can quickly tell to pass on certain messages and pass them up the chain because they indicate more severe problems than what they are trained for.
I would recommend breaking down first by area, then by severity.
Leave yourself LOTS of room between major areas as it's a real PITA, if not downright impossible, to move error numbers around after they are set. It's not a technical challenge, but more of a documentation and re-training challenge.
A simple scheme could be this:
- 1,000's belong to "base application messages"
- 2,000's belong to IO
- 3,000's belong to DB comms
- 9,000's belong to ugly abends that require immediate L3 investigation
where each of the blocks is a major area of your application. User Interface / DB hooks / Config mgmt / file IO / etc... are just a few examples of areas that could receive their own block of message numbers.
Within those groups:
0 - 250 are informational
251 - 500 are warning
501 - 750 are error
751 - 999 are debug / trace (assuming you don't have a separate facility for that)
If you can use a letter indicator at the end of the message, then you could skip this severity subgrouping. But not all event storage mechanisms allow for using a non-numeric character.
Another option would be to use the last digit of the message to indicate severity. In other words, error numbers ending in 0,1,2 are Info, ... 8,9 are debug / sky-is-falling.
Obviously, cater the numbers and ranges based upon your needs, the above are just examples.
This is a similar, but different layout than HTTP error codes.
With the primary difference being that it is an application area driving the organization / assigning of error message numbers. HTTP codes don't really have application areas to break things down by.
I'm not a big fan of just using sequential numbers or using skip counting. First off, there is no logical structure to those schemes and merely gives a hint as to when the messages were created. Knowing that 0010 was created as an error message long before message 750 is pretty much meaningless information.
I would put in a vote for logical organization even within the info / warning / error categories, but that can become very difficult or cumbersome to maintain.