Search code examples
javagoogle-app-engineloggingstackdriver

Google App Engine. Stackdriver. Logging with Java


I want to POST Logs to "Custom Logs" of Stackdriver. These feature is beta, and maybe therefore it has no description, how to use Logging with Java API on App Engine. Anyway I want to describe my problem: I use this API version:

"com.google.apis:google-api-services-logging:v2beta1-rev10-1.21.0"

So, first I build the Logging Object like this (I hope this is right):

public static Logging createAuthorizedClient() throws IOException {
    // Create the credential
    HttpTransport transport = new NetHttpTransport();
    JsonFactory jsonFactory = new JacksonFactory();
    GoogleCredential credential = GoogleCredential.getApplicationDefault(transport, jsonFactory);

    if (credential.createScopedRequired()) {
        credential = credential.createScoped(LoggingScopes.all());
    }

    return new Logging.Builder(transport, jsonFactory, credential).setApplicationName(SharedConstants.APPLICATION_ID).build();
}

After I get the Logging client, I try to push an Entry to the Log:

    LogEntry lEntry = new LogEntry();
    lEntry.setTextPayload("I want to see this log!");

    WriteLogEntriesRequest writeLogEntriesRequest = new WriteLogEntriesRequest();

    writeLogEntriesRequest.setLogName("My Super log");
    List<LogEntry> listEntries = new ArrayList<>();
    listEntries.add(lEntry);

    writeLogEntriesRequest.setEntries(listEntries);

    Logging logging = LoggingManager.createAuthorizedClient();
    Write write = logging.entries().write(writeLogEntriesRequest);
    WriteLogEntriesResponse writeLogResponse = write.execute();

But what I get is:

  com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 OK
{
  "code" : 400,
  "errors" : [ {
    "domain" : "global",
    "message" : "Invalid resource id",
    "reason" : "badRequest"
  } ],
  "message" : "Invalid resource id",
  "status" : "INVALID_ARGUMENT"
}

=== UPDATE: WORKING SOLUTION ===

Thanks to mshamma. Here is complete code, how to send the data to the logging:

    public boolean send() {
        WriteLogEntriesResponse response = null;
        try {
            final String now = getNowUtc();
            final String insertId = "entry-at-" + now;
            final Map<String, String> labels = ImmutableMap.of("project_id", SharedConstants.APPLICATION_ID, "name",
                    "projects/" + SharedConstants.APPLICATION_ID + "/logs/" + this.logName);

            Logging service = createAuthorizedClient();
            MonitoredResource ressource = new MonitoredResource();
            ressource.setType("logging_log");
            ressource.setLabels(labels);

            LogEntry entry = new LogEntry().setInsertId(insertId).setResource(ressource).setTimestamp(now)
                    .setJsonPayload(this.entriesMap)
                    .setLogName("projects/" + SharedConstants.APPLICATION_ID + "/logs/" + this.logName)
                    .setSeverity(this.severity);
            WriteLogEntriesRequest content = (new WriteLogEntriesRequest())
                    .setEntries(Collections.singletonList(entry));
            response = service.entries().write(content).execute();
        } catch (Exception e) {
        }
        return response != null;
    }

    private static String getNowUtc() {
        SimpleDateFormat dateFormatUtc = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        dateFormatUtc.setTimeZone(TimeZone.getTimeZone("UTC"));
        return dateFormatUtc.format(new Date());
    }

This code works fine with the last version of logging api

Thereby the EntriesMap is:

private Map<String, Object> entriesMap;

Solution

  • I ran into the same issue in the unmanaged Python environment. I got things working and I can see at least two issues in your code.

    1. The log name needs to follow the pattern: "projects/<project-id>/logs/<log-id>". See the documentation of the field here: https://cloud.google.com/logging/docs/api/ref_v2beta1/rest/v2beta1/LogEntry#SCHEMA_REPRESENTATION

    2. You should add a resource descriptor both to the log entry (lEntry) and the write log entry request (writeLogEntriesRequest). In the case of GAE, the resource type field should be set to "gae_app" and you must add three labels to the resource that identify your GAE deployment: "project_id", "module_id" and "version_id".

    I hope that will help resolve your issue!