新しい投稿

検索

記事
· 2024年12月19日 3m read

Robozinho em COS para logar cliente (IP e/ou EXE) que pode estar onerando seu servidor

Nós estávamos com uma ocorrência em um cliente em que todas as licenças estavam sendo consumidas e a CPU bastane onerada.

Consultávamos no portal de administração, na lista de processos, mas como o problema era intermitente, não conseguiamos identificar o "vilão".

Fizemos um programa simples, que coleta os processos e algumas informações destes, tais como : IP, executável etc.​​​​​​, e gravamos em arquivo .csv.

No portal de administração -> Operação do Sistema -> Gerenciador de Tarefas, cadastramos uma nova tarefa que executa este programa a cada 10 minutos.

​​​​​​​Quando o problema voltou a ocorrer, conseguimos verificar essa coleta de informações e vimos um IP e um determinado executável, repetindo em vários processos. Logo matamos a charada. 

​​​​​​​Segue abaixo o programa a fim de auxiliar os que podem passar pela mesma situação.

QGGETIP ; PEGA IPS DOS PROCESSOS
        // Abre o arquivo para escrita
        Set  file  = ##class ( %File ). %New ( "D:\TEMP\logprocips_" _ $zd ( $h ,8)_ "_" _ $tr ( $zt ( $piece ( $h , "," ,2),1), ":" , "_" )_ ".csv" )
        Do  file.Open ( "NW" ) // "W" para escrita         // Escrever cabeçalho no arquivo
        Do  file . WriteLine ( "PID;ClientIPAddress;ClientNodeName;Exe Name;data e Hora" )          

        Set  Rset  = ##class ( %ResultSet ). %New ( "%SYS.ProcessQuery:ListPids" )
        Do  Rset . Execute ()
        While  Rset . Next () {
        
            Set  pid  = Rset . GetData (1)
            Set  ipAddress  = $SYSTEM .Process . ClientIPAddress ( pid )
            Set  nodeName  = $SYSTEM .Process . ClientNodeName ( pid )
            Set  exeName  = $SYSTEM .Process . ClientExecutableName ( pid )
            
            set  dth = $zd ( $h ,4)_ " " _ $zt ( $piece ( $h , "," ,2),1)
            // Escrever as informações no arquivo
            Do  file . WriteLine ( pid _ ";" _ ipAddress _ ";" _ nodeName _ ";" _ exeName _ ";" _ dth )
        }
        
        // Fechar o arquivo
        Do  file . Close ()
        Write  "Exportação concluída com sucesso. Arquivo gerado:" , file.Name ,! 

       ​​​​​​​//Márcio Sorvi

1 Comment
ディスカッション (1)1
続けるにはログインするか新規登録を行ってください
記事
· 2024年12月19日 4m read

第五十三章 File 输入 输出 - OPEN模式参数

第五十三章 File 输入 输出 - OPEN模式参数

A /APPEND /APP

Append:WRITE 操作将数据附加到现有文件的末尾。默认设置是覆盖现有数据,而不是 append

S /STREAM

流格式,回车符、换行符或换页符作为默认终止符。S、V、F 和 U 模式是互斥的。Stream record format 是默认格式。

V /VARIABLE

请勿尝试在可变长度顺序文件末尾以外的任何位置插入记录;WRITE 将使文件中的所有数据从 WRITE 之后的点开始无法访问。S、V、F 和 U 模式是互斥的。流记录 (S) 格式是默认格式。

使用转换表写入的可变长度记录(例如使用 UTF8 转换的 Unicode 数据)可能会导致存储的记录具有与输入数据不同的字符串长度。IRIS 在读取此记录时使用原始输入字符串长度。

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
質問
· 2024年12月19日

Versión Evaluación de Cache II

Siguiendo con el hilo de Versión Evolución Cache, por si fuera interesante para alguien.

Instalada última versión de IRIS, tenido en cuenta el renombrando de CACHE.DAT a IRIS.DAT, no funciona. Si que monta correctamente las diferentes bases de datos, supongo que es debido a que es una licencia de la “Comunidad”

Al migrar los datos se ha producido una corrupción en los acentos y las eñes, cambiado el idioma local (enuw -> espw), si entras a la base de datos por el "terminal" del antiguo cubo todo parece normal.

Si utilizas una aplicación externa tipo "wrq reflection" (mi caso), no son posibles los acentos ni las eñes, de hecho, al pedir la contraseña, esta eñe no es correcta.

Salud

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
記事
· 2024年12月19日 14m read

Learn to create VSCode extensions with IRIS Global Editor app

VSCode is the most used IDE in the world. It is strategic have more extensions for VSCode for InterSystems technologies to keep increasing the developer community.

My new app IRIS VSCode Global Editor is an excellent sample to learn how to create extensions to IRIS. You can check it on https://openexchange.intersystems.com/package/IRIS-Global-VSCode-Editor.

To be ready to create extensions for VSCode

From https://code.visualstudio.com/api/get-started/your-first-extension you have all steps to get ready, but I will detail here to you.

1. Install Yeoman and start the creation of the extension project:

npm install --global yo generator-code

yo code

2. Answer the questions:

# ? What type of extension do you want to create? New Extension (TypeScript)
# ? What's the name of your extension? IRISExtension
### Press <Enter> to choose default for all options below ###

# ? What's the identifier of your extension? irisextension
# ? What's the description of your extension? LEAVE BLANK
# ? Initialize a git repository? Yes
# ? Bundle the source code with webpack? No
# ? Which package manager to use? npm

# ? Do you want to open the new folder with Visual Studio Code? Open with `code`

3. On VSCode, go to package.json, section contributes, to define new commands, views, editor and other elements created with your plugin, see this sample:

{
  "name": "iris-global-editor",
  "displayName": "iris-global-editor",
  "description": "IRIS Global Editor",
  "repository": "https://github.com/yurimarx/iris-global-editor",
  "version": "0.0.2",
  "engines": {
    "vscode": "^1.96.0"
  },
  "categories": [
    "Other"
  ],
  "activationEvents": [],
  "main": "./dist/extension.js",
  "contributes": {
    "views": {
      "explorer": [
        {
          "id": "irisGlobals",
          "name": "InterSystems IRIS Globals"
        }
      ]
    },
    "commands": [
      {
        "command": "irisGlobals.addEntry",
        "title": "Add",
        "icon": {
          "light": "resources/light/add.svg",
          "dark": "resources/dark/add.svg"
        }
      },
      {
        "command": "irisGlobals.deleteEntry",
        "title": "Delete",
        "icon": {
          "light": "resources/light/trash.svg",
          "dark": "resources/dark/trash.svg"
        }
      },
      {
        "command": "irisGlobals.editEntry",
        "title": "Edit",
        "icon": {
          "light": "resources/light/edit.svg",
          "dark": "resources/dark/edit.svg"
        }
      },
      {
        "command": "irisGlobals.editTextEntry",
        "title": "Editor",
        "icon": {
          "light": "resources/light/file.svg",
          "dark": "resources/dark/file.svg"
        }
      },
      {
        "command": "irisGlobals.refreshEntry",
        "title": "IRIS Globals: Refresh",
        "icon": {
          "light": "resources/light/refresh.svg",
          "dark": "resources/dark/refresh.svg"
        }
      },
      {
        "command": "irisGlobals.filterGlobals",
        "title": "IRIS Globals: Filter",
        "icon": {
          "light": "resources/light/filter.svg",
          "dark": "resources/dark/filter.svg"
        }
      }
    ],
    "menus": {
      "view/title": [
        {
          "command": "irisGlobals.filterGlobals",
          "when": "view == irisGlobals",
          "group": "navigation"
        },
        {
          "command": "irisGlobals.refreshEntry",
          "when": "view == irisGlobals",
          "group": "navigation"
        },
        {
          "command": "irisGlobals.addEntry",
          "when": "view == irisGlobals",
          "group": "navigation"
        }
      ],
      "view/item/context": [
        {
          "command": "irisGlobals.editEntry",
          "when": "view == irisGlobals",
          "group": "inline"
        },
        {
          "command": "irisGlobals.deleteEntry",
          "when": "view == irisGlobals",
          "group": "inline"
        },
        {
          "command": "irisGlobals.editTextEntry",
          "when": "view == irisGlobals",
          "group": "inline"
        }
      ]
    },
    "configuration": [
      {
        "id": "irisGlobals",
        "title": "Settings InterSystems IRIS Global Editor",
        "order": 1,
        "properties": {
          "conf.irisGlobalEditor.filter": {
            "type": "string",
            "default": "",
            "description": "Filter criteria to filter globals list"
          },
          "conf.irisGlobalEditor.serverconfig": {
            "type": "object",
            "order": 1,
            "description": "Connection settings",
            "properties": {
              "host": {
                "type": "string",
                "description": "InterSystems IRIS Host"
              },
              "namespace": {
                "type": "string",
                "description": "InterSystems IRIS Namespace"
              },
              "username": {
                "type": "string",
                "description": "User name credential"
              },
              "password": {
                "type": "string",
                "description": "Password credential"
              }
            },
            "additionalProperties": false
          }
        }
      }
    ]
  },
  "scripts": {
    "vscode:prepublish": "npm run package",
    "compile": "npm run check-types && npm run lint && node esbuild.js",
    "watch": "npm-run-all -p watch:*",
    "watch:esbuild": "node esbuild.js --watch",
    "watch:tsc": "tsc --noEmit --watch --project tsconfig.json",
    "package": "npm run check-types && npm run lint && node esbuild.js --production",
    "compile-tests": "tsc -p . --outDir out",
    "watch-tests": "tsc -p . -w --outDir out",
    "pretest": "npm run compile-tests && npm run compile && npm run lint",
    "check-types": "tsc --noEmit",
    "lint": "eslint src",
    "test": "vscode-test"
  },
  "devDependencies": {
    "@types/mocha": "^10.0.9",
    "@types/node": "20.x",
    "@types/vscode": "^1.96.0",
    "@typescript-eslint/eslint-plugin": "^8.10.0",
    "@typescript-eslint/parser": "^8.7.0",
    "@vscode/test-cli": "^0.0.10",
    "@vscode/test-electron": "^2.4.1",
    "axios": "^1.7.9",
    "esbuild": "^0.24.0",
    "eslint": "^9.13.0",
    "npm-run-all": "^4.1.5",
    "typescript": "^5.6.3"
  },
  "dependencies": {
    "axios": "^1.7.9",
    "formdata-node": "^6.0.3",
    "iris-global-editor": "file:"
  }
}

4. With the functionalities declared, it is necessary the implementation. My app implement a TreeView on src folder on file IrisGlobalsProvider. For treeviews it is required implement a vscode.TreeDataProvider, for other type of VSCode functions see the article https://code.visualstudio.com/api/extension-guides/overview. It is my Treeview implementation:

import * as vscode from 'vscode';
import * as path from 'path';
import {fileFromPath} from 'formdata-node/file-from-path';
import { log } from 'console';
import axios, { AxiosRequestConfig, AxiosResponse, RawAxiosRequestHeaders } from 'axios';

export class IrisGlobalsTreeProvider implements vscode.TreeDataProvider<IrisGlobal> {

  constructor(private context: vscode.ExtensionContext) {}

  baseURL: string = "/iris-global-yaml";
  
  private _onDidChangeTreeData: vscode.EventEmitter<IrisGlobal | undefined | null | void> = new vscode.EventEmitter<IrisGlobal | undefined | null | void>();
  readonly onDidChangeTreeData: vscode.Event<IrisGlobal | undefined | null | void> = this._onDidChangeTreeData.event;
  
  public refresh() {
		this._onDidChangeTreeData.fire(undefined);
	}

  public async delete(globalname: string) {
    
    const cfgValues:any = await this.getIrisGlobalsConfig();

    const headers: AxiosRequestConfig = {
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Basic ' + btoa(cfgValues.username + ":" + cfgValues.password)
      } as RawAxiosRequestHeaders,
    };
    
    const client = axios.create({
      baseURL: cfgValues.host + this.baseURL,
    });

    const globalParts = globalname.split(":", 2);

    const requestString = "/globals/" + cfgValues.namespace + "/" + globalParts[0].trim();
    
    const globalsYaml: AxiosResponse = await client.delete(requestString, headers);
    
    if (globalsYaml.status === 200) {
      vscode.window.showInformationMessage("Global successfully deleted");
    } else {
      vscode.window.showErrorMessage("Error on try to delete Global. Error: " + globalsYaml.statusText);
    }
  }

  private async getIrisGlobalsConfig() {
    
    try {
      const configuration = await vscode.workspace.getConfiguration('');
      return configuration.get('conf.irisGlobalEditor.serverconfig');
    } catch (error) {
      log(error);
      return null;
    }

  }

  public async add() {

    let selectedText = "";

    const addInput = await vscode.window.showInputBox({
      placeHolder: "GlobalName: Value",
      prompt: "Enter de name of the new Global and its value", 
      value: selectedText
    });
    
    if(addInput === '' || addInput === undefined){
      console.log(addInput);
      vscode.window.showErrorMessage('A Global Name and Value is mandatory to execute this action');
    } else {
      vscode.window.showInformationMessage(addInput!);
    }

    const cfgValues:any = await this.getIrisGlobalsConfig();

    const headers: AxiosRequestConfig = {
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Basic ' + btoa(cfgValues.username + ":" + cfgValues.password)
      } as RawAxiosRequestHeaders,
    };
    
    const client = axios.create({
      baseURL: cfgValues.host + this.baseURL,
    });

    const inputParts = addInput === undefined ? [] : addInput.split(':', 2);
    
    const requestString = "/globals/" + cfgValues.namespace + "/" + inputParts[0].trim() + "?globalvalue=" + inputParts[1].trim();
    
    const globalsYaml: AxiosResponse = await client.put(requestString, "{}", headers);
    
    if (globalsYaml.status === 200) {
      vscode.window.showInformationMessage("Global successfully assigned");
    } else {
      vscode.window.showErrorMessage("Error while Global assigned. Error: " + globalsYaml.statusText);
    }

  }

  public async edit(globalvalue: string) {

    let selectedText = globalvalue;

    const addInput = await vscode.window.showInputBox({
      placeHolder: "GlobalName: Value",
      prompt: "Enter de name of the selected Global and its value", 
      value: selectedText
    });
    
    if(addInput === '' || addInput === undefined){
      console.log(addInput);
      vscode.window.showErrorMessage('A Global Name and Value is mandatory to execute this action');
    } else {
      vscode.window.showInformationMessage(addInput!);
    }

    const cfgValues:any = await this.getIrisGlobalsConfig();

    const headers: AxiosRequestConfig = {
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Basic ' + btoa(cfgValues.username + ":" + cfgValues.password)
      } as RawAxiosRequestHeaders,
    };
    
    const client = axios.create({
      baseURL: cfgValues.host + this.baseURL,
    });

    const inputParts = addInput === undefined ? [] : addInput.split(':', 2);
    
    const requestString = "/globals/" + cfgValues.namespace + "/" + inputParts[0].trim() + "?globalvalue=" + inputParts[1].trim();
    
    const globalsYaml: AxiosResponse = await client.put(requestString, "{}", headers);
    
    if (globalsYaml.status === 200) {
      vscode.window.showInformationMessage("Global successfully assigned");
    } else {
      vscode.window.showErrorMessage("Error while Global assigned. Error: " + globalsYaml.statusText);
    }

  }

  public async saveGlobalWithYaml(filename: string) {
    
    if(filename.endsWith('.yml')) {
      const cfgValues:any = await this.getIrisGlobalsConfig();
  
      const headers: AxiosRequestConfig = {
        headers: {
          'Content-Type': 'multipart/form-data',
          'Authorization': 'Basic ' + btoa(cfgValues.username + ":" + cfgValues.password)
        } as RawAxiosRequestHeaders,
      };
      
      const client = axios.create({
        baseURL: cfgValues.host + this.baseURL
      });
  
      const requestString = "/globals/" + cfgValues.namespace;
      
      const formData = new FormData();
      formData.append('file', await fileFromPath(filename));
      
      try {
        const globalsYaml: AxiosResponse = await client.post(requestString, formData, headers);
    
        if (globalsYaml.statusText === "OK") {
          vscode.window.showInformationMessage("File " + filename + "sent with success and global saved");
        } else {
          vscode.window.showErrorMessage("Error while send yml file. Error: " + globalsYaml.statusText);
        }
      } catch (error) {
        vscode.window.showErrorMessage("Error while send yml file. Error: " + error);
      }

    }

  }

  public async editText(globalvalue: string) {

    const cfgValues:any = await this.getIrisGlobalsConfig();

    const headers: AxiosRequestConfig = {
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Basic ' + btoa(cfgValues.username + ":" + cfgValues.password)
      } as RawAxiosRequestHeaders,
    };
    
    const client = axios.create({
      baseURL: cfgValues.host + this.baseURL
    });

    const inputParts = globalvalue === undefined ? [] : globalvalue.split(':', 2);
    
    const requestString = "/globals/yaml/" + cfgValues.namespace + "/" + inputParts[0].trim();
    
    const globalsYaml: AxiosResponse = await client.get(requestString, headers);
    
    if (globalsYaml.status === 200) {
      vscode.workspace.openTextDocument({
        language: 'yaml',
        content: globalsYaml.data
      });
    } else {
      vscode.window.showErrorMessage("Error while get Global text content. Error: " + globalsYaml.statusText);
    }

  }

  getTreeItem(element: IrisGlobal): vscode.TreeItem {
    return element;
  }

  getChildren(element?: IrisGlobal): Thenable<IrisGlobal[]> {
      
    return Promise.resolve(this.getGlobals());
      
  }

  async filterGlobals() {
    
    const configuration = await vscode.workspace.getConfiguration('');
    var filter: string = configuration.get('conf.irisGlobalEditor.filter')!;
    
    var selectedText = filter;

    const addInput = await vscode.window.showInputBox({
      prompt: "Enter the filter to global name (partial name of global)",
      value: selectedText
    });
    
    if(addInput === undefined){
      console.log(addInput);
      vscode.window.showErrorMessage('A filter value is mandatory to execute this action');
    } else {
      await vscode.workspace.getConfiguration().update('conf.irisGlobalEditor.filter', addInput);
      this.getGlobals();
      this.refresh();
      vscode.window.showInformationMessage('Filtered with success');
    }

  }

  async getGlobals(): Promise<IrisGlobal[]> {

    let response: IrisGlobal[] = [];

    const cfgValues:any = await this.getIrisGlobalsConfig();

    const headers: AxiosRequestConfig = {
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Basic ' + btoa(cfgValues.username + ":" + cfgValues.password)
      } as RawAxiosRequestHeaders,
    };
    
    const client = axios.create({
      baseURL: cfgValues.host + this.baseURL,
    });

    const globalsYaml: AxiosResponse = await client.get("/globals/" + cfgValues.namespace, headers);

    var arr = globalsYaml.data.split("\r\n");
    if(arr.length > 0 && arr[0] === "# IRIS-Global-YAML") {
      arr.splice(0, 1);
    }
    const configuration = await vscode.workspace.getConfiguration('');
    var filter: string = configuration.get('conf.irisGlobalEditor.filter')!;
    
    if(filter !== undefined && filter !== null && filter !== "") {
      arr = arr.filter((el: string) => el.toLowerCase().includes(filter!.toLowerCase()));
    } 

    for (var i = 0; i < arr.length; i++) {
      const value = (arr[i] as string).trim();

      if(value !== "") {
        const item: IrisGlobal = {
          label: value,
          version: '1.0',
          collapsibleState: vscode.TreeItemCollapsibleState.None,
          iconPath: {
            light: this.context.asAbsolutePath(path.join('resources', 'light', 'dependency.svg')),
            dark: this.context.asAbsolutePath(path.join('resources', 'dark', 'dependency.svg'))
          }
        };
        response.push(item);
      }
      
    }
    
    return response;
    
  }

}


export class IrisGlobal extends vscode.TreeItem {
  
  constructor(
		public readonly label: string,
		public readonly version: string,
		public readonly collapsibleState: vscode.TreeItemCollapsibleState,
    public readonly iconPath: any
	) {
		super(label, collapsibleState);
    this.tooltip = `${this.label}-${this.version}`;
		this.description = this.description;
    this.iconPath = iconPath;
    this.contextValue = 'irisGlobals';
	}

  

}
  • I used axios to communicate with a REST API created for me to manage globals.
  • All methods for each function are created here.
  • It is necessary implement the interface vscode.TreeItem also, to define the data of treeview items.

5. On folder src, it is necessary register your implementation to be executed on the VSCode processes on the file extension.ts, see the sample:

// The module 'vscode' contains the VS Code extensibility API
// Import the module and reference it with the alias vscode in your code below
import * as vscode from 'vscode';
import { IrisGlobal, IrisGlobalsTreeProvider } from './IrisGlobalsProvider';

export function activate(context: vscode.ExtensionContext) {

	const irisGlobalsProvider = new IrisGlobalsTreeProvider(context);
	vscode.window.registerTreeDataProvider('irisGlobals', irisGlobalsProvider);
	const disposableRefresh = vscode.commands.registerCommand('irisGlobals.refreshEntry', () => irisGlobalsProvider.refresh());
	const disposableAdd = vscode.commands.registerCommand('irisGlobals.addEntry', () => irisGlobalsProvider.add());
	const filterGlobals = vscode.commands.registerCommand('irisGlobals.filterGlobals', () => irisGlobalsProvider.filterGlobals());
	const disposableDelete = vscode.commands.registerCommand('irisGlobals.deleteEntry', (node: IrisGlobal) => irisGlobalsProvider.delete(node.label));
	const disposableEdit = vscode.commands.registerCommand('irisGlobals.editEntry', (node: IrisGlobal) => irisGlobalsProvider.edit(node.label));
	const disposableTextEdit = vscode.commands.registerCommand('irisGlobals.editTextEntry', (node: IrisGlobal) => irisGlobalsProvider.editText(node.label));


	context.subscriptions.push(vscode.workspace.onDidSaveTextDocument(editorsaveevent => {      

        if (editorsaveevent) {
			irisGlobalsProvider.saveGlobalWithYaml(editorsaveevent.fileName);
        }

    }));
	
	context.subscriptions.push(disposableRefresh);
	context.subscriptions.push(disposableAdd);
	context.subscriptions.push(disposableDelete);
	context.subscriptions.push(disposableEdit);
	context.subscriptions.push(disposableTextEdit);
	context.subscriptions.push(filterGlobals);
}

// This method is called when your extension is deactivated
export function deactivate() {}
  • I registered my TreeView Provider class and all commands implementations.
  • I subscribed to the event saveTextDocument, to call the saveGlobalWithYaml always a yaml file are saved on VSCode.

It is simple, no? Enjoy!

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください
お知らせ
· 2024年12月19日

Le Père Fouettard a volé notre récapitulatif !

Chers membres de la Communauté,

Il semble que le Père Fouettard ait joué un mauvais tour et ait emporté notre récapitulatif avant qu’il ne puisse être publié ! 🎄😅 Pas d’inquiétude, nos lutins s’activent pour le récupérer, et il sera en ligne très bientôt.

Restez à l’écoute, nous vous promettons de le ramener à temps pour partager toute la magie (et les détails) que vous attendez. Merci pour votre patience et préparez-vous pour le retour de notre récap festif !

ディスカッション (0)1
続けるにはログインするか新規登録を行ってください