מענה לתקריות שימוש ב-Google Chat, ב-Vertex AI וב-Apps Script

במדריך הזה נסביר איך ליצור אפליקציה של Google Chat שתגיב לתקריות בזמן אמת. כשמגיבים לתקרית, האפליקציה יוצרת ומאכלסת מרחב משותף ב-Chat, מאפשרת לטפל בתקרית באמצעות הודעות, פקודות קו נטוי ודיאלוגים, ומשתמשת ב-AI כדי לסכם את התגובה לתקרית במסמך ב-Google Docs.

אירוע הוא אירוע שדורש טיפול מיידי של צוות אנשים כדי לטפל בו. דוגמאות לאירועים:

  • בקשת תמיכה דחופה נוצרת בפלטפורמה לניהול קשרי לקוחות (CRM), וצוות שירות צריך לשתף פעולה כדי לפתור אותה.
  • מערכת עוברת למצב אופליין ושולחת התראה לקבוצה של מהנדסי Site Reliability (SRE), כדי שיוכלו לעבוד יחד כדי להחזיר אותה לאינטרנט.
  • רעידת אדמה בעוצמה גבוהה מתרחשת, ועובדי החירום צריכים לתאם את התגובה שלהם.

לצורך המדריך הזה, ההתראה על התקרית מתחילה כשמישהו מדווח על התקרית בלחיצה על לחצן בדף אינטרנט. בדף האינטרנט מתבצעת סימולציה של אירוע, והמשתמשים מתבקשים להזין מידע בסיסי על האירוע: שם, תיאור וכתובות אימייל של צוות התגובה.

רוצה לראות את אפליקציית Chat לניהול אירועים?

  • האתר שבו מתחיל האירוע.
    איור 1. האתר שבו אפשר לדווח על אירוע.
  • התראה על יצירת המרחב המשותף ב-Chat של התקרית.
    איור 2. התראה על כך שנוצר מרחב משותף ב-Chat.
  • המרחב המשותף ב-Chat לתגובה לתקרית.
    איור 3. המרחב ב-Chat של התגובה לאירוע.
  • פתרון התקרית באמצעות פקודה של שורת הפקודה.
    איור 4. פתרון התקרית באמצעות פקודת קו נטוי.
  • תיבת הדו-שיח של פתרון התקרית.
    איור 5. תיבת הדו-שיח של פתרון אירוע.
  • מסמך Google Docs ששותף במרחב המשותף, שבו מפורטת פתרון התקרית.
    איור 6. מסמך Google Docs בנושא פתרון התקרית ששותף במרחב המשותף.
  • סיכום האירוע שנוצר על ידי ה-AI במסמך Google Docs.
    איור 7. מסמך Google Docs עם סיכום האירוע ותוצאת הטיפול באמצעות AI.

דרישות מוקדמות

אם אתם צריכים להפעיל בארגון אחת מהדרישות המוקדמות האלה, תוכלו לבקש מהאדמין ב-Google Workspace להפעיל אותה:

  • חשבון Google Workspace מסוג Business או Enterprise עם גישה ל-Google Chat.
  • כדי להפעיל את הספרייה (שיתוף אנשי קשר) ב-Google Workspace. אפליקציית ניהול התקרית משתמשת בספרייה כדי לחפש את פרטי הקשר של צוות התגובה לתקרית, כמו שם וכתובת אימייל. המשיבים צריכים להיות עם חשבון Google Chat מהארגון שלכם ב-Google Workspace.

מטרות

  • פיתוח אפליקציית Chat שמגיבה לתקריות.
  • כדי לעזור למשתמשים להגיב לתקריות, אתם יכולים:
    • יצירת מרחבי תגובה לתקריות.
    • פרסום הודעות עם סיכום של אירועים ותגובות.
    • תמיכה בשיתוף פעולה באמצעות תכונות אינטראקטיביות באפליקציית Chat.
  • סיכום שיחות ופתרונות באמצעות Vertex AI.

ארכיטקטורה

בתרשים הבא מוצגת הארכיטקטורה של המשאבים ב-Google Workspace וב-Google Cloud שמשמשים את אפליקציית Google Chat בתגובה לאירוע.

הארכיטקטורה של אפליקציית Google Chat בתגובה לאירוע

הארכיטקטורה מראה איך האפליקציה של Google Chat לטיפול בתקריות מעבדת אירוע ותוצאה.

  1. משתמש מתחיל אירוע מאתר חיצוני שמתארח ב-Apps Script.

  2. האתר שולח בקשת HTTP אסינכרונית לאפליקציית Google Chat, שמתארחת גם ב-Apps Script.

  3. אפליקציית Google Chat לתגובה לתקריות מעבדת את הבקשה:

    1. שירות Admin SDK של Apps Script מקבל מידע על חברי הצוות, כמו מזהה משתמש וכתובת אימייל.

    2. באמצעות קבוצה של בקשות HTTP ל-Chat API באמצעות השירות Advanced Chat של Apps Script, אפליקציית Google Chat לטיפול בתקריות יוצרת מרחב Chat לתקרית, מאכלסת אותו עם חברי הצוות ושולחת הודעה למרחב.

  4. חברי הצוות מדברים על האירוע במרחב המשותף ב-Chat.

  5. אחד מחברי הצוות מפעיל פקודת קו נטוי כדי לסמן שהבעיה נפתרה.

    1. קריאת HTTP ל-Chat API באמצעות השירות המתקדם של Apps Script ל-Chat מציגה את כל ההודעות במרחב המשותף ב-Chat.

    2. מערכת Vertex AI מקבלת את ההודעות שמפורטות ברשימה ויוצרת סיכום.

    3. השירות DocumentApp ב-Apps Script יוצר מסמך Docs ומוסיף למסמך את הסיכום של Vertex AI.

    4. אפליקציית Google Chat לתגובה לתקריות קוראת ל-Chat API כדי לשלוח הודעה עם קישור למסמך הסיכום ב-Docs.

הכנת הסביבה

בחלק הזה נסביר איך יוצרים ומגדירים פרויקט ב-Google Cloud לאפליקציית Chat.

יצירת פרויקט של Google Cloud

מסוף Google Cloud

  1. במסוף Google Cloud, נכנסים לתפריט > IAM & Admin > יצירת פרויקט.

    כניסה לדף Create a Project

  2. בשדה Project Name, מזינים שם תיאורי לפרויקט.

    אופציונלי: כדי לערוך את Project ID, לוחצים על Edit. אי אפשר לשנות את מזהה הפרויקט אחרי יצירת הפרויקט, לכן חשוב לבחור מזהה שמתאים לצרכים שלכם לכל משך החיים של הפרויקט.

  3. בשדה Location, לוחצים על Browse כדי להציג מיקומים פוטנציאליים לפרויקט. לאחר מכן לוחצים על בחירה.
  4. לוחצים על יצירה. מסוף Google Cloud מנווט לדף Dashboard והפרויקט נוצר תוך כמה דקות.

CLI של gcloud

נכנסים ל-Google Cloud CLI (gcloud) באחת מסביבות הפיתוח הבאות:

  • Cloud Shell: כדי להשתמש בטרמינל אונליין שבו כבר מוגדר ה-CLI של gcloud, צריך להפעיל את Cloud Shell.
    הפעלת Cloud Shell
  • מעטפת מקומית: כדי להשתמש בסביבת פיתוח מקומית צריך להתקין ולהפעיל את ה-CLI של gcloud.
    כדי ליצור פרויקט ב-Cloud, משתמשים בפקודה gcloud projects create:
    gcloud projects create PROJECT_ID
    מחליפים את PROJECT_ID על ידי הגדרת המזהה של הפרויקט שרוצים ליצור.

הפעלת החיוב בפרויקט ב-Cloud

מסוף Google Cloud

  1. נכנסים לדף Billing במסוף Google Cloud. לוחצים על תפריט > חיוב > My Projects.

    כניסה לדף Billing for My Projects

  2. בקטע Select an Organization (בחירת ארגון), בוחרים את הארגון שמשויך לפרויקט ב-Google Cloud.
  3. בשורת הפרויקט, פותחים את התפריט Actions (), לוחצים על Change billing ובוחרים את החשבון לחיוב ב-Cloud.
  4. לוחצים על Set account.

CLI של gcloud

  1. כדי להציג את החשבונות לחיוב הזמינים, מריצים את הפקודה:
    gcloud billing accounts list
  2. קישור חשבון לחיוב לפרויקט ב-Google Cloud:
    gcloud billing projects link PROJECT_ID --billing-account=BILLING_ACCOUNT_ID

    מחליפים את מה שכתוב בשדות הבאים:

    • PROJECT_ID הוא מזהה הפרויקט של הפרויקט ב-Cloud שרוצים להפעיל בו חיוב.
    • BILLING_ACCOUNT_ID הוא מזהה החשבון לחיוב לקישור לפרויקט ב-Google Cloud.

הפעלת ממשקי ה-API

מסוף Google Cloud

  1. במסוף Google Cloud, מפעילים את Google Chat API, את Google Docs API, את Admin SDK API ואת Vertex AI API.

    הפעלת ממשקי ה-API

  2. מוודאים שאתם מפעילים את ממשקי ה-API בפרויקט הנכון ב-Cloud ולוחצים על הבא.

  3. מוודאים שאתם מפעילים את ממשקי ה-API הנכונים ולוחצים על Enable.

CLI של gcloud

  1. אם צריך, מגדירים את הפרויקט הנוכחי ב-Cloud כפרויקט שיצרתם באמצעות הפקודה gcloud config set project:

    gcloud config set project PROJECT_ID

    מחליפים את PROJECT_ID ב-Project ID של הפרויקט ב-Cloud שיצרתם.

  2. מפעילים את Google Chat API,‏ Google Docs API,‏ Admin SDK API ו-Vertex AI API באמצעות הפקודה gcloud services enable:

    gcloud services enable chat.googleapis.com docs.googleapis.com admin.googleapis.com aiplatform.googleapis.com

הגדרת אימות והרשאה

האימות וההרשאה מאפשרים לאפליקציית Chat לגשת למשאבים ב-Google Workspace וב-Google Cloud כדי לעבד תגובה לתקרית.

במדריך הזה תפרסמו את האפליקציה באופן פנימי, כך שאפשר להשתמש במידע של placeholder. לפני שמפרסמים את האפליקציה באופן חיצוני, צריך להחליף את ה-placeholders בפרטים של מסך ההסכמה.

  1. במסוף Google Cloud, נכנסים אל תפריט > APIs & Services> OAuth consent screen.

    מעבר למסך ההסכמה של OAuth

  2. בקטע סוג משתמש, בוחרים באפשרות פנימי ולוחצים על יצירה.

  3. בשדה App name, מקלידים Incident Management.

  4. בקטע User support email, בוחרים את כתובת האימייל שלכם או קבוצת Google מתאימה.

  5. בקטע פרטים ליצירת קשר עם המפתח, מזינים את כתובת האימייל.

  6. לוחצים על שמירה והמשך.

  7. לוחצים על הוספה או הסרה של היקפים. תוצג חלונית עם רשימת ההיקפים לכל ממשק API שהפעלתם בפרויקט ב-Cloud.

  8. בקטע הוספת היקפים באופן ידני, מדביקים את ההיקפים הבאים:

    • https://www.googleapis.com/auth/chat.spaces.create
    • https://www.googleapis.com/auth/chat.memberships
    • https://www.googleapis.com/auth/chat.memberships.app
    • https://www.googleapis.com/auth/chat.messages
    • https://www.googleapis.com/auth/documents
    • https://www.googleapis.com/auth/admin.directory.user.readonly
    • https://www.googleapis.com/auth/script.external_request
    • https://www.googleapis.com/auth/userinfo.email
    • https://www.googleapis.com/auth/cloud-platform
  9. לוחצים על הוספה לטבלה.

  10. לוחצים על עדכון.

  11. לוחצים על שמירה והמשך.

  12. בודקים את הסיכום של רישום האפליקציה ולוחצים על Back to Dashboard (חזרה ללוח הבקרה).

יצירה ופריסה של אפליקציית Chat

בקטע הבא תעתיקו ותעדכנו פרויקט Apps Script שלם שמכיל את כל קוד האפליקציה הנדרש לאפליקציית Chat, כך שלא תצטרכו להעתיק ולהדביק כל קובץ.

חלק מהפונקציות כוללות קו תחתון בסוף השם שלהן, כמו processSlashCommand_() מ-ChatApp.gs. הקו התחתון מסתיר את הפונקציה מדף האינטרנט של הפעלת התקרית כשהדף פתוח בדפדפן. מידע נוסף זמין במאמר פונקציות פרטיות.

ב-Apps Script יש תמיכה בשני סוגי קבצים: סקריפטים מסוג .gs וקבצים מסוג .html. כדי לעמוד בדרישות התמיכה האלה, ה-JavaScript של האפליקציה בצד הלקוח נכלל בתגי <script /> וה-CSS שלה נכלל בתגי <style /> בתוך קובץ HTML.

לחלופין, אפשר להציג את הפרויקט כולו ב-GitHub.

הצגת הקוד ב-GitHub

הנה סקירה כללית של כל קובץ:

Consts.gs

הגדרת קבועים שמפנים אליהם קובצי קוד אחרים, כולל מזהה הפרויקט ב-Cloud, מזהה המיקום ב-Vertex AI ומזהה הפקודה עם קו נטוי לסגירת אירוע.

הצגת קוד Consts.gs

apps-script/incident-response/Consts.gs
const PROJECT_ID = 'replace-with-your-project-id';
const VERTEX_AI_LOCATION_ID = 'us-central1';
const CLOSE_INCIDENT_COMMAND_ID = 1;
ChatApp.gs

טיפול באירועי אינטראקציה ב-Chat, כולל הודעות, קליקים על כרטיסים, פקודות ותיבות דו-שיח. התגובה לפקודת ה-slash‏ /closeIncident היא פתיחת תיבת דו-שיח כדי לאסוף פרטים לגבי פתרון התקרית. קוראת את ההודעות במרחב המשותף באמצעות קריאה ל-method spaces.messages.list ב-Chat API. הצגת מזהי משתמשים באמצעות שירות הספרייה של Admin SDK ב-Apps Script.

הצגת קוד ChatApp.gs

apps-script/incident-response/ChatApp.gs
/**
 * Responds to a MESSAGE event in Google Chat.
 *
 * This app only responds to a slash command with the ID 1 ("/closeIncident").
 * It will respond to any other message with a simple "Hello" text message.
 *
 * @param {Object} event the event object from Google Chat
 */
function onMessage(event) {
  if (event.message.slashCommand) {
    return processSlashCommand_(event);
  }
  return { "text": "Hello from Incident Response app!" };
}

/**
 * Responds to a CARD_CLICKED event in Google Chat.
 *
 * This app only responds to one kind of dialog (Close Incident).
 *
 * @param {Object} event the event object from Google Chat
 */
function onCardClick(event) {
  if (event.isDialogEvent) {
    if (event.dialogEventType == 'SUBMIT_DIALOG') {
      return processSubmitDialog_(event);
    }
    return {
      actionResponse: {
        type: "DIALOG",
        dialogAction: {
          actionStatus: "OK"
        }
      }
    };
  }
}

/**
 * Responds to a MESSAGE event with a Slash command in Google Chat.
 *
 * This app only responds to a slash command with the ID 1 ("/closeIncident")
 * by returning a Dialog.
 *
 * @param {Object} event the event object from Google Chat
 */
function processSlashCommand_(event) {
  if (event.message.slashCommand.commandId != CLOSE_INCIDENT_COMMAND_ID) {
    return {
      "text": "Command not recognized. Use the command `/closeIncident` to close the incident managed by this space."
    };
  }
  const sections = [
    {
      header: "Close Incident",
      widgets: [
        {
          textInput: {
            label: "Please describe the incident resolution",
            type: "MULTIPLE_LINE",
            name: "description"
          }
        },
        {
          buttonList: {
            buttons: [
              {
                text: "Close Incident",
                onClick: {
                  action: {
                    function: "closeIncident"
                  }
                }
              }
            ]
          }
        }
      ]
    }
  ];
  return {
    actionResponse: {
      type: "DIALOG",
      dialogAction: {
        dialog: {
          body: {
            sections,
          }
        }
      }
    }
  };
}

/**
 * Responds to a CARD_CLICKED event with a Dialog submission in Google Chat.
 *
 * This app only responds to one kind of dialog (Close Incident).
 * It creates a Doc with a summary of the incident information and posts a message
 * to the space with a link to the Doc.
 *
 * @param {Object} event the event object from Google Chat
 */
function processSubmitDialog_(event) {
  const resolution = event.common.formInputs.description[""].stringInputs.value[0];
  const chatHistory = concatenateAllSpaceMessages_(event.space.name);
  const chatSummary = summarizeChatHistory_(chatHistory);
  const docUrl = createDoc_(event.space.displayName, resolution, chatHistory, chatSummary);
  return {
    actionResponse: {
      type: "NEW_MESSAGE",
    },
    text: `Incident closed with the following resolution: ${resolution}\n\nHere is the automatically generated post-mortem:\n${docUrl}`
  };
}

/**
 * Lists all the messages in the Chat space, then concatenate all of them into
 * a single text containing the full Chat history.
 *
 * For simplicity for this demo, it only fetches the first 100 messages.
 *
 * Messages with slash commands are filtered out, so the returned history will
 * contain only the conversations between users and not app command invocations.
 *
 * @return {string} a text containing all the messages in the space in the format:
 *          Sender's name: Message
 */
function concatenateAllSpaceMessages_(spaceName) {
  // Call Chat API method spaces.messages.list
  const response = Chat.Spaces.Messages.list(spaceName, { 'pageSize': 100 });
  const messages = response.messages;
  // Fetch the display names of the message senders and returns a text
  // concatenating all the messages.
  let userMap = new Map();
  return messages
    .filter(message => message.slashCommand === undefined)
    .map(message => `${getUserDisplayName_(userMap, message.sender.name)}: ${message.text}`)
    .join('\n');
}

/**
 * Obtains the display name of a user by using the Admin Directory API.
 *
 * The fetched display name is cached in the provided map, so we only call the API
 * once per user.
 *
 * If the user does not have a display name, then the full name is used.
 *
 * @param {Map} userMap a map containing the display names previously fetched
 * @param {string} userName the resource name of the user
 * @return {string} the user's display name
 */
function getUserDisplayName_(userMap, userName) {
  if (userMap.has(userName)) {
    return userMap.get(userName);
  }
  let displayName = 'Unknown User';
  try {
    const user = AdminDirectory.Users.get(
      userName.replace("users/", ""),
      { projection: 'BASIC', viewType: 'domain_public' });
    displayName = user.name.displayName ? user.name.displayName : user.name.fullName;
  } catch (e) {
    // Ignore error if the API call fails (for example, because it's an
    // out-of-domain user or Chat app)) and just use 'Unknown User'.
  }
  userMap.set(userName, displayName);
  return displayName;
}
ChatSpaceCreator.gs

השירות מקבל את נתוני הטופס שהמשתמשים מזינים בדף האינטרנט של הפעלת התקרית, ומשתמש בהם כדי להגדיר מרחב משותף ב-Chat על ידי יצירה ויישוב שלו, ולאחר מכן לפרסם הודעה על התקרית.

הצגת קוד ChatSpaceCreator.gs

apps-script/incident-response/ChatSpaceCreator.gs
/**
 * Creates a space in Google Chat with the provided title and members, and posts an
 * initial message to it.
 *
 * @param {Object} formData the data submitted by the user. It should contain the fields
 *                          title, description, and users.
 * @return {string} the resource name of the new space.
 */
function createChatSpace(formData) {
  const users = formData.users.trim().length > 0 ? formData.users.split(',') : [];
  const spaceName = setUpSpace_(formData.title, users);
  addAppToSpace_(spaceName);
  createMessage_(spaceName, formData.description);
  return spaceName;
}

/**
 * Creates a space in Google Chat with the provided display name and members.
 *
 * @return {string} the resource name of the new space.
 */
function setUpSpace_(displayName, users) {
  const memberships = users.map(email => ({
    member: {
      name: `users/${email}`,
      type: "HUMAN"
    }
  }));
  const request = {
    space: {
      displayName: displayName,
      spaceType: "SPACE",
      externalUserAllowed: true
    },
    memberships: memberships
  };
  // Call Chat API method spaces.setup
  const space = Chat.Spaces.setup(request);
  return space.name;
}

/**
 * Adds this Chat app to the space.
 *
 * @return {string} the resource name of the new membership.
 */
function addAppToSpace_(spaceName) {
  const request = {
    member: {
      name: "users/app",
      type: "BOT"
    }
  };
  // Call Chat API method spaces.members.create
  const membership = Chat.Spaces.Members.create(request, spaceName);
  return membership.name;
}

/**
 * Posts a text message to the space on behalf of the user.
 *
 * @return {string} the resource name of the new message.
 */
function createMessage_(spaceName, text) {
  const request = {
    text: text
  };
  // Call Chat API method spaces.messages.create
  const message = Chat.Spaces.Messages.create(request, spaceName);
  return message.name;
}
DocsApi.gs

הקריאה ל-Google Docs API יוצרת מסמך Google Docs ב-Google Drive של המשתמש, ומוסיפה למסמך סיכום של פרטי התקרית שנוצרו ב-VertexAiApi.gs.

הצגת קוד DocsApi.gs

apps-script/incident-response/DocsApi.gs
/**
 * Creates a Doc in the user's Google Drive and writes a summary of the incident information to it.
 *
 * @param {string} title The title of the incident
 * @param {string} resolution Incident resolution described by the user
 * @param {string} chatHistory The whole Chat history be included in the document
 * @param {string} chatSummary A summary of the Chat conversation to be included in the document
 * @return {string} the URL of the created Doc
 */
function createDoc_(title, resolution, chatHistory, chatSummary) {
  let doc = DocumentApp.create(title);
  let body = doc.getBody();
  body.appendParagraph(`Post-Mortem: ${title}`).setHeading(DocumentApp.ParagraphHeading.TITLE);
  body.appendParagraph("Resolution").setHeading(DocumentApp.ParagraphHeading.HEADING1);
  body.appendParagraph(resolution);
  body.appendParagraph("Summary of the conversation").setHeading(DocumentApp.ParagraphHeading.HEADING1);
  body.appendParagraph(chatSummary);
  body.appendParagraph("Full Chat history").setHeading(DocumentApp.ParagraphHeading.HEADING1);
  body.appendParagraph(chatHistory);
  return doc.getUrl();
}
VertexAiApi.gs

סיכום השיחה במרחב המשותף ב-Chat באמצעות Vertex AI. הסיכום הזה פורסם במסמך שנוצר במיוחד ב-DocsAPI.gs.

הצגת קוד VertexAiApi.gs

apps-script/incident-response/VertexAiApi.gs
/**
 * Summarizes a Chat conversation using the Vertex AI text prediction API.
 *
 * @param {string} chatHistory The Chat history that will be summarized.
 * @return {string} The content from the text prediction response.
 */
function summarizeChatHistory_(chatHistory) {
  const prompt =
    "Summarize the following conversation between Engineers resolving an incident"
      + " in a few sentences. Use only the information from the conversation.\n\n"
      + chatHistory;
  const request = {
    instances: [
      { prompt: prompt }
    ],
    parameters: {
      temperature: 0.2,
      maxOutputTokens: 256,
      topK: 40,
      topP: 0.95
    }
  }
  const fetchOptions = {
    method: 'POST',
    headers: { Authorization: 'Bearer ' + ScriptApp.getOAuthToken() },
    contentType: 'application/json',
    payload: JSON.stringify(request)
  }
  const response = UrlFetchApp.fetch(
    `https://${VERTEX_AI_LOCATION_ID}-aiplatform.googleapis.com/v1`
      + `/projects/${PROJECT_ID}/locations/${VERTEX_AI_LOCATION_ID}`
      + "/publishers/google/models/text-bison:predict",
    fetchOptions);
  const payload = JSON.parse(response.getContentText());
  return payload.predictions[0].content;
}
WebController.gs

האתר שמציג את האתר להתחלת אירוע.

הצגת הקוד מהאפליקציה WebController.gs

apps-script/incident-response/WebController.gs
/**
 * Serves the web page from Index.html.
 */
function doGet() {
  return HtmlService
    .createTemplateFromFile('Index')
    .evaluate();
}

/**
 * Serves the web content from the specified filename.
 */
function include(filename) {
  return HtmlService
    .createHtmlOutputFromFile(filename)
    .getContent();
}

/**
 * Returns the email address of the user running the script.
 */
function getUserEmail() {
  return Session.getActiveUser().getEmail();
}
Index.html

ה-HTML שמרכיב את האתר לאתחול התקרית.

הצגת הקוד מהאפליקציה Index.html

apps-script/incident-response/Index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <link href='https://fonts.googleapis.com/css?family=Roboto' rel='stylesheet'>
    <?!= include('Stylesheet'); ?>
  </head>
  <body>
    <div class="container">
      <div class="content">
        <h1>Incident Manager</h1>
        <form id="incident-form" onsubmit="handleFormSubmit(this)">
          <div id="form">
            <p>
              <label for="title">Incident title</label><br/>
              <input type="text" name="title" id="title" />
            </p>
            <p>
              <label for="users">Incident responders</label><br/>
              <small>
                Please enter a comma-separated list of email addresses of the users
                that should be added to the space.
                Do not include <?= getUserEmail() ?> as it will be added automatically.
              </small><br/>
              <input type="text" name="users" id="users" />
            </p>
            <p>
              <label for="description">Initial message</label></br>
              <small>This message will be posted after the space is created.</small><br/>
              <textarea name="description" id="description"></textarea>
            </p>
            <p class="text-center">
              <input type="submit" value="CREATE CHAT SPACE" />
            </p>
          </div>
          <div id="output" class="hidden"></div>
          <div id="clear" class="hidden">
            <input type="reset" value="CREATE ANOTHER INCIDENT" onclick="onReset()" />
          </div>
        </form>
      </div>
    </div>
    <?!= include('JavaScript'); ?>
  </body>
</html>
JavaScript.html

טיפול בהתנהגות הטופס, כולל שליחת, שגיאות וניקוי נתונים באתר של אתחול התקרית. הוא נכלל ב-Index.html באמצעות הפונקציה המותאמת אישית include ב-WebController.gs.

הצגת קוד JavaScript.html

apps-script/incident-response/JavaScript.html
<script>
  var formDiv = document.getElementById('form');
  var outputDiv = document.getElementById('output');
  var clearDiv = document.getElementById('clear');

  function handleFormSubmit(formObject) {
    event.preventDefault();
    outputDiv.innerHTML = 'Please wait while we create the space...';
    hide(formDiv);
    show(outputDiv);
    google.script.run
      .withSuccessHandler(updateOutput)
      .withFailureHandler(onFailure)
      .createChatSpace(formObject);
  }

  function updateOutput(response) {
    var spaceId = response.replace('spaces/', '');
    outputDiv.innerHTML =
      '<p>Space created!</p><p><a href="https://mail.google.com/chat/#chat/space/'
        + spaceId
        + '" target="_blank">Open space</a></p>';
    show(outputDiv);
    show(clearDiv);
  }

  function onFailure(error) {
    outputDiv.innerHTML = 'ERROR: ' + error.message;
    outputDiv.classList.add('error');
    show(outputDiv);
    show(clearDiv);
  }

  function onReset() {
    outputDiv.innerHTML = '';
    outputDiv.classList.remove('error');
    show(formDiv);
    hide(outputDiv);
    hide(clearDiv);
  }

  function hide(element) {
    element.classList.add('hidden');
  }

  function show(element) {
    element.classList.remove('hidden');
  }
</script>
Stylesheet.html

קובץ ה-CSS של האתר להפעלת אירוע. הוא כלול ב-Index.html על ידי פונקציית include בהתאמה אישית ב-WebController.gs.

הצגת קוד Stylesheet.html

apps-script/incident-response/Stylesheet.html
<style>
  * {
    box-sizing: border-box;
  }
  body {
    font-family: Roboto, Arial, Helvetica, sans-serif;
  }
  div.container {
    display: flex;
    justify-content: center;
    align-items: center;
    position: absolute;
    top: 0; bottom: 0; left: 0; right: 0;
  }
  div.content {
    width: 80%;
    max-width: 1000px;
    padding: 1rem;
    border: 1px solid #999;
    border-radius: 0.25rem;
    box-shadow: 0 2px 2px 0 rgba(66, 66, 66, 0.08), 0 2px 4px 2px rgba(66, 66, 66, 0.16);
  }
  h1 {
    text-align: center;
    padding-bottom: 1rem;
    margin: 0 -1rem 1rem -1rem;
    border-bottom: 1px solid #999;
  }
 #output {
    text-align: center;
    min-height: 250px;
  }
  div#clear {
    text-align: center;
    padding-top: 1rem;
    margin: 1rem -1rem 0 -1rem;
    border-top: 1px solid #999;
  }
  input[type=text], textarea {
    width: 100%;
    padding: 1rem 0.5rem;
    margin: 0.5rem 0;
    border: 0;
    border-bottom: 1px solid #999;
    background-color: #f0f0f0;
  }
  textarea {
    height: 5rem;
  }
  small {
    color: #999;
  }
  input[type=submit], input[type=reset] {
    padding: 1rem;
    border: none;
    background-color: #6200ee;
    color: #fff;
    border-radius: 0.25rem;
    width: 25%;
  }
  .hidden {
    display: none;
  }
  .text-center {
    text-align: center;
  }
  .error {
    color: red;
  }
</style>

איך מוצאים את מספר הפרויקט והמזהה שלו ב-Cloud

  1. נכנסים למסוף Google Cloud לפרויקט ב-Cloud.

    כניסה למסוף Google Cloud

  2. לוחצים על סמל ההגדרות והכלים > הגדרות הפרויקט.

  3. שימו לב לערכים בשדות Project number ו-Project ID. תוכלו להשתמש בהם בקטעים הבאים.

יצירת פרויקט Apps Script

כדי ליצור פרויקט Apps Script ולקשר אותו לפרויקט ב-Cloud:

  1. לוחצים על הלחצן הבא כדי לפתוח את פרויקט Apps Script‏ מענה על אירועים באמצעות Google Chat.
    פתיחת הפרויקט
  2. לוחצים על סקירה כללית.
  3. בדף הסקירה הכללית לוחצים על הסמל ליצירת עותק יצירת עותק.
  4. נותנים שם להעתקה של פרויקט Apps Script:

    1. לוחצים על עותק של 'מענה לתקריות באמצעות Google Chat'.

    2. בשדה Project title, כותבים Incident Management Chat app.

    3. לוחצים על Rename.

  5. בעותק של פרויקט Apps Script, נכנסים לקובץ Consts.gs ומחליפים את המזהה YOUR_PROJECT_ID במזהה הפרויקט ב-Cloud.

הגדרת הפרויקט ב-Cloud של פרויקט Apps Script

  1. בפרויקט של Apps Script, לוחצים על הסמל של הגדרות הפרויקט Project Settings.
  2. בקטע פרויקט Google Cloud Platform ‏ (GCP), לוחצים על שינוי פרויקט.
  3. בקטע מספר פרויקט GCP, מדביקים את מספר הפרויקט ב-Cloud.
  4. לוחצים על Set project. הפרויקט ב-Cloud והפרויקט ב-Apps Script מקושרים עכשיו.

יצירת פריסה של Apps Script

עכשיו, אחרי שכל הקוד מוכן, פורסים את הפרויקט ב-Apps Script. משתמשים במזהה הפריסה כשמגדירים את אפליקציית Chat ב-Google Cloud.

  1. ב-Apps Script, פותחים את הפרויקט של אפליקציית התגובה לאירוע.

    מעבר אל Apps Script

  2. לוחצים על Deploy (פריסה) > NewDeploy (פריסה חדשה).

  3. אם לא סימנתם את Add-on (תוסף) ואת Web app (אפליקציית אינטרנט), לצד Select type לוחצים על סוגי הפריסה הסמל של הגדרות הפרויקט ובוחרים באפשרות Add-on (תוסף) ו-Web app (אפליקציית אינטרנט).

  4. בקטע Description, מזינים תיאור של הגרסה הזו, למשל Complete version of incident management app.

  5. בקטע ביצוע כ, בוחרים באפשרות משתמש שניגש לאפליקציית האינטרנט.

  6. בקטע למי יש גישה, בוחרים באפשרות כל מי שנמצא בארגון שלך ב-Workspace, כאשר 'הארגון שלך ב-Workspace' הוא השם של הארגון שלכם ב-Google Workspace.

  7. לוחצים על פריסת. Apps Script מדווח על פריסה מוצלחת ומספק מזהה פריסה וכתובת URL לדף האינטרנט של הפעלת התקרית.

  8. מומלץ לרשום לפניכם את כתובת ה-URL של אפליקציית האינטרנט כדי להיכנס אליה מאוחר יותר כשמתחילים אירוע. מעתיקים את מזהה הפריסה. המזהה הזה משמש אתכם כשאתם מגדירים את אפליקציית Chat במסוף Google Cloud.

  9. לוחצים על סיום.

הגדרת אפליקציית Chat במסוף Google Cloud

בקטע הזה נסביר איך להגדיר את Google Chat API במסוף Google Cloud עם מידע על אפליקציית Chat, כולל מזהה הפריסה שיצרתם זה עתה מהפרויקט ב-Apps Script.

  1. במסוף Google Cloud, לוחצים על תפריט &gt; מוצרים נוספים &gt; Google Workspace &gt; ספריית מוצרים &gt; Google Chat API &gt; ניהול &gt; הגדרות אישיות.

    כניסה להגדרת Chat API

  2. בשדה App name, מקלידים Incident Management.

  3. בשדה כתובת ה-URL של הדמות, מקלידים https://developers.google.com/chat/images/quickstart-app-avatar.png.

  4. בקטע תיאור, מקלידים Responds to incidents..

  5. מעבירים את המתג הפעלת תכונות אינטראקטיביות למצב פעיל.

  6. בקטע פונקציונליות, בוחרים באפשרות קבלת הודעות אישיות והצטרפות למרחבים משותפים ולשיחות קבוצתיות.

  7. בקטע הגדרות החיבור, בוחרים באפשרות Apps Script.

  8. בשדה Deployment ID, מדביקים את מזהה הפריסה של Apps Script שהועתק קודם לכן מהפריסה של פרויקט Apps Script.

  9. רושמים פקודת קו נטוי שבה משתמשת אפליקציית Chat המוטמעת במלואה:

    1. בקטע Slash commands, לוחצים על Add a slash command.

    2. בשדה Name, מקלידים /closeIncident.

    3. בשדה Command ID, מקלידים 1.

    4. בקטע תיאור, מקלידים את הערך Closes the incident being discussed in the space.

    5. בוחרים באפשרות פתיחת תיבת דו-שיח.

    6. לוחצים על סיום. הפקודה של הלוכסן רשומה ומופיעה.

  10. בקטע הרשאות גישה, בוחרים באפשרות הפיכת אפליקציית Chat הזו לזמינה לאנשים ולקבוצות ספציפיים בדומיין Workspace ומזינים את כתובת האימייל שלכם.

  11. בקטע Logs (יומנים), בוחרים באפשרות Log errors to Logging (רישום שגיאות ביומן).

  12. לוחצים על שמירה. תופיע הודעת אישור על שמירת ההגדרות, והאפליקציה תהיה מוכנה לבדיקה.

בדיקת האפליקציה של Chat

כדי לבדוק את אפליקציית Chat לניהול אירועים, יוצרים אירוע מהדף באינטרנט ומוודאים שאפליקציית Chat פועלת כצפוי:

  1. עוברים לכתובת ה-URL של אפליקציית האינטרנט בפריסה של Apps Script.

  2. כשמערכת Apps Script מבקשת הרשאה לגשת לנתונים שלכם, לוחצים על בדיקת ההרשאות, נכנסים לחשבון Google המתאים בדומיין של Google Workspace ולוחצים על אישור.

  3. דף האינטרנט של אתחול האירוע ייפתח. מזינים את פרטי הבדיקה:

    1. בקטע שם האירוע, מקלידים The First Incident.
    2. אם רוצים, אפשר להזין את כתובות האימייל של שאר המשתתפים בתקרית בשדה Incident responders. הם צריכים להיות משתמשים עם חשבון Google Chat מהארגון שלכם ב-Google Workspace, או אם יצירת המרחב המשותף נכשלה. אין להזין את כתובת האימייל שלכם, כי היא כלולה באופן אוטומטי.
    3. בקטע הודעה ראשונית, מקלידים Testing the incident management Chat app.
  4. לוחצים על יצירת מרחב ב-Chat. תופיע ההודעה creating space.

  5. אחרי יצירת המרחב המשותף, תופיע ההודעה Space created!. לוחצים על פתיחת המרחב המשותף. המרחב המשותף ייפתח ב-Chat בכרטיסייה חדשה.

  6. אתם והגורמים האחרים שתגיבו לתקרית תוכלו לשלוח הודעות במרחב המשותף. האפליקציה מסכם את ההודעות האלה באמצעות Vertex AI ומשתפת מסמך רטרוספקטיבי.

  7. כדי לסיים את התגובה לאירוע ולהתחיל את תהליך הפתרון, מקלידים /closeIncident במרחב המשותף של Chat. תיפתח תיבת דו-שיח לניהול אירועים.

  8. בקטע Close event (סגירת האירוע), מזינים תיאור של הפתרון, למשל Test complete.

  9. לוחצים על Close Incident.

באפליקציית Incident Management מופיעות ההודעות במרחב המשותף, הן מסוכמות באמצעות Vertex AI, המערכת מדביקה את הסיכום במסמך ב-Google Docs ומשתפת את המסמך במרחב המשותף.

הסרת המשאבים

כדי להימנע מצבירת חיובים בחשבון Google Cloud על המשאבים שבהם השתמשתם במדריך הזה, מומלץ למחוק את הפרויקט ב-Cloud.

  1. במסוף Google Cloud, עוברים לדף Manage resources. לוחצים על תפריט > IAM & Admin > Manage Resources.

    כניסה ל-Resource Manager

  2. ברשימת הפרויקטים, בוחרים את הפרויקט שרוצים למחוק ולוחצים על Delete .
  3. כדי למחוק את הפרויקט, כותבים את מזהה הפרויקט בתיבת הדו-שיח ולוחצים על Shut down.