We have several billing enabled projects in our GCP account and each of them has several Compute Engine Instances. I want to remove non-critical instances just to reduce the unnecessary billing. But before I do that, I need to know which instance is being used for what and for that I need to know which user created it in the first place.

How do I get to know the creator of each instance either by using Google Cloud Shell or Google Cloud Console?


Note: I'm not a GCE user yet, the answer is based solely on documentation.

You could be Viewing Audit Logs in the Google Cloud Console, more specifically the Admin Activity logs:

Admin Activity logs contain log entries for API calls or other administrative actions that modify the configuration or metadata of resources. For example, the logs record when VM instances and App Engine applications are created and when permissions are changed. To view the logs, you must have the IAM roles Logging/Logs Viewer or Project/Viewer.

You would be looking for the User identities in audit logs:

Audit logs record the identity of the user performing logged actions. The identity is held in the AuthenticationInfo field of AuditLog objects.

Ideally you'd be looking for the GCE instance creation events, but some/all of those may be too old for the logs retention policy. Then maybe search for VM instance start or other relevant events.

You could also check and maybe cross-reference the audit logs info with that from Usage Reports or exported billing info.

If this is a regular, on-going activity you may want to setup an automated log exporting and processing pipeline.


Not sure if you sorted this out, but I had to do something similar to get who started the instance so I can badger them into stopping the instance if they are not using it. I put together a Logging query:

resource.type = gce_instance AND (jsonPayload.event_subtype = compute.instances.start OR jsonPayload.event_subtype = compute.instances.insert ) AND jsonPayload.event_type = GCE_OPERATION_DONE AND timestamp >= "2018-10-29T14:28:34-07:00" AND jsonPayload.actor.user!="" AND jsonPayload.resource.name=my-sweet-instance-name

And here is the nodejs function I put together to get it:

const Logging   = require( '@google-cloud/logging' );
const moment    = require( 'moment' );

const logging   = new Logging( );

var getStartInfo = function( instanceName, querySince, cb ) {

    var tstart = ( querySince ? querySince : moment( ).subtract( 48, 'hours' ).format( ) ); // 

    var theLogFilter = 'resource.type = gce_instance AND ' +
        '(jsonPayload.event_subtype = compute.instances.start OR jsonPayload.event_subtype = compute.instances.insert ) AND ' +
        'jsonPayload.event_type = GCE_OPERATION_DONE AND ' +
        'timestamp >= "' + tstart + '" AND ' +
        'jsonPayload.actor.user!="" AND ' +
        'jsonPayload.resource.name=' + instanceName;

    logging.getEntries( {
        filter: theLogFilter,
        autoPaginate: false
    }, ( err, entries, nextQuery, apiResponse ) => {

        if ( err ) {
            console.log( "ERROR: " + err );
            cb( err );

        var item, startedBy, startTime, runningTime, mostRecentStart;

        //console.log( 'Entries: ' + JSON.stringify( entries ) );
        // Mabye if none found, we try again with a longer querySince?
        if ( entries.length == 0 ) {

            console.log( "\nNo log entries found for instance '" + instanceName + "'. Filter:" );
            console.log( theLogFilter );
            cb( "No entries found" );

        // Are these sorted by time?
        for ( var i = 0; i < entries.length; i++ ) {

            startedBy = entries[ i ].metadata.jsonPayload.fields.actor.structValue.fields.user.stringValue;
            startTime = entries[ i ].metadata.jsonPayload.fields.event_timestamp_us.stringValue / 1000; // This is nano seconds since epoch


        if ( cb )
            cb( null, { "startedBy": startedBy, "startTime": moment( startTime ).format() } );

    } );


Hopefully that helps someone because it was a good bit of work to put together.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.