使用MONO在MAC OS上开发——同步日志(一)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 原先打算再写点EXT.NET方面的,由于现在在玩Silverlight和Android,所以不打算写下去了。而且最近很忙,所以发帖也不会很及时。   好了,转入正题了:最近客户有个需求,要求写个小程序监控生产线上的苹果一体机的日志文件并上传到服务器。

  原先打算再写点EXT.NET方面的,由于现在在玩Silverlight和Android,所以不打算写下去了。而且最近很忙,所以发帖也不会很及时。

  好了,转入正题了:最近客户有个需求,要求写个小程序监控生产线上的苹果一体机的日志文件并上传到服务器。开始想使用Perl或者Python,但是时间不够(因为对这两门语言还不太熟悉),于是想试试MONO。MONO虽然没想象中好用,但是还算勉强能用。

  虽然MonoDevelop还可以,但是还是比较喜欢使用VS开发。于是在VS里面先编码。值得注意的是:

  1. 如果是开发Winform程序,界面用GTK重画吧。
  2. 如果是在VS里面开发,最好将所有的编码和注释都用英文。否则换其他系统时,可能会出现乱码。
  3. 编写时需注意MONO是否支持,否则就是白写。

接下来,开始编码。

1.读取配置文件

  习惯用XML,发现不支持System.Xml.Linq,亦不支持System.Xml,读取ini文件也麻烦,于是干脆读取文本文件好了。示例配置如下:

MonitoringDirectoryType:['Immediate','Cycle']

Path:['/Users/PRODUCTION/Public/FinalTest/LogsFolder','/Users/PRODUCTION/Public/FinalTest/LogsFolder']

TargetPath:['/Volumes/mes_data/FINALTEST/n81a/{Y}/{M}/{D}/FIN012','/Volumes/mes_data/FINALTEST/n81a/{Y}/{M}/{D}/FIN012']

IncludeSubdirectories:['FALSE','false']

Filter:['*.TXT','*.CSV']

BackupPath:['/Users/PRODUCTION/BACKUP/{Y}/{M}/{D}','/Users/PRODUCTION/BACKUP/{Y}/{M}/{D}']

BackupExpired:['2','2']

CycleMinutes:['','1440']

相关解析代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using MonitoringApp.Custom;
using System.Text.RegularExpressions;
using Gtk;
namespace MonitoringApp.Code.App
{
    public class Configuration
    {

        private static bool isLoadFirst = false;
        private static List<MyConfig> configLst;
        public static List<MyConfig> ConfigLst
        {
            get
            {
                if (configLst == null)
                {
                    try
                    {
                        if (!isLoadFirst)
                            return LoadFromInitParams();
                        else
                            return null;
                    }
                    catch (Exception ex)
                    {
                            LogManager.WriteErrorLog(ex);

                        return null;
                    }
                }
                return configLst;
            }
            set { configLst = value; }
        }

        /// <summary>
        /// Load Configuration file
        /// </summary>
        /// <returns></returns>
        private static List<MyConfig> LoadFromInitParams()
        {
            isLoadFirst = true;
            string _configPath = Path.Combine(Directory.GetCurrentDirectory(), "Configuration.txt");
            if (File.Exists(_configPath))
            {
                if (ConfigLst == null)
                    ConfigLst = new List<MyConfig>();
                else
                    return ConfigLst;
                using (StreamReader sr = new StreamReader(_configPath))
                {
                    int lineIndex = 1;
                    while (sr.Peek() > 0)
                    {
                        string str = sr.ReadLine().Trim();
                        if (str.Length == 0)
                            continue;
                        if (!str.Contains("[") || !str.Contains("]"))
                        {
                            LogManager.WriteErrorLog(string.Format("Config Error:'[' OR ']' Not Exist.At Line {0}.", lineIndex));
                            continue;
                        }
                        if (!str.Contains(":"))
                        {
                            LogManager.WriteErrorLog(string.Format("Config Error:':' Not Exist.At Line {0}.", lineIndex));
                            continue;
                        }
                        string[] names = str.Split(':');
                        str = str.Substring(str.IndexOf(':') + 1).Trim(']').Trim('[').Trim('\'');
                        string[] strConfigs = str.Split(',');
                        SetConfig(names, ConfigLst, strConfigs, lineIndex == 1);
                        lineIndex++;
                    }
                }
                return ConfigLst;
            }
            else
            {
                LogManager.WriteErrorLog(string.Format("can't find config file.Path:{0}.",_configPath));
                return null;
            }
        }
        /// <summary>
        /// Set Config
        /// </summary>
        /// <param name="name"></param>
        /// <param name="lst"></param>
        /// <param name="strConfigs"></param>
        private static void SetConfig(string[] name, List<MyConfig> lst, string[] strConfigs, bool isLineOne)
        {
            try
            {
                var mcConfig = (MonitoringConfigurations)Enum.Parse(typeof(MonitoringConfigurations), name[0], true);
                //Set Values
                for (int i = 0; i < strConfigs.Length; i++)
                {
                    string value = strConfigs[i].Trim('\'');
                    switch (mcConfig)
                    {
                        case MonitoringConfigurations.MonitoringDirectoryType:
                            {
                                #region MonitoringDirectoryType Defalut:immediate
                                switch (value.ToLower())
                                {
                                    case "immediate":
                                        {
                                            if (isLineOne)
                                            {
                                                MyConfig myConfig = new MyConfig();
                                                myConfig.MDType = MonitoringDirectoryType.Immediate;
                                                lst.Add(myConfig);
                                            }
                                            else
                                            {
                                                lst[i].MDType = MonitoringDirectoryType.Immediate;
                                            }
                                            break;
                                        }
                                    case "cycle":
                                        {
                                            if (isLineOne)
                                            {
                                                MyConfig myConfig = new MyConfig();
                                                myConfig.MDType = MonitoringDirectoryType.Cycle;
                                                lst.Add(myConfig);
                                            }
                                            else
                                            {
                                                lst[i].MDType = MonitoringDirectoryType.Cycle;
                                            }
                                            break;
                                        }
                                    default:
                                        {
                                            if (isLineOne)
                                            {
                                                MyConfig myConfig = new MyConfig();
                                                myConfig.MDType = MonitoringDirectoryType.Immediate;
                                                lst.Add(myConfig);
                                            }
                                            else
                                            {
                                                lst[i].MDType = MonitoringDirectoryType.Immediate;
                                            }
                                            break;
                                        }
                                }
                                #endregion
                                break;
                            }
                        case MonitoringConfigurations.Path:
                            #region Path
                            if (isLineOne)
                            {
                                MyConfig myConfig = new MyConfig();
                                myConfig.Path = value;
                                lst.Add(myConfig);
                            }
                            else
                            {
                                lst[i].Path = value;
                            }
                            #endregion
                            break;
                        case MonitoringConfigurations.IncludeSubdirectories:
                            #region IncludeSubdirectories
                            if (isLineOne)
                            {
                                MyConfig myConfig = new MyConfig();
                                myConfig.IncludeSubdirectories = Convert.ToBoolean(value);
                                lst.Add(myConfig);
                            }
                            else
                            {
                                lst[i].IncludeSubdirectories = Convert.ToBoolean(value);
                            }
                            #endregion
                            break;
                        case MonitoringConfigurations.Filter:
                            #region Filter
                            if (isLineOne)
                            {
                                MyConfig myConfig = new MyConfig();
                                myConfig.Filter = value;
                                lst.Add(myConfig);
                            }
                            else
                            {
                                lst[i].Filter = value;
                            }
                            break;
                            #endregion
                        case MonitoringConfigurations.BackupPath:
                            #region BackupPath
                            if (isLineOne)
                            {
                                MyConfig myConfig = new MyConfig();
                                myConfig.BackupPath = value;
                                lst.Add(myConfig);
                            }
                            else
                            {
                                lst[i].BackupPath = value;
                            }
                            #endregion
                            break;
                        case MonitoringConfigurations.TargetPath:
                            #region TargetPath
                            if (isLineOne)
                            {
                                MyConfig myConfig = new MyConfig();
                                myConfig.TargetPath = value;
                                lst.Add(myConfig);
                            }
                            else
                            {
                                lst[i].TargetPath = value;
                            }
                            #endregion
                            break;
                        case MonitoringConfigurations.BackupExpired:
                            #region BackupExpired  Unit:days  Default:30
                            if (isLineOne)
                            {
                                MyConfig myConfig = new MyConfig();
                                myConfig.BackupExpired = Convert.ToInt32(value.Length == 0 ? "30" : value);
                                lst.Add(myConfig);
                            }
                            else
                            {
                                lst[i].BackupExpired = Convert.ToInt32(value.Length == 0 ? "30" : value);
                            }
                            #endregion
                            break;
                        case MonitoringConfigurations.CycleMinutes:
                            #region CycleMinutes  Unit:Minute  Default:60
                            if (isLineOne)
                            {
                                MyConfig myConfig = new MyConfig();
                                myConfig.CycleMinutes = Convert.ToInt32(value.Length == 0 ? "60" : value);
                                lst.Add(myConfig);
                            }
                            else
                            {
                                lst[i].CycleMinutes = Convert.ToInt32(value.Length == 0 ? "60" : value);
                            }
                            #endregion
                            break;
                        default:
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                LogManager.WriteErrorLog(ex);
            }


        }

    }
}

 

 

值得注意的是:

  1. 这里是按行读取的。从读取配置来看,可以看出,是支持多个配置项的。
  2. 如果出错,会记录日志。
  3. 和客户讲解如何配置是一件麻烦的事情。相关配置解释如下:
	MonitoringDirectoryType:目录类型,仅支持两个值(Immediate、Cycle)。Immediate表示即时监控(默认值),Cycle表示周期监控。	
	Path:监控目录路径。必须是存在的路径。
	TargetPath:目标目录路径。可以是远程目录路径。不能使用SMB路径,而应该是用如“/Volumes/mes_data/n81a”的类型。
	IncludeSubdirectories:是否涵盖子目录。
	Filter:过滤字符串。如“*”表示监控所有文件,“*.txt”表示监控所有的文本文件。
	BackupPath:备份路径。
	BackupExpired:备份过期时间。单位是天。必须为整数。默认值30天。
	CycleMinutes:周期循环时间。单位是分。 必须为整数。默认值60分钟。

 

然后针对配置写个说明文档,这样客户就会配置了。

2)记录日志

程序运行起来总不可避免的会遇到各种问题,记录日志就不可避免了。相关代码如下:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Gtk;

namespace MonitoringApp.Code.App
{
    public class LogManager
    {
        public static object obj = new object();
        static LogManager()
        {
        }
        #region Fields and Properties
        private static string _logPath = string.Empty;
        public static string LogPath
        {
            get
            {
                lock (obj)
                {
                    if (_logPath == string.Empty)
                    {
                        var _logStr = string.Format("{0}/log/{1}/{2}", Path.Combine(Directory.GetCurrentDirectory(), "Data"), DateTime.Now.ToString("yyyy-MM"), DateTime.Now.Day);
                        if (!System.IO.Directory.Exists(_logStr))
                            System.IO.Directory.CreateDirectory(_logStr);
                        return string.Format("{0}/", _logStr);
                    }
                    return _logPath;
                }
            }
            set { _logPath = value; }
        }
        private static string _logFielPrefix = string.Empty;
        public static string LogFielPrefix
        {
            get { return _logFielPrefix; }
            set { _logFielPrefix = value; }
        }
        #endregion

        #region Log

        public static void WriteLog(string logFile, string msg)
        {
            try
            {
                lock (obj)
                {
                    var _sb = new System.Text.StringBuilder();
                    _sb.Append(LogPath).Append(LogFielPrefix).Append(logFile).Append(".Log");
                    using (var _sw = System.IO.File.AppendText(_sb.ToString()))
                    {
                        _sw.WriteLine("==============================={0}===============================", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                        _sw.WriteLine(msg);
                        _sw.Flush();
                        _sw.Close();
                        Console.WriteLine(msg);

                    }
                }
            }
            catch
            { }
        }

        public static void WriteLog(LogFile logFile, string msg)
        {
            WriteLog(logFile.ToString(), msg);
        }
        public static void WriteTraceLog(string msg)
        {
            Console.WriteLine(msg);
        }

        public static void WriteErrorLog(string msg)
        {
            WriteLog(LogFile.Error, msg);
        }
        public static void WriteErrorLog(Exception ex)
        {
            var _sbError = new StringBuilder();
            _sbError.Append("[Message]").Append(ex.Message);
            _sbError.Append("\r\n[TargetSite]").Append(ex.TargetSite);
            _sbError.Append("\r\n[StackTrace]").Append(ex.StackTrace);
            _sbError.Append("\r\n[Source]").Append(ex.Source);
            foreach (var _item in ex.Data.Keys)
            {
                _sbError.Append("\r\n[").Append(_item).Append("]").Append(ex.Data[_item]);
            }
            if (ex.InnerException != null && ex.InnerException.Message != ex.Message)
            {
                _sbError.AppendLine("____________________________________________________________________________________");
                _sbError.Append("[Message]").Append(ex.InnerException.Message);
                _sbError.Append("\r\n[TargetSite]").Append(ex.InnerException.TargetSite);
                _sbError.Append("\r\n[StackTrace]").Append(ex.InnerException.StackTrace);
                _sbError.Append("\r\n[Source]").Append(ex.InnerException.Source);
                _sbError.AppendLine("____________________________________________________________________________________");
            }
            WriteLog(LogFile.Error, _sbError.ToString());
        }
        public static void WriteWarningLog(string msg)
        {
            WriteLog(LogFile.Warning, msg);
        }
        #endregion
    }

    public enum LogFile
    {
        Trace,
        Warning,
        Error,
        SQL,
        System
    }
}

值得注意的是“Directory.GetCurrentDirectory()可以获取到当前用户的个人目录,至于获取到程序当前目录路径,Winform的那一套不管用(如果哪位朋友找到了适合的方法,请留言)。苹果系统和Window系统差别太大,从没玩过苹果系统,刚开始玩还挺不习惯的。

接下来,讲述如何监控目录以及定时备份,最后讲述如何发布部署。发布部署才是最重要的一环。不上生产线,就不知道会有什么问题。当初以为这个小程序,一天就能搞定,结果中秋3天都废了。还好万幸搞定。时间关系,就此打住。

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
目录
相关文章
|
6月前
|
Web App开发 安全 iOS开发
基于PyCharm与Mac系统的Chrome历史记录清理工具开发实战
《基于PyCharm与Mac系统的Chrome历史记录清理工具开发实战》详细解析了如何在macOS下通过Python脚本自动化清理Chrome浏览器的历史记录。文章以`clear_chrome_history.py`为例,结合PyCharm开发环境,深入讲解技术实现。内容涵盖进程检测、文件清理、虚拟环境配置及断点调试技巧,并提供安全增强与跨平台适配建议。该工具不仅保障个人隐私,还适用于自动化运维场景,具备较高实用价值。
170 0
|
Rust 前端开发 JavaScript
Tauri 开发实践 — Tauri 日志记录功能开发
本文介绍了如何为 Tauri 应用配置日志记录。Tauri 是一个利用 Web 技术构建桌面应用的框架。文章详细说明了如何在 Rust 和 JavaScript 代码中设置和集成日志记录,并控制日志输出。通过添加 `log` crate 和 Tauri 日志插件,可以轻松实现多平台日志记录,包括控制台输出、Webview 控制台和日志文件。文章还展示了如何调整日志级别以优化输出内容。配置完成后,日志记录功能将显著提升开发体验和程序稳定性。
627 1
Tauri 开发实践 — Tauri 日志记录功能开发
|
7月前
|
前端开发 JavaScript 程序员
鸿蒙开发:console日志输出
针对初学者而言,大家只需要掌握住日志打印即可,等到了鸿蒙应用开发的时候,还有一个鸿蒙原生的打印工具HiLog,到时,我们也会详细的去讲述,也会针对HiLog,封装一个通用的工具类。
229 11
鸿蒙开发:console日志输出
|
7月前
|
缓存 Java 编译器
|
7月前
|
监控 Shell Linux
Android调试终极指南:ADB安装+多设备连接+ANR日志抓取全流程解析,覆盖环境变量配置/多设备调试/ANR日志分析全流程,附Win/Mac/Linux三平台解决方案
ADB(Android Debug Bridge)是安卓开发中的重要工具,用于连接电脑与安卓设备,实现文件传输、应用管理、日志抓取等功能。本文介绍了 ADB 的基本概念、安装配置及常用命令。包括:1) 基本命令如 `adb version` 和 `adb devices`;2) 权限操作如 `adb root` 和 `adb shell`;3) APK 操作如安装、卸载应用;4) 文件传输如 `adb push` 和 `adb pull`;5) 日志记录如 `adb logcat`;6) 系统信息获取如屏幕截图和录屏。通过这些功能,用户可高效调试和管理安卓设备。
|
11月前
|
监控 开发者
鸿蒙5.0版开发:使用HiLog打印日志(ArkTS)
在HarmonyOS 5.0中,HiLog是系统提供的日志系统,支持DEBUG、INFO、WARN、ERROR、FATAL五种日志级别。本文介绍如何在ArkTS中使用HiLog打印日志,并提供示例代码。通过合理使用HiLog,开发者可以更好地调试和监控应用。
813 16
|
开发工具 git
git显示开发日志+WinSW——将.exe文件注册为服务的一个工具+图床PicGo+kubeconfig 多个集群配置 如何切换
git显示开发日志+WinSW——将.exe文件注册为服务的一个工具+图床PicGo+kubeconfig 多个集群配置 如何切换
150 1
|
开发框架 缓存 安全
开发日志:IIS安全配置
开发日志:IIS安全配置
开发日志:IIS安全配置
|
Linux C语言 iOS开发
MacOS环境-手写操作系统-06-在mac下通过交叉编译:C语言结合汇编
MacOS环境-手写操作系统-06-在mac下通过交叉编译:C语言结合汇编
265 0
|
人工智能 Java Spring
Spring框架下,如何让你的日志管理像‘AI’一样智能,提升开发效率的秘密武器!
【8月更文挑战第31天】日志管理在软件开发中至关重要,不仅能帮助开发者追踪问题和调试程序,还是系统监控和运维的重要工具。在Spring框架下,通过合理配置Logback等日志框架,可大幅提升日志管理效率。本文将介绍如何引入日志框架、配置日志级别、在代码中使用Logger,以及利用ELK等工具进行日志聚合和分析,帮助你构建高效、可靠的日志管理系统,为开发和运维提供支持。
310 0

热门文章

最新文章

推荐镜像

更多