In Python App Engine How Do I Uniquely Identify An Instance Of My App Running On The Dev SDK?

StackOverflow https://stackoverflow.com/questions/7195930

  •  12-01-2021
  •  | 
  •  

Question

My application relies on an external service that it communicates with using urlfetch. I have multiple developers each running their own instance of my application on their development computers while they add features. Each developer instance needs to be able to uniquely identify itself to the external service so that the external service can keep their data separated.

I need a way to automatically generate a unique identifier for each developer from within the application.

Yes, I could just have each developer put a unique id in a variable in their code but I would much prefer it was automatic.

Also, I could probably read some information about the hardware on the computer (like MAC address) and use that but I want this code to use only things that work on the production server so that I can use it there eventually as well.

Was it helpful?

Solution

The only trick I've seen to identify instances is using a global variable address.

UNIQUE_INSTANCE_ID = {} # at module level
logging.debug("Instance %s." % (str("%X" % id( UNIQUE_INSTANCE_ID )).zfill(16)))

That seems to work fairly well to uniquely identify an instance; but it only identifies an instance, not a machine. So if you restart your instance, you get a new identifier. That might be a "feature".

You could also use some of the META variables; if developers are all running out of a home directory, you could parse a username out of 'PATH_TRANSLATED'.

At the very least, you could make injecting a UUID into the datastore part of the data population; store a metadata kind in the datastore and the cache, and wrap that UUID into the requests.

from uuid import uuid4
from google.appengine.ext import db
from google.appengine.api import memcache

cache = memcache.Client()

class InstanceStamp(db.Model):
    code = db.StringProperty()

    INSTANCE_STAMP_KEY = "instance_stamp"

    @classmethod
    def get_stamp(cls):
        cache_key = cls.INSTANCE_STAMP_KEY 
        stamp_code = cache.get(cache_key)
        if stamp_code is None:
            code = uuid4().hex
            stamp = cls.get_or_insert('instance_stamp', code=code)
            if stamp is not None:
                cache.set(cache_key, stamp.code, 300)
                stamp_code = stamp.code
        return stamp_code

OTHER TIPS

The string version of each db.Key instance has the same prefix and that prefix appears to be unique per developer instance. Even though they all have the same application id the encoded version of a key is different per machine.

For instance the string key for Foo:1 on one machine is:

ahNkZXZ-bWVkaWFjb29sZXItYXBwcgkLEgNGb28YAQw

On another machine it is:

ahFzfm1lZGlhY29vbGVyLWFwcHIJCxIDRm9vGAEM

I am not sure how many characters (bits?) of the key represents the application name instead of the type and id of the object so I don't think just using a sub-string containing the first N characters is the correct way to do this.

First attempt:

def get_unique_id():
    return str(db.Key.from_path('UNIQUE_INSTANCE_ID', 1))

What it does is create a bogus db.Key for a model type that does not exist. On different machines this gives a different value and on the same machine this consistently gives the same value.

UPDATE:

As @Nick Johnson pointed out this does not actually work as I expected and does not solve the problem. I had assumed it was the appid in app.yaml used in the key, however the appid used for keys is the appid from app.yaml with a prefix depending on whether the application is being run in the SDK or on the HR datastore so the string representation of those keys is different because the appid in them is different.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top