Managing your GIS servers

At version 1.2 the ArcGIS API for Python introduces a new server submodule under the gis.admin module that allows administrators to manage the ArcGIS servers powering their ArcGIS Enterprises. ArcGIS Enterprise includes several software components that are designed to work together. A basic ArcGIS Enterprise deployment can consist of the following:

Refer to ArcGIS Enterprise deployment patterns to learn more about different deployment patterns for ArcGIS Enterprise. No matter which pattern your deployment is, the server module can be used to access and manage it. The diagram below represents the main classes and methods available in the server module

To start with, import the Python API and connect to your GIS as an administrator.

Note: To make use of the server module, you need to connect it using an account with administrative privileges. The server module is only applicable if your GIS is an instance of ArcGIS Enterprise and would not work for ArcGIS Online.
from arcgis.gis import GIS
gis = GIS("", "username")
Enter password: ········

Accessing the servers behind your GIS

You can get the list of all servers hosted or federated to your Enterprise by calling the list() method from admin.servers object.

gis_servers = gis.admin.servers.list()
[<Server at>,
 <Server at>,
 <Server at>]
server1 = gis_servers[0]

Once you access your Server object, you can perform operations such as managing data stores, querying logs, accessing services, publishing new services etc. as explained in the rest of this guide

Validate your servers

You can quickly check if your servers are responding to your Enterprise by calling the validate() method. If you get back False, you may need to check one or more of your servers.


Managing the services on your server

Getting the list of services

One of the important tasks you can perform on a server is monitoring the services running on it and publishing new ones. You can list the services by calling list() method from the object. By default, you get the services running in root folder.
[<Service at>,
 <Service at>,
 <Service at>,
 <Service at>,
 <Service at>,
 <Service at>,
 <Service at>,
 <Service at>,
 <Service at>]

To get the services running in a different folder, specify its name as an argument. To get the list of folders on your server, call the folders property
['Hosted', 'System', 'Utilities', '/']

List the services running in System folder

hosted_services ='System')

#print the top 5 as a sample
[<Service at>,
 <Service at>,
 <Service at>,
 <Service at>]

Checking if a service exists

To check if a service exists on your server, call the exists() method and specify the folder name, service name and type. You can also use this method to verify if a folder exists on the server.

# check if a FeatureService called 'Ports' exists in Hosted folder'Hosted', name='Ports', service_type='FeatureServer')

Managing service folders

You can add or remove folders on your server by calling create_folder(), delete_folder().

Note: These folders are different from folders found on user's 'my contents'. To access those folders see ConentManager.create_folder and User.folders'crime_analysis')

You can delete this folder by calling delete_folder()'crime_analysis')

Administering services

If you noticed earlier, calling services.list() returns you a list of Service objects. Using a Service object, you can start, stop, delete, edit, rename and query the properties of a service.

# access the 'SampleWorldCities' service running on root folder
service1 =[-1]

Query the properties property to get details on the service
  "serviceName": "SampleWorldCities",
  "type": "MapServer",
  "description": "The SampleWorldCities service is provided so you can quickly and easily preview the functionality of the GIS server. Click the thumbnail image to open in a web application. This sample service is optional and can be deleted.",
  "capabilities": "Map,Query,Data",
  "provider": "ArcObjects",
  "clusterName": "default",
  "minInstancesPerNode": 1,
  "maxInstancesPerNode": 1,
  "instancesPerContainer": 1,
  "maxWaitTime": 60,
  "maxStartupTime": 300,
  "maxIdleTime": 180,
  "maxUsageTime": 600,
  "loadBalancing": "ROUND_ROBIN",
  "isolationLevel": "HIGH",
  "configuredState": "STARTED",
  "recycleInterval": 24,
  "recycleStartTime": "00:00",
  "keepAliveInterval": -1,
  "private": false,
  "isDefault": false,
  "maxUploadFileSize": 0,
  "allowedUploadFileTypes": "",
  "properties": {
    "useLocalCacheDir": "true",
    "outputDir": "/gisdata/arcgisserver/directories/arcgisoutput",
    "cacheDir": "/gisdata/arcgisserver/directories/arcgiscache",
    "maxScale": "4000",
    "maxRecordCount": "1000",
    "filePath": "${AGSSERVER}/framework/etc/data/WorldCities/",
    "supportedImageReturnTypes": "MIME+URL",
    "clientCachingAllowed": "true",
    "isCached": "false",
    "virtualOutputDir": "/rest/directories/arcgisoutput",
    "maxExportTilesCount": "100000",
    "ignoreCache": "false",
    "exportTilesAllowed": "false",
    "cacheOnDemand": "false",
    "minScale": "295000000"
  "portalProperties": {
    "isHosted": false,
    "portalItems": [
        "type": "MapServer",
        "itemID": "0102400090a144259679b6cde45b82b1"
        "type": "WMSServer",
        "itemID": "63250a9efb94447c80c9ca0ad578a4c5"
  "extensions": [
      "typeName": "WMSServer",
      "capabilities": "GetCapabilities,GetFeatureInfo,GetLegendGraphic,GetMap,GetSchemaExtension,GetStyles",
      "enabled": "true",
      "maxUploadFileSize": 0,
      "allowedUploadFileTypes": "",
      "properties": {
        "name": "SampleWorldCities",
        "title": "WMS"
      "typeName": "KmlServer",
      "capabilities": "SingleImage,SeparateImages,Vectors",
      "enabled": "false",
      "maxUploadFileSize": 0,
      "allowedUploadFileTypes": "",
      "properties": {
        "compatibilityMode": "GoogleEarth",
        "useDefaultSnippets": "true",
        "featureLimit": "1000000",
        "minRefreshPeriod": "30",
        "imageSize": "1024",
        "dpi": "96"
      "typeName": "FeatureServer",
      "capabilities": "Create,Query,Update,Delete,Uploads",
      "enabled": "false",
      "maxUploadFileSize": 0,
      "allowedUploadFileTypes": "",
      "properties": {}
  "frameworkProperties": {},
  "datasets": []

You can also query fine-grained information such as the capabilities enabled on the service

You can get the id of one or more Items corresponding to this service on the Enterprise as shown below:
   "type": "MapServer",
   "itemID": "0102400090a144259679b6cde45b82b1"
 }, {
   "type": "WMSServer",
   "itemID": "63250a9efb94447c80c9ca0ad578a4c5"

Getting status on a service

Calling the status property returns a dictionary with the real time state of the service.

{'configuredState': 'STARTED', 'realTimeState': 'STARTED'}

Starting and stopping a service

Call the start() and stop() methods to start and stop a service.

#call the status to confirm
{'configuredState': 'STOPPED', 'realTimeState': 'STOPPED'}
#start the service and confirm
{'configuredState': 'STARTED', 'realTimeState': 'STARTED'}

Publishing new services

You can publish new services to your server by calling publish_sd() method from object.

Note: You need a service definition file to publish a service. You can create SD files using ArcGIS Desktop and Pro. To automate the creation of SD files from your map or project files, refer to ArcPy documentation'/Users/atma6951/Documents/GIS_data/',
{'name': 'System/CachingControllers', 'type': 'GPServer'}
{'name': 'System/CachingToolsEx', 'type': 'GPServer'}
{'name': 'System/CachingTools', 'type': 'GPServer'}
{'name': 'System/DynamicMappingHost', 'type': 'MapServer'}
{'name': 'System/PublishingToolsEx', 'type': 'GPServer'}
{'name': 'System/PublishingTools', 'type': 'GPServer'}
WARNING 086222: Output directory in service definition is not set or is invalid. Using default output directory.
WARNING 086224: Cache directory in service definition is not set or is invalid. Using default cache directory.

Publishing a service to the server will create an item on the Enterprise. In this case, the service was called 'AGSMS_SD', hence the name of the item.

new_item ='owner:atma.mani', item_type = 'Map Service')[0]
Map Image Layer by atma.mani
Last Modified: August 08, 2017
0 comments, 0 views

Renaming a service

As ArcGIS administrators, you must be familiar that the name of the service forms its URL. You can rename a service, however, this operation should be used carefully since it would break all the layers and maps that refer to this service by its URL

# search for the service
new_service =[0]

Give this service a descriptive name. Service names cannot contain spaces or special characters.


Renaming will create a new item on the Enterprise corresponding to the new URL'owner:atma.mani', 'Map Service')
[<Item title:"AGSMS_SD" type:Map Image Layer owner:atma.mani>,
 <Item title:"SanDiego_boundary" type:Map Image Layer owner:atma.mani>]

The first Item is now stale and should be deleted by you. The second Item corresponds to the renamed service. You can access and print its url property to verify:

renamed_item ='owner:atma.mani', 'Map Service')[1]

Thus, you can rename services, or change their URLs using the Python API. You cannot however, use rename() to move a service from one folder into another folder on the server after it is published.

Deleting a service

To delete a service, simply call the delete() method on the Service object.

#Delete the San Diego service. Since it was renamed, you need to search for it
service_list =
[<Service at>,
 <Service at>,
 <Service at>,
 <Service at>,
 <Service at>,
 <Service at>]

Managing server data stores

ArcGIS Data Store is an application that lets you easily configure data storage for hosting and federated servers used with your Enterprise. ArcGIS Data Store provides you with a convenient setup and configuration experience that creates the following different types of data stores.

  • Relational data store -- Stores your portal's hosted feature layer data, including hosted feature layers created as output from spatial analysis tools run in the portal
  • Tile cache data store -- Stores caches for your portal's hosted scene layers
  • Spatiotemporal big data store -— Archives real-time observational data that you can use with an ArcGIS Server running ArcGIS GeoEvent Server that is federated with your portal; also stores the results generated using ArcGIS GeoAnalytics Server tools.

Using the Server.datastores object, you can list, add, remove datastore items as shown below:

Listing the data stores registered with the server

Calling the datastores.list() method returns you a list of Datastore objects.

dstores = server1.datastores.list()
dstore1 = dstores[0]

Print the path for each of these Datastore objects.

for dstore in dstores:

Registering new data stores with the server

You can add or register new data stores with your server by calling the corresponding add method such as add_folder(), add_database(), add_big_data(). To know what types of data stores are supported by your server, query the data_items property:

{'rootItems': ['/bigDataFileShares',

Add a folder data store

ca_datastore = server1.datastores.add_folder(name='CA_earthquakes', 
<Datastore title:"" type:"folder">

The add_folder() method returns you a Datastore object. This object can be used to inspect, modify or delete / unregister that data store entry. You can inspect the properties of the data store by querying the properties property.
  "path": "/fileShares/CA_earthquakes",
  "type": "folder",
  "id": "53c50994-9b2b-4cf2-bcfd-a59651cea8ed",
  "info": {
    "path": "\\teton\u0007tma_shared\\datasets\\californiapoints",
    "dataStoreConnectionType": "shared"

Validating data stores

You can validate the data store registered with your server to ensure your server can continue to access them.


You can validate all the data stores by calling the validate() method from the Server.datastores object


Removing data store entries

To remove a data store, simply call the delete() method from the corresponding Datastore object:


Querying server logs

ArcGIS Server records events that occur, and any errors associated with those events, to logs. Logs are an important tool for monitoring and troubleshooting problems with your site. Information in the logs will help you identify errors and provide context on how to address problems. Refer about server logs to learn more about your ArcGIS Server logs, setting different logging levels etc.

You can access a server's logs using the logs property of the Server object.

{'logDir': 'C:\\arcgisserver/logs\\',
 'logLevel': 'WARNING',
 'maxErrorReportsCount': 10,
 'maxLogFileAge': 90,
 'statisticsConfig': {'enabled': True,
  'maxHistory': 0,
  'samplingInterval': 30,
  'statisticsDir': 'C:\\arcgisserver\\directories\\arcgissystem'},
 'usageMeteringEnabled': False}

Filtering and querying server logs

Using the query() method, you can filter and search for server logs. Refer to the query API ref doc for all the arguments supported. In the example below, logs for the previous 10 days is searched.

import datetime
import pandas as pd
now =
start_time = now - datetime.timedelta(days=10)
datetime.datetime(2017, 7, 30, 15, 29, 4, 144692)

You can pass a Python Datetime object to the time arguments.

recent_logs = server1.logs.query(start_time = start_time)

#print a message as a sample
{'code': 6602,
 'elapsed': '',
 'machine': 'DEV005223.ESRI.COM',
 'message': "Failed to return the service configuration 'Utilities/PrintingTools.GPServer'. Server machine 'https://DEV005223.ESRI.COM:7443/arcgis/sharing/rest/content/items/430b49a241bd418aaf476d7e5a64fdb9' returned an error. 'Item does not exist or is inaccessible.'",
 'methodName': '',
 'process': '5660',
 'source': 'Admin',
 'thread': '14',
 'time': 1499634940286,
 'type': 'SEVERE',
 'user': ''}

You can construct a Pandas DataFrame from the query result and visualize the logs as a table:

log_df = pd.DataFrame.from_records(recent_logs)
log_df.head(5) #display the first 5 records
01497908616688False{'type': 'SEVERE', 'message': 'Failed to retur...1499634940286
11497908616688False{'type': 'SEVERE', 'message': 'Unable to conne...1499634940286
21497908616688False{'type': 'SEVERE', 'message': 'Unable to conne...1499634940286
31497908616688False{'type': 'SEVERE', 'message': 'Unable to conne...1499634940286
41497908616688False{'type': 'SEVERE', 'message': 'Unable to conne...1499634940286

You can quickly check for errors reports as shown below:

{'machineName': 'DEV005223.ESRI.COM', 'reportCount': 0}

Monitoring server usage

ArcGIS Server records various service statistics, such as total requests, average response time and timeouts. Administrators and publishers can use this information to monitor service activity to better understand how clients are using services. For example, monitoring server statistics help you answer questions such as:

  • What is the total number of requests that my ArcGIS Server site handled during the past week?
  • How was the service request load distributed during the past month?
  • How are my services performing on an hourly basis?
  • What was the maximum number of service instances used at any given time for a particular service?

To learn more about this, refer to about server statistics help page. To access this information, use the Server.usage property:

{'enabled': True,
 'maxHistory': 0,
 'samplingInterval': 30,
 'statisticsDir': 'C:\\arcgisserver\\directories\\arcgissystem'}

Using built-in reports

By default, when you install ArcGIS Server, you get three pre-configured reports. These reports are based on services that are already running on your server. You can access these and any new reports you create by querying the list() method.

usage_reports = server1.usage.list()
[<arcgis.gis.server.Report at 0x110a3f860>,
 <arcgis.gis.server.Report at 0x110a3f908>,
 <arcgis.gis.server.Report at 0x110a3f470>]

You get back a list of Report objects. Print the names of the reports:

for r in usage_reports:
Max response times for the last 7 days
Timed-out requests for the last 7 days
Total requests for the last 7 days

Querying maximum reponse times for the last 7 days

max_resp_report = usage_reports[0]

#Run the query
data = max_resp_report.query()

#display the keys in the report query response
dict_keys(['reportname', 'metadata', 'time-slices', 'report-data'])

Plot the response time in a bar chart

from datetime import datetime
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
%matplotlib inline
#store reponse times in Y axis
data_y = data['report']['report-data'][0][0]['data']

#convert dates to readable dates and store in X axis
data_x = [pd.to_datetime(datetime.fromtimestamp(d//1000)) \
          for d in data['report']['time-slices']]

df = pd.DataFrame(list(zip(data_x, data_y)), columns=["date", "count"])
q = df['count'].isnull() # change NaN values to 0
df.loc[q, 'count'] = 0
df.index = df['date']
df['count'] = df['count'] 

ax = df['count'].plot(kind='bar', x=df['date'])
ticklabels = ['']*len(df.index)
ticklabels[::4] = [item.strftime('%b %d') for item in df.index[::4]]
ax.set_title('Maximum reponse time in the last 7 days')
ax.set_ylabel('Time in seconds')
<matplotlib.figure.Figure at 0x113bd6748>

Creating Quick Reports

Quick reports are useful for administrators who want to get a one-shot set of data. This information is generated on the fly on ArcGIS Server, and allows for report generation for services or server information that may not be monitored all the time.

Note: On the fly reports that are deleted right after data is returned

The quick report supports various time spans:

  • LAST_DAY - 24 hours from your current time
  • LAST_WEEK - 7 days from your current date
  • LAST_MONTH - 31 days from your current date
  • LAST_YEAR - 365 days from your current date

Reporting Queries are made by specifying the resource you want to monitor. For example, administrators who want to monitor a specific folder, HOSTED, would set the query to: services/Hosted. The default is to monitor all services.

Quick report metrics are:

  • RequestCount - the number of requests received
  • RequestsFailed - the number of requests that failed
  • RequestsTimedOut - the number of requests that timed out
  • RequestMaxResponseTime - the maximum response time
  • RequestAvgResponseTime - the average response time
  • ServiceActiveInstances - the maximum number of active (running) service instances sampled at 1 minute intervals, for a specified service

Get the total number of requests in the last 1 year

data = server1.usage.quick_report(since="LAST_MONTH", metrics="RequestCount")
dict_keys(['reportname', 'metadata', 'time-slices', 'report-data'])

Plot the results in a bar chart

#store reponse times in Y axis
data_y = data['report']['report-data'][0][0]['data']

#convert dates to readable dates and store in X axis
data_x = [pd.to_datetime(datetime.fromtimestamp(d//1000)) \
          for d in data['report']['time-slices']]

#create a Pandas DataFrame from the report
df = pd.DataFrame(list(zip(data_x, data_y)), columns=["date", "count"])
q = df['count'].isnull() # change NaN values to 0
df.loc[q, 'count'] = 0
df.index = df['date']
df['count'] = df['count'] 

#plot as a bar chart
ax = df.plot(kind='bar', x=df['date'])
ticklabels = ['']*len(df.index)
ticklabels[::4] = [item.strftime('%b %d') for item in df.index[::4]]
<matplotlib.figure.Figure at 0x1134610b8>

Accessing the machines powering your servers

You can access the machines powering your GIS servers using the Server.machines property. By calling the list() method, you get back a list of Machine objects:

machine_list = server1.machines.list()
[<Machine at>]

Access the properties of a machine using properties.

m1 = machine_list[0]
  "machineName": "DEV005223.ESRI.COM",
  "platform": "Windows Server 2012 R2-amd64-6.3",
  "ports": {
    "OpenEJBPort": 4000,
    "JMXPort": 4001,
    "NamingPort": 4002,
    "DerbyPort": 4003,
    "tcpClusterPort": 4004,
    "HTTP": 6080,
    "webSocketsPort": 6180,
    "HTTPS": 6443
  "ServerStartTime": 1498283009444,
  "webServerMaxHeapSize": -1,
  "appServerMaxHeapSize": 256,
  "socMaxHeapSize": 64,
  "webServerSSLEnabled": true,
  "webServerCertificateAlias": "SelfSignedCertificate",
  "adminURL": "",
  "configuredState": "STARTED",
  "synchronize": false

Use the status property to verify the state of your machine.

{'configuredState': 'STARTED', 'realTimeState': 'STARTED'}

Get the list of SSL certificates:

{'certificates': ['selfsignedcertificate']}

Download existing certificates or import new ones to your server using the appropriate methods:


Monitoring your server licenses and system settings

Accessing system directories

Calling the directories property of Server.system returns you back a list of Directory objects.

all_dir = server1.system.directories().all()
<ServerDirectory at>

Print the name and path on disk for each of these server directories:

for fld in all_dir:
    print( + " : " +
arcgisjobs : /gisdata/arcgisserver/directories/arcgisjobs
arcgisjobregistry : /gisdata/arcgisserver/directories/arcgissystem/arcgisjobregistry
arcgisuploads : /gisdata/arcgisserver/directories/arcgissystem/arcgisuploads
arcgiscache : /gisdata/arcgisserver/directories/arcgiscache
arcgisinput : /gisdata/arcgisserver/directories/arcgissystem/arcgisinput
arcgisoutput : /gisdata/arcgisserver/directories/arcgisoutput
arcgisindex : /gisdata/arcgisserver/directories/arcgissystem/arcgisindex
kml : /gisdata/arcgisserver/directories/arcgissystem/kml
arcgissystem : /gisdata/arcgisserver/directories/arcgissystem

By calling the clean() and edit() methods on a Directory object, you can clean the contents or designate a different directory path for the server.

Monitoring server licenses and extensions

Use the licenses property of Server.system object to get a dictionary of various licenses and extensions available on the server.

dict_keys(['edition', 'level', 'datafeature', 'extensions', 'features'])

Find the license level of the current server:

{'canExpire': True,
 'expiration': 1508223600000,
 'featureName': 'esriServerLicenseAdvanced',
 'name': 'svradvanced',
 'version': '10.5'}

Print all the extensions and their expiration:

from datetime import datetime

for extn in server1.system.licenses['features']:
    #convert expiration to a readable format
    d = datetime.fromtimestamp(int(extn['expiration']/1000))
    print("{:50s} {}".format(extn['displayName'], d.isoformat()))
ArcGIS Server Advanced Core                        2017-10-17T00:00:00
SDE Enterprise Core                                2017-10-17T00:00:00
ArcGIS Aviation: Airports for Server               2017-10-17T00:00:00
Workflow Manager Extension for ArcGIS Server       2017-10-17T00:00:00
ArcGIS Aviation: Charting for Server               2017-10-17T00:00:00
Business Analyst Extension for ArcGIS Server       2017-10-17T00:00:00
ArcGIS for INSPIRE                                 2017-10-17T00:00:00
ArcGIS Maritime: Charting for Server               2017-10-17T00:00:00
Location Referencing for Server                    2017-10-17T00:00:00
ArcGIS Data Reviewer Server                        2017-10-17T00:00:00
Esri Roads and Highways for ArcGIS Server          2017-10-17T00:00:00
ArcGIS Maritime: Bathymetry for Server             2017-10-17T00:00:00
Esri Defense Mapping for Server                    2017-10-17T00:00:00
ArcGIS Server Enterprise                           2017-10-17T00:00:00
Esri Production Mapping for Server                 2017-10-17T00:00:00
Data Interoperability Extension for ArcGIS Server  2017-10-17T00:00:00
Network Analyst Extension for ArcGIS Server        2017-10-17T00:00:00
Roadway Reporter for Esri Roads and Highways       2017-10-17T00:00:00

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.